1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.internal.storage.dfs;
12
13 import java.io.IOException;
14 import java.util.Arrays;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.TreeSet;
20 import java.util.concurrent.locks.Lock;
21 import java.util.concurrent.locks.ReentrantLock;
22
23 import org.eclipse.jgit.annotations.Nullable;
24 import org.eclipse.jgit.internal.storage.reftable.MergedReftable;
25 import org.eclipse.jgit.internal.storage.reftable.ReftableConfig;
26 import org.eclipse.jgit.internal.storage.reftable.ReftableDatabase;
27 import org.eclipse.jgit.lib.BatchRefUpdate;
28 import org.eclipse.jgit.lib.NullProgressMonitor;
29 import org.eclipse.jgit.lib.ObjectId;
30 import org.eclipse.jgit.lib.Ref;
31 import org.eclipse.jgit.revwalk.RevWalk;
32 import org.eclipse.jgit.transport.ReceiveCommand;
33 import org.eclipse.jgit.util.RefList;
34 import org.eclipse.jgit.util.RefMap;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class DfsReftableDatabase extends DfsRefDatabase {
50 final ReftableDatabase reftableDatabase;
51
52 private DfsReader ctx;
53 private DfsReftableStack stack;
54
55
56
57
58
59
60
61 protected DfsReftableDatabase(DfsRepository repo) {
62 super(repo);
63 reftableDatabase = new ReftableDatabase() {
64 @Override
65 public MergedReftable openMergedReftable() throws IOException {
66 Lock l = DfsReftableDatabase.this.getLock();
67 l.lock();
68 try {
69 return new MergedReftable(stack().readers());
70 } finally {
71 l.unlock();
72 }
73 }
74 };
75 stack = null;
76 }
77
78
79 @Override
80 public boolean hasVersioning() {
81 return true;
82 }
83
84
85 @Override
86 public boolean performsAtomicTransactions() {
87 return true;
88 }
89
90
91 @Override
92 public BatchRefUpdate newBatchUpdate() {
93 DfsObjDatabase odb = getRepository().getObjectDatabase();
94 return new DfsReftableBatchRefUpdate(this, odb);
95 }
96
97
98
99
100
101
102 public ReftableConfig getReftableConfig() {
103 return new ReftableConfig(getRepository());
104 }
105
106
107
108
109
110
111 protected ReentrantLock getLock() {
112 return reftableDatabase.getLock();
113 }
114
115
116
117
118
119
120
121
122 protected boolean compactDuringCommit() {
123 return true;
124 }
125
126
127
128
129
130
131
132
133
134 protected DfsReftableStack stack() throws IOException {
135 if (!getLock().isLocked()) {
136 throw new IllegalStateException("most hold lock to access stack");
137 }
138 DfsObjDatabase odb = getRepository().getObjectDatabase();
139
140 if (ctx == null) {
141 ctx = odb.newReader();
142 }
143 if (stack == null) {
144 stack = DfsReftableStack.open(ctx, Arrays.asList(odb.getReftables()));
145 }
146 return stack;
147 }
148
149 @Override
150 public boolean isNameConflicting(String refName) throws IOException {
151 return reftableDatabase.isNameConflicting(refName, new TreeSet<>(), new HashSet<>());
152 }
153
154
155 @Override
156 public Ref exactRef(String name) throws IOException {
157 return reftableDatabase.exactRef(name);
158 }
159
160
161 @Override
162 public Map<String, Ref> getRefs(String prefix) throws IOException {
163 List<Ref> refs = reftableDatabase.getRefsByPrefix(prefix);
164 RefList.Builder<Ref> builder = new RefList.Builder<>(refs.size());
165 for (Ref r : refs) {
166 builder.add(r);
167 }
168 return new RefMap(prefix, builder.toRefList(), RefList.emptyList(),
169 RefList.emptyList());
170 }
171
172
173 @Override
174 public List<Ref> getRefsByPrefix(String prefix) throws IOException {
175
176 return reftableDatabase.getRefsByPrefix(prefix);
177 }
178
179
180 @Override
181 public List<Ref> getRefsByPrefixWithExclusions(String include, Set<String> excludes)
182 throws IOException {
183 return reftableDatabase.getRefsByPrefixWithExclusions(include, excludes);
184 }
185
186
187 @Override
188 public Set<Ref> getTipsWithSha1(ObjectId id) throws IOException {
189 if (!getReftableConfig().isIndexObjects()) {
190 return super.getTipsWithSha1(id);
191 }
192 return reftableDatabase.getTipsWithSha1(id);
193 }
194
195
196 @Override
197 public boolean hasFastTipsWithSha1() throws IOException {
198 return reftableDatabase.hasFastTipsWithSha1();
199 }
200
201
202 @Override
203 public Ref peel(Ref ref) throws IOException {
204 Ref oldLeaf = ref.getLeaf();
205 if (oldLeaf.isPeeled() || oldLeaf.getObjectId() == null) {
206 return ref;
207 }
208 return recreate(ref, doPeel(oldLeaf), hasVersioning());
209 }
210
211 @Override
212 boolean exists() throws IOException {
213 DfsObjDatabase odb = getRepository().getObjectDatabase();
214 return odb.getReftables().length > 0;
215 }
216
217 @Override
218 void clearCache() {
219 ReentrantLock l = getLock();
220 l.lock();
221 try {
222 if (ctx != null) {
223 ctx.close();
224 ctx = null;
225 }
226 reftableDatabase.clearCache();
227 if (stack != null) {
228 stack.close();
229 stack = null;
230 }
231 } finally {
232 l.unlock();
233 }
234 }
235
236
237 @Override
238 protected boolean compareAndPut(Ref oldRef, @Nullable Ref newRef)
239 throws IOException {
240 ReceiveCommand cmd = ReftableDatabase.toCommand(oldRef, newRef);
241 try (RevWalk rw = new RevWalk(getRepository())) {
242 rw.setRetainBody(false);
243 newBatchUpdate().setAllowNonFastForwards(true).addCommand(cmd)
244 .execute(rw, NullProgressMonitor.INSTANCE);
245 }
246 switch (cmd.getResult()) {
247 case OK:
248 return true;
249 case REJECTED_OTHER_REASON:
250 throw new IOException(cmd.getMessage());
251 case LOCK_FAILURE:
252 default:
253 return false;
254 }
255 }
256
257
258 @Override
259 protected boolean compareAndRemove(Ref oldRef) throws IOException {
260 return compareAndPut(oldRef, null);
261 }
262
263
264 @Override
265 protected RefCache scanAllRefs() throws IOException {
266 throw new UnsupportedOperationException();
267 }
268
269 @Override
270 void stored(Ref ref) {
271
272 }
273
274 @Override
275 void removed(String refName) {
276
277 }
278
279
280 @Override
281 protected void cachePeeledState(Ref oldLeaf, Ref newLeaf) {
282
283 }
284
285 }