19
19
import java .util .ArrayList ;
20
20
import java .util .Calendar ;
21
21
import java .util .Date ;
22
+ import java .util .HashMap ;
22
23
import java .util .List ;
23
24
import java .util .Map ;
24
- import java .util .concurrent .ConcurrentHashMap ;
25
25
import java .util .concurrent .TimeUnit ;
26
26
27
27
import org .eclipse .jgit .lib .ObjectId ;
@@ -58,7 +58,7 @@ public static CommitCache instance() {
58
58
}
59
59
60
60
protected CommitCache () {
61
- cache = new ConcurrentHashMap < String , ObjectCache < List < RepositoryCommit >> >();
61
+ cache = new HashMap < >();
62
62
}
63
63
64
64
/**
@@ -93,7 +93,9 @@ public synchronized void setCacheDays(int days) {
93
93
*
94
94
*/
95
95
public void clear () {
96
- cache .clear ();
96
+ synchronized (cache ) {
97
+ cache .clear ();
98
+ }
97
99
}
98
100
99
101
/**
@@ -103,8 +105,11 @@ public void clear() {
103
105
*/
104
106
public void clear (String repositoryName ) {
105
107
String repoKey = repositoryName .toLowerCase ();
106
- ObjectCache <List <RepositoryCommit >> repoCache = cache .remove (repoKey );
107
- if (repoCache != null ) {
108
+ boolean hadEntries = false ;
109
+ synchronized (cache ) {
110
+ hadEntries = cache .remove (repoKey ) != null ;
111
+ }
112
+ if (hadEntries ) {
108
113
logger .info (MessageFormat .format ("{0} commit cache cleared" , repositoryName ));
109
114
}
110
115
}
@@ -117,13 +122,17 @@ public void clear(String repositoryName) {
117
122
*/
118
123
public void clear (String repositoryName , String branch ) {
119
124
String repoKey = repositoryName .toLowerCase ();
120
- ObjectCache <List <RepositoryCommit >> repoCache = cache .get (repoKey );
121
- if (repoCache != null ) {
122
- List <RepositoryCommit > commits = repoCache .remove (branch .toLowerCase ());
123
- if (!ArrayUtils .isEmpty (commits )) {
124
- logger .info (MessageFormat .format ("{0}:{1} commit cache cleared" , repositoryName , branch ));
125
+ boolean hadEntries = false ;
126
+ synchronized (cache ) {
127
+ ObjectCache <List <RepositoryCommit >> repoCache = cache .get (repoKey );
128
+ if (repoCache != null ) {
129
+ List <RepositoryCommit > commits = repoCache .remove (branch .toLowerCase ());
130
+ hadEntries = !ArrayUtils .isEmpty (commits );
125
131
}
126
132
}
133
+ if (hadEntries ) {
134
+ logger .info (MessageFormat .format ("{0}:{1} commit cache cleared" , repositoryName , branch ));
135
+ }
127
136
}
128
137
129
138
/**
@@ -156,49 +165,55 @@ public List<RepositoryCommit> getCommits(String repositoryName, Repository repos
156
165
if (cacheDays > 0 && (sinceDate .getTime () >= cacheCutoffDate .getTime ())) {
157
166
// request fits within the cache window
158
167
String repoKey = repositoryName .toLowerCase ();
159
- if (!cache .containsKey (repoKey )) {
160
- cache .put (repoKey , new ObjectCache <List <RepositoryCommit >>());
161
- }
162
-
163
- ObjectCache <List <RepositoryCommit >> repoCache = cache .get (repoKey );
164
168
String branchKey = branch .toLowerCase ();
165
169
166
170
RevCommit tip = JGitUtils .getCommit (repository , branch );
167
171
Date tipDate = JGitUtils .getCommitDate (tip );
168
172
169
- List <RepositoryCommit > commits ;
170
- if (!repoCache .hasCurrent (branchKey , tipDate )) {
171
- commits = repoCache .getObject (branchKey );
172
- if (ArrayUtils .isEmpty (commits )) {
173
- // we don't have any cached commits for this branch, reload
174
- commits = get (repositoryName , repository , branch , cacheCutoffDate );
175
- repoCache .updateObject (branchKey , tipDate , commits );
176
- logger .debug (MessageFormat .format ("parsed {0} commits from {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs" ,
177
- commits .size (), repositoryName , branch , cacheCutoffDate , TimeUnit .NANOSECONDS .toMillis (System .nanoTime () - start )));
178
- } else {
179
- // incrementally update cache since the last cached commit
180
- ObjectId sinceCommit = commits .get (0 ).getId ();
181
- List <RepositoryCommit > incremental = get (repositoryName , repository , branch , sinceCommit );
182
- logger .info (MessageFormat .format ("incrementally added {0} commits to cache for {1}:{2} in {3} msecs" ,
183
- incremental .size (), repositoryName , branch , TimeUnit .NANOSECONDS .toMillis (System .nanoTime () - start )));
184
- incremental .addAll (commits );
185
- repoCache .updateObject (branchKey , tipDate , incremental );
186
- commits = incremental ;
173
+ ObjectCache <List <RepositoryCommit >> repoCache ;
174
+ synchronized (cache ) {
175
+ repoCache = cache .get (repoKey );
176
+ if (repoCache == null ) {
177
+ repoCache = new ObjectCache <>();
178
+ cache .put (repoKey , repoCache );
187
179
}
188
- } else {
189
- // cache is current
190
- commits = repoCache .getObject (branchKey );
191
- // evict older commits outside the cache window
192
- commits = reduce (commits , cacheCutoffDate );
193
- // update cache
194
- repoCache .updateObject (branchKey , tipDate , commits );
195
180
}
181
+ synchronized (repoCache ) {
182
+ List <RepositoryCommit > commits ;
183
+ if (!repoCache .hasCurrent (branchKey , tipDate )) {
184
+ commits = repoCache .getObject (branchKey );
185
+ if (ArrayUtils .isEmpty (commits )) {
186
+ // we don't have any cached commits for this branch, reload
187
+ commits = get (repositoryName , repository , branch , cacheCutoffDate );
188
+ repoCache .updateObject (branchKey , tipDate , commits );
189
+ logger .debug (MessageFormat .format ("parsed {0} commits from {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs" ,
190
+ commits .size (), repositoryName , branch , cacheCutoffDate , TimeUnit .NANOSECONDS .toMillis (System .nanoTime () - start )));
191
+ } else {
192
+ // incrementally update cache since the last cached commit
193
+ ObjectId sinceCommit = commits .get (0 ).getId ();
194
+ List <RepositoryCommit > incremental = get (repositoryName , repository , branch , sinceCommit );
195
+ logger .info (MessageFormat .format ("incrementally added {0} commits to cache for {1}:{2} in {3} msecs" ,
196
+ incremental .size (), repositoryName , branch , TimeUnit .NANOSECONDS .toMillis (System .nanoTime () - start )));
197
+ incremental .addAll (commits );
198
+ repoCache .updateObject (branchKey , tipDate , incremental );
199
+ commits = incremental ;
200
+ }
201
+ } else {
202
+ // cache is current
203
+ commits = repoCache .getObject (branchKey );
204
+ // evict older commits outside the cache window
205
+ commits = reduce (commits , cacheCutoffDate );
206
+ // update cache
207
+ repoCache .updateObject (branchKey , tipDate , commits );
208
+ }
196
209
197
- if (sinceDate .equals (cacheCutoffDate )) {
198
- list = commits ;
199
- } else {
200
- // reduce the commits to those since the specified date
201
- list = reduce (commits , sinceDate );
210
+ if (sinceDate .equals (cacheCutoffDate )) {
211
+ // Mustn't hand out the cached list; that's not thread-safe
212
+ list = new ArrayList <>(commits );
213
+ } else {
214
+ // reduce the commits to those since the specified date
215
+ list = reduce (commits , sinceDate );
216
+ }
202
217
}
203
218
logger .debug (MessageFormat .format ("retrieved {0} commits from cache of {1}:{2} since {3,date,yyyy-MM-dd} in {4} msecs" ,
204
219
list .size (), repositoryName , branch , sinceDate , TimeUnit .NANOSECONDS .toMillis (System .nanoTime () - start )));
@@ -222,8 +237,9 @@ public List<RepositoryCommit> getCommits(String repositoryName, Repository repos
222
237
*/
223
238
protected List <RepositoryCommit > get (String repositoryName , Repository repository , String branch , Date sinceDate ) {
224
239
Map <ObjectId , List <RefModel >> allRefs = JGitUtils .getAllRefs (repository , false );
225
- List <RepositoryCommit > commits = new ArrayList <RepositoryCommit >();
226
- for (RevCommit commit : JGitUtils .getRevLog (repository , branch , sinceDate )) {
240
+ List <RevCommit > revLog = JGitUtils .getRevLog (repository , branch , sinceDate );
241
+ List <RepositoryCommit > commits = new ArrayList <RepositoryCommit >(revLog .size ());
242
+ for (RevCommit commit : revLog ) {
227
243
RepositoryCommit commitModel = new RepositoryCommit (repositoryName , branch , commit );
228
244
List <RefModel > commitRefs = allRefs .get (commitModel .getId ());
229
245
commitModel .setRefs (commitRefs );
@@ -243,8 +259,9 @@ protected List<RepositoryCommit> get(String repositoryName, Repository repositor
243
259
*/
244
260
protected List <RepositoryCommit > get (String repositoryName , Repository repository , String branch , ObjectId sinceCommit ) {
245
261
Map <ObjectId , List <RefModel >> allRefs = JGitUtils .getAllRefs (repository , false );
246
- List <RepositoryCommit > commits = new ArrayList <RepositoryCommit >();
247
- for (RevCommit commit : JGitUtils .getRevLog (repository , sinceCommit .getName (), branch )) {
262
+ List <RevCommit > revLog = JGitUtils .getRevLog (repository , sinceCommit .getName (), branch );
263
+ List <RepositoryCommit > commits = new ArrayList <RepositoryCommit >(revLog .size ());
264
+ for (RevCommit commit : revLog ) {
248
265
RepositoryCommit commitModel = new RepositoryCommit (repositoryName , branch , commit );
249
266
List <RefModel > commitRefs = allRefs .get (commitModel .getId ());
250
267
commitModel .setRefs (commitRefs );
@@ -261,7 +278,7 @@ protected List<RepositoryCommit> get(String repositoryName, Repository repositor
261
278
* @return a list of commits
262
279
*/
263
280
protected List <RepositoryCommit > reduce (List <RepositoryCommit > commits , Date sinceDate ) {
264
- List <RepositoryCommit > filtered = new ArrayList <RepositoryCommit >();
281
+ List <RepositoryCommit > filtered = new ArrayList <RepositoryCommit >(commits . size () );
265
282
for (RepositoryCommit commit : commits ) {
266
283
if (commit .getCommitDate ().compareTo (sinceDate ) >= 0 ) {
267
284
filtered .add (commit );
0 commit comments