* @throws IOException if this operation can not be finished properly.
*/
private boolean compact(Segment segment, Segment segTarget, final boolean sibEnabled) throws IOException {
// Optimization: use the source segment index buffer file if it is available for compaction.
if(sibEnabled) {
SegmentIndexBuffer sibSource =
_dataArray.getSegmentManager()
.loadSegmentIndexBuffer(segment.getSegmentId(), segment.getLastForcedTime());
if(sibSource != null) {
return compact(segment, sibSource, segTarget);
}
}
Segment segSource = segment;
int segSourceId = segSource.getSegmentId();
int segTargetId = segTarget.getSegmentId();
Chronos c = new Chronos();
if(!segment.canReadFromBuffer() && segment.getLoadFactor() > 0.1) {
segSource = new BufferedSegment(segment, getByteBuffer((int)segment.getInitialSize()));
_log.info("buffering: " + c.tick() + " ms");
}
// Open the segment index buffer for the target segment
SegmentIndexBuffer sibTarget = sibEnabled ? _dataArray.getSegmentManager().openSegmentIndexBuffer(segTargetId) : null;
long sizeLimit = segTarget.getInitialSize();
long bytesTransferred = 0;
boolean succ = true;
try {
AddressFormat addrFormat = _dataArray._addressFormat;
for(int index = 0, cnt = _dataArray.length(); index < cnt; index++) {
long oldAddress = _dataArray.getAddress(index);
int oldSegPos = addrFormat.getOffset(oldAddress);
int oldSegInd = addrFormat.getSegment(oldAddress);
int length = addrFormat.getDataSize(oldAddress);
if (oldSegInd == segSourceId && oldSegPos >= Segment.dataStartPosition) {
if(length == 0) length = segSource.readInt(oldSegPos);
int byteCnt = 4 + length;
long newSegPos = segTarget.getAppendPosition();
long newAddress = addrFormat.composeAddress((int)newSegPos, segTargetId, length);
if(segTarget.getAppendPosition() + byteCnt >= sizeLimit) {
succ = false;
break;
}
// Transfer bytes from source to target
segSource.transferTo(oldSegPos, byteCnt, segTarget);
bytesTransferred += byteCnt;
if(sibTarget != null) sibTarget.add(index, (int)newSegPos);
_updateManager.addUpdate(index, byteCnt, newAddress, oldAddress, segTarget);
}
}
// Push whatever left into update queue