@ -11,12 +11,13 @@
package org.eclipse.jgit.internal.storage.file ;
package org.eclipse.jgit.internal.storage.file ;
import java.text.MessageFormat ;
import java.text.MessageFormat ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Collections ;
import java.util.Iterator ;
import java.util.LinkedList ;
import java.util.List ;
import java.util.List ;
import java.util.NoSuchElementException ;
import org.eclipse.jgit.internal.JGitText ;
import org.eclipse.jgit.internal.JGitText ;
import org.eclipse.jgit.internal.storage.pack.BitmapCommit ;
import org.eclipse.jgit.internal.storage.pack.ObjectToPack ;
import org.eclipse.jgit.internal.storage.pack.ObjectToPack ;
import org.eclipse.jgit.lib.AnyObjectId ;
import org.eclipse.jgit.lib.AnyObjectId ;
import org.eclipse.jgit.lib.BitmapIndex.Bitmap ;
import org.eclipse.jgit.lib.BitmapIndex.Bitmap ;
@ -39,8 +40,12 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
private final EWAHCompressedBitmap blobs ;
private final EWAHCompressedBitmap blobs ;
private final EWAHCompressedBitmap tags ;
private final EWAHCompressedBitmap tags ;
private final BlockList < PositionEntry > byOffset ;
private final BlockList < PositionEntry > byOffset ;
final BlockList < StoredBitmap >
byAddOrder = new BlockList < > ( ) ;
private final LinkedList < StoredBitmap >
bitmapsToWriteXorBuffer = new LinkedList < > ( ) ;
private List < StoredEntry > bitmapsToWrite = new ArrayList < > ( ) ;
final ObjectIdOwnerMap < PositionEntry >
final ObjectIdOwnerMap < PositionEntry >
positionEntries = new ObjectIdOwnerMap < > ( ) ;
positionEntries = new ObjectIdOwnerMap < > ( ) ;
@ -135,6 +140,63 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
addBitmap ( objectId , bitmap . retrieveCompressed ( ) , flags ) ;
addBitmap ( objectId , bitmap . retrieveCompressed ( ) , flags ) ;
}
}
/ * *
* Processes a commit and prepares its bitmap to write to the bitmap index
* file .
*
* @param c
* the commit corresponds to the bitmap .
* @param bitmap
* the bitmap to be written .
* @param flags
* the flags of the commit .
* /
public void processBitmapForWrite ( BitmapCommit c , Bitmap bitmap ,
int flags ) {
EWAHCompressedBitmap compressed = bitmap . retrieveCompressed ( ) ;
compressed . trim ( ) ;
StoredBitmap newest = new StoredBitmap ( c , compressed , null , flags ) ;
bitmapsToWriteXorBuffer . add ( newest ) ;
if ( bitmapsToWriteXorBuffer . size ( ) > MAX_XOR_OFFSET_SEARCH ) {
bitmapsToWrite . add (
generateStoredEntry ( bitmapsToWriteXorBuffer . pollFirst ( ) ) ) ;
}
if ( c . isAddToIndex ( ) ) {
// The Bitmap map in the base class is used to make revwalks
// efficient, so only add bitmaps that keep it efficient without
// bloating memory.
addBitmap ( c , bitmap , flags ) ;
}
}
private StoredEntry generateStoredEntry ( StoredBitmap bitmapToWrite ) {
int bestXorOffset = 0 ;
EWAHCompressedBitmap bestBitmap = bitmapToWrite . getBitmap ( ) ;
int offset = 1 ;
for ( StoredBitmap curr : bitmapsToWriteXorBuffer ) {
EWAHCompressedBitmap bitmap = curr . getBitmap ( )
. xor ( bitmapToWrite . getBitmap ( ) ) ;
if ( bitmap . sizeInBytes ( ) < bestBitmap . sizeInBytes ( ) ) {
bestBitmap = bitmap ;
bestXorOffset = offset ;
}
offset + + ;
}
PositionEntry entry = positionEntries . get ( bitmapToWrite ) ;
if ( entry = = null ) {
throw new IllegalStateException ( ) ;
}
bestBitmap . trim ( ) ;
StoredEntry result = new StoredEntry ( entry . namePosition , bestBitmap ,
bestXorOffset , bitmapToWrite . getFlags ( ) ) ;
return result ;
}
/ * *
/ * *
* Stores the bitmap for the objectId .
* Stores the bitmap for the objectId .
*
*
@ -150,7 +212,6 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
bitmap . trim ( ) ;
bitmap . trim ( ) ;
StoredBitmap result = new StoredBitmap ( objectId , bitmap , null , flags ) ;
StoredBitmap result = new StoredBitmap ( objectId , bitmap , null , flags ) ;
getBitmaps ( ) . add ( result ) ;
getBitmaps ( ) . add ( result ) ;
byAddOrder . add ( result ) ;
}
}
/** {@inheritDoc} */
/** {@inheritDoc} */
@ -236,15 +297,18 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
/** {@inheritDoc} */
/** {@inheritDoc} */
@Override
@Override
public int getBitmapCount ( ) {
public int getBitmapCount ( ) {
return getBitmaps ( ) . size ( ) ;
return bitmapsToWriteXorBuffer . size ( ) + bitmapsToWrite . size ( ) ;
}
}
/ * *
/ * *
* Remove all the bitmaps entries added .
* Remove all the bitmaps entries added .
*
* @param size
* the expected number of bitmap entries to be written .
* /
* /
public void clearBitmaps ( ) {
public void resetBitmaps ( int size ) {
byAddOrder . clear ( ) ;
getBitmaps ( ) . clear ( ) ;
getBitmaps ( ) . clear ( ) ;
bitmapsToWrite = new ArrayList < > ( size ) ;
}
}
/** {@inheritDoc} */
/** {@inheritDoc} */
@ -254,64 +318,18 @@ public class PackBitmapIndexBuilder extends BasePackBitmapIndex {
}
}
/ * *
/ * *
* Get an iterator over the xor compressed entries .
* Get list of xor compressed entries that need to be written .
*
*
* @return an iterator over the xor compressed entries .
* @return a list of the xor compressed entries .
* /
* /
public Iterable < StoredEntry > getCompressedBitmaps ( ) {
public List < StoredEntry > getCompressedBitmaps ( ) {
// Add order is from oldest to newest. The reverse add order is the
while ( ! bitmapsToWriteXorBuffer . isEmpty ( ) ) {
// output order.
bitmapsToWrite . add (
return ( ) - > new Iterator < StoredEntry > ( ) {
generateStoredEntry ( bitmapsToWriteXorBuffer . pollFirst ( ) ) ) ;
private int index = byAddOrder . size ( ) - 1 ;
@Override
public boolean hasNext ( ) {
return index > = 0 ;
}
@Override
public StoredEntry next ( ) {
if ( ! hasNext ( ) ) {
throw new NoSuchElementException ( ) ;
}
}
StoredBitmap item = byAddOrder . get ( index ) ;
int bestXorOffset = 0 ;
EWAHCompressedBitmap bestBitmap = item . getBitmap ( ) ;
// Attempt to compress the bitmap with an XOR of the
// previously written entries.
for ( int i = 1 ; i < = MAX_XOR_OFFSET_SEARCH ; i + + ) {
int curr = i + index ;
if ( curr > = byAddOrder . size ( ) ) {
break ;
}
StoredBitmap other = byAddOrder . get ( curr ) ;
EWAHCompressedBitmap bitmap = other . getBitmap ( )
. xor ( item . getBitmap ( ) ) ;
if ( bitmap . sizeInBytes ( ) < bestBitmap . sizeInBytes ( ) ) {
Collections . reverse ( bitmapsToWrite ) ;
bestBitmap = bitmap ;
return bitmapsToWrite ;
bestXorOffset = i ;
}
}
index - - ;
PositionEntry entry = positionEntries . get ( item ) ;
if ( entry = = null ) {
throw new IllegalStateException ( ) ;
}
bestBitmap . trim ( ) ;
return new StoredEntry ( entry . namePosition , bestBitmap ,
bestXorOffset , item . getFlags ( ) ) ;
}
@Override
public void remove ( ) {
throw new UnsupportedOperationException ( ) ;
}
} ;
}
}
/** Data object for the on disk representation of a bitmap entry. */
/** Data object for the on disk representation of a bitmap entry. */