1
2
3
4
5
6
7
8
9
10
11 package org.eclipse.jgit.internal.storage.reftable;
12
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.util.ArrayDeque;
16 import java.util.ArrayList;
17 import java.util.List;
18
19 import org.eclipse.jgit.internal.storage.reftable.ReftableWriter.Stats;
20 import org.eclipse.jgit.lib.PersonIdent;
21 import org.eclipse.jgit.lib.ReflogEntry;
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 public class ReftableCompactor {
38 private final ReftableWriter writer;
39 private final ArrayDeque<ReftableReader> tables = new ArrayDeque<>();
40
41 private boolean includeDeletes;
42 private long reflogExpireMinUpdateIndex = 0;
43 private long reflogExpireMaxUpdateIndex = Long.MAX_VALUE;
44 private long reflogExpireOldestReflogTimeMillis;
45 private Stats stats;
46
47
48
49
50
51
52
53
54 public ReftableCompactor(OutputStream out) {
55 writer = new ReftableWriter(out);
56 }
57
58
59
60
61
62
63
64
65 public ReftableCompactor setConfig(ReftableConfig cfg) {
66 writer.setConfig(cfg);
67 return this;
68 }
69
70
71
72
73
74
75
76
77
78
79 public ReftableCompactor setIncludeDeletes(boolean deletes) {
80 includeDeletes = deletes;
81 return this;
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95 public ReftableCompactor setReflogExpireMinUpdateIndex(long min) {
96 reflogExpireMinUpdateIndex = min;
97 return this;
98 }
99
100
101
102
103
104
105
106
107
108
109
110
111 public ReftableCompactor setReflogExpireMaxUpdateIndex(long max) {
112 reflogExpireMaxUpdateIndex = max;
113 return this;
114 }
115
116
117
118
119
120
121
122
123
124
125
126 public ReftableCompactor setReflogExpireOldestReflogTimeMillis(long timeMillis) {
127 reflogExpireOldestReflogTimeMillis = timeMillis;
128 return this;
129 }
130
131
132
133
134
135
136
137
138
139
140
141 public void addAll(List<ReftableReader> readers) throws IOException {
142 for (ReftableReader r : readers) {
143 tables.add(r);
144 }
145 }
146
147
148
149
150
151
152
153 public void compact() throws IOException {
154 MergedReftable mr = new MergedReftable(new ArrayList<>(tables));
155 mr.setIncludeDeletes(includeDeletes);
156
157 writer.setMaxUpdateIndex(mr.maxUpdateIndex());
158 writer.setMinUpdateIndex(mr.minUpdateIndex());
159
160 writer.begin();
161 mergeRefs(mr);
162 mergeLogs(mr);
163 writer.finish();
164 stats = writer.getStats();
165 }
166
167
168
169
170
171
172 public Stats getStats() {
173 return stats;
174 }
175
176 private void mergeRefs(MergedReftable mr) throws IOException {
177 try (RefCursor rc = mr.allRefs()) {
178 while (rc.next()) {
179 writer.writeRef(rc.getRef(), rc.getRef().getUpdateIndex());
180 }
181 }
182 }
183
184 private void mergeLogs(MergedReftable mr) throws IOException {
185 if (reflogExpireOldestReflogTimeMillis == Long.MAX_VALUE) {
186 return;
187 }
188
189 try (LogCursor lc = mr.allLogs()) {
190 while (lc.next()) {
191 long updateIndex = lc.getUpdateIndex();
192 if (updateIndex > reflogExpireMaxUpdateIndex || updateIndex < reflogExpireMinUpdateIndex) {
193 continue;
194 }
195
196 String refName = lc.getRefName();
197 ReflogEntry log = lc.getReflogEntry();
198 if (log == null) {
199 if (includeDeletes) {
200 writer.deleteLog(refName, updateIndex);
201 }
202 continue;
203 }
204
205 PersonIdent who = log.getWho();
206 if (who.getWhen().getTime() >= reflogExpireOldestReflogTimeMillis) {
207 writer.writeLog(
208 refName,
209 updateIndex,
210 who,
211 log.getOldId(),
212 log.getNewId(),
213 log.getComment());
214 }
215 }
216 }
217 }
218 }