1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 package org.eclipse.jgit.internal.storage.file;
45
46 import static java.lang.Integer.valueOf;
47 import static org.junit.Assert.assertEquals;
48 import static org.junit.Assert.assertNotEquals;
49 import static org.junit.Assert.assertNotNull;
50
51 import java.io.IOException;
52 import java.util.Collection;
53 import java.util.Collections;
54 import java.util.concurrent.BrokenBarrierException;
55 import java.util.concurrent.Callable;
56 import java.util.concurrent.CyclicBarrier;
57 import java.util.concurrent.ExecutorService;
58 import java.util.concurrent.Executors;
59 import java.util.concurrent.Future;
60 import java.util.concurrent.TimeUnit;
61
62 import org.eclipse.jgit.internal.JGitText;
63 import org.eclipse.jgit.internal.storage.pack.PackWriter;
64 import org.eclipse.jgit.junit.TestRepository;
65 import org.eclipse.jgit.lib.EmptyProgressMonitor;
66 import org.eclipse.jgit.lib.NullProgressMonitor;
67 import org.eclipse.jgit.lib.ObjectId;
68 import org.eclipse.jgit.lib.Sets;
69 import org.eclipse.jgit.revwalk.RevBlob;
70 import org.eclipse.jgit.revwalk.RevCommit;
71 import org.junit.Test;
72
73 public class GcConcurrentTest extends GcTestCase {
74 @Test
75 public void concurrentRepack() throws Exception {
76 final CyclicBarrier syncPoint = new CyclicBarrier(2);
77
78 class DoRepack extends EmptyProgressMonitor implements
79 Callable<Integer> {
80
81 @Override
82 public void beginTask(String title, int totalWork) {
83 if (title.equals(JGitText.get().writingObjects)) {
84 try {
85 syncPoint.await();
86 } catch (InterruptedException e) {
87 Thread.currentThread().interrupt();
88 } catch (BrokenBarrierException ignored) {
89
90 }
91 }
92 }
93
94
95 @Override
96 public Integer call() throws Exception {
97 try {
98 gc.setProgressMonitor(this);
99 gc.repack();
100 return valueOf(0);
101 } catch (IOException e) {
102
103
104
105 Thread.currentThread().interrupt();
106 try {
107 syncPoint.await();
108 } catch (InterruptedException ignored) {
109
110 }
111 return valueOf(1);
112 }
113 }
114 }
115
116 RevBlob a = tr.blob("a");
117 tr.lightweightTag("t", a);
118
119 ExecutorService pool = Executors.newFixedThreadPool(2);
120 try {
121 DoRepack repack1 = new DoRepack();
122 DoRepack repack2 = new DoRepack();
123 Future<Integer> result1 = pool.submit(repack1);
124 Future<Integer> result2 = pool.submit(repack2);
125 assertEquals(0, result1.get().intValue() + result2.get().intValue());
126 } finally {
127 pool.shutdown();
128 pool.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
129 }
130 }
131
132 @Test
133 public void repackAndGetStats() throws Exception {
134 TestRepository<FileRepository>.BranchBuilder test = tr.branch("test");
135 test.commit().add("a", "a").create();
136 GC gc1 = new GC(tr.getRepository());
137 gc1.setPackExpireAgeMillis(0);
138 gc1.gc();
139 test.commit().add("b", "b").create();
140
141
142
143
144 FileRepository r2 = new FileRepository(
145 tr.getRepository().getDirectory());
146 GC gc2 = new GC(r2);
147 gc2.setPackExpireAgeMillis(0);
148 gc2.gc();
149
150 new GC(tr.getRepository()).getStatistics();
151 }
152
153 @Test
154 public void repackAndUploadPack() throws Exception {
155 TestRepository<FileRepository>.BranchBuilder test = tr.branch("test");
156
157 test.commit().add("a", "a").create();
158
159 GC gc1 = new GC(tr.getRepository());
160 gc1.setPackExpireAgeMillis(0);
161 gc1.gc();
162
163 RevCommit b = test.commit().add("b", "b").create();
164
165 FileRepository r2 = new FileRepository(
166 tr.getRepository().getDirectory());
167 GC gc2 = new GC(r2);
168 gc2.setPackExpireAgeMillis(0);
169 gc2.gc();
170
171
172
173
174
175
176 try (PackWriter pw = new PackWriter(tr.getRepository())) {
177 pw.setUseBitmaps(true);
178 pw.preparePack(NullProgressMonitor.INSTANCE, Sets.of(b),
179 Collections.<ObjectId> emptySet());
180 new GC(tr.getRepository()).getStatistics();
181 }
182 }
183
184 PackFile getSinglePack(FileRepository r) {
185 Collection<PackFile> packs = r.getObjectDatabase().getPacks();
186 assertEquals(1, packs.size());
187 return packs.iterator().next();
188 }
189
190 @Test
191 public void repackAndCheckBitmapUsage() throws Exception {
192
193
194
195 TestRepository<FileRepository>.BranchBuilder test = tr.branch("test");
196 test.commit().add("a", "a").create();
197 FileRepository repository = tr.getRepository();
198 GC gc1 = new GC(repository);
199 gc1.setPackExpireAgeMillis(0);
200 gc1.gc();
201 String oldPackName = getSinglePack(repository).getPackName();
202 RevCommit b = test.commit().add("b", "b").create();
203
204
205 FileRepository repository2 = new FileRepository(repository.getDirectory());
206 GC gc2 = new GC(repository2);
207 gc2.setPackExpireAgeMillis(0);
208 gc2.gc();
209 String newPackName = getSinglePack(repository2).getPackName();
210
211 assertNotEquals(oldPackName, newPackName);
212
213
214
215
216 assertNotEquals(getSinglePack(repository).getPackName(), newPackName);
217
218
219
220 repository.getObjectDatabase().open(b).getSize();
221 assertEquals(getSinglePack(repository).getPackName(), newPackName);
222 assertNotNull(getSinglePack(repository).getBitmapIndex());
223 }
224 }