Long startCacheFlush(final byte[] encodedRegionName, final Map<byte[], Long> familyToSeq) {
    Map<ImmutableByteArray, Long> oldSequenceIds = null;
    Long lowestUnflushedInRegion = HConstants.NO_SEQNUM;
    synchronized (tieLock) {
      Map<ImmutableByteArray, Long> m = this.lowestUnflushedSequenceIds.get(encodedRegionName);
      if (m != null) {
        // NOTE: Removal from this.lowestUnflushedSequenceIds must be done in controlled
        // circumstance because another concurrent thread now may add sequenceids for this family
        // (see above in getOrCreateLowestSequenceId). Make sure you are ok with this. Usually it
        // is fine because updates are blocked when this method is called. Make sure!!!
        for (Map.Entry<byte[], Long> entry : familyToSeq.entrySet()) {
          ImmutableByteArray familyNameWrapper = ImmutableByteArray.wrap((byte[]) entry.getKey());
          Long seqId = null;
          if (entry.getValue() == HConstants.NO_SEQNUM) {
            seqId = m.remove(familyNameWrapper);
          } else {
            seqId = m.replace(familyNameWrapper, entry.getValue());
          }
          if (seqId != null) {
            if (oldSequenceIds == null) {
              oldSequenceIds = new HashMap<>();
            }
            oldSequenceIds.put(familyNameWrapper, seqId);
          }
        }
        if (oldSequenceIds != null && !oldSequenceIds.isEmpty()) {
          if (this.flushingSequenceIds.put(encodedRegionName, oldSequenceIds) != null) {
            LOG.warn("Flushing Map not cleaned up for " + Bytes.toString(encodedRegionName)
              + ", sequenceid=" + oldSequenceIds);
          }
        }
        if (m.isEmpty()) {
          // Remove it otherwise it will be in oldestUnflushedStoreSequenceIds for ever
          // even if the region is already moved to other server.
          // Do not worry about data racing, we held write lock of region when calling
          // startCacheFlush, so no one can add value to the map we removed.
          this.lowestUnflushedSequenceIds.remove(encodedRegionName);
        } else {
          // Flushing a subset of the region families. Return the sequence id of the oldest entry.
          lowestUnflushedInRegion = Collections.min(m.values());
        }
      }
    }
    // Do this check outside lock.
    if (oldSequenceIds != null && oldSequenceIds.isEmpty()) {
      // TODO: if we have no oldStoreSeqNum, and WAL is not disabled, presumably either
      // the region is already flushing (which would make this call invalid), or there
      // were no appends after last flush, so why are we starting flush? Maybe we should
      // assert not empty. Less rigorous, but safer, alternative is telling the caller to stop.
      // For now preserve old logic.
      LOG.warn("Couldn't find oldest sequenceid for " + Bytes.toString(encodedRegionName));
    }
    return lowestUnflushedInRegion;
  }
@param encodedRegionName Region to flush.
@param families          Families to flush. May be a subset of all families in the region.
@return Returns {@link HConstants#NO_SEQNUM} if we are flushing the whole region OR if we are
        flushing a subset of all families but there are no edits in those families not being
        flushed; in other words, this is effectively same as a flush of all of the region
        though we were passed a subset of regions. Otherwise, it returns the sequence id of the
        oldest/lowest outstanding edit.
hbase-server/src/main/java/org/apache/hadoop/hbase/regionserver/wal/SequenceIdAccounting.java