Skip to content

Commit 112419e

Browse files
idodeclareVladimir Kotal
authored andcommitted
Detect if add() is called while complete() is running
1 parent 6d95dac commit 112419e

File tree

1 file changed

+34
-17
lines changed

1 file changed

+34
-17
lines changed

opengrok-indexer/src/main/java/org/opengrok/indexer/index/PendingFileCompleter.java

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -62,8 +62,8 @@
6262
* <p>
6363
* No methods are thread-safe between each other. E.g.,
6464
* {@link #complete()} should only be called by a single thread after all
65-
* additions of {@link PendingFileDeletion}s and {@link PendingFileRenaming}s
66-
* are indicated.
65+
* additions of {@link PendingSymlinkage}s, {@link PendingFileDeletion}s, and
66+
* {@link PendingFileRenaming}s are indicated.
6767
* <p>
6868
* {@link #add(org.opengrok.indexer.index.PendingSymlinkage)} should only
6969
* be called in serial from a single thread in an isolated stage.
@@ -88,6 +88,8 @@ class PendingFileCompleter {
8888

8989
private final Object INSTANCE_LOCK = new Object();
9090

91+
private volatile boolean completing;
92+
9193
/**
9294
* Descending path segment length comparator.
9395
*/
@@ -121,8 +123,12 @@ class PendingFileCompleter {
121123
* @param e element to be added to this set
122124
* @return {@code true} if this instance's set did not already contain the
123125
* specified element
126+
* @throws IllegalStateException if {@link #complete()} is running
124127
*/
125128
public boolean add(PendingFileDeletion e) {
129+
if (completing) {
130+
throw new IllegalStateException("complete() is running");
131+
}
126132
return deletions.add(e);
127133
}
128134

@@ -132,8 +138,12 @@ public boolean add(PendingFileDeletion e) {
132138
* @param e element to be added to this set
133139
* @return {@code true} if this instance's set did not already contain the
134140
* specified element
141+
* @throws IllegalStateException if {@link #complete()} is running
135142
*/
136143
public boolean add(PendingSymlinkage e) {
144+
if (completing) {
145+
throw new IllegalStateException("complete() is running");
146+
}
137147
return linkages.add(e);
138148
}
139149

@@ -145,8 +155,12 @@ public boolean add(PendingSymlinkage e) {
145155
* @param e element to be added to this set
146156
* @return {@code true} if this instance's set did not already contain the
147157
* specified element
158+
* @throws IllegalStateException if {@link #complete()} is running
148159
*/
149160
public boolean add(PendingFileRenaming e) {
161+
if (completing) {
162+
throw new IllegalStateException("complete() is running");
163+
}
150164
synchronized (INSTANCE_LOCK) {
151165
boolean rc = renames.add(e);
152166
deletions.remove(new PendingFileDeletion(e.getAbsolutePath()));
@@ -156,7 +170,7 @@ public boolean add(PendingFileRenaming e) {
156170

157171
/**
158172
* Complete all the tracked file operations: first in a stage for pending
159-
* deletions next in a stage for pending renamings, and finally in a stage
173+
* deletions, next in a stage for pending renamings, and finally in a stage
160174
* for pending symbolic linkages.
161175
* <p>
162176
* All operations in each stage are tried in parallel, and any failure is
@@ -171,6 +185,15 @@ public boolean add(PendingFileRenaming e) {
171185
* @throws java.io.IOException if an I/O error occurs
172186
*/
173187
public int complete() throws IOException {
188+
completing = true;
189+
try {
190+
return completeInner();
191+
} finally {
192+
completing = false;
193+
}
194+
}
195+
196+
private int completeInner() throws IOException {
174197
Instant start = Instant.now();
175198
int numDeletions = completeDeletions();
176199
if (LOGGER.isLoggable(Level.FINE)) {
@@ -346,8 +369,7 @@ private int completeLinkages() throws IOException {
346369

347370
private void doDelete(PendingFileDeletionExec del) {
348371
File f = new File(TandemPath.join(del.absolutePath, PENDING_EXTENSION));
349-
File parent = f.getParentFile();
350-
del.absoluteParent = parent;
372+
del.absoluteParent = f.getParentFile();
351373

352374
doDelete(f);
353375
f = new File(del.absolutePath);
@@ -436,10 +458,7 @@ private boolean needLink(PendingSymlinkageExec lnk) {
436458
return true;
437459
}
438460
// not needed if source's canonical matches re-resolved target canonical
439-
if (tgtCanonical.equals(srcCanonical)) {
440-
return false;
441-
}
442-
return true;
461+
return !tgtCanonical.equals(srcCanonical);
443462
}
444463

445464
/**
@@ -488,9 +507,7 @@ private void tryDeleteParents(List<PendingFileDeletionExec> dels) {
488507
for (File dir : parents) {
489508
skels.reset();
490509
findFilelessChildren(skels, dir);
491-
skels.childDirs.forEach((childDir) -> {
492-
tryDeleteDirectory(childDir);
493-
});
510+
skels.childDirs.forEach(this::tryDeleteDirectory);
494511
tryDeleteDirectory(dir);
495512
}
496513
}
@@ -572,7 +589,7 @@ private static int countPathSegments(String path) {
572589
}
573590

574591
private static class PendingFileDeletionExec {
575-
String absolutePath;
592+
final String absolutePath;
576593
File absoluteParent;
577594
IOException exception;
578595
PendingFileDeletionExec(String absolutePath) {
@@ -581,8 +598,8 @@ private static class PendingFileDeletionExec {
581598
}
582599

583600
private static class PendingFileRenamingExec {
584-
String source;
585-
String target;
601+
final String source;
602+
final String target;
586603
IOException exception;
587604
PendingFileRenamingExec(String source, String target) {
588605
this.source = source;
@@ -591,8 +608,8 @@ private static class PendingFileRenamingExec {
591608
}
592609

593610
private static class PendingSymlinkageExec {
594-
String source;
595-
String targetRel;
611+
final String source;
612+
final String targetRel;
596613
IOException exception;
597614
PendingSymlinkageExec(String source, String relTarget) {
598615
this.source = source;

0 commit comments

Comments
 (0)