long segmentIndex = segment.m_index;
File segmentFile = segment.m_file;
RandomAccessFile ras = new RandomAccessFile(segmentFile, "rw");
FileChannel fc = ras.getChannel();
MBBContainer readBufferC = DBBPool.wrapMBB(fc.map(MapMode.READ_WRITE, 0, fc.size()));
final ByteBuffer readBuffer = readBufferC.b();
final long buffAddr = readBufferC.address();
try {
//Get the number of objects and then iterator over them
int numObjects = readBuffer.getInt();
int size = readBuffer.getInt();
int objectsProcessed = 0;
exportLog.debug("PBD " + m_nonce + " has " + numObjects + " objects to parse and truncate");
for (int ii = 0; ii < numObjects; ii++) {
final int nextObjectLength = readBuffer.getInt();
final int nextObjectFlags = readBuffer.getInt();
final boolean compressed = nextObjectFlags == PBDSegment.FLAG_COMPRESSED;
final int uncompressedLength = compressed ? (int)Snappy.uncompressedLength(buffAddr + readBuffer.position(), nextObjectLength) : nextObjectLength;
objectsProcessed++;
//Copy the next object into a separate heap byte buffer
//do the old limit stashing trick to avoid buffer overflow
BBContainer nextObject = null;
if (compressed) {
decompressionBuffer.b().clear();
if (decompressionBuffer.b().remaining() < uncompressedLength ) {
decompressionBuffer.discard();
decompressionBuffer = DBBPool.allocateDirect(uncompressedLength);
}
nextObject = DBBPool.dummyWrapBB(decompressionBuffer.b());
final long sourceAddr = (buffAddr + readBuffer.position());
final long destAddr = nextObject.address();
Snappy.rawUncompress(sourceAddr, nextObjectLength, destAddr);
readBuffer.position(readBuffer.position() + nextObjectLength);
} else {
final int oldLimit = readBuffer.limit();
readBuffer.limit(readBuffer.position() + nextObjectLength);
nextObject = DBBPool.dummyWrapBB(readBuffer.slice());
readBuffer.position(readBuffer.limit());
readBuffer.limit(oldLimit);
}
try {
//Handoff the object to the truncator and await a decision
ByteBuffer retval = truncator.parse(nextObject.b());
if (retval == null) {
//Nothing to do, leave the object alone and move to the next
continue;
} else {
//If the returned bytebuffer is empty, remove the object and truncate the file
if (retval.remaining() == 0) {
if (ii == 0) {
/*
* If truncation is occuring at the first object
* Whammo! Delete the file. Do it by setting the lastSegmentIndex
* to 1 previous. We may end up with an empty finished segment
* set.
*/
lastSegmentIndex = segmentIndex - 1;
} else {
addToNumObjects(-(numObjects - (objectsProcessed - 1)));
//Don't forget to update the number of entries in the file
ByteBuffer numObjectsBuffer = ByteBuffer.allocate(4);
numObjectsBuffer.putInt(0, ii);
fc.position(0);
while (numObjectsBuffer.hasRemaining()) {
fc.write(numObjectsBuffer);
}
fc.truncate(readBuffer.position() - (nextObjectLength + PBDSegment.m_objectHeaderBytes));
}
} else {
addToNumObjects(-(numObjects - objectsProcessed));
//Partial object truncation
ByteBuffer copy = ByteBuffer.allocate(retval.remaining());
copy.put(retval);
copy.flip();
readBuffer.position(readBuffer.position() - (nextObjectLength + PBDSegment.m_objectHeaderBytes));
readBuffer.putInt(copy.remaining());
readBuffer.putInt(0);
readBuffer.put(copy);
readBuffer.putInt(0, ii + 1);
/*
* SHOULD REALLY make a copy of the original and then swap them with renaming
*/
fc.truncate(readBuffer.position());
}
//Set last segment and break the loop over this segment
if (lastSegmentIndex == null) {
lastSegmentIndex = segmentIndex;
}
break;
}
} finally {
nextObject.discard();
}
}
//If this is set the just processed segment was the last one
if (lastSegmentIndex != null) {
break;
}
} finally {
fc.close();
readBufferC.discard();
}
}
} finally {
decompressionBuffer.discard();
}