Skip to content

Commit 738d15a

Browse files
committed
extract revision from a cache file using parser
1 parent f055d2d commit 738d15a

File tree

2 files changed

+66
-25
lines changed

2 files changed

+66
-25
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/history/AnnotationData.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public AnnotationData(String filename) {
6060
* shortening with very long filenames), on the other hand it is necessary to deserialize the object
6161
* to tell whether it is stale.
6262
*/
63-
private String revision;
63+
String revision;
6464

6565
public List<AnnotationLine> getLines() {
6666
return annotationLines;

opengrok-indexer/src/main/java/org/opengrok/indexer/history/FileAnnotationCache.java

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@
2222
*/
2323
package org.opengrok.indexer.history;
2424

25+
import com.fasterxml.jackson.core.JsonToken;
2526
import com.fasterxml.jackson.databind.ObjectMapper;
27+
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
28+
import com.fasterxml.jackson.dataformat.smile.SmileParser;
2629
import com.fasterxml.jackson.dataformat.smile.databind.SmileMapper;
2730
import io.micrometer.core.instrument.Counter;
2831
import io.micrometer.core.instrument.MeterRegistry;
@@ -61,13 +64,54 @@ public void initialize() {
6164
}
6265

6366
/**
64-
* Read annotation from a file.
67+
* Read serialized {@link AnnotationData} from a file and create {@link Annotation} instance out of it.
6568
*/
6669
static Annotation readCache(File file) throws IOException {
6770
ObjectMapper mapper = new SmileMapper();
6871
return new Annotation(mapper.readValue(file, AnnotationData.class));
6972
}
7073

74+
/**
75+
* Retrieve revision from the cache for given file. This is done in a fashion that keeps I/O low.
76+
* Assumes that {@link AnnotationData#revision} is serialized in the cache file as the first member.
77+
* @param file source root file
78+
* @return revision from the cache file or {@code null}
79+
* @throws CacheException on error
80+
*/
81+
@Nullable
82+
String getRevision(File file) throws CacheException {
83+
File cacheFile;
84+
try {
85+
cacheFile = getCachedFile(file);
86+
} catch (CacheException e) {
87+
throw new CacheException("failed to get annotation cache file", e);
88+
}
89+
90+
SmileFactory factory = new SmileFactory();
91+
try (SmileParser parser = factory.createParser(cacheFile)) {
92+
parser.nextToken();
93+
while (parser.getCurrentToken() != null) {
94+
if (parser.getCurrentToken().equals(JsonToken.FIELD_NAME)) {
95+
break;
96+
}
97+
parser.nextToken();
98+
}
99+
100+
if (parser.getCurrentName().equals("revision")) {
101+
parser.nextToken();
102+
if (!parser.getCurrentToken().equals(JsonToken.VALUE_STRING)) {
103+
LOGGER.log(Level.WARNING, "failed to get revision from ''{0}''", cacheFile);
104+
return null;
105+
}
106+
return parser.getValueAsString();
107+
} else {
108+
return null;
109+
}
110+
} catch (IOException e) {
111+
throw new CacheException(e);
112+
}
113+
}
114+
71115
@Override
72116
public String getCacheFileSuffix() {
73117
return "";
@@ -111,29 +155,26 @@ public Annotation get(File file, @Nullable String rev) throws CacheException {
111155
Annotation annotation = null;
112156
String latestRevision = LatestRevisionUtil.getLatestRevision(file);
113157
if (rev == null || (latestRevision != null && latestRevision.equals(rev))) {
114-
// read from the cache
115-
annotation = readAnnotation(file);
116-
if (annotation != null) {
117-
/*
118-
* Double check that the cached annotation is not stale by comparing the stored revision
119-
* with revision to be fetched.
120-
* This should be more robust than the file time stamp based check performed by history cache,
121-
* at the expense of having to read from the annotation cache.
122-
*/
123-
final String storedRevision = annotation.getRevision();
124-
/*
125-
* Even though store() does not allow to store annotation with null revision, the check
126-
* should be present to catch weird cases of someone not using the store() or general badness.
127-
*/
128-
if (storedRevision == null) {
129-
LOGGER.log(Level.FINER, "no stored revision in annotation cache for ''{0}''", file);
130-
annotation = null;
131-
} else if (!storedRevision.equals(latestRevision)) {
132-
LOGGER.log(Level.FINER,
133-
"stored revision {0} for ''{1}'' does not match latest revision {2}",
134-
new Object[]{storedRevision, file, rev});
135-
annotation = null;
136-
}
158+
/*
159+
* Double check that the cached annotation is not stale by comparing the stored revision
160+
* with revision to be fetched.
161+
* This should be more robust than the file time stamp based check performed by history cache,
162+
* at the expense of having to read some content from the annotation cache.
163+
*/
164+
final String storedRevision = getRevision(file);
165+
/*
166+
* Even though store() does not allow to store annotation with null revision, the check
167+
* should be present to catch weird cases of someone not using the store() or general badness.
168+
*/
169+
if (storedRevision == null) {
170+
LOGGER.log(Level.FINER, "no stored revision in annotation cache for ''{0}''", file);
171+
} else if (!storedRevision.equals(latestRevision)) {
172+
LOGGER.log(Level.FINER,
173+
"stored revision {0} for ''{1}'' does not match latest revision {2}",
174+
new Object[]{storedRevision, file, rev});
175+
} else {
176+
// read from the cache
177+
annotation = readAnnotation(file);
137178
}
138179
}
139180

0 commit comments

Comments
 (0)