docs: private void compactPartition(final int partitionNumber) throws IOException {
  		// do nothing if table was closed, parameter is invalid or no garbage exists
  		if (this.closed || partitionNumber >= this.partitions.size() || this.partitions.get(partitionNumber).isCompacted()) {
  			return;
  		}
  		// release all segments owned by compaction partition
  		this.compactionMemory.clearAllMemory(availableMemory);
  		this.compactionMemory.allocateSegments(1);
  		this.compactionMemory.pushDownPages();
  		T tempHolder = this.buildSideSerializer.createInstance();
  		final int numPartitions = this.partitions.size();
  		InMemoryPartition<T> partition = this.partitions.remove(partitionNumber);
  		MemorySegment[] overflowSegments = partition.overflowSegments;
  		long pointer;
  		int pointerOffset;
  		int bucketOffset;
  		final int bucketsPerSegment = this.bucketsPerSegmentMask + 1;
  		for (int i = 0, bucket = partitionNumber; i < this.buckets.length && bucket < this.numBuckets; i++) {
  			MemorySegment segment = this.buckets[i];
  			// go over all buckets in the segment belonging to the partition
  			for (int k = bucket % bucketsPerSegment; k < bucketsPerSegment && bucket < this.numBuckets; k += numPartitions, bucket += numPartitions) {
  				bucketOffset = k * HASH_BUCKET_SIZE;
  				if((int)segment.get(bucketOffset + HEADER_PARTITION_OFFSET) != partitionNumber) {
  					throw new IOException("Accessed wrong bucket! wanted: " + partitionNumber + " got: " + segment.get(bucketOffset + HEADER_PARTITION_OFFSET));
  				}
  				// loop over all segments that are involved in the bucket (original bucket plus overflow buckets)
  				int countInSegment = segment.getInt(bucketOffset + HEADER_COUNT_OFFSET);
  				int numInSegment = 0;
  				pointerOffset = bucketOffset + BUCKET_POINTER_START_OFFSET;
  				while (true) {
  					while (numInSegment < countInSegment) {
  						pointer = segment.getLong(pointerOffset);
  						tempHolder = partition.readRecordAt(pointer, tempHolder);
  						pointer = this.compactionMemory.appendRecord(tempHolder);
  						segment.putLong(pointerOffset, pointer);
  						pointerOffset += POINTER_LEN;
  						numInSegment++;
  					}
  					// this segment is done. check if there is another chained bucket
  					final long forwardPointer = segment.getLong(bucketOffset + HEADER_FORWARD_OFFSET);
  					if (forwardPointer == BUCKET_FORWARD_POINTER_NOT_SET) {
  						break;
  					}
  					final int overflowSegNum = (int) (forwardPointer >>> 32);
  					segment = overflowSegments[overflowSegNum];
  					bucketOffset = (int) forwardPointer;
  					countInSegment = segment.getInt(bucketOffset + HEADER_COUNT_OFFSET);
  					pointerOffset = bucketOffset + BUCKET_POINTER_START_OFFSET;
  					numInSegment = 0;
  				}
  				segment = this.buckets[i];
  			}
  		}
  		// swap partition with compaction partition
  		this.compactionMemory.setPartitionNumber(partitionNumber);
  		this.partitions.add(partitionNumber, compactionMemory);
  		this.partitions.get(partitionNumber).overflowSegments = partition.overflowSegments;
  		this.partitions.get(partitionNumber).numOverflowSegments = partition.numOverflowSegments;
  		this.partitions.get(partitionNumber).nextOverflowBucket = partition.nextOverflowBucket;
  		this.partitions.get(partitionNumber).setIsCompacted(true);
  		//this.partitions.get(partitionNumber).pushDownPages();
  		this.compactionMemory = partition;
  		this.compactionMemory.resetRecordCounter();
  		this.compactionMemory.setPartitionNumber(-1);
  		this.compactionMemory.overflowSegments = null;
  		this.compactionMemory.numOverflowSegments = 0;
  		this.compactionMemory.nextOverflowBucket = 0;
  		// try to allocate maximum segment count
  		this.compactionMemory.clearAllMemory(this.availableMemory);
  		int maxSegmentNumber = this.getMaxPartition();
  		this.compactionMemory.allocateSegments(maxSegmentNumber);
  		this.compactionMemory.resetRWViews();
  		this.compactionMemory.pushDownPages();
  	}