public void free(String queryId, String fragmentInstanceId, String planNodeId, long bytes) {
    Validate.notNull(queryId, "queryId can not be null.");
    Validate.isTrue(bytes > 0L);

    try {
      queryMemoryReservations
          .get(queryId)
          .get(fragmentInstanceId)
          .computeIfPresent(
              planNodeId,
              (k, reservedMemory) -> {
                if (reservedMemory < bytes) {
                  throw new IllegalArgumentException("Free more memory than has been reserved.");
                }
                return reservedMemory - bytes;
              });
    } catch (NullPointerException e) {
      throw new IllegalArgumentException("RelatedMemoryReserved can't be null when freeing memory");
    }

    memoryBlock.release(bytes);

    if (memoryReservationFutures.isEmpty()) {
      return;
    }
    Iterator<MemoryReservationFuture<Void>> iterator = memoryReservationFutures.iterator();
    while (iterator.hasNext()) {
      MemoryReservationFuture<Void> future = iterator.next();
      synchronized (future) {
        if (future.isCancelled() || future.isDone()) {
          iterator.remove();
          continue;
        }
        long bytesToReserve = future.getBytesToReserve();
        String curQueryId = future.getQueryId();
        String curFragmentInstanceId = future.getFragmentInstanceId();
        String curPlanNodeId = future.getPlanNodeId();
        long maxBytesCanReserve = future.getMaxBytesCanReserve();
        if (tryReserve(
            curQueryId, curFragmentInstanceId, curPlanNodeId, bytesToReserve, maxBytesCanReserve)) {
          future.set(null);
          iterator.remove();
        } else {
          rollbackReserve(curQueryId, curFragmentInstanceId, curPlanNodeId, bytesToReserve);
        }
      }
    }
  }
Cancel the specified memory reservation. If the reservation has finished, do nothing.

@param future The future returned from {@link #reserve(String, String, String, long, long)}
@return If the future has not complete, return the number of bytes being reserved. Otherwise,
    return 0.
iotdb-core/datanode/src/main/java/org/apache/iotdb/db/queryengine/execution/memory/MemoryPool.java