void setLastIndexedOffset(long currentLastIndexedOffset, int cacheGeneration) {
        val candidates = new ArrayList<MigrationCandidate>();
        synchronized (this) {
            // Update stored last indexed offset.
            Preconditions.checkArgument(currentLastIndexedOffset >= this.lastIndexedOffset,
                    "currentLastIndexedOffset (%s) must be at least the current value (%s).",
                    currentLastIndexedOffset, this.lastIndexedOffset);
            this.lastIndexedOffset = currentLastIndexedOffset;

            // Remove obsolete backpointers. They now exist in the index.
            this.backpointers.keySet().removeIf(sourceOffset -> sourceOffset < currentLastIndexedOffset);
            for (val tailHash : this.tailOffsets.entrySet()) {
                val offset = tailHash.getValue();
                if (offset.getSegmentOffset() < currentLastIndexedOffset) {
                    // This entry has already been indexed, so it should be removed from the tail cache.
                    CacheEntry cacheEntry = this.cacheEntries.computeIfAbsent(getHashGroup(tailHash.getKey()),
                            hg -> new CacheEntry(hg, cacheGeneration));
                    candidates.add(new MigrationCandidate(tailHash.getKey(), cacheEntry, offset));
                }
            }
        }

        candidates.forEach(mc -> mc.cacheEntry.update(mc.keyHash, mc.offset.encode(), cacheGeneration));
        synchronized (this) {
            // Finally, remove tail hashes, but ONLY if they haven't changed - it's possible that since we released the lock
            // above a newer value was recorded; we shouldn't be removing it then. We use Map.remove(Key, Value) for this.
            candidates.forEach(c -> this.tailOffsets.remove(c.keyHash, c.offset));
        }
    }
void setLastIndexedOffset ( long currentLastIndexedOffset , int cacheGeneration ) { val candidates = new ArrayList < MigrationCandidate > ( ) ; synchronized ( this ) { Preconditions . checkArgument ( currentLastIndexedOffset >= this . lastIndexedOffset , "currentLastIndexedOffset (%s) must be at least the current value (%s)." , currentLastIndexedOffset , this . lastIndexedOffset ) ; this . lastIndexedOffset = currentLastIndexedOffset ; this . backpointers . keySet ( ) . removeIf ( sourceOffset -> sourceOffset < currentLastIndexedOffset ) ; for ( val tailHash : this . tailOffsets . entrySet ( ) ) { val offset = tailHash . getValue ( ) ; if ( offset . getSegmentOffset ( ) < currentLastIndexedOffset ) { CacheEntry cacheEntry = this . cacheEntries . computeIfAbsent ( getHashGroup ( tailHash . getKey ( ) ) , hg -> new CacheEntry ( hg , cacheGeneration ) ) ; candidates . add ( new MigrationCandidate ( tailHash . getKey ( ) , cacheEntry , offset ) ) ; } } } candidates . forEach ( mc -> mc . cacheEntry . update ( mc . keyHash , mc . offset . encode ( ) , cacheGeneration ) ) ; synchronized ( this ) { candidates . forEach ( c -> this . tailOffsets . remove ( c . keyHash , c . offset ) ) ; } }
Updates the Last Indexed Offset (cached value of the Segment's {@link TableAttributes#INDEX_OFFSET} attribute).
Clears out any backpointers whose source offsets will be smaller than the new value for Last Indexed Offset.