protected void mergePhase() throws TeiidComponentException, TeiidProcessingException {
while(this.activeTupleBuffers.size() > 1) {
ArrayList<SortedSublist> sublists = new ArrayList<SortedSublist>(activeTupleBuffers.size());
TupleBuffer merged = createTupleBuffer();
int desiredSpace = activeTupleBuffers.size() * schemaSize;
int reserved = Math.min(desiredSpace, this.bufferManager.getMaxProcessingKB());
bufferManager.reserveBuffers(reserved, BufferReserveMode.FORCE);
if (desiredSpace > reserved) {
reserved += bufferManager.reserveBuffers(desiredSpace - reserved, BufferReserveMode.WAIT);
}
int maxSortIndex = Math.max(2, reserved / schemaSize); //always allow progress
//release any partial excess
int release = reserved % schemaSize > 0 ? 1 : 0;
bufferManager.releaseBuffers(release);
reserved -= release;
try {
if (LogManager.isMessageToBeRecorded(org.teiid.logging.LogConstants.CTX_DQP, MessageLevel.TRACE)) {
LogManager.logTrace(org.teiid.logging.LogConstants.CTX_DQP, "Merging", maxSortIndex, "sublists out of", activeTupleBuffers.size()); //$NON-NLS-1$ //$NON-NLS-2$
}
// initialize the sublists with the min value
for(int i = 0; i<maxSortIndex; i++) {
TupleBuffer activeID = activeTupleBuffers.get(i);
SortedSublist sortedSublist = new SortedSublist();
sortedSublist.its = activeID.createIndexedTupleSource();
sortedSublist.index = i;
if (activeID == output) {
sortedSublist.limit = output.getRowCount();
}
incrementWorkingTuple(sublists, sortedSublist);
}
// iteratively process the lowest tuple
while (sublists.size() > 0) {
SortedSublist sortedSublist = sublists.remove(sublists.size() - 1);
merged.addTuple(sortedSublist.tuple);
if (this.output != null && sortedSublist.index > masterSortIndex) {
this.output.addTuple(sortedSublist.tuple); //a new distinct row
}
incrementWorkingTuple(sublists, sortedSublist);
}
// Remove merged sublists
for(int i=0; i<maxSortIndex; i++) {
TupleBuffer id = activeTupleBuffers.remove(0);
if (id != this.output) {
id.remove();
}
}
merged.saveBatch();
this.activeTupleBuffers.add(merged);
masterSortIndex = masterSortIndex - maxSortIndex + 1;
if (masterSortIndex < 0) {
masterSortIndex = this.activeTupleBuffers.size() - 1;
}
} finally {
this.bufferManager.releaseBuffers(reserved);
}
}
// Close sorted source (all others have been removed)
if (doneReading) {
if (this.output != null) {
this.output.close();
TupleBuffer last = activeTupleBuffers.remove(0);
if (output != last) {
last.remove();
}
} else {
activeTupleBuffers.get(0).close();
activeTupleBuffers.get(0).setForwardOnly(false);
}