View Javadoc
1   /*
2    * Copyright (C) 2012, 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  
11  package org.eclipse.jgit.internal.storage.file;
12  
13  import java.io.File;
14  import java.io.IOException;
15  import java.io.InputStream;
16  import java.text.MessageFormat;
17  
18  import org.eclipse.jgit.errors.CorruptObjectException;
19  import org.eclipse.jgit.internal.JGitText;
20  import org.eclipse.jgit.lib.AnyObjectId;
21  import org.eclipse.jgit.lib.ObjectId;
22  import org.eclipse.jgit.util.io.SilentFileInputStream;
23  
24  import com.googlecode.javaewah.EWAHCompressedBitmap;
25  
26  /**
27   * Logical representation of the bitmap data stored in the pack index.
28   * {@link org.eclipse.jgit.lib.ObjectId}s are encoded as a single integer in the
29   * range [0, {@link #getObjectCount()}). Compressed bitmaps are available at
30   * certain {@code ObjectId}s, which represent all of the objects reachable from
31   * that {@code ObjectId} (include the {@code ObjectId} itself). The meaning of
32   * the positions in the bitmaps can be decoded using {@link #getObject(int)} and
33   * {@link #ofObjectType(EWAHCompressedBitmap, int)}. Furthermore,
34   * {@link #findPosition(AnyObjectId)} can be used to build other bitmaps that a
35   * compatible with the encoded bitmaps available from the index.
36   */
37  public abstract class PackBitmapIndex {
38  	/** Flag bit denoting the bitmap should be reused during index creation. */
39  	public static final int FLAG_REUSE = 1;
40  
41  	/**
42  	 * Read an existing pack bitmap index file from a buffered stream.
43  	 * <p>
44  	 * The format of the file will be automatically detected and a proper access
45  	 * implementation for that format will be constructed and returned to the
46  	 * caller. The file may or may not be held open by the returned instance.
47  	 *
48  	 * @param idxFile
49  	 *            existing pack .bitmap to read.
50  	 * @param packIndex
51  	 *            the pack index for the corresponding pack file.
52  	 * @param reverseIndex
53  	 *            the pack reverse index for the corresponding pack file.
54  	 * @return a copy of the index in-memory.
55  	 * @throws java.io.IOException
56  	 *             the stream cannot be read.
57  	 * @throws CorruptObjectException
58  	 *             the stream does not contain a valid pack bitmap index.
59  	 */
60  	public static PackBitmapIndex open(File idxFile, PackIndex packIndex,
61  			PackReverseIndex reverseIndex)
62  			throws IOException {
63  		try (SilentFileInputStream fd = new SilentFileInputStream(idxFile)) {
64  			try {
65  				return read(fd, packIndex, reverseIndex);
66  			} catch (IOException ioe) {
67  				throw new IOException(
68  						MessageFormat.format(JGitText.get().unreadablePackIndex,
69  								idxFile.getAbsolutePath()),
70  						ioe);
71  			}
72  		}
73  	}
74  
75  	/**
76  	 * Read an existing pack bitmap index file from a buffered stream.
77  	 * <p>
78  	 * The format of the file will be automatically detected and a proper access
79  	 * implementation for that format will be constructed and returned to the
80  	 * caller. The file may or may not be held open by the returned instance.
81  	 *
82  	 * @param fd
83  	 *            stream to read the bitmap index file from. The stream must be
84  	 *            buffered as some small IOs are performed against the stream.
85  	 *            The caller is responsible for closing the stream.
86  	 * @param packIndex
87  	 *            the pack index for the corresponding pack file.
88  	 * @param reverseIndex
89  	 *            the pack reverse index for the corresponding pack file.
90  	 * @return a copy of the index in-memory.
91  	 * @throws java.io.IOException
92  	 *             the stream cannot be read.
93  	 * @throws CorruptObjectException
94  	 *             the stream does not contain a valid pack bitmap index.
95  	 */
96  	public static PackBitmapIndex read(InputStream fd, PackIndex packIndex,
97  			PackReverseIndex reverseIndex) throws IOException {
98  		return new PackBitmapIndexV1(fd, packIndex, reverseIndex);
99  	}
100 
101 	/**
102 	 * Read an existing pack bitmap index file from a buffered stream.
103 	 * <p>
104 	 * The format of the file will be automatically detected and a proper access
105 	 * implementation for that format will be constructed and returned to the
106 	 * caller. The file may or may not be held open by the returned instance.
107 	 *
108 	 * @param fd
109 	 *            stream to read the bitmap index file from. The stream must be
110 	 *            buffered as some small IOs are performed against the stream.
111 	 *            The caller is responsible for closing the stream.
112 	 * @param packIndexSupplier
113 	 *            the supplier for pack index for the corresponding pack file.
114 	 * @param reverseIndexSupplier
115 	 *            the supplier for pack reverse index for the corresponding pack
116 	 *            file.
117 	 * @param loadParallelRevIndex
118 	 *            whether reverse index should be loaded in parallel
119 	 * @return a copy of the index in-memory.
120 	 * @throws java.io.IOException
121 	 *             the stream cannot be read.
122 	 * @throws CorruptObjectException
123 	 *             the stream does not contain a valid pack bitmap index.
124 	 */
125 	public static PackBitmapIndex read(InputStream fd,
126 			SupplierWithIOException<PackIndex> packIndexSupplier,
127 			SupplierWithIOException<PackReverseIndex> reverseIndexSupplier,
128 			boolean loadParallelRevIndex)
129 			throws IOException {
130 		return new PackBitmapIndexV1(fd, packIndexSupplier,
131 				reverseIndexSupplier, loadParallelRevIndex);
132 	}
133 
134 	/** Footer checksum applied on the bottom of the pack file. */
135 	byte[] packChecksum;
136 
137 	/**
138 	 * Finds the position in the bitmap of the object.
139 	 *
140 	 * @param objectId
141 	 *            the id for which the bitmap position will be found.
142 	 * @return the bitmap id or -1 if the object was not found.
143 	 */
144 	public abstract int findPosition(AnyObjectId objectId);
145 
146 	/**
147 	 * Get the object at the bitmap position.
148 	 *
149 	 * @param position
150 	 *            the id for which the object will be found.
151 	 * @return the ObjectId.
152 	 * @throws java.lang.IllegalArgumentException
153 	 *             when the item is not found.
154 	 */
155 	public abstract ObjectId getObject(int position)
156 			throws IllegalArgumentException;
157 
158 	/**
159 	 * Returns a bitmap containing positions for objects that have the given Git
160 	 * type.
161 	 *
162 	 * @param bitmap
163 	 *            the object bitmap.
164 	 * @param type
165 	 *            the Git type.
166 	 * @return the object bitmap with only objects of the Git type.
167 	 */
168 	public abstract EWAHCompressedBitmap ofObjectType(
169 			EWAHCompressedBitmap bitmap, int type);
170 
171 	/**
172 	 * Returns the previously constructed bitmap for the object.
173 	 *
174 	 * @param objectId
175 	 *            the id for which the bitmap will be found.
176 	 * @return the bitmap or null if the object was not found.
177 	 */
178 	public abstract EWAHCompressedBitmap getBitmap(AnyObjectId objectId);
179 
180 	/**
181 	 * Obtain the total number of objects described by this index.
182 	 * {@code getObjectCount() - 1} is the largest bit that will be set in a
183 	 * bitmap.
184 	 *
185 	 * @return number of objects in this index, and likewise in the associated
186 	 *         pack that this index was generated from.
187 	 */
188 	public abstract int getObjectCount();
189 
190 	/**
191 	 * Returns the number of bitmaps in this bitmap index.
192 	 *
193 	 * @return the number of bitmaps in this bitmap index.
194 	 */
195 	public abstract int getBitmapCount();
196 
197 	/**
198 	 * Supplier that propagates IOException.
199 	 *
200 	 * @param <T>
201 	 *            the return type which is expected from {@link #get()}
202 	 */
203 	@FunctionalInterface
204 	public interface SupplierWithIOException<T> {
205 		/**
206 		 * @return result
207 		 * @throws IOException
208 		 */
209 		T get() throws IOException;
210 	}
211 }