private void loadPartitionInMem(int pid, RunFileWriter wr, int[] buffs)
      throws HyracksDataException {
    RunFileReader r = wr.createReader();
    r.open();
    int counter = 0;
    ByteBuffer mBuff = null;
    reloadBuffer.clear();
    while (r.nextFrame(reloadBuffer)) {
      mBuff = memBuffs[buffs[counter]];
      if (mBuff == null) {
        mBuff = ctx.allocateFrame();
        memBuffs[buffs[counter]] = mBuff;
      }
      FrameUtils.copy(reloadBuffer, mBuff);
      counter++;
      reloadBuffer.clear();
    }

    int curNext = nextBuff[buffs[buffs.length - 1]];
    nextBuff[buffs[buffs.length - 1]] = END_OF_PARTITION;
    nextFreeBuffIx = curNext;

    r.close();
    pStatus.set(pid, false);
    buildRFWriters[pid] = null;
  }
  private int allocateFreeBuffer(int pid) {
    if (nextFreeBuffIx != NO_MORE_FREE_BUFFER) {
      if (memBuffs[nextFreeBuffIx] == null) {
        memBuffs[nextFreeBuffIx] = ctx.allocateFrame();
      }
      int curPartBuffIx = curPBuff[pid];
      curPBuff[pid] = nextFreeBuffIx;
      int oldNext = nextBuff[nextFreeBuffIx];
      nextBuff[nextFreeBuffIx] = curPartBuffIx;
      if (oldNext == UNALLOCATED_FRAME) {
        nextFreeBuffIx++;
        if (nextFreeBuffIx == memForJoin) { // No more free buffer
          nextFreeBuffIx = NO_MORE_FREE_BUFFER;
        }
      } else {
        nextFreeBuffIx = oldNext;
      }
      (memBuffs[curPBuff[pid]]).clear();

      freeFramesCounter--;
      return (curPBuff[pid]);
    } else {
      return NO_MORE_FREE_BUFFER; // A partitions needs to be spilled (if feasible)
    }
  }
 private void partitionTune() throws HyracksDataException {
   reloadBuffer = ctx.allocateFrame();
   ArrayList<Integer> reloadSet = selectPartitionsToReload();
   for (int i = 0; i < reloadSet.size(); i++) {
     int pid = reloadSet.get(i);
     int[] buffsToLoad = new int[buildPSizeInFrames[pid]];
     for (int j = 0; j < buffsToLoad.length; j++) {
       buffsToLoad[j] = nextFreeBuffIx;
       int oldNext = nextBuff[nextFreeBuffIx];
       if (oldNext == UNALLOCATED_FRAME) {
         nextFreeBuffIx++;
         if (nextFreeBuffIx == memForJoin) { // No more free buffer
           nextFreeBuffIx = NO_MORE_FREE_BUFFER;
         }
       } else {
         nextFreeBuffIx = oldNext;
       }
     }
     curPBuff[pid] = buffsToLoad[0];
     for (int k = 1; k < buffsToLoad.length; k++) {
       nextBuff[buffsToLoad[k - 1]] = buffsToLoad[k];
     }
     loadPartitionInMem(pid, buildRFWriters[pid], buffsToLoad);
   }
   reloadSet.clear();
   reloadSet = null;
 }
  public void initBuild() {
    memBuffs = new ByteBuffer[memForJoin];
    curPBuff = new int[numOfPartitions];
    nextBuff = new int[memForJoin];
    pStatus = new BitSet(numOfPartitions);
    buildPSizeInTups = new int[numOfPartitions];

    buildPSizeInFrames = new int[numOfPartitions];
    freeFramesCounter = memForJoin - numOfPartitions;

    for (int i = 0;
        i < numOfPartitions;
        i++) { // Allocating one buffer per partition and setting as the head of the chain of
               // buffers for that partition
      memBuffs[i] = ctx.allocateFrame();
      curPBuff[i] = i;
      nextBuff[i] = -1;
      buildPSizeInFrames[i] = 1; // The dedicated initial buffer
    }

    nextFreeBuffIx =
        ((numOfPartitions < memForJoin)
            ? numOfPartitions
            : NO_MORE_FREE_BUFFER); // Setting the chain of unallocated frames
    for (int i = numOfPartitions; i < memBuffs.length; i++) {
      nextBuff[i] = UNALLOCATED_FRAME;
    }

    buildTupAppender = new FrameTupleAppender(ctx.getFrameSize());
  }
  public void initProbe() {

    sPartBuffs = new ByteBuffer[numOfSpilledParts];
    for (int i = 0; i < numOfSpilledParts; i++) {
      sPartBuffs[i] = ctx.allocateFrame();
    }
    curPBuff = new int[numOfPartitions];
    int nextBuffIxToAlloc = 0;
    /* We only need to allocate one frame per spilled partition.
     * Resident partitions do not need frames in probe, as their tuples join
     * immediately with the resident build tuples using the inMemoryHashJoin */
    for (int i = 0; i < numOfPartitions; i++) {
      curPBuff[i] = (pStatus.get(i)) ? nextBuffIxToAlloc++ : BUFFER_FOR_RESIDENT_PARTS;
    }
    probePSizeInTups = new int[numOfPartitions];
    probeRFWriters = new RunFileWriter[numOfPartitions];

    probeResBuff = ctx.allocateFrame();

    probeTupAppenderToResident = new FrameTupleAppender(ctx.getFrameSize());
    probeTupAppenderToResident.reset(probeResBuff, true);

    probeTupAppenderToSpilled = new FrameTupleAppender(ctx.getFrameSize());
  }