Skip to content

Commit 6d18e3b

Browse files
committed
新增单线程断点接口
1 parent 24730f1 commit 6d18e3b

File tree

12 files changed

+489
-16
lines changed

12 files changed

+489
-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 进行对象的高级上传
@@ -258,9 +259,22 @@ void AsyncPutObjectDemo(qcloud_cos::CosAPI& cos) {
258259
/*
259260
* 该 Demo 示范用户如何自行组合分块上传各接口进行对象上传
260261
* 分块操作基于初始化、上传分块、完成分块三个接口可以实现将对象切分为多个分块,然后再将这些分块上传到 cos,最后发起 Complete 完成分块上传
261-
* 与本节中的高级上传接口配置一样,可通过全局设置上传线程池大小、分块大小。该上传线程池上是每次上传独立的。
262262
* 本 Demo 中的上传分块接口 UploadPartData 仅支持传入流,最多支持10000分块,每个分块大小为1MB - 5GB,最后一个分块可以小于1MB
263263
*/
264+
265+
int SslCtxCallback(void *ssl_ctx, void *data) {
266+
std::cout << "ssl_ctx: " << ssl_ctx << " data: " << data << std::endl;
267+
268+
SSL_CTX *ctx = (SSL_CTX *)ssl_ctx;
269+
std::cout << "ssl_ctx in" << std::endl;
270+
SSL_CTX_use_PrivateKey_file(ctx, "/data/cert/client_key.key", SSL_FILETYPE_PEM);
271+
SSL_CTX_use_certificate_chain_file(ctx, "/data/cert/client_cert.cer");
272+
std::cout << "ssl_ctx out" << std::endl;
273+
274+
return 0;
275+
}
276+
277+
264278
void PutPartDemo(qcloud_cos::CosAPI& cos) {
265279
std::string object_name = "big_file.txt";
266280

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

276290
// 2. UploadPartData
277291
// UploadPartData 部分,可以根据实际选择分块数量和分块大小,这里以 2 个分块为例
292+
293+
// Complete 需要的两个列表:
278294
std::vector<std::string> etags;
279295
std::vector<uint64_t> part_numbers;
296+
280297
std::string upload_id = init_resp.GetUploadId();
281298
{
282299
uint64_t part_number = 1;
283-
// 模拟上传分块数据,这里以 1M 为例
284-
std::vector<char> data(1024 * 1024, 'A');
300+
// 模拟上传分块数据,这里以 100M 为例
301+
uint64_t copy_size = 1024 * 1024 * 100;
302+
std::vector<char> data(copy_size, 'A');
285303
std::string content(data.begin(), data.end());
286304
std::istringstream iss(content);
287305
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
288306
req.SetPartNumber(part_number);
307+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
308+
uint64_t traffic_limit = 8192*1024*10; // 100MB 文件 5M
309+
req.SetTrafficLimit(traffic_limit);
289310
qcloud_cos::UploadPartDataResp resp;
311+
std::chrono::time_point<std::chrono::steady_clock> start_ts, end_ts;
312+
start_ts = std::chrono::steady_clock::now();
290313
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
314+
end_ts = std::chrono::steady_clock::now();
315+
auto time_consumed_ms =
316+
std::chrono::duration_cast<std::chrono::milliseconds>(end_ts - start_ts)
317+
.count();
318+
float rate =
319+
((float)copy_size / 1024 / 1024) / ((float)time_consumed_ms / 1000);
320+
SDK_LOG_ERR("send part_number: %d, send_size: %" PRIu64 " MB, time_consumed: %" PRIu64
321+
" 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);
291322
std::cout << "==================UploadPartDataResp1=====================" << std::endl;
292323
PrintResult(result, resp);
293324
std::cout << "==========================================================" << std::endl;
@@ -298,12 +329,38 @@ void PutPartDemo(qcloud_cos::CosAPI& cos) {
298329
}
299330
{
300331
uint64_t part_number = 2;
301-
std::istringstream iss("The last part can be smaller than 1MB");
332+
uint64_t copy_size = 1024 * 1024 * 100;
333+
std::vector<char> data(copy_size, 'A');
334+
std::string content(data.begin(), data.end());
335+
std::istringstream iss(content);
302336
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
303337
req.SetPartNumber(part_number);
338+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
339+
uint64_t traffic_limit = 8192 * 1024 * 5 ;
340+
req.SetTrafficLimit(traffic_limit);
341+
qcloud_cos::UploadPartDataResp resp;
342+
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
343+
std::cout << "==================UploadPartDataResp2=====================" << std::endl;
344+
PrintResult(result, resp);
345+
std::cout << "==========================================================" << std::endl;
346+
if (result.IsSucc()) {
347+
part_numbers.push_back(part_number);
348+
etags.push_back(resp.GetEtag());
349+
}
350+
}
351+
{
352+
uint64_t part_number = 3;
353+
uint64_t copy_size = 1024 * 1024 * 10;
354+
std::vector<char> data(copy_size, 'A');
355+
std::string content(data.begin(), data.end());
356+
std::istringstream iss(content);
357+
qcloud_cos::UploadPartDataReq req(bucket_name, object_name, upload_id, iss);
358+
req.SetPartNumber(part_number);
359+
// 限速上传对象,默认单位为 bit/s,限速值设置范围为 819200 - 838860800, 即800Kb/s-800Mb/s
360+
uint64_t traffic_limit = 8192 * 1024;
361+
req.SetTrafficLimit(traffic_limit);
304362
qcloud_cos::UploadPartDataResp resp;
305363
qcloud_cos::CosResult result = cos.UploadPartData(req, &resp);
306-
307364
std::cout << "==================UploadPartDataResp2=====================" << std::endl;
308365
PrintResult(result, resp);
309366
std::cout << "==========================================================" << std::endl;
@@ -328,11 +385,51 @@ void PutPartDemo(qcloud_cos::CosAPI& cos) {
328385

329386
return;
330387
}
388+
void PutObjectResumableSingleThreadSyncDemo(qcloud_cos::CosAPI& cos) {
389+
std::string local_file = "SingleThreadSync.txt";
390+
std::string object_name = "SingleThreadSync.txt";
391+
392+
qcloud_cos::PutObjectResumableSingleSyncReq req(bucket_name, object_name, local_file);
393+
req.SetHttps();
394+
req.AddHeader("x-cos-meta-ssss1","1xxxxxxx");
395+
req.AddHeader("x-cos-meta-ssss2","2xxxxxxx");
396+
req.AddHeader("x-cos-meta-ssss3","3xxxxxxx");
397+
req.AddHeader("x-cos-meta-ssss4","4xxxxxxx");
398+
uint64_t traffic_limit = 8192 * 1024;//1MB
399+
req.SetTrafficLimit(traffic_limit);
400+
req.SetCheckCRC64(true);
401+
qcloud_cos::PutObjectResumableSingleSyncResp resp;
402+
std::chrono::time_point<std::chrono::steady_clock> start_ts, end_ts;
403+
start_ts = std::chrono::steady_clock::now();
404+
qcloud_cos::CosResult result = cos.PutObjectResumableSingleThreadSync(req, &resp);
405+
end_ts = std::chrono::steady_clock::now();
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)