* @throws SQLException
*/
SpoolingResultIterator(ResultIterator scanner, MemoryManager mm, final int thresholdBytes, final long maxSpoolToDisk) throws SQLException {
boolean success = false;
boolean usedOnDiskIterator = false;
final MemoryChunk chunk = mm.allocate(0, thresholdBytes);
File tempFile = null;
try {
// Can't be bigger than int, since it's the max of the above allocation
int size = (int)chunk.getSize();
tempFile = File.createTempFile("ResultSpooler",".bin");
DeferredFileOutputStream spoolTo = new DeferredFileOutputStream(size, tempFile) {
@Override
protected void thresholdReached() throws IOException {
super.thresholdReached();
chunk.close();
}
};
DataOutputStream out = new DataOutputStream(spoolTo);
final long maxBytesAllowed = maxSpoolToDisk == -1 ?
Long.MAX_VALUE : thresholdBytes + maxSpoolToDisk;
long bytesWritten = 0L;
int maxSize = 0;
for (Tuple result = scanner.next(); result != null; result = scanner.next()) {
int length = TupleUtil.write(result, out);
bytesWritten += length;
if(bytesWritten > maxBytesAllowed){
throw new SpoolTooBigToDiskException("result too big, max allowed(bytes): " + maxBytesAllowed);
}
maxSize = Math.max(length, maxSize);
}
spoolTo.close();
if (spoolTo.isInMemory()) {
byte[] data = spoolTo.getData();
chunk.resize(data.length);
spoolFrom = new InMemoryResultIterator(data, chunk);
} else {
spoolFrom = new OnDiskResultIterator(maxSize, spoolTo.getFile());
usedOnDiskIterator = true;
}
success = true;
} catch (IOException e) {
throw ServerUtil.parseServerException(e);
} finally {
try {
scanner.close();
} finally {
try {
if (!usedOnDiskIterator) {
tempFile.delete();
}
} finally {
if (!success) {
chunk.close();
}
}
}
}
}