Skip to content

Commit a217ec6

Browse files
committed
Merge branch 'dev/demo_optimized' into 'master' (merge request !45)
dev/demo_optimized 新增单线程断点接口
2 parents bd1f35c + e8e642e commit a217ec6

File tree

13 files changed

+556
-16
lines changed

13 files changed

+556
-16
lines changed

demo/object_op_demo/multi_put_object_demo.cpp

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "cos_api.h"
99
#include "cos_sys_config.h"
1010
#include "util/auth_tool.h"
11+
#include <openssl/ssl.h>
1112

1213
/**
1314
* 本样例演示了如何使用 COS C++ SDK 进行对象的高级上传
@@ -47,6 +48,8 @@ void PrintResult(const qcloud_cos::CosResult& result, const qcloud_cos::BaseResp
4748
qcloud_cos::CosAPI InitCosAPI() {
4849
qcloud_cos::CosConfig config(appid, tmp_secret_id, tmp_secret_key, region);
4950
config.SetTmpToken(tmp_token); // 推荐使用临时密钥初始化 CosAPI 对象, 如果您使用永久密钥初始化 CosAPI 对象,请注释
51+
config.SetDestDomain("xxxxx.xxxxx.com");
52+
config.SetDomainSameToHost(true);
5053
qcloud_cos::CosAPI cos_tmp(config);
5154
return cos_tmp;
5255
}
@@ -258,9 +261,22 @@ void AsyncPutObjectDemo(qcloud_cos::CosAPI& cos) {
258261
/*
259262
* 该 Demo 示范用户如何自行组合分块上传各接口进行对象上传
260263
* 分块操作基于初始化、上传分块、完成分块三个接口可以实现将对象切分为多个分块,然后再将这些分块上传到 cos,最后发起 Complete 完成分块上传
261-
* 与本节中的高级上传接口配置一样,可通过全局设置上传线程池大小、分块大小。该上传线程池上是每次上传独立的。
262264
* 本 Demo 中的上传分块接口 UploadPartData 仅支持传入流,最多支持10000分块,每个分块大小为1MB - 5GB,最后一个分块可以小于1MB
263265
*/
266+
267+
int SslCtxCallback(void *ssl_ctx, void *data) {
268+
std::cout << "ssl_ctx: " << ssl_ctx << " data: " << data << std::endl;
269+
270+
SSL_CTX *ctx = (SSL_CTX *)ssl_ctx;
271+
std::cout << "ssl_ctx in" << std::endl;
272+
SSL_CTX_use_PrivateKey_file(ctx, "/data/cert/client_key.key", SSL_FILETYPE_PEM);
273+
SSL_CTX_use_certificate_chain_file(ctx, "/data/cert/client_cert.cer");
274+
std::cout << "ssl_ctx out" << std::endl;
275+
276+
return 0;
277+
}
278+
279+
264280
void PutPartDemo(qcloud_cos::CosAPI& cos) {
265281
std::string object_name = "big_file.txt";
266282

@@ -275,19 +291,36 @@ void PutPartDemo(qcloud_cos::CosAPI& cos) {
275291

276292
// 2. UploadPartData
277293
// UploadPartData 部分,可以根据实际选择分块数量和分块大小,这里以 2 个分块为例
294+
295+
// Complete 需要的两个列表:
278296
std::vector<std::string> etags;
279297
std::vector<uint64_t> part_numbers;
298+
280299
std::string upload_id = init_resp.GetUploadId();
281300
{
282301
uint64_t part_number = 1;
283-
// 模拟上传分块数据,这里以 1M 为例
284-
std::vector<char> data(1024 * 1024, 'A');
302+
// 模拟上传分块数据,这里以 100M 为例
303+
uint64_t copy_size = 1024 * 1024 * 100;
304+
std::vector<char> data(copy_size, 'A');
285305
std::string content(data.begin(), data.end());
286306
std::istringstream iss(content);
287307
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
288308
req.SetPartNumber(part_number);
309+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
310+
uint64_t traffic_limit = 8192*1024*10; // 100MB 文件 5M
311+
req.SetTrafficLimit(traffic_limit);
289312
qcloud_cos::UploadPartDataResp resp;
313+
std::chrono::time_point<std::chrono::steady_clock> start_ts, end_ts;
314+
start_ts = std::chrono::steady_clock::now();
290315
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
316+
end_ts = std::chrono::steady_clock::now();
317+
auto time_consumed_ms =
318+
std::chrono::duration_cast<std::chrono::milliseconds>(end_ts - start_ts)
319+
.count();
320+
float rate =
321+
((float)copy_size / 1024 / 1024) / ((float)time_consumed_ms / 1000);
322+
SDK_LOG_ERR("send part_number: %d, send_size: %" PRIu64 " MB, time_consumed: %" PRIu64
323+
" ms, rate: %.2f MB/s , traffic_limit : %.2f MB", part_number, copy_size/ 1024 / 1024, time_consumed_ms, rate, traffic_limit/1024/1024/8.0);
291324
std::cout << "==================UploadPartDataResp1=====================" << std::endl;
292325
PrintResult(result, resp);
293326
std::cout << "==========================================================" << std::endl;
@@ -298,12 +331,38 @@ void PutPartDemo(qcloud_cos::CosAPI& cos) {
298331
}
299332
{
300333
uint64_t part_number = 2;
301-
std::istringstream iss("The last part can be smaller than 1MB");
334+
uint64_t copy_size = 1024 * 1024 * 100;
335+
std::vector<char> data(copy_size, 'A');
336+
std::string content(data.begin(), data.end());
337+
std::istringstream iss(content);
302338
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
303339
req.SetPartNumber(part_number);
340+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
341+
uint64_t traffic_limit = 8192 * 1024 * 5 ;
342+
req.SetTrafficLimit(traffic_limit);
343+
qcloud_cos::UploadPartDataResp resp;
344+
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
345+
std::cout << "==================UploadPartDataResp2=====================" << std::endl;
346+
PrintResult(result, resp);
347+
std::cout << "==========================================================" << std::endl;
348+
if (result.IsSucc()) {
349+
part_numbers.push_back(part_number);
350+
etags.push_back(resp.GetEtag());
351+
}
352+
}
353+
{
354+
uint64_t part_number = 3;
355+
uint64_t copy_size = 1024 * 1024 * 10;
356+
std::vector<char> data(copy_size, 'A');
357+
std::string content(data.begin(), data.end());
358+
std::istringstream iss(content);
359+
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
360+
req.SetPartNumber(part_number);
361+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
362+
uint64_t traffic_limit = 8192 * 1024;
363+
req.SetTrafficLimit(traffic_limit);
304364
qcloud_cos::UploadPartDataResp resp;
305365
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
306-
307366
std::cout << "==================UploadPartDataResp2=====================" << std::endl;
308367
PrintResult(result, resp);
309368
std::cout << "==========================================================" << std::endl;
@@ -328,11 +387,49 @@ void PutPartDemo(qcloud_cos::CosAPI& cos) {
328387

329388
return;
330389
}
390+
void PutObjectResumableSingleThreadSyncDemo(qcloud_cos::CosAPI& cos) {
391+
std::string local_file = "SingleThreadSync.txt";
392+
std::string object_name = "SingleThreadSync.txt";
393+
394+
qcloud_cos::PutObjectResumableSingleSyncReq req(bucket_name, object_name, local_file);
395+
req.SetHttps();
396+
req.AddHeader("x-cos-meta-ssss1","1xxxxxxx");
397+
req.AddHeader("x-cos-meta-ssss2","2xxxxxxx");
398+
req.AddHeader("x-cos-meta-ssss3","3xxxxxxx");
399+
req.AddHeader("x-cos-meta-ssss4","4xxxxxxx");
400+
uint64_t traffic_limit = 8192 * 1024;//1MB
401+
req.SetTrafficLimit(traffic_limit);
402+
req.SetCheckCRC64(true);
403+
req.SetSSLCtxCallback(SslCtxCallback, nullptr);
404+
qcloud_cos::PutObjectResumableSingleSyncResp resp;
405+
qcloud_cos::CosResult result = cos.PutObjectResumableSingleThreadSync(req, &resp);
406+
if (result.IsSucc()) {
407+
std::cout << "MultiUpload Succ." << std::endl;
408+
std::cout << resp.GetLocation() << std::endl;
409+
std::cout << resp.GetKey() << std::endl;
410+
std::cout << resp.GetBucket() << std::endl;
411+
std::cout << resp.GetEtag() << std::endl;
412+
} else {
413+
std::cout << "MultiUpload Fail." << std::endl;
414+
// 获取具体失败在哪一步
415+
std::string resp_tag = resp.GetRespTag();
416+
if ("Init" == resp_tag) {
417+
// print result
418+
} else if ("Upload" == resp_tag) {
419+
// print result
420+
} else if ("Complete" == resp_tag) {
421+
// print result
422+
}
423+
PrintResult(result, resp);
424+
}
425+
std::cout << "===========================================================" << std::endl;
426+
}
331427
int main() {
332428
qcloud_cos::CosAPI cos = InitCosAPI();
333429
CosSysConfig::SetLogLevel((LOG_LEVEL)COS_LOG_ERR);
334430
MultiUploadObjectDemo(cos);
335431
AsyncMultiPutObjectDemo(cos);
336432
AsyncPutObjectDemo(cos);
337433
PutPartDemo(cos);
338-
}
434+
PutObjectResumableSingleThreadSyncDemo(cos);
435+
}

include/cos_api.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ class CosAPI {
758758
CosResult MultiGetObject(const MultiGetObjectReq& req,
759759
MultiGetObjectResp* resp);
760760

761+
CosResult PutObjectResumableSingleThreadSync(const PutObjectResumableSingleSyncReq& req,
762+
PutObjectResumableSingleSyncResp* resp);
763+
761764
/* Resumable接口 */
762765

763766
/// \brief 封装了初始化分块上传、分块上传、完成分块上传三步,支持断点续传

include/cos_defines.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212

1313
namespace qcloud_cos {
1414

15-
#define COS_CPP_SDK_VERSON "v5.5.15"
15+
#define COS_CPP_SDK_VERSON "v5.5.16"
1616

1717
/// 路径分隔符
1818
const char kPathDelimiter[] = "/";

include/op/object_op.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,12 @@ class ObjectOp : public BaseOp {
180180
const SharedTransferHandler& handler = nullptr,
181181
bool change_backup_domain = false);
182182

183+
/// \brief 单线程同步分块上传
184+
///
185+
/// \return result
186+
CosResult UploadObjectResumableSingleThreadSync(const PutObjectByFileReq& req,
187+
PutObjectResumableSingleSyncResp* resp);
188+
183189
/// \brief 舍弃一个分块上传并删除已上传的块
184190
///
185191
/// \param req AbortMultiUpload请求
@@ -427,6 +433,11 @@ class ObjectOp : public BaseOp {
427433
const SharedTransferHandler& handler = nullptr,
428434
bool change_backup_domain = false);
429435

436+
CosResult SingleThreadUpload(const PutObjectByFileReq& req, const std::string& upload_id,
437+
const std::vector<std::string>& already_exist_parts,
438+
bool resume_flag, std::vector<std::string>* etags_ptr,
439+
std::vector<uint64_t>* part_numbers_ptr, PutObjectByFileResp* resp);
440+
430441
/// \brief 读取文件内容, 并返回读取的长度
431442
// uint64_t GetContent(const std::string& src, std::string* file_content) const;
432443

include/request/object_req.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1722,6 +1722,17 @@ class MultiGetObjectReq : public GetObjectByFileReq {
17221722
virtual ~MultiGetObjectReq() {}
17231723
};
17241724

1725+
class PutObjectResumableSingleSyncReq : public PutObjectByFileReq {
1726+
public:
1727+
PutObjectResumableSingleSyncReq(const std::string& bucket_name,
1728+
const std::string& object_name,
1729+
const std::string& local_file_path)
1730+
: PutObjectByFileReq(bucket_name, object_name, local_file_path) {
1731+
SetCheckCRC64(true);
1732+
}
1733+
virtual ~PutObjectResumableSingleSyncReq() {}
1734+
};
1735+
17251736
/* Async接口 */
17261737

17271738
#if 0

include/response/object_resp.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,41 @@ class MultiGetObjectResp : public GetObjectByFileResp {
670670
~MultiGetObjectResp() {}
671671
};
672672

673+
class PutObjectResumableSingleSyncResp : public GetObjectByFileResp {
674+
public:
675+
PutObjectResumableSingleSyncResp() {}
676+
677+
virtual ~PutObjectResumableSingleSyncResp() {}
678+
679+
std::string GetRespTag() { return m_resp_tag; }
680+
681+
std::string GetLocation() const { return m_location; }
682+
683+
std::string GetKey() const { return m_key; }
684+
685+
std::string GetBucket() const { return m_bucket; }
686+
687+
void CopyFrom(const InitMultiUploadResp& resp);
688+
689+
void CopyFrom(const PutObjectByFileResp& resp);
690+
691+
void CopyFrom(const CompleteMultiUploadResp& resp);
692+
693+
/// \brief Server端加密使用的算法
694+
std::string GetXCosServerSideEncryption() const {
695+
return GetHeader("x-cos-server-side-encryption");
696+
}
697+
698+
private:
699+
std::string m_location; // Object的外网访问域名
700+
std::string m_bucket;
701+
std::string m_key;
702+
std::string m_upload_id;
703+
704+
// FIXME(sevenyou) 先这么搞吧
705+
std::string m_resp_tag; // 用于区分是哪一种response
706+
};
707+
673708
/* Async接口 */
674709

675710
//typedef PutObjectByFileResp PutObjectAsyncResp;

src/cos_api.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,11 @@ CosResult CosAPI::MultiPutObject(const MultiPutObjectReq& req,
586586
return result;
587587
}
588588

589+
CosResult CosAPI::PutObjectResumableSingleThreadSync(const PutObjectResumableSingleSyncReq& req,
590+
PutObjectResumableSingleSyncResp* resp){
591+
return m_object_op.UploadObjectResumableSingleThreadSync(static_cast<PutObjectByFileReq>(req), resp);
592+
}
593+
589594
CosResult CosAPI::AbortMultiUpload(const AbortMultiUploadReq& req,
590595
AbortMultiUploadResp* resp) {
591596
CosResult result = m_object_op.AbortMultiUpload(req, resp);

0 commit comments

Comments
 (0)