28
28
import com .google .cloud .storage .Storage ;
29
29
import com .google .cloud .storage .Storage .BlobListOption ;
30
30
import com .google .cloud .storage .Storage .CopyRequest ;
31
+ import com .google .cloud .storage .StorageException ;
31
32
import org .elasticsearch .common .SuppressForbidden ;
32
33
import org .elasticsearch .common .blobstore .BlobContainer ;
33
34
import org .elasticsearch .common .blobstore .BlobMetaData ;
47
48
import java .nio .channels .Channels ;
48
49
import java .nio .channels .ReadableByteChannel ;
49
50
import java .nio .channels .WritableByteChannel ;
51
+ import java .nio .file .FileAlreadyExistsException ;
50
52
import java .nio .file .NoSuchFileException ;
51
53
import java .util .Collection ;
52
54
import java .util .List ;
53
55
import java .util .Map ;
54
56
import java .util .stream .Collectors ;
55
57
58
+ import static java .net .HttpURLConnection .HTTP_PRECON_FAILED ;
59
+
56
60
class GoogleCloudStorageBlobStore extends AbstractComponent implements BlobStore {
57
61
58
62
// The recommended maximum size of a blob that should be uploaded in a single
@@ -204,24 +208,32 @@ void writeBlob(String blobName, InputStream inputStream, long blobSize) throws I
204
208
* @param inputStream the stream containing the blob data
205
209
*/
206
210
private void writeBlobResumable (BlobInfo blobInfo , InputStream inputStream ) throws IOException {
207
- final WriteChannel writeChannel = SocketAccess .doPrivilegedIOException (() -> storage .writer (blobInfo ));
208
- Streams .copy (inputStream , Channels .newOutputStream (new WritableByteChannel () {
209
- @ Override
210
- public boolean isOpen () {
211
- return writeChannel .isOpen ();
212
- }
211
+ try {
212
+ final WriteChannel writeChannel = SocketAccess .doPrivilegedIOException (
213
+ () -> storage .writer (blobInfo , Storage .BlobWriteOption .doesNotExist ()));
214
+ Streams .copy (inputStream , Channels .newOutputStream (new WritableByteChannel () {
215
+ @ Override
216
+ public boolean isOpen () {
217
+ return writeChannel .isOpen ();
218
+ }
213
219
214
- @ Override
215
- public void close () throws IOException {
216
- SocketAccess .doPrivilegedVoidIOException (writeChannel ::close );
217
- }
220
+ @ Override
221
+ public void close () throws IOException {
222
+ SocketAccess .doPrivilegedVoidIOException (writeChannel ::close );
223
+ }
218
224
219
- @ SuppressForbidden (reason = "Channel is based of a socket not a file" )
220
- @ Override
221
- public int write (ByteBuffer src ) throws IOException {
222
- return SocketAccess .doPrivilegedIOException (() -> writeChannel .write (src ));
225
+ @ SuppressForbidden (reason = "Channel is based of a socket not a file" )
226
+ @ Override
227
+ public int write (ByteBuffer src ) throws IOException {
228
+ return SocketAccess .doPrivilegedIOException (() -> writeChannel .write (src ));
229
+ }
230
+ }));
231
+ } catch (StorageException se ) {
232
+ if (se .getCode () == HTTP_PRECON_FAILED ) {
233
+ throw new FileAlreadyExistsException (blobInfo .getBlobId ().getName (), null , se .getMessage ());
223
234
}
224
- }));
235
+ throw se ;
236
+ }
225
237
}
226
238
227
239
/**
@@ -238,7 +250,17 @@ private void writeBlobMultipart(BlobInfo blobInfo, InputStream inputStream, long
238
250
assert blobSize <= LARGE_BLOB_THRESHOLD_BYTE_SIZE : "large blob uploads should use the resumable upload method" ;
239
251
final ByteArrayOutputStream baos = new ByteArrayOutputStream (Math .toIntExact (blobSize ));
240
252
Streams .copy (inputStream , baos );
241
- SocketAccess .doPrivilegedVoidIOException (() -> storage .create (blobInfo , baos .toByteArray ()));
253
+ SocketAccess .doPrivilegedVoidIOException (
254
+ () -> {
255
+ try {
256
+ storage .create (blobInfo , baos .toByteArray (), Storage .BlobTargetOption .doesNotExist ());
257
+ } catch (StorageException se ) {
258
+ if (se .getCode () == HTTP_PRECON_FAILED ) {
259
+ throw new FileAlreadyExistsException (blobInfo .getBlobId ().getName (), null , se .getMessage ());
260
+ }
261
+ throw se ;
262
+ }
263
+ });
242
264
}
243
265
244
266
/**
@@ -295,8 +317,8 @@ void deleteBlobs(Collection<String> blobNames) throws IOException {
295
317
/**
296
318
* Moves a blob within the same bucket
297
319
*
298
- * @param sourceBlob name of the blob to move
299
- * @param targetBlob new name of the blob in the same bucket
320
+ * @param sourceBlobName name of the blob to move
321
+ * @param targetBlobName new name of the blob in the same bucket
300
322
*/
301
323
void moveBlob (String sourceBlobName , String targetBlobName ) throws IOException {
302
324
final BlobId sourceBlobId = BlobId .of (bucket , sourceBlobName );
0 commit comments