private boolean compact ( Segment segment , SegmentIndexBuffer sibSource , Segment segTarget ) throws IOException { 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 = _dataArray . getSegmentManager ( ) . openSegmentIndexBuffer ( segTargetId ) ; long sizeLimit = segTarget . getInitialSize ( ) ; long bytesTransferred = 0 ; boolean succ = true ; try { AddressFormat addrFormat = _dataArray . _addressFormat ; SegmentIndexBuffer . IndexOffset reuse = new SegmentIndexBuffer . IndexOffset ( ) ; for ( int i = 0 , cnt = sibSource . size ( ) ; i < cnt ; i ++ ) { sibSource . get ( i , reuse ) ; int index = reuse . getIndex ( ) ; int sibSegPos = reuse . getOffset ( ) ; long oldAddress = _dataArray . getAddress ( index ) ; int oldSegPos = addrFormat . getOffset ( oldAddress ) ; if ( sibSegPos != oldSegPos ) continue ; 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 ; sibTarget . add ( index , ( int ) newSegPos ) ; _updateManager . addUpdate ( index , byteCnt , newAddress , oldAddress , segTarget ) ; } } // Push whatever left into update queue _updateManager . endUpdate ( segTarget ) ; _log . info ( "bytes fastscanned from " + segSource . getSegmentId ( ) + ": " + bytesTransferred + " time: " + c . tick ( ) + " ms" ) ; return succ ; } finally { if ( segSource . getClass ( ) == BufferedSegment . class ) { segSource . close ( false ) ; segSource = null ; } } }
Compacts data from the specified source Segment into the specified target Segment .