forked from caoXF/curve
448 lines
14 KiB
C++
448 lines
14 KiB
C++
/*
|
|
* Copyright (c) 2020 NetEase Inc.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
/*
|
|
* Project: curve
|
|
* File Created: Thursday, 16th May 2019 3:46:05 pm
|
|
* Author: tongguangxun
|
|
*/
|
|
|
|
#include <glog/logging.h>
|
|
|
|
#include <string>
|
|
#include <memory>
|
|
|
|
#include "curvesnapshot_python/libcurveSnapshot.h"
|
|
#include "src/client/libcurve_snapshot.h"
|
|
#include "src/client/client_config.h"
|
|
#include "include/client/libcurve.h"
|
|
#include "src/client/client_common.h"
|
|
#include "src/common/concurrent/concurrent.h"
|
|
|
|
using curve::client::UserInfo;
|
|
using curve::client::ClientConfig;
|
|
using curve::client::SnapshotClient;
|
|
using curve::client::SnapCloneClosure;
|
|
using curve::client::FileServiceOption;
|
|
using curve::client::ClientConfigOption;
|
|
using curve::common::Mutex;
|
|
using curve::common::ConditionVariable;
|
|
|
|
class TaskTracker {
|
|
public:
|
|
TaskTracker()
|
|
: concurrent_(0),
|
|
lastErr_(0) {}
|
|
|
|
/**
|
|
* @brief 增加一个追踪任务
|
|
*/
|
|
void AddOneTrace() {
|
|
concurrent_.fetch_add(1, std::memory_order_acq_rel);
|
|
}
|
|
|
|
/**
|
|
* @brief 获取任务数量
|
|
*
|
|
* @return 任务数量
|
|
*/
|
|
uint32_t GetTaskNum() const {
|
|
return concurrent_;
|
|
}
|
|
|
|
/**
|
|
* @brief 处理任务返回值
|
|
*
|
|
* @param retCode 返回值
|
|
*/
|
|
void HandleResponse(int retCode) {
|
|
if (retCode < 0) {
|
|
lastErr_ = retCode;
|
|
}
|
|
if (1 == concurrent_.fetch_sub(1, std::memory_order_acq_rel)) {
|
|
// 最后一次需拿锁再发信号,防止先发信号后等待导致死锁
|
|
std::unique_lock<Mutex> lk(cv_m);
|
|
cv_.notify_all();
|
|
} else {
|
|
cv_.notify_all();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief 等待追踪的所有任务完成
|
|
*/
|
|
void Wait() {
|
|
std::unique_lock<Mutex> lk(cv_m);
|
|
cv_.wait(lk, [this](){
|
|
return concurrent_.load(std::memory_order_acquire) == 0;});
|
|
}
|
|
|
|
/**
|
|
* @brief 获取最后一个错误
|
|
*
|
|
* @return 错误码
|
|
*/
|
|
int GetResult() {
|
|
return lastErr_;
|
|
}
|
|
|
|
private:
|
|
// 等待的条件变量
|
|
ConditionVariable cv_;
|
|
Mutex cv_m;
|
|
// 并发数量
|
|
std::atomic<uint32_t> concurrent_;
|
|
// 错误码
|
|
int lastErr_;
|
|
};
|
|
|
|
struct SnapCloneTestClosure : public SnapCloneClosure {
|
|
explicit SnapCloneTestClosure(std::shared_ptr<TaskTracker> tracker)
|
|
: tracker_(tracker) {}
|
|
void Run() {
|
|
std::unique_ptr<SnapCloneTestClosure> self_guard(this);
|
|
tracker_->HandleResponse(GetRetCode());
|
|
}
|
|
std::shared_ptr<TaskTracker> tracker_;
|
|
};
|
|
|
|
bool globalinited = false;
|
|
SnapshotClient* globalSnapshotclient = nullptr;
|
|
|
|
int Init(const char* path) {
|
|
if (globalinited) {
|
|
return 0;
|
|
}
|
|
|
|
ClientConfig cc;
|
|
if (-1 == cc.Init(path)) {
|
|
LOG(ERROR) << "config init failed!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
FileServiceOption fileopt = cc.GetFileServiceOption();
|
|
ClientConfigOption copt;
|
|
copt.loginfo = fileopt.loginfo;
|
|
copt.ioOpt = fileopt.ioOpt;
|
|
copt.metaServerOpt = fileopt.metaServerOpt;
|
|
|
|
if (globalSnapshotclient == nullptr) {
|
|
globalSnapshotclient = new SnapshotClient();
|
|
int ret = globalSnapshotclient->Init(copt);
|
|
globalinited = ret == 0 ? true : false;
|
|
}
|
|
|
|
return globalinited ? 0 : -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
void ChunkIDInfo2LocalInfo(CChunkIDInfo* localinfo,
|
|
const curve::client::ChunkIDInfo& idinfo) {
|
|
localinfo->cid_.value = idinfo.cid_;
|
|
localinfo->cpid_.value = idinfo.cpid_;
|
|
localinfo->lpid_.value = idinfo.lpid_;
|
|
}
|
|
|
|
void LocalInfo2ChunkIDInfo(const CChunkIDInfo& localinfo,
|
|
curve::client::ChunkIDInfo* idinfo) {
|
|
idinfo->cid_ = localinfo.cid_.value;
|
|
idinfo->cpid_ = localinfo.cpid_.value;
|
|
idinfo->lpid_ = localinfo.lpid_.value;
|
|
}
|
|
|
|
int CreateSnapShot(const char* filename,
|
|
const CUserInfo_t userinfo,
|
|
type_uInt64_t* seq) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
int ret = globalSnapshotclient->CreateSnapShot(
|
|
filename,
|
|
UserInfo(userinfo.owner, userinfo.password),
|
|
&seq->value);
|
|
LOG(INFO) << "create snapshot ret = " << ret
|
|
<< ", seq = " << seq->value;
|
|
return ret;
|
|
}
|
|
|
|
int DeleteSnapShot(const char* filename,
|
|
const CUserInfo_t userinfo,
|
|
type_uInt64_t seq) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
return globalSnapshotclient->DeleteSnapShot(filename,
|
|
UserInfo(userinfo.owner, userinfo.password),
|
|
seq.value);
|
|
}
|
|
|
|
int GetSnapShot(const char* filename, const CUserInfo_t userinfo,
|
|
type_uInt64_t seq, CFInfo_t* snapinfo) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
curve::client::FInfo_t fileinfo;
|
|
|
|
int ret = globalSnapshotclient->GetSnapShot(filename,
|
|
UserInfo(userinfo.owner, userinfo.password),
|
|
seq.value,
|
|
&fileinfo);
|
|
if (ret == LIBCURVE_ERROR::OK) {
|
|
snapinfo->id.value = fileinfo.id;
|
|
snapinfo->parentid.value = fileinfo.parentid;
|
|
snapinfo->filetype = static_cast<CFileType>(fileinfo.filetype);
|
|
snapinfo->chunksize.value = fileinfo.chunksize;
|
|
snapinfo->segmentsize.value = fileinfo.segmentsize;
|
|
snapinfo->length.value = fileinfo.length;
|
|
snapinfo->ctime.value = fileinfo.ctime;
|
|
snapinfo->seqnum.value = fileinfo.seqnum;
|
|
memset(snapinfo->owner, 0, 256);
|
|
memset(snapinfo->filename, 0, 256);
|
|
memcpy(snapinfo->owner, fileinfo.owner.c_str(), 256);
|
|
memcpy(snapinfo->filename, fileinfo.filename.c_str(), 256);
|
|
snapinfo->filestatus = static_cast<CFileStatus>(fileinfo.filestatus);
|
|
LOG(INFO) << "origin owner = " << fileinfo.owner;
|
|
LOG(INFO) << "origin filename = " << fileinfo.filename;
|
|
LOG(INFO) << "owner = " << snapinfo->owner;
|
|
LOG(INFO) << "filename = " << snapinfo->filename;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int GetSnapshotSegmentInfo(const char* filename,
|
|
const CUserInfo_t userinfo,
|
|
type_uInt64_t seq,
|
|
type_uInt64_t offset,
|
|
CSegmentInfo *segInfo) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::SegmentInfo seg;
|
|
int ret = globalSnapshotclient->GetSnapshotSegmentInfo(filename,
|
|
UserInfo(userinfo.owner, userinfo.password),
|
|
seq.value,
|
|
offset.value,
|
|
&seg);
|
|
if (ret == LIBCURVE_ERROR::OK) {
|
|
segInfo->segmentsize.value = seg.segmentsize;
|
|
segInfo->chunksize.value = seg.chunksize;
|
|
segInfo->startoffset.value = seg.startoffset;
|
|
segInfo->chunkVecSize.value = seg.chunkvec.size();
|
|
for (int i = 0; i < seg.chunkvec.size(); i++) {
|
|
CChunkIDInfo_t tempIDInfo;
|
|
ChunkIDInfo2LocalInfo(&tempIDInfo, seg.chunkvec[i]);
|
|
segInfo->chunkvec.push_back(tempIDInfo);
|
|
}
|
|
segInfo->lpcpIDInfo.lpid.value = seg.lpcpIDInfo.lpid;
|
|
segInfo->lpcpIDInfo.cpidVecSize.value = seg.lpcpIDInfo.cpidVec.size();
|
|
for (int i = 0; i < seg.lpcpIDInfo.cpidVec.size(); i++) {
|
|
segInfo->lpcpIDInfo.cpidVec.push_back(seg.lpcpIDInfo.cpidVec[i]);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int GetOrAllocateSegmentInfo(const char* filename,
|
|
type_uInt64_t offset,
|
|
type_uInt64_t segmentsize,
|
|
type_uInt64_t chunksize,
|
|
const CUserInfo_t userinfo,
|
|
CSegmentInfo *segInfo) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::FInfo_t fileinfo;
|
|
fileinfo.segmentsize = segmentsize.value;
|
|
fileinfo.chunksize = chunksize.value;
|
|
fileinfo.fullPathName = std::string(filename);
|
|
fileinfo.filename = std::string(filename);
|
|
fileinfo.userinfo = UserInfo(userinfo.owner, userinfo.password);
|
|
|
|
curve::client::SegmentInfo seg;
|
|
int ret = globalSnapshotclient->GetOrAllocateSegmentInfo(false,
|
|
offset.value,
|
|
&fileinfo,
|
|
&seg);
|
|
segInfo->segmentsize.value = seg.segmentsize;
|
|
segInfo->chunksize.value = seg.chunksize;
|
|
segInfo->startoffset.value = seg.startoffset;
|
|
segInfo->chunkVecSize.value = seg.chunkvec.size();
|
|
for (int i = 0; i < seg.chunkvec.size(); i++) {
|
|
CChunkIDInfo_t tempIDInfo;
|
|
ChunkIDInfo2LocalInfo(&tempIDInfo, seg.chunkvec[i]);
|
|
segInfo->chunkvec.push_back(tempIDInfo);
|
|
}
|
|
|
|
segInfo->lpcpIDInfo.lpid.value = seg.lpcpIDInfo.lpid;
|
|
segInfo->lpcpIDInfo.cpidVecSize.value = seg.lpcpIDInfo.cpidVec.size();
|
|
for (int i = 0; i < seg.lpcpIDInfo.cpidVec.size(); i++) {
|
|
segInfo->lpcpIDInfo.cpidVec.push_back(seg.lpcpIDInfo.cpidVec[i]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int ReadChunkSnapshot(CChunkIDInfo cidinfo,
|
|
type_uInt64_t seq,
|
|
type_uInt64_t offset,
|
|
type_uInt64_t len,
|
|
char *buf) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::ChunkIDInfo idinfo;
|
|
LocalInfo2ChunkIDInfo(cidinfo, &idinfo);
|
|
auto tracker = std::make_shared<TaskTracker>();
|
|
SnapCloneTestClosure *cb = new SnapCloneTestClosure(tracker);
|
|
|
|
tracker->AddOneTrace();
|
|
int ret = globalSnapshotclient->ReadChunkSnapshot(idinfo, seq.value,
|
|
offset.value, len.value,
|
|
buf, cb);
|
|
tracker->Wait();
|
|
if (ret < 0) {
|
|
return ret;
|
|
} else {
|
|
if (tracker->GetResult() < 0) {
|
|
return tracker->GetResult();
|
|
} else {
|
|
return len.value;
|
|
}
|
|
}
|
|
}
|
|
|
|
int DeleteChunkSnapshotOrCorrectSn(CChunkIDInfo cidinfo,
|
|
type_uInt64_t correctedSeq) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::ChunkIDInfo idinfo;
|
|
LocalInfo2ChunkIDInfo(cidinfo, &idinfo);
|
|
int ret = globalSnapshotclient->DeleteChunkSnapshotOrCorrectSn(idinfo,
|
|
correctedSeq.value);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int GetChunkInfo(CChunkIDInfo cidinfo, CChunkInfoDetail *chunkInfo) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::ChunkInfoDetail cinfodetail;
|
|
curve::client::ChunkIDInfo idinfo;
|
|
LocalInfo2ChunkIDInfo(cidinfo, &idinfo);
|
|
|
|
int ret = globalSnapshotclient->GetChunkInfo(idinfo, &cinfodetail);
|
|
chunkInfo->snSize.value = cinfodetail.chunkSn.size();
|
|
for (int i = 0; i < cinfodetail.chunkSn.size(); i++) {
|
|
chunkInfo->chunkSn.push_back(cinfodetail.chunkSn[i]);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
int CheckSnapShotStatus(const char* filename,
|
|
const CUserInfo_t userinfo,
|
|
type_uInt64_t seq,
|
|
type_uInt32_t* filestatus) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::FileStatus fs;
|
|
int ret = globalSnapshotclient->CheckSnapShotStatus(filename,
|
|
UserInfo(userinfo.owner, userinfo.password),
|
|
seq.value,
|
|
&fs);
|
|
filestatus->value = static_cast<uint32_t>(fs);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int CreateCloneChunk(const char* location,
|
|
const CChunkIDInfo chunkidinfo,
|
|
type_uInt64_t sn,
|
|
type_uInt64_t correntSn,
|
|
type_uInt64_t chunkSize) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
|
|
curve::client::ChunkIDInfo idinfo;
|
|
LocalInfo2ChunkIDInfo(chunkidinfo, &idinfo);
|
|
auto tracker = std::make_shared<TaskTracker>();
|
|
SnapCloneTestClosure *cb = new SnapCloneTestClosure(tracker);
|
|
|
|
tracker->AddOneTrace();
|
|
int ret = globalSnapshotclient->CreateCloneChunk(location, idinfo,
|
|
sn.value, correntSn.value,
|
|
chunkSize.value,
|
|
cb);
|
|
tracker->Wait();
|
|
if (ret < 0) {
|
|
return ret;
|
|
} else {
|
|
return tracker->GetResult();
|
|
}
|
|
}
|
|
|
|
|
|
int RecoverChunk(const CChunkIDInfo chunkidinfo,
|
|
type_uInt64_t offset,
|
|
type_uInt64_t len) {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return -LIBCURVE_ERROR::FAILED;
|
|
}
|
|
curve::client::ChunkIDInfo idinfo;
|
|
LocalInfo2ChunkIDInfo(chunkidinfo, &idinfo);
|
|
auto tracker = std::make_shared<TaskTracker>();
|
|
SnapCloneTestClosure *cb = new SnapCloneTestClosure(tracker);
|
|
|
|
tracker->AddOneTrace();
|
|
int ret = globalSnapshotclient->RecoverChunk(idinfo,
|
|
offset.value,
|
|
len.value,
|
|
cb);
|
|
tracker->Wait();
|
|
if (ret < 0) {
|
|
return ret;
|
|
} else {
|
|
return tracker->GetResult();
|
|
}
|
|
}
|
|
|
|
void UnInit() {
|
|
if (globalSnapshotclient == nullptr) {
|
|
LOG(ERROR) << "not init!";
|
|
return;
|
|
}
|
|
globalSnapshotclient->UnInit();
|
|
}
|