Skip to content

Commit f43d335

Browse files
authored
Merge pull request #237 from tencentyun/dev/checkPointUpload
upload part preflight
2 parents 54d290d + 9005517 commit f43d335

File tree

4 files changed

+78
-2
lines changed

4 files changed

+78
-2
lines changed

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<modelVersion>4.0.0</modelVersion>
55
<groupId>com.qcloud</groupId>
66
<artifactId>cos_api</artifactId>
7-
<version>5.6.244</version>
7+
<version>5.6.244.2</version>
88
<packaging>jar</packaging>
99
<name>cos-java-sdk</name>
1010
<description>java sdk for qcloud cos</description>

src/main/java/com/qcloud/cos/COSClient.java

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public class COSClient implements COS {
166166

167167
private CosHttpClient cosHttpClient;
168168

169-
private ConcurrentHashMap<String, Long> preflightBuckets = new ConcurrentHashMap<>();
169+
private static ConcurrentHashMap<String, Long> preflightBuckets = new ConcurrentHashMap<>();
170170

171171
public COSClient(COSCredentials cred, ClientConfig clientConfig) {
172172
this(new COSStaticCredentialsProvider(cred), clientConfig);
@@ -1699,6 +1699,18 @@ public UploadPartResult uploadPart(UploadPartRequest uploadPartRequest)
16991699
rejectNull(partSize, "The part size parameter must be specified when uploading a part");
17001700
rejectNull(clientConfig.getRegion(),
17011701
"region is null, region in clientConfig must be specified when uploading a part");
1702+
1703+
try {
1704+
preflightObj(uploadPartRequest);
1705+
} catch (CosServiceException cse) {
1706+
String msg = String.format("fail to do the preflight request due to the service exception[statusCode:%s, requestId:%s], will not do the upload part request", cse.getStatusCode(), cse.getRequestId());
1707+
log.warn(msg);
1708+
throw cse;
1709+
} catch (CosClientException cce) {
1710+
log.warn("fail to do the preflight request due to the client exception, will not do the upload part request", cce);
1711+
throw cce;
1712+
}
1713+
17021714
CosHttpRequest<UploadPartRequest> request =
17031715
createRequest(bucketName, key, uploadPartRequest, HttpMethodName.PUT);
17041716
request.addParameter("uploadId", uploadId);
@@ -1762,6 +1774,21 @@ private UploadPartResult doUploadPart(final String bucketName, final String key,
17621774
ObjectMetadata metadata = invoke(request, new CosMetadataResponseHandler());
17631775
final String etag = metadata.getETag();
17641776

1777+
if (metadata.isNeedPreflight()) {
1778+
Long currentTime = System.currentTimeMillis();
1779+
if ((preflightBuckets.get(bucketName) == null) || ((currentTime - preflightBuckets.get(bucketName)) > clientConfig.getPreflightStatusUpdateInterval())) {
1780+
String reqMsg = String.format("will update preflight status, bucket[%s]", bucketName);
1781+
log.info(reqMsg);
1782+
preflightBuckets.put(bucketName, currentTime);
1783+
}
1784+
} else {
1785+
Long currentTime = System.currentTimeMillis();
1786+
if ((preflightBuckets.get(bucketName) != null) && ((currentTime - preflightBuckets.get(bucketName)) > clientConfig.getPreflightStatusUpdateInterval())) {
1787+
String reqMsg = String.format("will remove bucket[%s] from preflight lists", bucketName);
1788+
log.info(reqMsg);
1789+
preflightBuckets.remove(bucketName);
1790+
}
1791+
}
17651792

17661793
if (md5DigestStream != null && !skipMd5CheckStrategy
17671794
.skipClientSideValidationPerUploadPartResponse(metadata)) {
@@ -5576,5 +5603,37 @@ private void preflightObj(PutObjectRequest putObjectRequest) throws CosClientExc
55765603
invoke(request, voidCosResponseHandler);
55775604
}
55785605
}
5606+
5607+
private void preflightObj(UploadPartRequest uploadPartRequest) throws CosClientException, CosServiceException {
5608+
String bucketName = uploadPartRequest.getBucketName();
5609+
String key = uploadPartRequest.getKey();
5610+
rejectEmpty(bucketName,
5611+
"The bucket name parameter must be specified when doing preflight request");
5612+
rejectEmpty(key,
5613+
"The key parameter must be specified when doing preflight request");
5614+
if (clientConfig.isCheckPreflightStatus() && preflightBuckets.containsKey(bucketName)) {
5615+
String reqMsg = String.format("will do preflight request for upload part object[%s] to the bucket[%s]", key, bucketName);
5616+
log.debug(reqMsg);
5617+
uploadPartRequest.setHasDonePreflight(true);
5618+
CosServiceRequest serviceRequest = new CosServiceRequest();
5619+
Map<String, String> customHeaders = uploadPartRequest.getCustomRequestHeaders();
5620+
if (customHeaders != null) {
5621+
for (Map.Entry<String, String> e : customHeaders.entrySet()) {
5622+
serviceRequest.putCustomRequestHeader(e.getKey(), e.getValue());
5623+
}
5624+
}
5625+
CosHttpRequest<CosServiceRequest> request = createRequest(bucketName, key, serviceRequest, HttpMethodName.HEAD);
5626+
if (uploadPartRequest.getFixedEndpointAddr() != null) {
5627+
request.setEndpoint(uploadPartRequest.getFixedEndpointAddr());
5628+
}
5629+
request.addParameter("preflight", null);
5630+
ObjectMetadata metadata = uploadPartRequest.getObjectMetadata();
5631+
if (metadata != null) {
5632+
populateRequestMetadata(request, metadata);
5633+
}
5634+
request.addHeader("x-cos-next-action", "UploadPart");
5635+
invoke(request, voidCosResponseHandler);
5636+
}
5637+
}
55795638
}
55805639

src/main/java/com/qcloud/cos/model/UploadPartRequest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ public class UploadPartRequest extends CosServiceRequest implements SSECustomerK
9999
*/
100100
private SSECustomerKey sseCustomerKey;
101101

102+
private boolean hasDonePreflight = false;
102103

103104
/**
104105
* Sets the stream containing the data to upload for the new part.
@@ -583,4 +584,12 @@ public int getTrafficLimit() {
583584
public void setTrafficLimit(int trafficLimit) {
584585
this.trafficLimit = trafficLimit;
585586
}
587+
588+
public boolean hasDonePreflight() {
589+
return hasDonePreflight;
590+
}
591+
592+
public void setHasDonePreflight(boolean hasDonePreflight) {
593+
this.hasDonePreflight = hasDonePreflight;
594+
}
586595
}

src/main/java/com/qcloud/cos/retry/PredefinedRetryPolicies.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.qcloud.cos.internal.CosServiceRequest;
2626

2727
import com.qcloud.cos.model.PutObjectRequest;
28+
import com.qcloud.cos.model.UploadPartRequest;
2829
import org.apache.http.HttpResponse;
2930
import org.apache.http.client.CircularRedirectException;
3031
import org.slf4j.Logger;
@@ -74,6 +75,13 @@ public <X extends CosServiceRequest> boolean shouldRetry(CosHttpRequest<X> reque
7475
}
7576
}
7677

78+
if (!isRetryAfterPreflight() && request.getOriginalRequest() != null && request.getOriginalRequest() instanceof UploadPartRequest && ((UploadPartRequest) request.getOriginalRequest()).hasDonePreflight()) {
79+
if (((CosServiceException) exception).getStatusCode() == 503 && Objects.equals(((CosServiceException) exception).getErrorCode(), "SlowDown")) {
80+
log.info("will not retry for 503 while upload part, because preflight request has been done");
81+
return false;
82+
}
83+
}
84+
7785
return true;
7886
}
7987

0 commit comments

Comments
 (0)