Enables implementations of the BlobContainer interface to (#19749)

conform with the requirements of the writeBlob method by
throwing a FileAlreadyExistsException if attempting to write
to a blob that already exists. This change means implementations
of BlobContainer should never overwrite blobs - to overwrite a
blob, it must first be deleted and then can be written again.

Closes #15579
This commit is contained in:
Ali Beyad 2016-08-02 09:48:21 -04:00 committed by GitHub
parent c0b71d26cf
commit c4ae23f5d8
7 changed files with 23 additions and 3 deletions

View File

@ -21,6 +21,7 @@ package org.elasticsearch.common.blobstore;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.util.Map; import java.util.Map;
@ -68,8 +69,8 @@ public interface BlobContainer {
* @param blobSize * @param blobSize
* The size of the blob to be written, in bytes. It is implementation dependent whether * The size of the blob to be written, in bytes. It is implementation dependent whether
* this value is used in writing the blob to the repository. * this value is used in writing the blob to the repository.
* @throws IOException if the input stream could not be read, a blob by the same name already exists, * @throws FileAlreadyExistsException if a blob by the same name already exists
* or the target blob could not be written to. * @throws IOException if the input stream could not be read, or the target blob could not be written to.
*/ */
void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException; void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException;

View File

@ -32,6 +32,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
@ -108,6 +109,9 @@ public class FsBlobContainer extends AbstractBlobContainer {
@Override @Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException { public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
if (blobExists(blobName)) {
throw new FileAlreadyExistsException("blob [" + blobName + "] already exists, cannot overwrite");
}
final Path file = path.resolve(blobName); final Path file = path.resolve(blobName);
try (OutputStream outputStream = Files.newOutputStream(file, StandardOpenOption.CREATE_NEW)) { try (OutputStream outputStream = Files.newOutputStream(file, StandardOpenOption.CREATE_NEW)) {
Streams.copy(inputStream, outputStream, new byte[blobStore.bufferSizeInBytes()]); Streams.copy(inputStream, outputStream, new byte[blobStore.bufferSizeInBytes()]);

View File

@ -34,6 +34,7 @@ import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.util.Map; import java.util.Map;
@ -84,6 +85,9 @@ public class AzureBlobContainer extends AbstractBlobContainer {
@Override @Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException { public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
if (blobExists(blobName)) {
throw new FileAlreadyExistsException("blob [" + blobName + "] already exists, cannot overwrite");
}
logger.trace("writeBlob({}, stream, {})", blobName, blobSize); logger.trace("writeBlob({}, stream, {})", blobName, blobSize);
try (OutputStream stream = createOutput(blobName)) { try (OutputStream stream = createOutput(blobName)) {
Streams.copy(inputStream, stream); Streams.copy(inputStream, stream);

View File

@ -26,6 +26,7 @@ import org.elasticsearch.common.blobstore.support.AbstractBlobContainer;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.FileAlreadyExistsException;
import java.util.Map; import java.util.Map;
public class GoogleCloudStorageBlobContainer extends AbstractBlobContainer { public class GoogleCloudStorageBlobContainer extends AbstractBlobContainer {
@ -65,6 +66,9 @@ public class GoogleCloudStorageBlobContainer extends AbstractBlobContainer {
@Override @Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException { public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
if (blobExists(blobName)) {
throw new FileAlreadyExistsException("blob [" + blobName + "] already exists, cannot overwrite");
}
blobStore.writeBlob(buildKey(blobName), inputStream, blobSize); blobStore.writeBlob(buildKey(blobName), inputStream, blobSize);
} }

View File

@ -34,6 +34,7 @@ import org.elasticsearch.repositories.hdfs.HdfsBlobStore.Operation;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
@ -107,6 +108,9 @@ final class HdfsBlobContainer extends AbstractBlobContainer {
@Override @Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException { public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
if (blobExists(blobName)) {
throw new FileAlreadyExistsException("blob [" + blobName + "] already exists, cannot overwrite");
}
store.execute(new Operation<Void>() { store.execute(new Operation<Void>() {
@Override @Override
public Void run(FileContext fileContext) throws IOException { public Void run(FileContext fileContext) throws IOException {

View File

@ -39,6 +39,7 @@ import org.elasticsearch.common.io.Streams;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.NoSuchFileException; import java.nio.file.NoSuchFileException;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
@ -100,6 +101,9 @@ public class S3BlobContainer extends AbstractBlobContainer {
@Override @Override
public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException { public void writeBlob(String blobName, InputStream inputStream, long blobSize) throws IOException {
if (blobExists(blobName)) {
throw new FileAlreadyExistsException("blob [" + blobName + "] already exists, cannot overwrite");
}
try (OutputStream stream = createOutput(blobName)) { try (OutputStream stream = createOutput(blobName)) {
Streams.copy(inputStream, stream); Streams.copy(inputStream, stream);
} }

View File

@ -128,7 +128,6 @@ public abstract class ESBlobStoreContainerTestCase extends ESTestCase {
} }
} }
@AwaitsFix(bugUrl = "https://github.com/elastic/elasticsearch/issues/15579")
public void testVerifyOverwriteFails() throws IOException { public void testVerifyOverwriteFails() throws IOException {
try (final BlobStore store = newBlobStore()) { try (final BlobStore store = newBlobStore()) {
final String blobName = "foobar"; final String blobName = "foobar";