Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ public class FsBlobStore implements BlobStore {

private final boolean readOnly;

public FsBlobStore(Settings settings, Path path) throws IOException {
public FsBlobStore(Settings settings, Path path, boolean readonly) throws IOException {
this.path = path;
this.readOnly = settings.getAsBoolean("readonly", false);
if (!this.readOnly) {
this.readOnly = readonly;
if (this.readOnly == false) {
Files.createDirectories(path);
}
this.bufferSizeInBytes = (int) settings.getAsBytesSize("repositories.fs.buffer_size",
Expand Down Expand Up @@ -74,6 +74,11 @@ public BlobContainer blobContainer(BlobPath path) {

@Override
public void delete(BlobPath path) throws IOException {
assert readOnly == false : "should not delete anything from a readonly repository: " + path;
//noinspection ConstantConditions in case assertions are disabled
if (readOnly) {
throw new ElasticsearchException("unexpectedly deleting [" + path + "] from a readonly repository");
}
IOUtils.rm(buildPath(path));
}

Expand All @@ -84,7 +89,7 @@ public void close() {

private synchronized Path buildAndCreate(BlobPath path) throws IOException {
Path f = buildPath(path);
if (!readOnly) {
if (readOnly == false) {
Files.createDirectories(f);
}
return f;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public FsRepository(RepositoryMetaData metadata, Environment environment, NamedX
protected BlobStore createBlobStore() throws Exception {
final String location = REPOSITORIES_LOCATION_SETTING.get(metadata.settings());
final Path locationFile = environment.resolveRepoFile(location);
return new FsBlobStore(environment.settings(), locationFile);
return new FsBlobStore(environment.settings(), locationFile, isReadOnly());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,6 @@ protected BlobStore newBlobStore() throws IOException {
} else {
settings = Settings.EMPTY;
}
return new FsBlobStore(settings, createTempDir());
return new FsBlobStore(settings, createTempDir(), false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,14 @@ protected BlobStore newBlobStore() throws IOException {
} else {
settings = Settings.EMPTY;
}
return new FsBlobStore(settings, createTempDir());
return new FsBlobStore(settings, createTempDir(), false);
}

public void testReadOnly() throws Exception {
Settings settings = Settings.builder().put("readonly", true).build();
Path tempDir = createTempDir();
Path path = tempDir.resolve("bar");

try (FsBlobStore store = new FsBlobStore(settings, path)) {
try (FsBlobStore store = new FsBlobStore(Settings.EMPTY, path, true)) {
assertFalse(Files.exists(path));
BlobPath blobPath = BlobPath.cleanPath().add("foo");
store.blobContainer(blobPath);
Expand All @@ -61,8 +60,7 @@ public void testReadOnly() throws Exception {
assertFalse(Files.exists(storePath));
}

settings = randomBoolean() ? Settings.EMPTY : Settings.builder().put("readonly", false).build();
try (FsBlobStore store = new FsBlobStore(settings, path)) {
try (FsBlobStore store = new FsBlobStore(Settings.EMPTY, path, false)) {
assertTrue(Files.exists(path));
BlobPath blobPath = BlobPath.cleanPath().add("foo");
BlobContainer container = store.blobContainer(blobPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,22 @@
*/
package org.elasticsearch.repositories.fs;

import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.repositories.Repository;
import org.elasticsearch.repositories.blobstore.ESBlobStoreRepositoryIntegTestCase;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.concurrent.ExecutionException;
import java.util.stream.Stream;

import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
import static org.hamcrest.Matchers.instanceOf;

public class FsBlobStoreRepositoryIT extends ESBlobStoreRepositoryIntegTestCase {
Expand All @@ -41,4 +51,47 @@ protected void createTestRepository(String name, boolean verify) {
protected void afterCreationCheck(Repository repository) {
assertThat(repository, instanceOf(FsRepository.class));
}

public void testMissingDirectoriesNotCreatedInReadonlyRepository() throws IOException, ExecutionException, InterruptedException {
final String repoName = randomAsciiName();
final Path repoPath = randomRepoPath();

logger.info("--> creating repository {} at {}", repoName, repoPath);

assertAcked(client().admin().cluster().preparePutRepository(repoName).setType("fs").setSettings(Settings.builder()
.put("location", repoPath)
.put("compress", randomBoolean())
.put("chunk_size", randomIntBetween(100, 1000), ByteSizeUnit.BYTES)));

String indexName = randomAsciiName();
int docCount = iterations(10, 1000);
logger.info("--> create random index {} with {} records", indexName, docCount);
addRandomDocuments(indexName, docCount);
assertHitCount(client().prepareSearch(indexName).setSize(0).get(), docCount);

final String snapshotName = randomAsciiName();
logger.info("--> create snapshot {}:{}", repoName, snapshotName);
assertSuccessfulSnapshot(client().admin().cluster().prepareCreateSnapshot(repoName, snapshotName)
.setWaitForCompletion(true).setIndices(indexName));

assertAcked(client().admin().indices().prepareDelete(indexName));
assertAcked(client().admin().cluster().prepareDeleteRepository(repoName));

final Path deletedPath;
try (Stream<Path> contents = Files.list(repoPath.resolve("indices"))) {
//noinspection OptionalGetWithoutIsPresent because we know there's a subdirectory
deletedPath = contents.filter(Files::isDirectory).findAny().get();
IOUtils.rm(deletedPath);
}
assertFalse(Files.exists(deletedPath));

assertAcked(client().admin().cluster().preparePutRepository(repoName).setType("fs").setSettings(Settings.builder()
.put("location", repoPath).put("readonly", true)));

final ElasticsearchException exception = expectThrows(ElasticsearchException.class, () ->
client().admin().cluster().prepareRestoreSnapshot(repoName, snapshotName).setWaitForCompletion(randomBoolean()).get());
assertThat(exception.getRootCause(), instanceOf(NoSuchFileException.class));

assertFalse("deleted path is not recreated in readonly repository", Files.exists(deletedPath));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,7 @@ public void writeBlobAtomic(String blobName, InputStream inputStream, long blobS
}

protected BlobStore createTestBlobStore() throws IOException {
Settings settings = Settings.builder().build();
return new FsBlobStore(settings, randomRepoPath());
return new FsBlobStore(Settings.EMPTY, randomRepoPath(), false);
}

protected void randomCorruption(BlobContainer blobContainer, String blobName) throws IOException {
Expand Down