private int alloc(int num_bytes) throws IOException
  {
    int new_adr = 0; // the address of the block.
    int new_size = 0; // the size of the block.

    // The current bucket is the first place to look for space.
    for (int i = 0; i < bucket.av_count; i++) {
      if (bucket.av_size[i] >= num_bytes) {
        new_adr = bucket.av_adr[i];
        new_size = bucket.av_size[i];
        bucket.removeAvail(i);
        break;
      }
    }

    // If we did not find some space, we have more work to do.
    if (new_adr == 0) {
      // If the header avail table is less than half full, and there's something on the stack.
      if (av_count <= av_length / 2 - 1 && av_next_block != 0) popAvailBlock();

      // Check the header avail table.
      for (int i = 0; i < av_count; i++) {
        if (av_size[i] >= num_bytes) {
          new_adr = av_adr[i];
          new_size = av_size[i];
          removeAvail(i);
          break;
        }
      }

      if (new_adr == 0) {
        // Get another full block from end of file.
        new_adr = this.next_block;
        new_size = this.block_size;
        while (new_size < num_bytes)
          new_size += this.block_size;
        this.next_block += new_size;
      }

      header_changed = true;
    }

    // Put the unused space back in the avail block.
    free(new_adr + num_bytes, new_size - num_bytes);

    // return the address
    return new_adr;
  }