private long prepareOneHeaderForMove(int victimHeaderIx, boolean isDiscard, int maxListIx) {
      byte header = headers[victimHeaderIx];
      if (header == 0) return -1;
      int freeListIx = freeListFromHeader(header);
      if (freeListIx > maxListIx) {
        // This can only come from a brute force discard; for now we don't discard blocks larger
        // than the target block. We could discard it and add remainder to free lists.
        // By definition if we are fragmented there should be a smaller buffer somewhere.
        return -1;
      }
      if (buffers[victimHeaderIx] == null && (header & 1) == 1) {
        return -1; // There's no buffer and another move is reserving this.
      }
      FreeList freeList = freeLists[freeListIx];
      freeList.lock.lock();
      try {
        if (headers[victimHeaderIx] != header) {
          // We bail if there are any changes. Note that we don't care about ABA here - all the
          // stuff on the left has been taken out already so noone can touch it, and all the stuff
          // on the right is yet to be seen so we don't care if they changed with this - if it's
          // in the same free list, the processing sequence will remain the same going right.
          return -1;
        }
        LlapAllocatorBuffer buffer = buffers[victimHeaderIx];
         if (buffer == null && (header & 1) == 1) {
          return -1; // The only ABA problem we care about. Ok to have another buffer in there;
                     // not ok to have a location locked by someone else.
        }
        int allocSize = 0;
        if (buffer != null) {
          // The buffer can only be removed after the removed flag has been set. If we are able to
          // lock it here, noone can set the removed flag and thus remove it. That would also mean
          // that the header is not free, and noone will touch the header either.
          if (!buffer.startMoveOrDiscard(arenaIx, victimHeaderIx, isDiscard)) {
            return -1;
          }
          CasLog.logMove(arenaIx, victimHeaderIx, System.identityHashCode(buffer));
          allocSize = allocSizeFromFreeList(freeListIx);
        } else {
          // Take the empty buffer out of the free list.
          setHeaderNoBufAlloc(victimHeaderIx, freeListIx, CasLog.Src.EMPTY_V);
          removeBlockFromFreeList(freeList, victimHeaderIx, freeListIx);
        }
        return makeIntPair(allocSize, freeListIx);
      } finally {
        freeList.lock.unlock();
      }
    }
Prepares victimHeaderIx header to be moved - locks if it's allocated, takes out of
the free list if not.
@return the list level to which the header belongs if this succeeded, -1 if not.
llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java