You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PackReverseIndex.java 5.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
  3. * and other copyright owners as documented in the project's IP log.
  4. *
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Distribution License v1.0 which
  7. * accompanies this distribution, is reproduced below, and is
  8. * available at http://www.eclipse.org/org/documents/edl-v10.php
  9. *
  10. * All rights reserved.
  11. *
  12. * Redistribution and use in source and binary forms, with or
  13. * without modification, are permitted provided that the following
  14. * conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright
  17. * notice, this list of conditions and the following disclaimer.
  18. *
  19. * - Redistributions in binary form must reproduce the above
  20. * copyright notice, this list of conditions and the following
  21. * disclaimer in the documentation and/or other materials provided
  22. * with the distribution.
  23. *
  24. * - Neither the name of the Eclipse Foundation, Inc. nor the
  25. * names of its contributors may be used to endorse or promote
  26. * products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  30. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  31. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  32. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  33. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  34. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  35. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  36. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  37. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  38. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  40. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  41. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  42. */
  43. package org.eclipse.jgit.lib;
  44. import java.util.Arrays;
  45. import org.eclipse.jgit.errors.CorruptObjectException;
  46. import org.eclipse.jgit.lib.PackIndex.MutableEntry;
  47. /**
  48. * <p>
  49. * Reverse index for forward pack index. Provides operations based on offset
  50. * instead of object id. Such offset-based reverse lookups are performed in
  51. * O(log n) time.
  52. * </p>
  53. *
  54. * @see PackIndex
  55. * @see PackFile
  56. */
  57. class PackReverseIndex {
  58. /** Index we were created from, and that has our ObjectId data. */
  59. private final PackIndex index;
  60. /**
  61. * (offset31, truly) Offsets accommodating in 31 bits.
  62. */
  63. private final int offsets32[];
  64. /**
  65. * Offsets not accommodating in 31 bits.
  66. */
  67. private final long offsets64[];
  68. /** Position of the corresponding {@link #offsets32} in {@link #index}. */
  69. private final int nth32[];
  70. /** Position of the corresponding {@link #offsets64} in {@link #index}. */
  71. private final int nth64[];
  72. /**
  73. * Create reverse index from straight/forward pack index, by indexing all
  74. * its entries.
  75. *
  76. * @param packIndex
  77. * forward index - entries to (reverse) index.
  78. */
  79. PackReverseIndex(final PackIndex packIndex) {
  80. index = packIndex;
  81. final long cnt = index.getObjectCount();
  82. final long n64 = index.getOffset64Count();
  83. final long n32 = cnt - n64;
  84. if (n32 > Integer.MAX_VALUE || n64 > Integer.MAX_VALUE
  85. || cnt > 0xffffffffL)
  86. throw new IllegalArgumentException(
  87. "Huge indexes are not supported by jgit, yet");
  88. offsets32 = new int[(int) n32];
  89. offsets64 = new long[(int) n64];
  90. nth32 = new int[offsets32.length];
  91. nth64 = new int[offsets64.length];
  92. int i32 = 0;
  93. int i64 = 0;
  94. for (final MutableEntry me : index) {
  95. final long o = me.getOffset();
  96. if (o < Integer.MAX_VALUE)
  97. offsets32[i32++] = (int) o;
  98. else
  99. offsets64[i64++] = o;
  100. }
  101. Arrays.sort(offsets32);
  102. Arrays.sort(offsets64);
  103. int nth = 0;
  104. for (final MutableEntry me : index) {
  105. final long o = me.getOffset();
  106. if (o < Integer.MAX_VALUE)
  107. nth32[Arrays.binarySearch(offsets32, (int) o)] = nth++;
  108. else
  109. nth64[Arrays.binarySearch(offsets64, o)] = nth++;
  110. }
  111. }
  112. /**
  113. * Search for object id with the specified start offset in this pack
  114. * (reverse) index.
  115. *
  116. * @param offset
  117. * start offset of object to find.
  118. * @return object id for this offset, or null if no object was found.
  119. */
  120. ObjectId findObject(final long offset) {
  121. if (offset <= Integer.MAX_VALUE) {
  122. final int i32 = Arrays.binarySearch(offsets32, (int) offset);
  123. if (i32 < 0)
  124. return null;
  125. return index.getObjectId(nth32[i32]);
  126. } else {
  127. final int i64 = Arrays.binarySearch(offsets64, offset);
  128. if (i64 < 0)
  129. return null;
  130. return index.getObjectId(nth64[i64]);
  131. }
  132. }
  133. /**
  134. * Search for the next offset to the specified offset in this pack (reverse)
  135. * index.
  136. *
  137. * @param offset
  138. * start offset of previous object (must be valid-existing
  139. * offset).
  140. * @param maxOffset
  141. * maximum offset in a pack (returned when there is no next
  142. * offset).
  143. * @return offset of the next object in a pack or maxOffset if provided
  144. * offset was the last one.
  145. * @throws CorruptObjectException
  146. * when there is no object with the provided offset.
  147. */
  148. long findNextOffset(final long offset, final long maxOffset)
  149. throws CorruptObjectException {
  150. if (offset <= Integer.MAX_VALUE) {
  151. final int i32 = Arrays.binarySearch(offsets32, (int) offset);
  152. if (i32 < 0)
  153. throw new CorruptObjectException(
  154. "Can't find object in (reverse) pack index for the specified offset "
  155. + offset);
  156. if (i32 + 1 == offsets32.length) {
  157. if (offsets64.length > 0)
  158. return offsets64[0];
  159. return maxOffset;
  160. }
  161. return offsets32[i32 + 1];
  162. } else {
  163. final int i64 = Arrays.binarySearch(offsets64, offset);
  164. if (i64 < 0)
  165. throw new CorruptObjectException(
  166. "Can't find object in (reverse) pack index for the specified offset "
  167. + offset);
  168. if (i64 + 1 == offsets64.length)
  169. return maxOffset;
  170. return offsets64[i64 + 1];
  171. }
  172. }
  173. }