Skip to content

Commit 8dfa60d

Browse files
author
Vladimir Dolzhenko
committed
enforcing access to blobStore / blobContainer only to snapshot and generic threads
1 parent d8c9593 commit 8dfa60d

File tree

5 files changed

+91
-28
lines changed

5 files changed

+91
-28
lines changed

server/src/main/java/org/elasticsearch/repositories/RepositoriesService.java

+21-17
Original file line numberDiff line numberDiff line change
@@ -221,15 +221,17 @@ public void verifyRepository(final String repositoryName, final ActionListener<V
221221
verifyAction.verify(repositoryName, verificationToken, new ActionListener<VerifyResponse>() {
222222
@Override
223223
public void onResponse(VerifyResponse verifyResponse) {
224-
try {
225-
repository.endVerification(verificationToken);
226-
} catch (Exception e) {
227-
logger.warn(() -> new ParameterizedMessage(
228-
"[{}] failed to finish repository verification", repositoryName), e);
229-
listener.onFailure(e);
230-
return;
231-
}
232-
listener.onResponse(verifyResponse);
224+
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
225+
try {
226+
repository.endVerification(verificationToken);
227+
} catch (Exception e) {
228+
logger.warn(() -> new ParameterizedMessage(
229+
"[{}] failed to finish repository verification", repositoryName), e);
230+
listener.onFailure(e);
231+
return;
232+
}
233+
listener.onResponse(verifyResponse);
234+
});
233235
}
234236

235237
@Override
@@ -238,14 +240,16 @@ public void onFailure(Exception e) {
238240
}
239241
});
240242
} catch (Exception e) {
241-
try {
242-
repository.endVerification(verificationToken);
243-
} catch (Exception inner) {
244-
inner.addSuppressed(e);
245-
logger.warn(() -> new ParameterizedMessage(
246-
"[{}] failed to finish repository verification", repositoryName), inner);
247-
}
248-
listener.onFailure(e);
243+
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
244+
try {
245+
repository.endVerification(verificationToken);
246+
} catch (Exception inner) {
247+
inner.addSuppressed(e);
248+
logger.warn(() -> new ParameterizedMessage(
249+
"[{}] failed to finish repository verification", repositoryName), inner);
250+
}
251+
listener.onFailure(e);
252+
});
249253
}
250254
} else {
251255
listener.onResponse(new VerifyResponse(new DiscoveryNode[0], new VerificationFailure[0]));

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,8 @@ protected BlobStore getBlobStore() {
298298
* maintains single lazy instance of {@link BlobContainer}
299299
*/
300300
protected BlobContainer blobContainer() {
301+
verificationThreadCheck();
302+
301303
BlobContainer blobContainer = this.blobContainer.get();
302304
if (blobContainer == null) {
303305
synchronized (lock) {
@@ -316,6 +318,8 @@ protected BlobContainer blobContainer() {
316318
* maintains single lazy instance of {@link BlobStore}
317319
*/
318320
protected BlobStore blobStore() {
321+
verificationThreadCheck();
322+
319323
BlobStore store = blobStore.get();
320324
if (store == null) {
321325
synchronized (lock) {
@@ -324,7 +328,6 @@ protected BlobStore blobStore() {
324328
if (lifecycle.started() == false) {
325329
throw new RepositoryException(metadata.name(), "repository is not in started state");
326330
}
327-
verificationThreadCheck();
328331
try {
329332
store = createBlobStore();
330333
} catch (RepositoryException e) {

server/src/test/java/org/elasticsearch/repositories/blobstore/BlobStoreRepositoryTests.java

+29-2
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,16 @@
2424
import org.elasticsearch.client.Client;
2525
import org.elasticsearch.common.UUIDs;
2626
import org.elasticsearch.common.settings.Settings;
27+
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
28+
import org.elasticsearch.env.Environment;
29+
import org.elasticsearch.plugins.Plugin;
30+
import org.elasticsearch.plugins.RepositoryPlugin;
2731
import org.elasticsearch.repositories.IndexId;
2832
import org.elasticsearch.repositories.RepositoriesService;
33+
import org.elasticsearch.repositories.Repository;
2934
import org.elasticsearch.repositories.RepositoryData;
3035
import org.elasticsearch.repositories.RepositoryException;
36+
import org.elasticsearch.repositories.fs.FsRepository;
3137
import org.elasticsearch.snapshots.SnapshotId;
3238
import org.elasticsearch.snapshots.SnapshotState;
3339
import org.elasticsearch.test.ESIntegTestCase;
@@ -37,8 +43,10 @@
3743
import java.nio.file.Path;
3844
import java.util.ArrayList;
3945
import java.util.Arrays;
46+
import java.util.Collection;
4047
import java.util.Collections;
4148
import java.util.List;
49+
import java.util.Map;
4250
import java.util.stream.Collectors;
4351

4452
import static org.elasticsearch.repositories.RepositoryDataTests.generateRandomRepoData;
@@ -50,6 +58,25 @@
5058
*/
5159
public class BlobStoreRepositoryTests extends ESSingleNodeTestCase {
5260

61+
static final String REPO_TYPE = "fsLike";
62+
63+
protected Collection<Class<? extends Plugin>> getPlugins() {
64+
return Arrays.asList(FsLikeRepoPlugin.class);
65+
}
66+
67+
public static class FsLikeRepoPlugin extends org.elasticsearch.plugins.Plugin implements RepositoryPlugin {
68+
69+
@Override
70+
public Map<String, Repository.Factory> getRepositories(Environment env, NamedXContentRegistry namedXContentRegistry) {
71+
return Collections.singletonMap(REPO_TYPE,
72+
(metadata) -> new FsRepository(metadata, env, namedXContentRegistry) {
73+
@Override
74+
protected void verificationThreadCheck() {
75+
}
76+
});
77+
}
78+
}
79+
5380
public void testRetrieveSnapshots() throws Exception {
5481
final Client client = client();
5582
final Path location = ESIntegTestCase.randomRepoPath(node().settings());
@@ -58,7 +85,7 @@ public void testRetrieveSnapshots() throws Exception {
5885
logger.info("--> creating repository");
5986
PutRepositoryResponse putRepositoryResponse =
6087
client.admin().cluster().preparePutRepository(repositoryName)
61-
.setType("fs")
88+
.setType(REPO_TYPE)
6289
.setSettings(Settings.builder().put(node().settings()).put("location", location))
6390
.get();
6491
assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));
@@ -210,7 +237,7 @@ private BlobStoreRepository setupRepo() {
210237

211238
PutRepositoryResponse putRepositoryResponse =
212239
client.admin().cluster().preparePutRepository(repositoryName)
213-
.setType("fs")
240+
.setType(REPO_TYPE)
214241
.setSettings(Settings.builder().put(node().settings()).put("location", location))
215242
.get();
216243
assertThat(putRepositoryResponse.isAcknowledged(), equalTo(true));

server/src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreIT.java

+19-3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.snapshots;
2121

22+
import org.apache.lucene.util.SetOnce;
2223
import org.elasticsearch.ExceptionsHelper;
2324
import org.elasticsearch.Version;
2425
import org.elasticsearch.action.ActionFuture;
@@ -93,6 +94,7 @@
9394
import org.elasticsearch.script.StoredScriptsIT;
9495
import org.elasticsearch.snapshots.mockstore.MockRepository;
9596
import org.elasticsearch.test.junit.annotations.TestLogging;
97+
import org.elasticsearch.threadpool.ThreadPool;
9698

9799
import java.io.IOException;
98100
import java.nio.channels.SeekableByteChannel;
@@ -1262,7 +1264,7 @@ public void testDeleteSnapshotWithMissingIndexAndShardMetadata() throws Exceptio
12621264
RepositoriesService service = internalCluster().getInstance(RepositoriesService.class, internalCluster().getMasterName());
12631265
Repository repository = service.repository("test-repo");
12641266

1265-
final Map<String, IndexId> indexIds = repository.getRepositoryData().getIndices();
1267+
final Map<String, IndexId> indexIds = getRepositoryData(repository).getIndices();
12661268
final Path indicesPath = repo.resolve("indices");
12671269

12681270
logger.info("--> delete index metadata and shard metadata");
@@ -2564,7 +2566,7 @@ public void testDeleteOrphanSnapshot() throws Exception {
25642566

25652567
logger.info("--> emulate an orphan snapshot");
25662568
RepositoriesService repositoriesService = internalCluster().getInstance(RepositoriesService.class, internalCluster().getMasterName());
2567-
final RepositoryData repositoryData = repositoriesService.repository(repositoryName).getRepositoryData();
2569+
final RepositoryData repositoryData = getRepositoryData(repositoriesService.repository(repositoryName));
25682570
final IndexId indexId = repositoryData.resolveIndexId(idxName);
25692571

25702572
clusterService.submitStateUpdateTask("orphan snapshot test", new ClusterStateUpdateTask() {
@@ -2785,7 +2787,8 @@ public void testRestoreSnapshotWithCorruptedIndexMetadata() throws Exception {
27852787
RepositoriesService service = internalCluster().getInstance(RepositoriesService.class, internalCluster().getMasterName());
27862788
Repository repository = service.repository("test-repo");
27872789

2788-
final Map<String, IndexId> indexIds = repository.getRepositoryData().getIndices();
2790+
final RepositoryData repositoryData = getRepositoryData(repository);
2791+
final Map<String, IndexId> indexIds = repositoryData.getIndices();
27892792
assertThat(indexIds.size(), equalTo(nbIndices));
27902793

27912794
// Choose a random index from the snapshot
@@ -3446,6 +3449,19 @@ public void testAbortedSnapshotDuringInitDoesNotStart() throws Exception {
34463449
}
34473450
}
34483451

3452+
private RepositoryData getRepositoryData(Repository repository) throws InterruptedException {
3453+
ThreadPool threadPool = internalCluster().getInstance(ThreadPool.class, internalCluster().getMasterName());
3454+
final SetOnce<RepositoryData> repositoryData = new SetOnce<>();
3455+
final CountDownLatch latch = new CountDownLatch(1);
3456+
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
3457+
repositoryData.set(repository.getRepositoryData());
3458+
latch.countDown();
3459+
});
3460+
3461+
latch.await();
3462+
return repositoryData.get();
3463+
}
3464+
34493465
private void verifySnapshotInfo(final GetSnapshotsResponse response, final Map<String, List<String>> indicesPerSnapshot) {
34503466
for (SnapshotInfo snapshotInfo : response.getSnapshots()) {
34513467
final List<String> expected = snapshotInfo.indices();

test/framework/src/main/java/org/elasticsearch/repositories/blobstore/ESBlobStoreRepositoryIntegTestCase.java

+18-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.elasticsearch.repositories.blobstore;
2020

21+
import org.apache.lucene.util.SetOnce;
2122
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotRequestBuilder;
2223
import org.elasticsearch.action.admin.cluster.snapshots.create.CreateSnapshotResponse;
2324
import org.elasticsearch.action.admin.cluster.snapshots.restore.RestoreSnapshotRequestBuilder;
@@ -32,12 +33,14 @@
3233
import org.elasticsearch.snapshots.SnapshotMissingException;
3334
import org.elasticsearch.snapshots.SnapshotRestoreException;
3435
import org.elasticsearch.test.ESIntegTestCase;
36+
import org.elasticsearch.threadpool.ThreadPool;
3537

3638
import java.util.Arrays;
3739
import java.util.HashSet;
3840
import java.util.List;
3941
import java.util.Locale;
4042
import java.util.Set;
43+
import java.util.concurrent.CountDownLatch;
4144
import java.util.concurrent.ExecutionException;
4245

4346
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
@@ -202,7 +205,7 @@ public void testMultipleSnapshotAndRollback() throws Exception {
202205
}
203206
}
204207

205-
public void testIndicesDeletedFromRepository() {
208+
public void testIndicesDeletedFromRepository() throws Exception {
206209
Client client = client();
207210

208211
logger.info("--> creating repository");
@@ -244,12 +247,22 @@ public void testIndicesDeletedFromRepository() {
244247

245248
logger.info("--> verify index folder deleted from blob container");
246249
RepositoriesService repositoriesSvc = internalCluster().getInstance(RepositoriesService.class, internalCluster().getMasterName());
250+
ThreadPool threadPool = internalCluster().getInstance(ThreadPool.class, internalCluster().getMasterName());
247251
@SuppressWarnings("unchecked") BlobStoreRepository repository = (BlobStoreRepository) repositoriesSvc.repository(repoName);
248-
BlobContainer indicesBlobContainer = repository.blobStore().blobContainer(repository.basePath().add("indices"));
249-
RepositoryData repositoryData = repository.getRepositoryData();
250-
for (IndexId indexId : repositoryData.getIndices().values()) {
252+
253+
final SetOnce<BlobContainer> indicesBlobContainer = new SetOnce<>();
254+
final SetOnce<RepositoryData> repositoryData = new SetOnce<>();
255+
final CountDownLatch latch = new CountDownLatch(1);
256+
threadPool.executor(ThreadPool.Names.SNAPSHOT).execute(() -> {
257+
indicesBlobContainer.set(repository.blobStore().blobContainer(repository.basePath().add("indices")));
258+
repositoryData.set(repository.getRepositoryData());
259+
latch.countDown();
260+
});
261+
262+
latch.await();
263+
for (IndexId indexId : repositoryData.get().getIndices().values()) {
251264
if (indexId.getName().equals("test-idx-3")) {
252-
assertFalse(indicesBlobContainer.blobExists(indexId.getId())); // deleted index
265+
assertFalse(indicesBlobContainer.get().blobExists(indexId.getId())); // deleted index
253266
}
254267
}
255268
}

0 commit comments

Comments
 (0)