@Override
  public void readFromString(String src) {
    if (StringUtils.isEmpty(src)) {
      highWatermark = Long.MAX_VALUE;
      exceptions = new long[0];
      abortedBits = new BitSet();
      return;
    }

    String[] values = src.split(":");
    highWatermark = Long.parseLong(values[0]);
    minOpenTxn = Long.parseLong(values[1]);
    List<Long> openTxns = new ArrayList<>();
    List<Long> abortedTxns = new ArrayList<>();
    if (values.length == 3) {
      if (!values[2].isEmpty()) {
        openTxns = readTxnListFromRangeString(values[2]);
      }
    } else if (values.length > 3)  {
      if (!values[2].isEmpty()) {
        openTxns = readTxnListFromRangeString(values[2]);
      }
      if (!values[3].isEmpty()) {
        abortedTxns = readTxnListFromRangeString(values[3]);
      }
    }
    exceptions = new long[openTxns.size() + abortedTxns.size()];
    abortedBits = new BitSet(exceptions.length);

    int exceptionIndex = 0;
    int openIndex = 0;
    int abortIndex = 0;
    while (openIndex < openTxns.size() || abortIndex < abortedTxns.size()) {
      if (abortIndex == abortedTxns.size() ||
          (openIndex < openTxns.size() && openTxns.get(openIndex) < abortedTxns.get(abortIndex))) {
        exceptions[exceptionIndex++] = openTxns.get(openIndex++);
      } else {
        abortedBits.set(exceptionIndex);
        exceptions[exceptionIndex++] = abortedTxns.get(abortIndex++);
      }
    }
  }
txnlist is represented in ranges like this: 10-20,14,16-50
if the range is smaller then 5 it will not get merged, to avoid unnecessary overhead
storage-api/src/java/org/apache/hadoop/hive/common/ValidReadTxnList.java