Skip to content

Commit 4020e4e

Browse files
committed
Do not check for Azure container existence (#31617)
The current AzureStorageServiceImpl always checks if the Azure container exists before reading or writing an object to the Azure container. This commit removes this behavior, reducing the number of overhall requests executed for all snapshots operations.
1 parent 509421f commit 4020e4e

File tree

3 files changed

+41
-47
lines changed

3 files changed

+41
-47
lines changed

plugins/repository-azure/src/main/java/org/elasticsearch/cloud/azure/blobstore/AzureBlobContainer.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ public void writeBlob(String blobName, InputStream inputStream, long blobSize) t
100100
public void deleteBlob(String blobName) throws IOException {
101101
logger.trace("deleteBlob({})", blobName);
102102

103-
if (!blobExists(blobName)) {
104-
throw new NoSuchFileException("Blob [" + blobName + "] does not exist");
105-
}
106-
107103
try {
108104
blobStore.deleteBlob(buildKey(blobName));
109-
} catch (URISyntaxException | StorageException e) {
110-
logger.warn("can not access [{}] in container {{}}: {}", blobName, blobStore, e.getMessage());
105+
} catch (StorageException e) {
106+
if (e.getHttpStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) {
107+
throw new NoSuchFileException(e.getMessage());
108+
}
109+
throw new IOException(e);
110+
} catch (URISyntaxException e) {
111111
throw new IOException(e);
112112
}
113113
}

plugins/repository-azure/src/main/java/org/elasticsearch/cloud/azure/storage/AzureStorageServiceImpl.java

+27-36
Original file line numberDiff line numberDiff line change
@@ -158,19 +158,17 @@ public void createContainer(String account, String container) throws URISyntaxEx
158158
public void deleteFiles(String account, String container, String path) throws URISyntaxException, StorageException {
159159
final Tuple<CloudBlobClient, Supplier<OperationContext>> client = client(account);
160160
// container name must be lower case.
161-
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
162161
logger.trace(() -> new ParameterizedMessage("delete files container [{}], path [{}]", container, path));
163162
SocketAccess.doPrivilegedVoidException(() -> {
164-
if (blobContainer.exists()) {
165-
// list the blobs using a flat blob listing mode
166-
for (final ListBlobItem blobItem : blobContainer.listBlobs(path, true, EnumSet.noneOf(BlobListingDetails.class), null,
167-
client.v2().get())) {
168-
final String blobName = blobNameFromUri(blobItem.getUri());
169-
logger.trace(() -> new ParameterizedMessage("removing blob [{}] full URI was [{}]", blobName, blobItem.getUri()));
170-
// don't call {@code #deleteBlob}, use the same client
171-
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blobName);
172-
azureBlob.delete(DeleteSnapshotsOption.NONE, null, null, client.v2().get());
173-
}
163+
// list the blobs using a flat blob listing mode
164+
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
165+
for (final ListBlobItem blobItem : blobContainer.listBlobs(path, true, EnumSet.noneOf(BlobListingDetails.class), null,
166+
client.v2().get())) {
167+
final String blobName = blobNameFromUri(blobItem.getUri());
168+
logger.trace(() -> new ParameterizedMessage("removing blob [{}] full URI was [{}]", blobName, blobItem.getUri()));
169+
// don't call {@code #deleteBlob}, use the same client
170+
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blobName);
171+
azureBlob.delete(DeleteSnapshotsOption.NONE, null, null, client.v2().get());
174172
}
175173
});
176174
}
@@ -200,11 +198,8 @@ public boolean blobExists(String account, String container, String blob)
200198
final Tuple<CloudBlobClient, Supplier<OperationContext>> client = client(account);
201199
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
202200
return SocketAccess.doPrivilegedException(() -> {
203-
if (blobContainer.exists(null, null, client.v2().get())) {
204-
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blob);
205-
return azureBlob.exists(null, null, client.v2().get());
206-
}
207-
return false;
201+
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blob);
202+
return azureBlob.exists(null, null, client.v2().get());
208203
});
209204
}
210205

@@ -215,11 +210,9 @@ public void deleteBlob(String account, String container, String blob) throws URI
215210
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
216211
logger.trace(() -> new ParameterizedMessage("delete blob for container [{}], blob [{}]", container, blob));
217212
SocketAccess.doPrivilegedVoidException(() -> {
218-
if (blobContainer.exists(null, null, client.v2().get())) {
219-
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blob);
220-
logger.trace(() -> new ParameterizedMessage("container [{}]: blob [{}] found. removing.", container, blob));
221-
azureBlob.delete(DeleteSnapshotsOption.NONE, null, null, client.v2().get());
222-
}
213+
final CloudBlockBlob azureBlob = blobContainer.getBlockBlobReference(blob);
214+
logger.trace(() -> new ParameterizedMessage("container [{}]: blob [{}] found. removing.", container, blob));
215+
azureBlob.delete(DeleteSnapshotsOption.NONE, null, null, client.v2().get());
223216
});
224217
}
225218

@@ -245,19 +238,17 @@ public Map<String, BlobMetaData> listBlobsByPrefix(String account, String contai
245238
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
246239
logger.trace(() -> new ParameterizedMessage("listing container [{}], keyPath [{}], prefix [{}]", container, keyPath, prefix));
247240
SocketAccess.doPrivilegedVoidException(() -> {
248-
if (blobContainer.exists()) {
249-
for (final ListBlobItem blobItem : blobContainer.listBlobs(keyPath + (prefix == null ? "" : prefix), false,
250-
enumBlobListingDetails, null, client.v2().get())) {
251-
final URI uri = blobItem.getUri();
252-
logger.trace(() -> new ParameterizedMessage("blob url [{}]", uri));
253-
// uri.getPath is of the form /container/keyPath.* and we want to strip off the /container/
254-
// this requires 1 + container.length() + 1, with each 1 corresponding to one of the /
255-
final String blobPath = uri.getPath().substring(1 + container.length() + 1);
256-
final BlobProperties properties = ((CloudBlockBlob) blobItem).getProperties();
257-
final String name = blobPath.substring(keyPath.length());
258-
logger.trace(() -> new ParameterizedMessage("blob url [{}], name [{}], size [{}]", uri, name, properties.getLength()));
259-
blobsBuilder.put(name, new PlainBlobMetaData(name, properties.getLength()));
260-
}
241+
for (final ListBlobItem blobItem : blobContainer.listBlobs(keyPath + (prefix == null ? "" : prefix), false,
242+
enumBlobListingDetails, null, client.v2().get())) {
243+
final URI uri = blobItem.getUri();
244+
logger.trace(() -> new ParameterizedMessage("blob url [{}]", uri));
245+
// uri.getPath is of the form /container/keyPath.* and we want to strip off the /container/
246+
// this requires 1 + container.length() + 1, with each 1 corresponding to one of the /
247+
final String blobPath = uri.getPath().substring(1 + container.length() + 1);
248+
final BlobProperties properties = ((CloudBlockBlob) blobItem).getProperties();
249+
final String name = blobPath.substring(keyPath.length());
250+
logger.trace(() -> new ParameterizedMessage("blob url [{}], name [{}], size [{}]", uri, name, properties.getLength()));
251+
blobsBuilder.put(name, new PlainBlobMetaData(name, properties.getLength()));
261252
}
262253
});
263254
return blobsBuilder.immutableMap();
@@ -271,8 +262,8 @@ public void writeBlob(String account, String container, String blobName, InputSt
271262
final CloudBlobContainer blobContainer = client.v1().getContainerReference(container);
272263
final CloudBlockBlob blob = blobContainer.getBlockBlobReference(blobName);
273264
try {
274-
SocketAccess.doPrivilegedVoidException(() -> blob.upload(inputStream, blobSize, AccessCondition.generateIfNotExistsCondition(),
275-
null, client.v2().get()));
265+
SocketAccess.doPrivilegedVoidException(() ->
266+
blob.upload(inputStream, blobSize, AccessCondition.generateIfNotExistsCondition(), null, client.v2().get()));
276267
} catch (final StorageException se) {
277268
if (se.getHttpStatusCode() == HttpURLConnection.HTTP_CONFLICT &&
278269
StorageErrorCodeStrings.BLOB_ALREADY_EXISTS.equals(se.getErrorCode())) {

plugins/repository-azure/src/test/java/org/elasticsearch/cloud/azure/storage/AzureStorageServiceMock.java

+8-5
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
import com.microsoft.azure.storage.OperationContext;
2323
import com.microsoft.azure.storage.StorageException;
2424
import com.microsoft.azure.storage.blob.CloudBlobClient;
25-
2625
import org.elasticsearch.common.blobstore.BlobMetaData;
2726
import org.elasticsearch.common.blobstore.support.PlainBlobMetaData;
2827
import org.elasticsearch.common.collect.MapBuilder;
@@ -72,9 +71,11 @@ public void createContainer(String account, String container) {
7271
}
7372

7473
@Override
75-
public void deleteFiles(String account, String container, String path) {
74+
public void deleteFiles(String account, String container, String path) throws URISyntaxException, StorageException {
7675
final Map<String, BlobMetaData> blobs = listBlobsByPrefix(account, container, path, null);
77-
blobs.keySet().forEach(key -> deleteBlob(account, container, key));
76+
for (String key : blobs.keySet()) {
77+
deleteBlob(account, container, key);
78+
}
7879
}
7980

8081
@Override
@@ -83,8 +84,10 @@ public boolean blobExists(String account, String container, String blob) {
8384
}
8485

8586
@Override
86-
public void deleteBlob(String account, String container, String blob) {
87-
blobs.remove(blob);
87+
public void deleteBlob(String account, String container, String blob) throws URISyntaxException, StorageException {
88+
if (blobs.remove(blob) == null) {
89+
throw new StorageException("BlobNotFound", "[" + blob + "] does not exist.", 404, null, null);
90+
}
8891
}
8992

9093
@Override

0 commit comments

Comments
 (0)