Source:
<code>private Object doResumableUpload() throws IOException { if (retriesAttempted >= UPLOAD_RETRIES) { throw new IOException( String.format("Too many retry attempts. Resumable upload failed for '%s'", resourceId)); } uploadId = startResumableUpload(); InsertChunkResponseObserver responseObserver; long writeOffset = retriesAttempted > 0 ? getCommittedWriteSize(uploadId) : 0; objectHasher = retriesAttempted > 0 ? objectHasher : Hashing.crc32c().newHasher(); responseObserver = new InsertChunkResponseObserver(uploadId, writeOffset); StreamObserver<InsertObjectRequest> requestStreamObserver = stub.withDeadlineAfter(WRITE_STREAM_TIMEOUT.toMillis(), MILLISECONDS) .insertObject(responseObserver); boolean objectFinalized = false; while (!objectFinalized) { InsertObjectRequest insertRequest; if (dataChunkMap.size() > 0 && dataChunkMap.lastKey() >= writeOffset) { insertRequest = buildRequestFromBufferedDataChunk(dataChunkMap, writeOffset); writeOffset += insertRequest.getChecksummedData().getContent().size(); } else { ByteString data = ByteString.readFrom(ByteStreams.limit(pipeSource, MAX_BYTES_PER_MESSAGE)); dataChunkMap.put(writeOffset, data); if (dataChunkMap.size() >= NUMBER_OF_REQUESTS_TO_RETAIN) { dataChunkMap.remove(dataChunkMap.firstKey()); } insertRequest = buildInsertRequest(writeOffset, data, false); writeOffset += data.size(); } requestStreamObserver.onNext(insertRequest); objectFinalized = insertRequest.getFinishWrite(); if (responseObserver.hasTransientError()) { retriesAttempted++; return doResumableUpload(); } } requestStreamObserver.onCompleted(); try { responseObserver.done.await(); if (responseObserver.hasTransientError()) { retriesAttempted++; <START> return doResumableUpload(); <END> } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException( String.format("Resumable upload failed for '%s'", getResourceString()), e); } return responseObserver.getResponseOrThrow(); }</code><technical_language>This is users recursion for retries, iteration instead - easier follow iterative code</technical_language>

Target:
private Object doResumableUpload() throws IOException { while (retriesAttempted++ < UPLOAD_RETRIES) { uploadId = startResumableUpload(); InsertChunkResponseObserver responseObserver; long writeOffset = retriesAttempted > 1 ? getCommittedWriteSize(uploadId) : 0; responseObserver = new InsertChunkResponseObserver(uploadId, writeOffset); StreamObserver<InsertObjectRequest> requestStreamObserver = stub.withDeadlineAfter(WRITE_STREAM_TIMEOUT.toMillis(), MILLISECONDS) .insertObject(responseObserver); boolean objectFinalized = false; while (!objectFinalized) { InsertObjectRequest insertRequest; if (dataChunkMap.size() > 0 && dataChunkMap.lastKey() >= writeOffset) { insertRequest = buildRequestFromBufferedDataChunk(dataChunkMap, writeOffset); writeOffset += insertRequest.getChecksummedData().getContent().size(); } else { ByteString data = ByteString.readFrom(ByteStreams.limit(pipeSource, MAX_BYTES_PER_MESSAGE)); dataChunkMap.put(writeOffset, data); if (dataChunkMap.size() >= NUMBER_OF_REQUESTS_TO_RETAIN) { dataChunkMap.remove(dataChunkMap.firstKey()); } insertRequest = buildInsertRequest(writeOffset, data, false); writeOffset += data.size(); } requestStreamObserver.onNext(insertRequest); objectFinalized = insertRequest.getFinishWrite(); if (responseObserver.hasTransientError()) { break; } } if (responseObserver.hasTransientError()) { continue; } requestStreamObserver.onCompleted(); try { responseObserver.done.await(); if (responseObserver.hasTransientError()) { continue; } } catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new IOException( String.format("Resumable upload failed for '%s'", getResourceString()), e); } return responseObserver.getResponseOrThrow(); } throw new IOException( String.format("Too many retry attempts. Resumable upload failed for '%s'", resourceId)); }