Skip to content

Commit c540d39

Browse files
Gracefully handle concurent repository modifications
1 parent 46ade8d commit c540d39

File tree

2 files changed

+32
-12
lines changed

2 files changed

+32
-12
lines changed

server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java

+30-11
Original file line numberDiff line numberDiff line change
@@ -919,18 +919,30 @@ public void endVerification(String seed) {
919919

920920
@Override
921921
public RepositoryData getRepositoryData() {
922-
final long generation;
923-
try {
924-
generation = latestIndexBlobId();
925-
} catch (IOException ioe) {
926-
throw new RepositoryException(metadata.name(), "Could not determine repository generation from root blobs", ioe);
927-
}
928-
final long genToLoad = latestKnownRepoGen.updateAndGet(known -> Math.max(known, generation));
929-
if (genToLoad != generation) {
930-
logger.warn("Determined repository generation [" + generation + "] from repository contents but correct generation must be " +
931-
"at least [" + genToLoad + "]");
922+
// Retry loading RepositoryData in a loop in case we run into concurrent modifications of the repository.
923+
while (true) {
924+
final long generation;
925+
try {
926+
generation = latestIndexBlobId();
927+
} catch (IOException ioe) {
928+
throw new RepositoryException(metadata.name(), "Could not determine repository generation from root blobs", ioe);
929+
}
930+
final long genToLoad = latestKnownRepoGen.updateAndGet(known -> Math.max(known, generation));
931+
if (genToLoad != generation) {
932+
logger.warn("Determined repository generation [" + generation
933+
+ "] from repository contents but correct generation must be at least [" + genToLoad + "]");
934+
}
935+
try {
936+
return getRepositoryData(genToLoad);
937+
} catch (RepositoryException e) {
938+
if (genToLoad != latestKnownRepoGen.get()) {
939+
logger.warn("Failed to load repository data generation [" + genToLoad +
940+
"] because a concurrent operation moved the current generation to [" + latestKnownRepoGen.get() + "]", e);
941+
continue;
942+
}
943+
throw e;
944+
}
932945
}
933-
return getRepositoryData(genToLoad);
934946
}
935947

936948
private RepositoryData getRepositoryData(long indexGen) {
@@ -947,6 +959,13 @@ private RepositoryData getRepositoryData(long indexGen) {
947959
return RepositoryData.snapshotsFromXContent(parser, indexGen);
948960
}
949961
} catch (IOException ioe) {
962+
// If we fail to load the generation we tracked in latestKnownRepoGen we reset it.
963+
// This is done as a fail-safe in case a user manually deletes the contents of the repository in which case subsequent
964+
// operations must start from the EMPTY_REPO_GEN again
965+
if (RepositoryData.EMPTY_REPO_GEN ==
966+
latestKnownRepoGen.updateAndGet(known -> known == indexGen ? RepositoryData.EMPTY_REPO_GEN : known)) {
967+
logger.warn("Resetting repository generation tracker because we failed to read generation [" + indexGen + "]");
968+
}
950969
throw new RepositoryException(metadata.name(), "could not read repository data from index blob", ioe);
951970
}
952971
}

test/framework/src/main/java/org/elasticsearch/repositories/AbstractThirdPartyRepositoryTestCase.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ public void setUp() throws Exception {
7676
@Override
7777
public void tearDown() throws Exception {
7878
deleteAndAssertEmpty(getRepository().basePath());
79-
client().admin().cluster().prepareDeleteRepository("test-repo").get();
8079
super.tearDown();
8180
}
8281

@@ -170,6 +169,8 @@ protected void assertBlobsByPrefix(BlobPath path, String prefix, Map<String, Blo
170169
}
171170

172171
public void testCleanup() throws Exception {
172+
createRepository("test-repo");
173+
173174
createIndex("test-idx-1");
174175
createIndex("test-idx-2");
175176
createIndex("test-idx-3");

0 commit comments

Comments
 (0)