docs: public void open(final MutableObjectIterator<BT> buildSide,	final MutableObjectIterator<PT> probeSide,
  		boolean buildOuterJoin) throws IOException {
  
  		this.buildSideOuterJoin = buildOuterJoin;
  
  		// sanity checks
  		if (!this.closed.compareAndSet(true, false)) {
  			throw new IllegalStateException("Hash Join cannot be opened, because it is currently not closed.");
  		}
  		
  		// grab the write behind buffers first
  		for (int i = this.numWriteBehindBuffers; i > 0; --i) {
  			this.writeBehindBuffers.add(this.availableMemory.remove(this.availableMemory.size() - 1));
  		}
  		// open builds the initial table by consuming the build-side input
  		this.currentRecursionDepth = 0;
  		buildInitialTable(buildSide);
  		
  		// the first prober is the probe-side input
  		this.probeIterator = new ProbeIterator<PT>(probeSide, this.probeSideSerializer.createInstance());
  		
  		// the bucket iterator can remain constant over the time
  		this.bucketIterator = new HashBucketIterator<BT, PT>(this.buildSideSerializer, this.recordComparator, probedSet, buildOuterJoin);
  	}