private long evictOrPurge(boolean isPurge) {
    flushAllBPWrappers();
    long evicted = 0;
    LlapCacheableBuffer oldTail;
    listLock.lock();
    try {
      LlapCacheableBuffer current = listTail;
      LlapCacheableBuffer lockedHead = null;
      LlapCacheableBuffer lockedTail = null;
      oldTail = listTail;
      while (current != null) {
        // Case for when there is proactive eviction, but current buffer is not marked -> thus need to be kept
        if (!isPurge && !current.isMarkedForEviction()) {
          LlapCacheableBuffer newCurrent = current.prev;
          oldTail = removeFromLocalList(oldTail, current);

          current.indexInHeap = LlapCacheableBuffer.IN_LIST;
          if (lockedHead != null) {
            current.next = lockedHead;
            lockedHead.prev = current;
            lockedHead = current;
          } else {
            lockedHead = current;
            lockedTail = current;
            current.next = null;
          }

          current = newCurrent;
          continue;
        }
        int invalidateResult = current.invalidate();
        current.indexInHeap = LlapCacheableBuffer.NOT_IN_CACHE;
        if (invalidateResult == LlapCacheableBuffer.INVALIDATE_OK) {
          current = current.prev;
        }
        if (invalidateResult == LlapCacheableBuffer.INVALIDATE_ALREADY_INVALID && instantProactiveEviction &&
            current.isMarkedForEviction()) {
          // Found a marked and instantly deallocated buffer. If this is a purge we need to do a proper cleanup of
          // this buffer. If this is a proactive sweep, cleanup will be done later in this method.
          if (isPurge) {
            evictionListener.notifyProactivelyEvicted(current);
          } else {
            current = current.prev;
            continue;
          }
        }

        // Runs if invalidation didn't succeed due to a non-proactive eviction cause (e.g. buffer is locked and
        // currently being used). Also runs if there was proactive eviction (+instant dealloc) and this is a purge run.
        // In either case we need to remove this buffer from the list of to-be-removed buffers.
        if (invalidateResult != LlapCacheableBuffer.INVALIDATE_OK) {
          // Remove from the list.
          LlapCacheableBuffer newCurrent = current.prev;
          oldTail = removeFromLocalList(oldTail, current);
          current = newCurrent;
        }
      }
      listHead = lockedHead;
      listTail = lockedTail;
    } finally {
      listLock.unlock();
    }

    LlapCacheableBuffer[] oldHeap;
    int oldHeapSize;
    heapLock.lock();
    try {
      oldHeap = heap;
      oldHeapSize = heapSize;
      heap = new LlapCacheableBuffer[maxHeapSize];
      heapSize = 0;
      for (int i = 0; i < oldHeapSize; ++i) {
        LlapCacheableBuffer result = oldHeap[i];
        // Case for when there is proactive eviction, but current buffer is not marked -> thus need to be kept
        if (!isPurge && !result.isMarkedForEviction()) {
          oldHeap[i] = null;
          result.indexInHeap = heapSize;
          heapifyUpUnderLock(result, result.lastUpdate);
          ++heapSize;
          continue;
        }

        result.indexInHeap = LlapCacheableBuffer.NOT_IN_CACHE;
        int invalidateResult = result.invalidate();
        if (invalidateResult != LlapCacheableBuffer.INVALIDATE_OK) {
          if (invalidateResult == LlapCacheableBuffer.INVALIDATE_ALREADY_INVALID && instantProactiveEviction &&
              result.isMarkedForEviction()) {
            // Found a marked and instantly deallocated buffer. If this is a purge we need to do a proper cleanup of
            // this buffer. If this is a proactive sweep cleanup will be done later in this method.
            if (isPurge) {
              oldHeap[i] = null;
              evictionListener.notifyProactivelyEvicted(result);
            }
          } else {
            // Other - non proactive eviction relating cases
            oldHeap[i] = null; // Removed from heap without evicting.
          }
        }
      }
    } finally {
      heapLock.unlock();
    }
    LlapCacheableBuffer current = oldTail;
    while (current != null) {
      evicted += current.getMemoryUsage();
      if (isPurge) {
        evictionListener.notifyEvicted(current);
      } else {
        evictionListener.notifyProactivelyEvicted(current);
      }
      current = current.prev;
    }
    for (int i = 0; i < oldHeapSize; ++i) {
      current = oldHeap[i];
      if (current == null) {
        continue;
      }
      evicted += current.getMemoryUsage();
      if (isPurge) {
        evictionListener.notifyEvicted(current);
      } else {
        evictionListener.notifyProactivelyEvicted(current);
      }
    }
    if (isPurge) {
      LlapIoImpl.LOG.info("PURGE: evicted {} from LRFU policy",
          LlapUtil.humanReadableByteCount(evicted));
    } else {
      LlapIoImpl.LOG.info("PROACTIVE_EVICTION: evicted {} from LRFU policy",
          LlapUtil.humanReadableByteCount(evicted));
    }
    return evicted;
  }
Flushes all BPWrappers which will in turn clear IO-Threads' threadlocal buffers.
llap-server/src/java/org/apache/hadoop/hive/llap/cache/LowLevelLrfuCachePolicy.java