Skip to content

Commit 43460b9

Browse files
committed
Use StorageRpc.rewrite to implement Storage.copy
- rename BlobRewriter to CopyWriter - update Storage.copy and Blob.copyTo methods to use StorageRpc.openRewrite - update Blob and Storage unit and intergration tests - update StorageExample
1 parent 15372f1 commit 43460b9

File tree

9 files changed

+204
-379
lines changed

9 files changed

+204
-379
lines changed

gcloud-java-examples/src/main/java/com/google/gcloud/examples/StorageExample.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.gcloud.storage.BlobId;
2525
import com.google.gcloud.storage.BlobInfo;
2626
import com.google.gcloud.storage.BlobReadChannel;
27+
import com.google.gcloud.storage.CopyWriter;
2728
import com.google.gcloud.storage.BlobWriteChannel;
2829
import com.google.gcloud.storage.Bucket;
2930
import com.google.gcloud.storage.BucketInfo;
@@ -366,21 +367,25 @@ public String params() {
366367
private static class CopyAction extends StorageAction<CopyRequest> {
367368
@Override
368369
public void run(Storage storage, CopyRequest request) {
369-
BlobInfo copiedBlobInfo = storage.copy(request);
370-
System.out.println("Copied " + copiedBlobInfo);
370+
CopyWriter copyWriter = storage.copy(request);
371+
while (!copyWriter.isDone()) {
372+
copyWriter.copyChunk();
373+
}
374+
System.out.println("Copied " + copyWriter.result());
371375
}
372376

373377
@Override
374378
CopyRequest parse(String... args) {
375-
if (args.length != 4) {
379+
if (args.length != 5) {
376380
throw new IllegalArgumentException();
377381
}
378-
return CopyRequest.of(args[0], args[1], BlobInfo.builder(args[2], args[3]).build());
382+
return CopyRequest.of(args[0], args[1],
383+
BlobInfo.builder(args[2], args[3]).contentType(args[4]).build());
379384
}
380385

381386
@Override
382387
public String params() {
383-
return "<from_bucket> <from_path> <to_bucket> <to_path>";
388+
return "<from_bucket> <from_path> <to_bucket> <to_path> <to_content_type>";
384389
}
385390
}
386391

gcloud-java-storage/src/main/java/com/google/gcloud/storage/Blob.java

+17-14
Original file line numberDiff line numberDiff line change
@@ -213,19 +213,20 @@ public Blob update(BlobInfo blobInfo, BlobTargetOption... options) {
213213
}
214214

215215
/**
216-
* Copies this blob to the specified target. Possibly copying also some of the metadata
217-
* (e.g. content-type).
216+
* Sends a copy request for the current blob to the target blob. Possibly also some of the
217+
* metadata are copied (e.g. content-type).
218218
*
219219
* @param targetBlob target blob's id
220220
* @param options source blob options
221-
* @return the copied blob
221+
* @return a {@link CopyWriter} object that can be used to get information on the newly created
222+
* blob or to complete the copy if more than one RPC request is needed
222223
* @throws StorageException upon failure
223224
*/
224-
public Blob copyTo(BlobId targetBlob, BlobSourceOption... options) {
225+
public CopyWriter copyTo(BlobId targetBlob, BlobSourceOption... options) {
225226
BlobInfo updatedInfo = info.toBuilder().blobId(targetBlob).build();
226227
CopyRequest copyRequest = CopyRequest.builder().source(info.bucket(), info.name())
227228
.sourceOptions(convert(info, options)).target(updatedInfo).build();
228-
return new Blob(storage, storage.copy(copyRequest));
229+
return storage.copy(copyRequest);
229230
}
230231

231232
/**
@@ -240,33 +241,35 @@ public boolean delete(BlobSourceOption... options) {
240241
}
241242

242243
/**
243-
* Copies this blob to the target bucket, preserving its name. Possibly copying also some of the
244-
* metadata (e.g. content-type).
244+
* Sends a copy request for the current blob to the target bucket, preserving its name. Possibly
245+
* copying also some of the metadata (e.g. content-type).
245246
*
246247
* @param targetBucket target bucket's name
247248
* @param options source blob options
248-
* @return the copied blob
249+
* @return a {@link CopyWriter} object that can be used to get information on the newly created
250+
* blob or to complete the copy if more than one RPC request is needed
249251
* @throws StorageException upon failure
250252
*/
251-
public Blob copyTo(String targetBucket, BlobSourceOption... options) {
253+
public CopyWriter copyTo(String targetBucket, BlobSourceOption... options) {
252254
return copyTo(targetBucket, info.name(), options);
253255
}
254256

255257
/**
256-
* Copies this blob to the target bucket with a new name. Possibly copying also some of the
257-
* metadata (e.g. content-type).
258+
* Sends a copy request for the current blob to the target blob. Possibly also some of the
259+
* metadata are copied (e.g. content-type).
258260
*
259261
* @param targetBucket target bucket's name
260262
* @param targetBlob target blob's name
261263
* @param options source blob options
262-
* @return the copied blob
264+
* @return a {@link CopyWriter} object that can be used to get information on the newly created
265+
* blob or to complete the copy if more than one RPC request is needed
263266
* @throws StorageException upon failure
264267
*/
265-
public Blob copyTo(String targetBucket, String targetBlob, BlobSourceOption... options) {
268+
public CopyWriter copyTo(String targetBucket, String targetBlob, BlobSourceOption... options) {
266269
BlobInfo updatedInfo = info.toBuilder().blobId(BlobId.of(targetBucket, targetBlob)).build();
267270
CopyRequest copyRequest = CopyRequest.builder().source(info.bucket(), info.name())
268271
.sourceOptions(convert(info, options)).target(updatedInfo).build();
269-
return new Blob(storage, storage.copy(copyRequest));
272+
return storage.copy(copyRequest);
270273
}
271274

272275
/**

gcloud-java-storage/src/main/java/com/google/gcloud/storage/BlobRewriter.java renamed to gcloud-java-storage/src/main/java/com/google/gcloud/storage/CopyWriter.java

+25-20
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,20 @@
3232
import java.util.concurrent.Callable;
3333

3434
/**
35-
* Google Storage blob rewriter.
35+
* Google Storage blob copy writer. This class holds the result of a copy request.
36+
* If source and destination blobs do not share the same location or storage class more than one
37+
* RPC request is needed to copy the blob. When this is the case {@link #copyChunk()} can be used
38+
* to copy to destination other chunks of the source blob.
39+
*
40+
* @see <a href="https://cloud.google.com/storage/docs/json_api/v1/objects/rewrite">Rewrite</a>
3641
*/
37-
public final class BlobRewriter implements Restorable<BlobRewriter> {
42+
public class CopyWriter implements Restorable<CopyWriter> {
3843

3944
private final StorageOptions serviceOptions;
4045
private final StorageRpc storageRpc;
4146
private RewriteResponse rewriteResponse;
4247

43-
BlobRewriter(StorageOptions serviceOptions, RewriteResponse rewriteResponse) {
48+
CopyWriter(StorageOptions serviceOptions, RewriteResponse rewriteResponse) {
4449
this.serviceOptions = serviceOptions;
4550
this.rewriteResponse = rewriteResponse;
4651
this.storageRpc = serviceOptions.rpc();
@@ -69,14 +74,14 @@ public Boolean isDone() {
6974
}
7075

7176
/**
72-
* Returns the number of bytes written.
77+
* Returns the number of bytes copied.
7378
*/
74-
public Long totalBytesRewritten() {
79+
public Long totalBytesCopied() {
7580
return rewriteResponse.totalBytesRewritten;
7681
}
7782

7883
/**
79-
* Rewrite the next chunk of the blob. An RPC is issued only if rewrite has not finished yet
84+
* Copies the next chunk of the blob. An RPC is issued only if copy has not finished yet
8085
* ({@link #isDone} returns {@code false}).
8186
*
8287
* @throws StorageException upon failure
@@ -97,7 +102,7 @@ public RewriteResponse call() {
97102
}
98103

99104
@Override
100-
public RestorableState<BlobRewriter> capture() {
105+
public RestorableState<CopyWriter> capture() {
101106
return StateImpl.builder(
102107
serviceOptions,
103108
BlobId.fromPb(rewriteResponse.rewriteRequest.source),
@@ -108,11 +113,11 @@ public RestorableState<BlobRewriter> capture() {
108113
.isDone(isDone())
109114
.megabytesRewrittenPerCall(rewriteResponse.rewriteRequest.megabytesRewrittenPerCall)
110115
.rewriteToken(rewriteResponse.rewriteToken)
111-
.totalBytesRewritten(totalBytesRewritten())
116+
.totalBytesRewritten(totalBytesCopied())
112117
.build();
113118
}
114119

115-
static class StateImpl implements RestorableState<BlobRewriter>, Serializable {
120+
static class StateImpl implements RestorableState<CopyWriter>, Serializable {
116121

117122
private static final long serialVersionUID = 8279287678903181701L;
118123

@@ -125,7 +130,7 @@ static class StateImpl implements RestorableState<BlobRewriter>, Serializable {
125130
private final Long blobSize;
126131
private final Boolean isDone;
127132
private final String rewriteToken;
128-
private final Long totalBytesRewritten;
133+
private final Long totalBytesCopied;
129134
private final Long megabytesRewrittenPerCall;
130135

131136
StateImpl(Builder builder) {
@@ -138,7 +143,7 @@ static class StateImpl implements RestorableState<BlobRewriter>, Serializable {
138143
this.blobSize = builder.blobSize;
139144
this.isDone = builder.isDone;
140145
this.rewriteToken = builder.rewriteToken;
141-
this.totalBytesRewritten = builder.totalBytesRewritten;
146+
this.totalBytesCopied = builder.totalBytesCopied;
142147
this.megabytesRewrittenPerCall = builder.megabytesRewrittenPerCall;
143148
}
144149

@@ -153,7 +158,7 @@ static class Builder {
153158
private Long blobSize;
154159
private Boolean isDone;
155160
private String rewriteToken;
156-
private Long totalBytesRewritten;
161+
private Long totalBytesCopied;
157162
private Long megabytesRewrittenPerCall;
158163

159164
private Builder(StorageOptions options, BlobId source,
@@ -187,7 +192,7 @@ Builder rewriteToken(String rewriteToken) {
187192
}
188193

189194
Builder totalBytesRewritten(Long totalBytesRewritten) {
190-
this.totalBytesRewritten = totalBytesRewritten;
195+
this.totalBytesCopied = totalBytesRewritten;
191196
return this;
192197
}
193198

@@ -196,7 +201,7 @@ Builder megabytesRewrittenPerCall(Long megabytesRewrittenPerCall) {
196201
return this;
197202
}
198203

199-
RestorableState<BlobRewriter> build() {
204+
RestorableState<CopyWriter> build() {
200205
return new StateImpl(this);
201206
}
202207
}
@@ -208,19 +213,19 @@ static Builder builder(StorageOptions options, BlobId source,
208213
}
209214

210215
@Override
211-
public BlobRewriter restore() {
216+
public CopyWriter restore() {
212217
RewriteRequest rewriteRequest = new RewriteRequest(
213218
source.toPb(), sourceOptions, target.toPb(), targetOptions, megabytesRewrittenPerCall);
214219
RewriteResponse rewriteResponse = new RewriteResponse(rewriteRequest,
215220
result != null ? result.toPb() : null, blobSize, isDone, rewriteToken,
216-
totalBytesRewritten);
217-
return new BlobRewriter(serviceOptions, rewriteResponse);
221+
totalBytesCopied);
222+
return new CopyWriter(serviceOptions, rewriteResponse);
218223
}
219224

220225
@Override
221226
public int hashCode() {
222227
return Objects.hash(serviceOptions, source, sourceOptions, target, targetOptions, result,
223-
blobSize, isDone, megabytesRewrittenPerCall, rewriteToken, totalBytesRewritten);
228+
blobSize, isDone, megabytesRewrittenPerCall, rewriteToken, totalBytesCopied);
224229
}
225230

226231
@Override
@@ -242,7 +247,7 @@ public boolean equals(Object obj) {
242247
&& Objects.equals(this.blobSize, other.blobSize)
243248
&& Objects.equals(this.isDone, other.isDone)
244249
&& Objects.equals(this.megabytesRewrittenPerCall, other.megabytesRewrittenPerCall)
245-
&& Objects.equals(this.totalBytesRewritten, other.totalBytesRewritten);
250+
&& Objects.equals(this.totalBytesCopied, other.totalBytesCopied);
246251
}
247252

248253
@Override
@@ -251,7 +256,7 @@ public String toString() {
251256
.add("source", source)
252257
.add("target", target)
253258
.add("isDone", isDone)
254-
.add("totalBytesRewritten", totalBytesRewritten)
259+
.add("totalBytesRewritten", totalBytesCopied)
255260
.add("blobSize", blobSize)
256261
.toString();
257262
}

0 commit comments

Comments
 (0)