docs: public void insertOrReplaceRecord(T record) throws IOException {
  		if (this.closed) {
  			return;
  		}
  
  		final int searchHashCode = MathUtils.jenkinsHash(this.buildSideComparator.hash(record));
  		final int posHashCode = searchHashCode % this.numBuckets;
  		
  		// get the bucket for the given hash code
  		final MemorySegment originalBucket = this.buckets[posHashCode >> this.bucketsPerSegmentBits];
  		final int originalBucketOffset = (posHashCode & this.bucketsPerSegmentMask) << NUM_INTRA_BUCKET_BITS;
  		
  		MemorySegment bucket = originalBucket;
  		int bucketInSegmentOffset = originalBucketOffset;
  		
  		// get the basic characteristics of the bucket
  		final int partitionNumber = bucket.get(bucketInSegmentOffset + HEADER_PARTITION_OFFSET);
  		final InMemoryPartition<T> partition = this.partitions.get(partitionNumber);
  		final MemorySegment[] overflowSegments = partition.overflowSegments;
  		
  		this.buildSideComparator.setReference(record);
  		
  		int countInSegment = bucket.getInt(bucketInSegmentOffset + HEADER_COUNT_OFFSET);
  		int numInSegment = 0;
  		int posInSegment = bucketInSegmentOffset + BUCKET_HEADER_LENGTH;
  
  		// loop over all segments that are involved in the bucket (original bucket plus overflow buckets)
  		while (true) {
  			
  			while (numInSegment < countInSegment) {
  				
  				final int thisCode = bucket.getInt(posInSegment);
  				posInSegment += HASH_CODE_LEN;
  					
  				// check if the hash code matches
  				if (thisCode == searchHashCode) {
  					// get the pointer to the pair
  					final int pointerOffset = bucketInSegmentOffset + BUCKET_POINTER_START_OFFSET + (numInSegment * POINTER_LEN);
  					final long pointer = bucket.getLong(pointerOffset);
  					
  					// deserialize the key to check whether it is really equal, or whether we had only a hash collision
  					T valueAtPosition = partition.readRecordAt(pointer);
  					if (this.buildSideComparator.equalToReference(valueAtPosition)) {
  						long newPointer = insertRecordIntoPartition(record, partition, true);
  						bucket.putLong(pointerOffset, newPointer);
  						return;
  					}
  				}
  				numInSegment++;
  			}
  			
  			// this segment is done. check if there is another chained bucket
  			long newForwardPointer = bucket.getLong(bucketInSegmentOffset + HEADER_FORWARD_OFFSET);
  			if (newForwardPointer == BUCKET_FORWARD_POINTER_NOT_SET) {
  				
  				// nothing found. append and insert
  				long pointer = insertRecordIntoPartition(record, partition, false);
  
  				if (countInSegment < NUM_ENTRIES_PER_BUCKET) {
  					// we are good in our current bucket, put the values
  					bucket.putInt(bucketInSegmentOffset + BUCKET_HEADER_LENGTH + (countInSegment * HASH_CODE_LEN), searchHashCode); // hash code
  					bucket.putLong(bucketInSegmentOffset + BUCKET_POINTER_START_OFFSET + (countInSegment * POINTER_LEN), pointer); // pointer
  					bucket.putInt(bucketInSegmentOffset + HEADER_COUNT_OFFSET, countInSegment + 1); // update count
  				}
  				else {
  					insertBucketEntryFromStart(originalBucket, originalBucketOffset, searchHashCode, pointer, partitionNumber);
  				}
  				return;
  			}
  			
  			final int overflowSegNum = (int) (newForwardPointer >>> 32);
  			bucket = overflowSegments[overflowSegNum];
  			bucketInSegmentOffset = (int) newForwardPointer;
  			countInSegment = bucket.getInt(bucketInSegmentOffset + HEADER_COUNT_OFFSET);
  			posInSegment = bucketInSegmentOffset + BUCKET_HEADER_LENGTH;
  			numInSegment = 0;
  		}
  	}