Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

InMemoryRepository.java 7.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. package org.eclipse.jgit.internal.storage.dfs;
  2. import java.io.ByteArrayOutputStream;
  3. import java.io.FileNotFoundException;
  4. import java.io.IOException;
  5. import java.nio.ByteBuffer;
  6. import java.util.ArrayList;
  7. import java.util.Collection;
  8. import java.util.List;
  9. import java.util.concurrent.atomic.AtomicInteger;
  10. import org.eclipse.jgit.annotations.Nullable;
  11. import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
  12. import org.eclipse.jgit.internal.storage.pack.PackExt;
  13. import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
  14. import org.eclipse.jgit.lib.RefDatabase;
  15. /**
  16. * Git repository stored entirely in the local process memory.
  17. * <p>
  18. * This implementation builds on the DFS repository by storing all reference and
  19. * object data in the local process. It is not very efficient and exists only
  20. * for unit testing and small experiments.
  21. * <p>
  22. * The repository is thread-safe. Memory used is released only when this object
  23. * is garbage collected. Closing the repository has no impact on its memory.
  24. */
  25. public class InMemoryRepository extends DfsRepository {
  26. /** Builder for in-memory repositories. */
  27. public static class Builder
  28. extends DfsRepositoryBuilder<Builder, InMemoryRepository> {
  29. @Override
  30. public InMemoryRepository build() throws IOException {
  31. return new InMemoryRepository(this);
  32. }
  33. }
  34. static final AtomicInteger packId = new AtomicInteger();
  35. private final MemObjDatabase objdb;
  36. private final MemRefDatabase refdb;
  37. private String gitwebDescription;
  38. /**
  39. * Initialize a new in-memory repository.
  40. *
  41. * @param repoDesc
  42. * description of the repository.
  43. */
  44. public InMemoryRepository(DfsRepositoryDescription repoDesc) {
  45. this(new Builder().setRepositoryDescription(repoDesc));
  46. }
  47. InMemoryRepository(Builder builder) {
  48. super(builder);
  49. objdb = new MemObjDatabase(this);
  50. refdb = new MemRefDatabase();
  51. }
  52. /** {@inheritDoc} */
  53. @Override
  54. public MemObjDatabase getObjectDatabase() {
  55. return objdb;
  56. }
  57. /** {@inheritDoc} */
  58. @Override
  59. public RefDatabase getRefDatabase() {
  60. return refdb;
  61. }
  62. /**
  63. * Enable (or disable) the atomic reference transaction support.
  64. * <p>
  65. * Useful for testing atomic support enabled or disabled.
  66. *
  67. * @param atomic
  68. * whether to use atomic reference transaction support
  69. */
  70. public void setPerformsAtomicTransactions(boolean atomic) {
  71. refdb.performsAtomicTransactions = atomic;
  72. }
  73. /** {@inheritDoc} */
  74. @Override
  75. @Nullable
  76. public String getGitwebDescription() {
  77. return gitwebDescription;
  78. }
  79. /** {@inheritDoc} */
  80. @Override
  81. public void setGitwebDescription(@Nullable String d) {
  82. gitwebDescription = d;
  83. }
  84. /** DfsObjDatabase used by InMemoryRepository. */
  85. public static class MemObjDatabase extends DfsObjDatabase {
  86. private List<DfsPackDescription> packs = new ArrayList<>();
  87. private int blockSize;
  88. MemObjDatabase(DfsRepository repo) {
  89. super(repo, new DfsReaderOptions());
  90. }
  91. /**
  92. * @param blockSize
  93. * force a different block size for testing.
  94. */
  95. public void setReadableChannelBlockSizeForTest(int blockSize) {
  96. this.blockSize = blockSize;
  97. }
  98. @Override
  99. protected synchronized List<DfsPackDescription> listPacks() {
  100. return packs;
  101. }
  102. @Override
  103. protected DfsPackDescription newPack(PackSource source) {
  104. int id = packId.incrementAndGet();
  105. return new MemPack(
  106. "pack-" + id + "-" + source.name(), //$NON-NLS-1$ //$NON-NLS-2$
  107. getRepository().getDescription(),
  108. source);
  109. }
  110. @Override
  111. protected synchronized void commitPackImpl(
  112. Collection<DfsPackDescription> desc,
  113. Collection<DfsPackDescription> replace) {
  114. List<DfsPackDescription> n;
  115. n = new ArrayList<>(desc.size() + packs.size());
  116. n.addAll(desc);
  117. n.addAll(packs);
  118. if (replace != null)
  119. n.removeAll(replace);
  120. packs = n;
  121. clearCache();
  122. }
  123. @Override
  124. protected void rollbackPack(Collection<DfsPackDescription> desc) {
  125. // Do nothing. Pack is not recorded until commitPack.
  126. }
  127. @Override
  128. protected ReadableChannel openFile(DfsPackDescription desc, PackExt ext)
  129. throws FileNotFoundException, IOException {
  130. MemPack memPack = (MemPack) desc;
  131. byte[] file = memPack.get(ext);
  132. if (file == null)
  133. throw new FileNotFoundException(desc.getFileName(ext));
  134. return new ByteArrayReadableChannel(file, blockSize);
  135. }
  136. @Override
  137. protected DfsOutputStream writeFile(DfsPackDescription desc,
  138. PackExt ext) throws IOException {
  139. MemPack memPack = (MemPack) desc;
  140. return new Out() {
  141. @Override
  142. public void flush() {
  143. memPack.put(ext, getData());
  144. }
  145. };
  146. }
  147. }
  148. private static class MemPack extends DfsPackDescription {
  149. final byte[][] fileMap = new byte[PackExt.values().length][];
  150. MemPack(String name, DfsRepositoryDescription repoDesc, PackSource source) {
  151. super(repoDesc, name, source);
  152. }
  153. void put(PackExt ext, byte[] data) {
  154. fileMap[ext.getPosition()] = data;
  155. }
  156. byte[] get(PackExt ext) {
  157. return fileMap[ext.getPosition()];
  158. }
  159. }
  160. private abstract static class Out extends DfsOutputStream {
  161. private final ByteArrayOutputStream dst = new ByteArrayOutputStream();
  162. private byte[] data;
  163. @Override
  164. public void write(byte[] buf, int off, int len) {
  165. data = null;
  166. dst.write(buf, off, len);
  167. }
  168. @Override
  169. public int read(long position, ByteBuffer buf) {
  170. byte[] d = getData();
  171. int n = Math.min(buf.remaining(), d.length - (int) position);
  172. if (n == 0)
  173. return -1;
  174. buf.put(d, (int) position, n);
  175. return n;
  176. }
  177. byte[] getData() {
  178. if (data == null)
  179. data = dst.toByteArray();
  180. return data;
  181. }
  182. @Override
  183. public abstract void flush();
  184. @Override
  185. public void close() {
  186. flush();
  187. }
  188. }
  189. private static class ByteArrayReadableChannel implements ReadableChannel {
  190. private final byte[] data;
  191. private final int blockSize;
  192. private int position;
  193. private boolean open = true;
  194. ByteArrayReadableChannel(byte[] buf, int blockSize) {
  195. data = buf;
  196. this.blockSize = blockSize;
  197. }
  198. @Override
  199. public int read(ByteBuffer dst) {
  200. int n = Math.min(dst.remaining(), data.length - position);
  201. if (n == 0)
  202. return -1;
  203. dst.put(data, position, n);
  204. position += n;
  205. return n;
  206. }
  207. @Override
  208. public void close() {
  209. open = false;
  210. }
  211. @Override
  212. public boolean isOpen() {
  213. return open;
  214. }
  215. @Override
  216. public long position() {
  217. return position;
  218. }
  219. @Override
  220. public void position(long newPosition) {
  221. position = (int) newPosition;
  222. }
  223. @Override
  224. public long size() {
  225. return data.length;
  226. }
  227. @Override
  228. public int blockSize() {
  229. return blockSize;
  230. }
  231. @Override
  232. public void setReadAheadBytes(int b) {
  233. // Unnecessary on a byte array.
  234. }
  235. }
  236. /** DfsRefDatabase used by InMemoryRepository. */
  237. protected class MemRefDatabase extends DfsReftableDatabase {
  238. boolean performsAtomicTransactions = true;
  239. /** Initialize a new in-memory ref database. */
  240. protected MemRefDatabase() {
  241. super(InMemoryRepository.this);
  242. }
  243. @Override
  244. public ReftableConfig getReftableConfig() {
  245. ReftableConfig cfg = new ReftableConfig();
  246. cfg.setAlignBlocks(false);
  247. cfg.setIndexObjects(false);
  248. cfg.fromConfig(getRepository().getConfig());
  249. return cfg;
  250. }
  251. @Override
  252. public boolean performsAtomicTransactions() {
  253. return performsAtomicTransactions;
  254. }
  255. }
  256. }