private int allocateWithSplit(int freeListIx, MemoryBuffer[] dest,
        long[] destHeaders, int destIx, int destCount, int allocSize, int maxSplitFreeListIx) {
      if (data == null) return -1; // not allocated yet
      FreeList freeList = freeLists[freeListIx];
      int remaining = -1;
      freeList.lock.lock();
      try {
        // Try to allocate from target-sized free list, maybe we'll get lucky.
        destIx = allocateFromFreeListUnderLock(
            freeList, freeListIx, dest, destHeaders, destIx, destCount, allocSize);
        remaining = destCount - destIx;
        if (remaining == 0) return destIx;
      } finally {
        freeList.lock.unlock();
      }
      int headerStep = 1 << freeListIx; // Number of headers (smallest blocks) per target block.
      int splitListIx = freeListIx + 1; // Next free list from which we will be splitting.
      // Each iteration of this loop tries to split blocks from one level of the free list into
      // target size blocks; if we cannot satisfy the allocation from the free list containing the
      // blocks of a particular size, we'll try to split yet larger blocks, until we run out.
      if (maxSplitFreeListIx == -1) {
        maxSplitFreeListIx = freeLists.length - 1;
      }
      while (remaining > 0 && splitListIx <= maxSplitFreeListIx) {
        int splitWaysLog2 = (splitListIx - freeListIx);
        assert splitWaysLog2 > 0;
        int splitWays = 1 << splitWaysLog2; // How many ways each block splits into target size.
        int lastSplitBlocksRemaining = -1; // How many target-sized blocks remain from last split.
        int lastSplitNextHeader = -1; // The header index for the beginning of the remainder.
        FreeList splitList = freeLists[splitListIx];
        splitList.lock.lock();
        try {
          int headerIx = splitList.listHead; // Index of the next free block to split.
          while (headerIx >= 0 && remaining > 0) {
            int origOffset = offsetFromHeaderIndex(headerIx), offset = origOffset;
            // We will split the block at headerIx [splitWays] ways, and take [toTake] blocks,
            // which will leave [lastSplitBlocksRemaining] free blocks of target size.
            int toTake = Math.min(splitWays, remaining);
            remaining -= toTake;
            lastSplitBlocksRemaining = splitWays - toTake; // Whatever remains.
            // Take toTake blocks by splitting the block at offset.
            for (; toTake > 0; ++destIx, --toTake, headerIx += headerStep, offset += allocSize) {
              if (assertsEnabled) {
                checkHeader(headerIx, -1, false); // Cannot validate the list, it may be unset
              }
              if (dest != null) {
                LlapAllocatorBuffer buffer = (LlapAllocatorBuffer)dest[destIx];
                initializeNewlyAllocated(buffer, allocSize, headerIx, offset);
                setHeaderAlloc(headerIx, freeListIx, buffer, CasLog.Src.ALLOC_SPLIT_BUF);
              } else {
                destHeaders[destIx] = makeIntPair(arenaIx, headerIx);
                setHeaderNoBufAlloc(headerIx, freeListIx, CasLog.Src.ALLOC_SPLIT_DEFRAG);
              }
            }
            lastSplitNextHeader = headerIx; // If anything remains, this is where it starts.
            headerIx = getNextFreeListItem(origOffset);
          }
          replaceListHeadUnderLock(splitList, headerIx); // In the end, update free list head.
        } finally {
          splitList.lock.unlock();
        }
        CasLog.Src src = (dest != null) ? CasLog.Src.SPLIT_AFTER_BUF : CasLog.Src.SPLIT_AFTER_DEFRAG;
        if (remaining == 0) {
          // We have just obtained all we needed by splitting some block; now we need
          // to put the space remaining from that block into lower free lists.
          // We'll put at most one block into each list, since 2 blocks can always be combined
          // to make a larger-level block. Each bit in the remaining target-sized blocks count
          // is one block in a list offset from target-sized list by bit index.
          // We do the merges here too, since the block we just allocated could immediately be
          // moved out, then the resulting free space abandoned.
          int newListIndex = freeListIx;
          while (lastSplitBlocksRemaining > 0) {
            if ((lastSplitBlocksRemaining & 1) == 1) {
              addToFreeListWithMerge(lastSplitNextHeader, newListIndex, src);
              lastSplitNextHeader += (1 << newListIndex);
            }
            lastSplitBlocksRemaining >>>= 1;
            ++newListIndex;
          }
        }
        ++splitListIx;
      }
      return destIx;
    }
Unsets the headers (meaning this does not refer to a buffer).
llap-server/src/java/org/apache/hadoop/hive/llap/cache/BuddyAllocator.java