code: public void close() {
  		// make sure that we close only once
  		if (!this.closed.compareAndSet(false, true)) {
  			return;
  		}
  		
  		// clear the iterators, so the next call to next() will notice
  		this.bucketIterator = null;
  		this.probeIterator = null;
  		
  		// release the table structure
  		releaseTable();
  		
  		// clear the memory in the partitions
  		clearPartitions();
  		
  		// clear the current probe side channel, if there is one
  		if (this.currentSpilledProbeSide != null) {
  			try {
  				this.currentSpilledProbeSide.closeAndDelete();
  			}
  			catch (Throwable t) {
  				LOG.warn("Could not close and delete the temp file for the current spilled partition probe side.", t);
  			}
  		}
  		
  		// clear the partitions that are still to be done (that have files on disk)
  		for (int i = 0; i < this.partitionsPending.size(); i++) {
  			final HashPartition<BT, PT> p = this.partitionsPending.get(i);
  			p.clearAllMemory(this.availableMemory);
  		}
  		
  		// return the write-behind buffers
  		for (int i = 0; i < this.numWriteBehindBuffers + this.writeBehindBuffersAvailable; i++) {
  			try {
  				this.availableMemory.add(this.writeBehindBuffers.take());
  			}
  			catch (InterruptedException iex) {
  				throw new RuntimeException("Hashtable closing was interrupted");
  			}
  		}
  		this.writeBehindBuffersAvailable = 0;
  	}
docs: Closes the hash table. This effectively releases all internal structures and closes all
  open files and removes them. The call to this method is valid both as a cleanup after the
  complete inputs were properly processed, and as an cancellation call, which cleans up
  all resources that are currently held by the hash join.