In the future we should move away from this behavior, and only create an object if write is
+ * called.
+ */
+ protected boolean writeCalledAtLeastOnce;
+
+ protected BaseStorageWriteChannel(Decoder In the future we should move away from this behavior, and only create an object if write is
- * called.
- */
- private boolean writeCalledAtLeastOnce = false;
+ private final ClientStreamingCallable A "Resumable" upload will sync the transmitted data with GCS upon each individual flush and
+ * when the channel is closed.
+ *
+ * If an error is returned the individual flush can be transparently retried.
+ */
+ ResumableUploadBuilder resumable() {
+ return new ResumableUploadBuilder(httpClientContext);
+ }
+
+ static final class ResumableUploadBuilder {
+
+ @NonNull private final HttpClientContext httpClientContext;
+ private RetryingDependencies deps;
+ private ResultRetryAlgorithm> alg;
+ private LongConsumer committedBytesCallback;
+
+ ResumableUploadBuilder(@NonNull HttpClientContext httpClientContext) {
+ this.httpClientContext = httpClientContext;
+ this.deps = RetryingDependencies.attemptOnce();
+ this.alg = Retrying.neverRetry();
+ this.committedBytesCallback = l -> {};
+ }
+
+ ResumableUploadBuilder setCommittedBytesCallback(@NonNull LongConsumer committedBytesCallback) {
+ this.committedBytesCallback =
+ requireNonNull(committedBytesCallback, "committedBytesCallback must be non null");
+ return this;
+ }
+
+ ResumableUploadBuilder withRetryConfig(
+ @NonNull RetryingDependencies deps, @NonNull ResultRetryAlgorithm> alg) {
+ this.deps = requireNonNull(deps, "deps must be non null");
+ this.alg = requireNonNull(alg, "alg must be non null");
+ return this;
+ }
+
+ /**
+ * Do not apply any intermediate buffering. Any call to {@link
+ * java.nio.channels.WritableByteChannel#write(ByteBuffer)} will be segmented as is and sent to
+ * GCS.
+ *
+ * Note: this is considered an advanced API, and should not be used in circumstances in which
+ * control of {@link ByteBuffer}s sent to {@code write} is not self-contained.
+ */
+ UnbufferedResumableUploadBuilder unbuffered() {
+ return new UnbufferedResumableUploadBuilder();
+ }
+
+ /** Buffer up to {@link #DEFAULT_BUFFER_CAPACITY} worth of bytes before attempting to flush */
+ BufferedResumableUploadBuilder buffered() {
+ return buffered(BufferHandle.allocate(DEFAULT_BUFFER_CAPACITY));
+ }
+
+ /**
+ * Buffer using {@code byteBuffer} worth of space before attempting to flush.
+ *
+ * The provided {@link ByteBuffer} should be aligned with GCSs block size of 256
+ * KiB.
+ */
+ BufferedResumableUploadBuilder buffered(ByteBuffer byteBuffer) {
+ return buffered(BufferHandle.handleOf(byteBuffer));
+ }
+
+ BufferedResumableUploadBuilder buffered(BufferHandle bufferHandle) {
+ return new BufferedResumableUploadBuilder(bufferHandle);
+ }
+
+ /**
+ * When constructing any of our channel sessions, there is always a {@link
+ * GapicUnbufferedWritableByteChannel} at the bottom of it. This method creates a BiFunction
+ * which will instantiate the {@link GapicUnbufferedWritableByteChannel} when provided with a
+ * {@code StartT} value and a {@code SettableApiFuture As part of providing the function, the provided parameters {@code FlusherFactory} and
+ * {@code f} are "bound" into the returned function. In conjunction with the configured fields
+ * of this class a new instance of {@link GapicUnbufferedWritableByteChannel} can be
+ * constructed.
+ */
+ private BiFunction<
+ JsonResumableWrite, SettableApiFuture