PackBitmapIndexRemapper.java

  1. /*
  2.  * Copyright (C) 2013, Google Inc. and others
  3.  *
  4.  * This program and the accompanying materials are made available under the
  5.  * terms of the Eclipse Distribution License v. 1.0 which is available at
  6.  * https://www.eclipse.org/org/documents/edl-v10.php.
  7.  *
  8.  * SPDX-License-Identifier: BSD-3-Clause
  9.  */

  10. package org.eclipse.jgit.internal.storage.file;

  11. import java.util.Collections;
  12. import java.util.Iterator;
  13. import java.util.NoSuchElementException;

  14. import org.eclipse.jgit.internal.storage.file.BasePackBitmapIndex.StoredBitmap;
  15. import org.eclipse.jgit.lib.AnyObjectId;
  16. import org.eclipse.jgit.lib.BitmapIndex;
  17. import org.eclipse.jgit.lib.ObjectId;

  18. import com.googlecode.javaewah.EWAHCompressedBitmap;
  19. import com.googlecode.javaewah.IntIterator;

  20. /**
  21.  * A PackBitmapIndex that remaps the bitmaps in the previous index to the
  22.  * positions in the new pack index. Note, unlike typical PackBitmapIndex
  23.  * implementations this implementation is not thread safe, as it is intended to
  24.  * be used with a PackBitmapIndexBuilder, which is also not thread safe.
  25.  */
  26. public class PackBitmapIndexRemapper extends PackBitmapIndex
  27.         implements Iterable<PackBitmapIndexRemapper.Entry> {

  28.     private final BasePackBitmapIndex oldPackIndex;
  29.     final PackBitmapIndex newPackIndex;
  30.     private final BitSet inflated;
  31.     private final int[] prevToNewMapping;

  32.     /**
  33.      * A PackBitmapIndex that maps the positions in the prevBitmapIndex to the
  34.      * ones in the newIndex.
  35.      *
  36.      * @param prevBitmapIndex
  37.      *            the bitmap index with the old mapping.
  38.      * @param newIndex
  39.      *            the bitmap index with the new mapping.
  40.      * @return a bitmap index that attempts to do the mapping between the two.
  41.      */
  42.     public static PackBitmapIndexRemapper newPackBitmapIndex(
  43.             BitmapIndex prevBitmapIndex, PackBitmapIndex newIndex) {
  44.         if (!(prevBitmapIndex instanceof BitmapIndexImpl))
  45.             return new PackBitmapIndexRemapper(newIndex);

  46.         PackBitmapIndex prevIndex = ((BitmapIndexImpl) prevBitmapIndex)
  47.                 .getPackBitmapIndex();
  48.         if (!(prevIndex instanceof BasePackBitmapIndex))
  49.             return new PackBitmapIndexRemapper(newIndex);

  50.         return new PackBitmapIndexRemapper(
  51.                 (BasePackBitmapIndex) prevIndex, newIndex);
  52.     }

  53.     private PackBitmapIndexRemapper(PackBitmapIndex newPackIndex) {
  54.         this.oldPackIndex = null;
  55.         this.newPackIndex = newPackIndex;
  56.         this.inflated = null;
  57.         this.prevToNewMapping = null;
  58.     }

  59.     private PackBitmapIndexRemapper(
  60.             BasePackBitmapIndex oldPackIndex, PackBitmapIndex newPackIndex) {
  61.         this.oldPackIndex = oldPackIndex;
  62.         this.newPackIndex = newPackIndex;
  63.         inflated = new BitSet(newPackIndex.getObjectCount());

  64.         prevToNewMapping = new int[oldPackIndex.getObjectCount()];
  65.         for (int pos = 0; pos < prevToNewMapping.length; pos++)
  66.             prevToNewMapping[pos] = newPackIndex.findPosition(
  67.                     oldPackIndex.getObject(pos));
  68.     }

  69.     /** {@inheritDoc} */
  70.     @Override
  71.     public int findPosition(AnyObjectId objectId) {
  72.         return newPackIndex.findPosition(objectId);
  73.     }

  74.     /** {@inheritDoc} */
  75.     @Override
  76.     public ObjectId getObject(int position) throws IllegalArgumentException {
  77.         return newPackIndex.getObject(position);
  78.     }

  79.     /** {@inheritDoc} */
  80.     @Override
  81.     public int getObjectCount() {
  82.         return newPackIndex.getObjectCount();
  83.     }

  84.     /** {@inheritDoc} */
  85.     @Override
  86.     public EWAHCompressedBitmap ofObjectType(
  87.             EWAHCompressedBitmap bitmap, int type) {
  88.         return newPackIndex.ofObjectType(bitmap, type);
  89.     }

  90.     /** {@inheritDoc} */
  91.     @Override
  92.     public Iterator<Entry> iterator() {
  93.         if (oldPackIndex == null)
  94.             return Collections.<Entry> emptyList().iterator();

  95.         final Iterator<StoredBitmap> it = oldPackIndex.getBitmaps().iterator();
  96.         return new Iterator<>() {
  97.             private Entry entry;

  98.             @Override
  99.             public boolean hasNext() {
  100.                 while (entry == null && it.hasNext()) {
  101.                     StoredBitmap sb = it.next();
  102.                     if (newPackIndex.findPosition(sb) != -1)
  103.                         entry = new Entry(sb, sb.getFlags());
  104.                 }
  105.                 return entry != null;
  106.             }

  107.             @Override
  108.             public Entry next() {
  109.                 if (!hasNext())
  110.                     throw new NoSuchElementException();

  111.                 Entry res = entry;
  112.                 entry = null;
  113.                 return res;
  114.             }

  115.             @Override
  116.             public void remove() {
  117.                 throw new UnsupportedOperationException();
  118.             }
  119.         };
  120.     }

  121.     /** {@inheritDoc} */
  122.     @Override
  123.     public EWAHCompressedBitmap getBitmap(AnyObjectId objectId) {
  124.         EWAHCompressedBitmap bitmap = newPackIndex.getBitmap(objectId);
  125.         if (bitmap != null || oldPackIndex == null)
  126.             return bitmap;

  127.         StoredBitmap oldBitmap = oldPackIndex.getBitmaps().get(objectId);
  128.         if (oldBitmap == null)
  129.             return null;

  130.         if (newPackIndex.findPosition(objectId) == -1)
  131.             return null;

  132.         inflated.clear();
  133.         for (IntIterator i = oldBitmap.getBitmapWithoutCaching()
  134.                 .intIterator(); i.hasNext();)
  135.             inflated.set(prevToNewMapping[i.next()]);
  136.         bitmap = inflated.toEWAHCompressedBitmap();
  137.         bitmap.trim();
  138.         return bitmap;
  139.     }

  140.     /** An entry in the old PackBitmapIndex. */
  141.     public static final class Entry extends ObjectId {
  142.         private final int flags;

  143.         Entry(AnyObjectId src, int flags) {
  144.             super(src);
  145.             this.flags = flags;
  146.         }

  147.         /** @return the flags associated with the bitmap. */
  148.         public int getFlags() {
  149.             return flags;
  150.         }
  151.     }

  152.     /** {@inheritDoc} */
  153.     @Override
  154.     public int getBitmapCount() {
  155.         // The count is only useful for the end index, not the remapper.
  156.         return 0;
  157.     }
  158. }