Change the BlobContainer interface to throw a NoSuchFileFoundException

for reads and deletes if the blob does not exist.
This commit is contained in:
Ali Beyad 2016-07-02 16:06:38 -04:00
parent abaf8443e5
commit 630218a16f
7 changed files with 35 additions and 17 deletions

View File

@ -23,6 +23,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.NoSuchFileException;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
@ -53,7 +54,8 @@ public interface BlobContainer {
* @param blobName * @param blobName
* The name of the blob to get an {@link InputStream} for. * The name of the blob to get an {@link InputStream} for.
* @return The {@code InputStream} to read the blob. * @return The {@code InputStream} to read the blob.
* @throws IOException if the blob does not exist or can not be read. * @throws NoSuchFileException if the blob does not exist
* @throws IOException if the blob can not be read.
*/ */
InputStream readBlob(String blobName) throws IOException; InputStream readBlob(String blobName) throws IOException;
@ -95,7 +97,8 @@ public interface BlobContainer {
* *
* @param blobName * @param blobName
* The name of the blob to delete. * The name of the blob to delete.
* @throws IOException if the blob does not exist, or if the blob exists but could not be deleted. * @throws NoSuchFileException if the blob does not exist
* @throws IOException if the blob exists but could not be deleted.
*/ */
void deleteBlob(String blobName) throws IOException; void deleteBlob(String blobName) throws IOException;

View File

@ -32,6 +32,7 @@ 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.Files; import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
@ -95,7 +96,11 @@ public class FsBlobContainer extends AbstractBlobContainer {
@Override @Override
public InputStream readBlob(String name) throws IOException { public InputStream readBlob(String name) throws IOException {
return new BufferedInputStream(Files.newInputStream(path.resolve(name)), blobStore.bufferSizeInBytes()); final Path resolvedPath = path.resolve(name);
if (!Files.exists(resolvedPath)) {
throw new NoSuchFileException("[" + resolvedPath + "] file not found");
}
return new BufferedInputStream(Files.newInputStream(resolvedPath), blobStore.bufferSizeInBytes());
} }
@Override @Override

View File

@ -30,12 +30,12 @@ import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers; import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.repositories.RepositoryException; import org.elasticsearch.repositories.RepositoryException;
import java.io.FileNotFoundException;
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.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.NoSuchFileException;
import java.util.Map; import java.util.Map;
/** /**
@ -72,14 +72,14 @@ public class AzureBlobContainer extends AbstractBlobContainer {
logger.trace("readBlob({})", blobName); logger.trace("readBlob({})", blobName);
if (!blobExists(blobName)) { if (!blobExists(blobName)) {
throw new IOException("Blob [" + blobName + "] does not exist"); throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
} }
try { try {
return blobStore.getInputStream(blobStore.container(), buildKey(blobName)); return blobStore.getInputStream(blobStore.container(), buildKey(blobName));
} catch (StorageException e) { } catch (StorageException e) {
if (e.getHttpStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { if (e.getHttpStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) {
throw new FileNotFoundException(e.getMessage()); throw new NoSuchFileException(e.getMessage());
} }
throw new IOException(e); throw new IOException(e);
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
@ -108,7 +108,7 @@ public class AzureBlobContainer extends AbstractBlobContainer {
return new AzureOutputStream(blobStore.getOutputStream(blobStore.container(), buildKey(blobName))); return new AzureOutputStream(blobStore.getOutputStream(blobStore.container(), buildKey(blobName)));
} catch (StorageException e) { } catch (StorageException e) {
if (e.getHttpStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { if (e.getHttpStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) {
throw new FileNotFoundException(e.getMessage()); throw new NoSuchFileException(e.getMessage());
} }
throw new IOException(e); throw new IOException(e);
} catch (URISyntaxException e) { } catch (URISyntaxException e) {

View File

@ -41,9 +41,9 @@ import org.elasticsearch.common.component.AbstractComponent;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.CountDown; import org.elasticsearch.common.util.concurrent.CountDown;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.NoSuchFileException;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
@ -189,6 +189,9 @@ public class GoogleCloudStorageBlobStore extends AbstractComponent implements Bl
* @return an InputStream * @return an InputStream
*/ */
InputStream readBlob(String blobName) throws IOException { InputStream readBlob(String blobName) throws IOException {
if (!blobExists(blobName)) {
throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
}
return doPrivileged(() -> { return doPrivileged(() -> {
try { try {
Storage.Objects.Get object = client.objects().get(bucket, blobName); Storage.Objects.Get object = client.objects().get(bucket, blobName);
@ -196,7 +199,7 @@ public class GoogleCloudStorageBlobStore extends AbstractComponent implements Bl
} catch (GoogleJsonResponseException e) { } catch (GoogleJsonResponseException e) {
GoogleJsonError error = e.getDetails(); GoogleJsonError error = e.getDetails();
if ((e.getStatusCode() == HTTP_NOT_FOUND) || ((error != null) && (error.getCode() == HTTP_NOT_FOUND))) { if ((e.getStatusCode() == HTTP_NOT_FOUND) || ((error != null) && (error.getCode() == HTTP_NOT_FOUND))) {
throw new FileNotFoundException(e.getMessage()); throw new NoSuchFileException(e.getMessage());
} }
throw e; throw e;
} }
@ -227,6 +230,9 @@ public class GoogleCloudStorageBlobStore extends AbstractComponent implements Bl
* @param blobName name of the blob * @param blobName name of the blob
*/ */
void deleteBlob(String blobName) throws IOException { void deleteBlob(String blobName) throws IOException {
if (!blobExists(blobName)) {
throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
}
doPrivileged(() -> client.objects().delete(bucket, blobName).execute()); doPrivileged(() -> client.objects().delete(bucket, blobName).execute());
} }

View File

@ -32,9 +32,9 @@ import org.elasticsearch.common.blobstore.support.AbstractBlobContainer;
import org.elasticsearch.common.blobstore.support.PlainBlobMetaData; import org.elasticsearch.common.blobstore.support.PlainBlobMetaData;
import org.elasticsearch.repositories.hdfs.HdfsBlobStore.Operation; import org.elasticsearch.repositories.hdfs.HdfsBlobStore.Operation;
import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.NoSuchFileException;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
@ -69,7 +69,7 @@ final class HdfsBlobContainer extends AbstractBlobContainer {
@Override @Override
public void deleteBlob(String blobName) throws IOException { public void deleteBlob(String blobName) throws IOException {
if (!blobExists(blobName)) { if (!blobExists(blobName)) {
throw new IOException("Blob [" + blobName + "] does not exist"); throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
} }
store.execute(new Operation<Boolean>() { store.execute(new Operation<Boolean>() {
@ -93,6 +93,9 @@ final class HdfsBlobContainer extends AbstractBlobContainer {
@Override @Override
public InputStream readBlob(String blobName) throws IOException { public InputStream readBlob(String blobName) throws IOException {
if (!blobExists(blobName)) {
throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
}
// FSDataInputStream does buffering internally // FSDataInputStream does buffering internally
return store.execute(new Operation<InputStream>() { return store.execute(new Operation<InputStream>() {
@Override @Override

View File

@ -23,6 +23,7 @@ import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.AbstractFileSystem; import org.apache.hadoop.fs.AbstractFileSystem;
import org.apache.hadoop.fs.FileContext; import org.apache.hadoop.fs.FileContext;
import org.apache.hadoop.fs.UnsupportedFileSystemException; import org.apache.hadoop.fs.UnsupportedFileSystemException;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.blobstore.BlobStore; import org.elasticsearch.common.blobstore.BlobStore;
import org.elasticsearch.repositories.ESBlobStoreContainerTestCase; import org.elasticsearch.repositories.ESBlobStoreContainerTestCase;
@ -55,7 +56,8 @@ public class HdfsBlobStoreContainerTests extends ESBlobStoreContainerTestCase {
}); });
} }
public FileContext createContext(URI uri) { @SuppressForbidden(reason = "lesser of two evils (the other being a bunch of JNI/classloader nightmares)")
private FileContext createContext(URI uri) {
// mirrors HdfsRepository.java behaviour // mirrors HdfsRepository.java behaviour
Configuration cfg = new Configuration(true); Configuration cfg = new Configuration(true);
cfg.setClassLoader(HdfsRepository.class.getClassLoader()); cfg.setClassLoader(HdfsRepository.class.getClassLoader());
@ -85,8 +87,7 @@ public class HdfsBlobStoreContainerTests extends ESBlobStoreContainerTestCase {
// set file system to TestingFs to avoid a bunch of security // set file system to TestingFs to avoid a bunch of security
// checks, similar to what is done in HdfsTests.java // checks, similar to what is done in HdfsTests.java
cfg.set(String.format("fs.AbstractFileSystem.%s.impl", uri.getScheme()), cfg.set("fs.AbstractFileSystem." + uri.getScheme() + ".impl", TestingFs.class.getName());
TestingFs.class.getName());
// create the FileContext with our user // create the FileContext with our user
return Subject.doAs(subject, new PrivilegedAction<FileContext>() { return Subject.doAs(subject, new PrivilegedAction<FileContext>() {

View File

@ -37,10 +37,10 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.MapBuilder; import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.common.io.Streams; import org.elasticsearch.common.io.Streams;
import java.io.FileNotFoundException;
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.NoSuchFileException;
import java.security.AccessController; import java.security.AccessController;
import java.security.PrivilegedActionException; import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
@ -89,7 +89,7 @@ public class S3BlobContainer extends AbstractBlobContainer {
} else { } else {
if (e instanceof AmazonS3Exception) { if (e instanceof AmazonS3Exception) {
if (404 == ((AmazonS3Exception) e).getStatusCode()) { if (404 == ((AmazonS3Exception) e).getStatusCode()) {
throw new FileNotFoundException("Blob object [" + blobName + "] not found: " + e.getMessage()); throw new NoSuchFileException("Blob object [" + blobName + "] not found: " + e.getMessage());
} }
} }
throw e; throw e;
@ -116,7 +116,7 @@ public class S3BlobContainer extends AbstractBlobContainer {
@Override @Override
public void deleteBlob(String blobName) throws IOException { public void deleteBlob(String blobName) throws IOException {
if (!blobExists(blobName)) { if (!blobExists(blobName)) {
throw new IOException("Blob [" + blobName + "] does not exist"); throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
} }
try { try {