* Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
* ubs-io is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
#include "mirror_client.h"
#include <dlfcn.h>
#include <functional>
#include <string>
#include <vector>
#include "bio_client.h"
#include "bio_client_agent.h"
#include "bio_client_log.h"
#include "bio_client_net.h"
#include "bio_crc_util.h"
#include "bio_functions.h"
#include "bio_monotonic.h"
#include "bio_trace.h"
#include "bio_tracepoint_helper.h"
#include "message_op.h"
using namespace ock::bio;
static const uint32_t IO_EXTRATEGE_TIME = 3;
BResult MirrorClient::SendCreateFlowRequestRemote(uint16_t nodeId, CmPtInfo &ptEntry, FlowInfo &flowInfo)
{
BResult ret = BIO_OK;
CreateFlowRequest req;
if (flowInfo.opType == 0) {
req = {
{MESSAGE_MAGIC, flowInfo.ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()}, flowInfo.opType, 0, false};
} else if (flowInfo.opType == 1) {
req = {{MESSAGE_MAGIC, flowInfo.ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()},
flowInfo.opType,
flowInfo.flowId,
flowInfo.isDegrade};
}
static uint32_t createFlowRTimeout = NO_60;
uint64_t startTime = Monotonic::TimeSec();
CreateFlowResponse rsp;
do {
ret = net::BioClientNet::Instance()->SendSync<CreateFlowRequest, CreateFlowResponse>(
static_cast<BioNodeId>(nodeId), BIO_OP_SDK_CREATE_FLOW, req, rsp);
uint64_t retryTime = Monotonic::TimeSec() - startTime;
if (UNLIKELY(ret == BIO_NOT_READY && retryTime < createFlowRTimeout)) {
CLIENT_LOG_WARN("Remote cache service not ready, need retry, ret:" << ret << ", nodeId:" << nodeId
<< ", ptId:" << flowInfo.ptId << ".");
sleep(NO_3);
} else {
break;
}
} while (ret == BIO_NOT_READY);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send sync create flow request failed, ret:" << ret << ", nodeId:" << nodeId
<< ", ptId:" << flowInfo.ptId << ".");
return ret;
}
if (flowInfo.opType == 0) {
flowInfo.flowId = rsp.flowId;
flowInfo.isDegrade = rsp.isDegrade;
}
return ret;
}
BResult MirrorClient::SendDestroyFlowRequestRemote(uint16_t nodeId, CmPtInfo &ptEntry, uint16_t ptId, uint64_t flowId)
{
DestroyFlowRequest req = {{MESSAGE_MAGIC, ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()}, flowId};
DestroyFlowResponse rsp;
BResult ret = net::BioClientNet::Instance()->SendSync<DestroyFlowRequest, DestroyFlowResponse>(
static_cast<BioNodeId>(nodeId), BIO_OP_SDK_DESTROY_FLOW, req, rsp);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send sync destroy flow request failed, ret:" << ret << ", nodeId:" << nodeId << ", ptId:"
<< ptId << ", flowId:" << flowId << ".");
}
return ret;
}
BResult MirrorClient::CreateFlowImpl(uint16_t nodeId, CmPtInfo &ptEntry, FlowInfo &flowInfo)
{
if (LIKELY(nodeId == mLocalNid.VNodeId())) {
return agent::BioClientAgent::Instance()->CreateFlowLocal(getpid(), ptEntry, flowInfo);
} else {
return SendCreateFlowRequestRemote(nodeId, ptEntry, flowInfo);
}
}
BResult MirrorClient::DestroyFlowImpl(uint16_t nodeId, CmPtInfo &ptEntry, uint16_t ptId, uint64_t flowId)
{
if (LIKELY(nodeId == mLocalNid.VNodeId())) {
return agent::BioClientAgent::Instance()->DestroyFlowLocal(getpid(), ptEntry, ptId, flowId);
} else {
return SendDestroyFlowRequestRemote(nodeId, ptEntry, ptId, flowId);
}
}
BResult MirrorClient::CreateFlow(uint16_t ptId)
{
BResult ret = Insert(ptId);
if (ret != BIO_OK) {
CLIENT_LOG_WARN("Insert failed, ret:" << ret << ", ptId:" << ptId << ".");
return BIO_INNER_RETRY;
}
CmPtInfo ptEntry;
ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret:" << ret << ", ptId:" << ptId << ".");
Delete(ptId, 0);
return ret;
}
FlowInfo flowInfo = {ptId, 0, UINT64_MAX, false};
ret = CreateFlowImpl(ptEntry.masterNodeId, ptEntry, flowInfo);
if (UNLIKELY(ret != BIO_OK || flowInfo.flowId == UINT64_MAX)) {
CLIENT_LOG_ERROR("Create master flow failed, ret:" << ret << ", ptId:" << ptId
<< ", masterNid:" << ptEntry.masterNodeId << ".");
Delete(ptId, 0);
return ret;
}
for (uint32_t idx = 0; idx < ptEntry.copys.size(); idx++) {
if (ptEntry.copys[idx].nodeId == ptEntry.masterNodeId) {
continue;
}
if (ptEntry.copys[idx].state != CM_COPY_RUNNING && ptEntry.copys[idx].state != CM_COPY_RECOVERY) {
continue;
}
flowInfo.opType = 1;
ret = CreateFlowImpl(ptEntry.copys[idx].nodeId, ptEntry, flowInfo);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Create slave flow failed, ret:" << ret << ", ptId:" << ptId
<< ", slaveNid:" << ptEntry.copys[idx].nodeId << ".");
Delete(ptId, 0);
return ret;
}
}
ret = Update(ptId, ptEntry.version, flowInfo.flowId, flowInfo.isDegrade);
if (ret != BIO_OK) {
LOG_ERROR("Update flow info failed, ret " << ret);
Delete(ptId, 0);
return ret;
}
CLIENT_LOG_INFO("Create flow instance success, ptId:" << ptId << ", ptv:" << ptEntry.version
<< ", flowId:" << flowInfo.flowId
<< ", isDegrade:" << flowInfo.isDegrade << ".");
return BIO_OK;
}
BResult MirrorClient::DestroyFlow(uint16_t ptId, uint64_t flowId)
{
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret:" << ret << ", ptId:" << ptId << ".");
return ret;
}
for (uint32_t idx = 0; idx < ptEntry.copys.size(); idx++) {
if (ptEntry.copys[idx].state != CM_COPY_RUNNING && ptEntry.copys[idx].state != CM_COPY_RECOVERY) {
continue;
}
ret = DestroyFlowImpl(ptEntry.copys[idx].nodeId, ptEntry, ptId, flowId);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Destroy flow failed, ret:" << ret << ", ptId:" << ptId << ", nid:"
<< ptEntry.copys[idx].nodeId << ", flowId:" << flowId << ".");
continue;
}
}
return BIO_OK;
}
BResult MirrorClient::LoadAffinityFlow()
{
std::vector<uint16_t> ptVec = ListLocalAffinityPt();
for (uint16_t &ptId : ptVec) {
BResult ret = CreateFlow(ptId);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Create affinity flow instance failed, ret:" << ret << ", ptId:" << ptId << ".");
} else {
CLIENT_LOG_INFO("Load affinity flow success, ptId:" << ptId << ".");
}
}
return BIO_OK;
}
BResult MirrorClient::InitializeBioQos()
{
mBioQos = BioQos::Instance();
if (UNLIKELY(mBioQos == nullptr)) {
CLIENT_LOG_ERROR("Boostio client qos instance failed.");
return BIO_INNER_ERR;
}
return mBioQos->Initialize(static_cast<uint32_t>(mLocalNid.VNodeId()), mMode, mScene);
}
BResult MirrorClient::LoadOriginView()
{
bool isRetry = false;
uint64_t retryTime;
uint64_t startTime = Monotonic::TimeSec();
uint64_t retryCnt = 0;
BResult ret = BIO_OK;
do {
isRetry = false;
ret = LoadOriginViewImpl();
if (LIKELY(ret == BIO_OK)) {
return BIO_OK;
}
if (ret == BIO_ALLOC_FAIL || ret == BIO_INNER_RETRY || ret == BIO_NET_RETRY || ret == BIO_CHECK_PT_FAIL) {
CLIENT_LOG_INFO("Delay retry, times:" << ++retryCnt << ", ret:" << ret << ".");
retryTime = Monotonic::TimeSec() - startTime;
if (retryTime < BIO_INIT_TIMEOUT_TIME) {
isRetry = true;
sleep(BIO_IO_INTERAL_TIME);
}
}
} while (isRetry);
return ret;
}
BResult MirrorClient::GetFileLocation(uint16_t masterPtId, uint16_t slavePtId,
FileLocationQueryRsp &fileLocationQueryRsp)
{
return agent::BioClientAgent::Instance()->SendGetNodeInfoRequest(masterPtId, slavePtId, fileLocationQueryRsp);
}
BResult MirrorClient::LoadOriginViewImpl()
{
auto ret = agent::BioClientAgent::Instance()->GetClusterNodeView(mCurNodeTimes, mNodeView);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Get cluster node view failed, ret:" << ret << ".");
return ret;
}
CLIENT_LOG_INFO("Current node times:" << mCurNodeTimes);
ret = agent::BioClientAgent::Instance()->GetPtView(mCurPtTimes, mPtView);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Get pt view failed, ret:" << ret << ".");
return ret;
}
CLIENT_LOG_INFO("Current pt times:" << mCurPtTimes);
ret = agent::BioClientAgent::Instance()->GetLocalNodeInfo(mNetProtocol, mLocalNid);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Get local node info failed, ret:" << ret << ".");
return ret;
}
auto tempPtView = mPtView;
for (auto &item : tempPtView) {
IoStrategy *ioStrategy = new (std::nothrow) IoStrategy();
if (UNLIKELY(ioStrategy == nullptr)) {
CLIENT_LOG_ERROR("Alloc io strategy failed.");
return BIO_ALLOC_FAIL;
}
ioStrategy->expired = Monotonic::TimeSec() + IO_EXTRATEGE_TIME;
ioStrategy->strategy = 0;
mIoStrategy[item.first] = ioStrategy;
}
if (mNodeView.empty() || mPtView.empty()) {
return BIO_INNER_RETRY;
}
CLIENT_LOG_INFO("Load origin view success, localNid:" << mLocalNid.VNodeId() << ", protocol:" << mNetProtocol);
return BIO_OK;
}
void MirrorClient::FreeIoStrategy()
{
for (auto &ioStrategy : mIoStrategy) {
delete ioStrategy.second;
}
mIoStrategy.clear();
return;
}
std::vector<uint16_t> MirrorClient::ListLocalAffinityPt()
{
std::vector<uint16_t> ans;
mLock.LockRead();
auto tempPtView = mPtView;
for (auto &item : tempPtView) {
if (mLocalNid.VNodeId() == item.second.masterNodeId) {
ans.emplace_back(item.first);
}
}
mLock.UnLock();
return ans;
}
uint16_t MirrorClient::SelectingPt(uint64_t objectId, AffinityStrategy affinity)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
uint64_t retryCnt = 0;
uint16_t ptId = UINT16_MAX;
do {
isRetry = false;
ptId = SelectingPtImpl(objectId, affinity);
if (ptId == UINT16_MAX) {
uint64_t retryTime = Monotonic::TimeSec() - startTime;
CLIENT_LOG_INFO("Select pt delay retry, cost time:" << retryTime << ", times:" << ++retryCnt << ".");
if (retryTime < mTimeOut) {
mUpdateView();
isRetry = true;
sleep(BIO_IO_INTERAL_TIME);
}
}
} while (isRetry);
BIO_TP_START(SDK_MIRROR_SELECT_PT_FAIL, &ptId, UINT16_MAX);
BIO_TP_END;
return ptId;
}
uint16_t MirrorClient::SelectingPtImpl(uint64_t objectId, AffinityStrategy affinity)
{
size_t v = std::hash<std::uint64_t>{}(objectId);
uint16_t ptId = UINT16_MAX;
if (LIKELY(affinity == LOCAL_AFFINITY)) {
std::vector<uint16_t> ptVec = ListLocalAffinityPt();
if (!ptVec.empty()) {
ptId = ptVec[v % ptVec.size()];
}
} else if (affinity == GLOBAL_BALANCE) {
mLock.LockRead();
size_t ptNum = mPtView.size();
if (ptNum != 0) {
ptId = mPtView[v % ptNum].ptId;
}
mLock.UnLock();
} else {
CLIENT_LOG_ERROR("Invalid affinity type or pt view is empty, objectId:" << objectId << ", affinity:" << affinity
<< ".");
}
BIO_TP_START(SDK_MIRROR_SET_PT_ID_FAIL, &ptId, 0);
BIO_TP_END;
if (UNLIKELY(ptId == UINT16_MAX)) {
CLIENT_LOG_ERROR("Selecting pt failed, objectId:" << objectId << ", affinity:" << affinity << ".");
}
return ptId;
}
BResult MirrorClient::GetPtEntry(uint16_t ptId, CmPtInfo &ptEntry)
{
mLock.LockRead();
auto iter = mPtView.find(ptId);
bool isFind = false;
BIO_TP_START(SDK_MIRROR_PT_VIEW_FIND_FAIL, &isFind, false);
isFind = (iter != mPtView.end());
BIO_TP_END;
if (UNLIKELY(!isFind)) {
mLock.UnLock();
CLIENT_LOG_ERROR("Invalid pt id:" << ptId << ".");
return BIO_INVALID_PARAM;
}
bool isPtNormal = false;
BIO_TP_START(SDK_MIRROR_CHECK_PT_FAIL, &isPtNormal, false);
isPtNormal = (iter->second.state != CM_PT_FAULT);
BIO_TP_END;
if (UNLIKELY(!isPtNormal)) {
CLIENT_LOG_ERROR("Pt stat is fault, pt id:" << ptId << ", state:" << iter->second.state << ".");
mLock.UnLock();
return BIO_CHECK_PT_FAIL;
}
ptEntry = iter->second;
mLock.UnLock();
return BIO_OK;
}
uint32_t MirrorClient::CalcPtQuota(CmPtInfo &ptEntry)
{
uint32_t quota = 0;
for (uint32_t idx = 0; idx < ptEntry.copys.size(); idx++) {
if (ptEntry.copys[idx].state != CM_COPY_RUNNING && ptEntry.copys[idx].state != CM_COPY_RECOVERY) {
continue;
}
quota++;
}
return quota;
}
BResult MirrorClient::Initialize(UpdateView updateView, uint32_t scene, uint32_t alignSize, uint32_t timeOut,
bool enableCrc)
{
mEnableCrc = enableCrc;
mUpdateView = updateView;
mScene = static_cast<WorkerScene>(scene);
mAlignSize = alignSize;
mTimeOut = timeOut;
BIO_TRACE_START(SDK_TRACE_INIT_LOAD_VIEW);
BResult ret = LoadOriginView();
BIO_TRACE_END(SDK_TRACE_INIT_LOAD_VIEW, ret);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Sdk load origin view failed, ret:" << ret << ".");
return ret;
}
ret = InitializeBioQos();
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Sdk init qos failed, ret:" << ret << ".");
return ret;
}
CLIENT_LOG_INFO("Mirror client initialize, clcEnable: " << mEnableCrc << ", scene:" << mScene << ", alignSize:"
<< mAlignSize << ", timeOut:" << mTimeOut << ".");
return BIO_OK;
}
BResult MirrorClient::Start()
{
return LoadAffinityFlow();
}
BResult MirrorClient::PutCheckPtState(CmPtInfo ptEntry)
{
if (ptEntry.state == CM_PT_NORMAL || ptEntry.state == CM_PT_BYPASS) {
return BIO_OK;
}
mUpdateView();
return BIO_CHECK_PT_FAIL;
}
BResult MirrorClient::Put(MirrorPut ¶m)
{
bool isAllocMem = false;
char *value = param.value;
BResult ret = PutAlignSize(value, param, isAllocMem);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Align size failed, ret: " << ret << ", key:" << param.key << ".");
return ret;
}
uint16_t ptId = ParseLocation(param.location);
CmPtInfo ptEntry;
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
do {
isRetry = false;
if (UNLIKELY((ret = GetPtEntry(ptId, ptEntry)) != BIO_OK)) {
break;
}
if (UNLIKELY((ret = PutCheckPtState(ptEntry)) != BIO_OK)) {
break;
}
QosApplyParam applyParam{startTime, param.key, param.length};
ret = mBioQos->Apply(QOS_CONCURRENCY | QOS_QUOTA, QUOTA_WRITE, applyParam, &ptEntry);
if (LIKELY(ret == BIO_OK)) {
ret = PutImpl(param, ptId, ptEntry);
mBioQos->Release(QOS_CONCURRENCY, QUOTA_WRITE);
if (LIKELY(ret == BIO_OK)) {
break;
}
}
isRetry = FailHandler(ret, startTime, NO_44);
} while (isRetry);
if (isAllocMem) {
free(param.value);
param.value = value;
}
return ret;
}
BResult MirrorClient::PreparePutWithSpace(MirrorPut ¶m, CmPtInfo &ptEntry, CacheSpaceDesc &spaceInfo,
PutRequest *&req)
{
if (spaceInfo.descriptorSize == 0 || spaceInfo.descriptorSize > CACHE_SPACE_DEC_SIZE) {
CLIENT_LOG_ERROR("Too large descriptorSize:" << spaceInfo.descriptorSize << ", it should be less than "
<< CACHE_SPACE_DEC_SIZE << ".");
return BIO_INNER_ERR;
}
uint8_t *reqTmp = nullptr;
BIO_TP_START(SDK_MIRROR_PREPARE_PUT_WITH_SPACE_FAIL, 0);
reqTmp = new (std::nothrow) uint8_t[sizeof(PutRequest) + spaceInfo.descriptorSize];
BIO_TP_END;
if (UNLIKELY(reqTmp == nullptr)) {
CLIENT_LOG_ERROR("Alloc put memory failed, len:" << sizeof(PutRequest) + spaceInfo.descriptorSize << ".");
return BIO_INNER_ERR;
}
req = static_cast<PutRequest *>(static_cast<void *>(reqTmp));
req->comm = {MESSAGE_MAGIC, ptEntry.ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
req->tenantId = param.attr.mTenantId;
req->affinity = param.attr.affinity;
req->strategy = param.attr.strategy;
CopyKey(req->key, param.key, KEY_MAX_SIZE);
req->length = param.length;
req->mrKey = net::BioClientNet::Instance()->GetLocalMrKey();
req->sliceLen = spaceInfo.descriptorSize;
mBioQos->GetKey(req->quotaNid, req->quotaCid);
if (mIoStrategy[ptEntry.ptId]->expired > Monotonic::TimeSec()) {
req->ioStrategy = mIoStrategy[ptEntry.ptId]->strategy;
} else {
req->ioStrategy = 0;
}
req->memFromServer = true;
req->mrAddress = 0ULL;
auto ret = memcpy_s(req->sliceBuf, spaceInfo.descriptorSize, spaceInfo.descriptorInfo, spaceInfo.descriptorSize);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Memory copy failed, ret:" << ret << ".");
delete[] reqTmp;
req = nullptr;
}
return ret;
}
BResult MirrorClient::PutImpl(MirrorPut ¶m, CacheSpaceDesc &spaceInfo)
{
uint16_t ptId = ParseLocation(spaceInfo.loc);
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret: " << ret << ", ptId:" << ptId << ", key:" << param.key << ".");
return ret;
}
PutRequest *req = nullptr;
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE);
ret = PreparePutWithSpace(param, ptEntry, spaceInfo, req);
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Prepare put with space failed, ret:" << ret << ", key:" << param.key << ", length:"
<< param.length << ", loc0:" << spaceInfo.loc.location[0]
<< ", loc1:" << spaceInfo.loc.location[1] << ".");
return ret;
}
BIO_TRACE_START(SDK_TRACE_PUT_SEND);
ret = SendPutRequestImpl(ptEntry, param, req);
BIO_TRACE_END(SDK_TRACE_PUT_SEND, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send put request failed, ret:" << ret << ", ptId:" << ptId << ", key:" << param.key << ".");
}
delete[] static_cast<uint8_t *>(static_cast<void *>(req));
return ret;
}
BResult MirrorClient::PutAlignSize(const char *value, MirrorPut ¶m, bool &isAllocMem)
{
if (UNLIKELY((mScene == SCENE_BIGDATA) && (param.length % mAlignSize != 0))) {
uint64_t length = (((param.length) + (mAlignSize)-1) & ~((mAlignSize)-1));
BIO_TRACE_START(SDK_TRACE_PUT_ALIGN_IO);
if ((param.value = static_cast<char *>(malloc(length))) == nullptr) {
BIO_TRACE_END(SDK_TRACE_PUT_ALIGN_IO, BIO_ALLOC_FAIL);
CLIENT_LOG_ERROR("Alloc memory failed, size:" << length << ".");
return BIO_ALLOC_FAIL;
}
auto ret = memcpy_s(param.value, length, value, param.length);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Memory copy failed, ret:" << ret << ".");
free(param.value);
param.value = nullptr;
return BIO_INNER_ERR;
}
param.length = length;
isAllocMem = true;
BIO_TRACE_END(SDK_TRACE_PUT_ALIGN_IO, BIO_OK);
}
return BIO_OK;
}
bool MirrorClient::FailHandler(const BResult result, uint64_t startTime, uint64_t timeOut)
{
uint64_t costTime = Monotonic::TimeSec() - startTime;
BIO_TP_START(SDK_MIRROR_CLIENT_SET_RETRY_TIME, &costTime, (mTimeOut + 1));
BIO_TP_END;
if (UNLIKELY(costTime >= timeOut)) {
return false;
}
bool isRetry = false;
uint16_t sleepTime = 0;
switch (result) {
case BIO_ALLOC_FAIL:
case BIO_INNER_RETRY:
case BIO_NET_RETRY:
case BIO_CHECK_PT_FAIL:
case BIO_DISK_IOERR:
isRetry = true;
sleepTime = BIO_IO_INTERAL_TIME;
mUpdateView();
break;
case BIO_QUOTA_NOT_ENOUGH:
isRetry = true;
sleepTime = NO_1;
break;
default:
isRetry = false;
break;
}
sleep(sleepTime);
return isRetry;
}
BResult MirrorClient::Put(MirrorPut ¶m, CacheSpaceDesc &spaceInfo)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
ret = PutImpl(param, spaceInfo);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::PutImpl(MirrorPut ¶m, uint16_t ptId, CmPtInfo &ptEntry)
{
BIO_TRACE_START(SDK_TRACE_PUT_ALLOC_OFF);
auto ret = AllocPutOffset(ptId, ptEntry.version, param.length, param.flowId, param.flowOffset, param.flowIndex);
BIO_TRACE_END(SDK_TRACE_PUT_ALLOC_OFF, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc put offset failed, ret:" << ret << ", ptId:" << ptId << ", flowId:" << param.flowId
<< ", key:" << param.key << ".");
ret = (ret == BIO_NOT_EXISTS) ? BIO_INNER_RETRY : ret;
return ret;
}
ret = SendPutRequest(ptEntry, param);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send put request failed, ret:" << ret << ", ptId:" << ptId << ", flowId:" << param.flowId
<< ", key:" << param.key << ".");
Delete(ptId, param.flowId);
ret = (ret == BIO_NOT_EXISTS) ? BIO_INNER_RETRY : ret;
}
return ret;
}
BResult MirrorClient::Get(MirrorGet ¶m, uint64_t &realLen)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
QosApplyParam applyParam{startTime, param.key};
ret = mBioQos->Apply(QOS_CONCURRENCY, QUOTA_READ, applyParam);
ret = GetImpl(param, realLen);
mBioQos->Release(QOS_CONCURRENCY, QUOTA_READ);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, NO_55);
} while (isRetry);
return ret;
}
BResult MirrorClient::GetImpl(MirrorGet ¶m, uint64_t &realLen)
{
uint16_t ptId = ParseLocation(param.location);
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret: " << ret << ", ptId:" << ptId << ", key:" << param.key << ".");
return ret;
}
GetRequest req;
req.comm = {MESSAGE_MAGIC, ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
CopyKey(req.key, param.key, KEY_MAX_SIZE);
req.ptId = ptId;
req.offset = param.offset;
req.length = param.length;
req.isConvDeploy = (mMode == WorkerMode::CONVERGENCE);
req.enableCrc = mEnableCrc;
BIO_TRACE_START(SDK_TRACE_GET_SEND);
ret = SendGetRequest(ptEntry, req, param.value, realLen);
BIO_TRACE_END(SDK_TRACE_GET_SEND, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send get request failed, ret:" << ret << ", ptId:" << ptId << ", key:" << param.key << ".");
}
return ret;
}
BResult MirrorClient::DeleteKey(const char *key, const ObjLocation &location)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
ret = DeleteKeyImpl(key, location);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::DeleteKeyImpl(const char *key, const ObjLocation &location)
{
uint16_t ptId = ParseLocation(location);
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret: " << ret << ", ptId:" << ptId << ", key:" << key << ".");
return ret;
}
DeleteRequest req{};
req.comm = {MESSAGE_MAGIC, ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
CopyKey(req.key, key, KEY_MAX_SIZE);
ret = SendDeleteRequest(ptEntry, req);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send delete request failed, ret:" << ret << ", ptId:" << ptId << ", key:" << key << ".");
}
return ret;
}
BResult MirrorClient::Load(LoadPara ¶, const ObjLocation &location, const Bio::LoadCallback &callback,
void *context)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
ret = LoadImpl(para, location, callback, context);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::LoadImpl(LoadPara ¶, const ObjLocation &location, const Bio::LoadCallback &callback,
void *context)
{
uint16_t ptId = ParseLocation(location);
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret: " << ret << ", ptId:" << ptId << ", key:" << para.key << ".");
return ret;
}
LoadRequest req;
req.comm = {MESSAGE_MAGIC, ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
CopyKey(req.key, para.key, KEY_MAX_SIZE);
req.offset = para.offset;
req.length = para.length;
ret = SendLoadRequest(ptEntry, req, callback, context);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send stat request failed, ret:" << ret << ", ptId:" << ptId << ", key:" << para.key << ".");
}
return ret;
}
BResult MirrorClient::ListAll(const char *prefix, std::unordered_map<std::string, ObjStat> &objs)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
ret = ListAllImpl(prefix, objs);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::ListAllImpl(const char *prefix, std::unordered_map<std::string, ObjStat> &objs)
{
ListRequest req;
req.comm = {MESSAGE_MAGIC, 0, 0, mLocalNid.VNodeId(), getpid()};
CopyKey(req.prefix, prefix, KEY_MAX_SIZE);
return SendListRequest(req, objs);
}
BResult MirrorClient::StatObject(const char *key, const ObjLocation &location, ObjStat &stat)
{
bool isRetry = false;
uint64_t startTime = Monotonic::TimeSec();
BResult ret = BIO_OK;
do {
isRetry = false;
ret = StatObjectImpl(key, location, stat);
if (LIKELY(ret == BIO_OK)) {
break;
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::StatObjectImpl(const char *key, const ObjLocation &location, ObjStat &stat)
{
uint16_t ptId = ParseLocation(location);
CmPtInfo ptEntry;
BResult ret = GetPtEntry(ptId, ptEntry);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Get pt entry failed, ret: " << ret << ", ptId:" << ptId << ", key:" << key << ".");
return ret;
}
StatRequest req{};
req.comm = {MESSAGE_MAGIC, ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
CopyKey(req.key, key, KEY_MAX_SIZE);
ret = SendStatRequest(ptEntry, req, stat);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send stat request failed, ret:" << ret << ", ptId:" << ptId << ", key:" << key << ".");
}
return ret;
}
BResult MirrorClient::NotifyUpdate(bool &flag)
{
auto ret = SendNotifyUpdateRequest(flag);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send update request failed, ret:" << ret << ".");
}
return ret;
}
BResult MirrorClient::AddDisk(const char *diskPath)
{
bool isRetry = false;
uint64_t retryTime;
uint64_t startTime = Monotonic::TimeSec();
uint64_t retryCnt = 0;
BResult ret = BIO_OK;
do {
isRetry = false;
ret = AddDiskImpl(diskPath);
if (LIKELY(ret == BIO_OK)) {
return BIO_OK;
}
if (ret == BIO_INNER_RETRY || ret == BIO_NET_RETRY || ret == BIO_CHECK_PT_FAIL) {
CLIENT_LOG_INFO("Add disk delay retry, times:" << ++retryCnt << ", ret:" << ret << ".");
BIO_TP_START(SDK_MIRROR_CLIENT_SET_RETRY_TIME, &retryTime, (mTimeOut + 1));
BIO_TP_END;
retryTime = Monotonic::TimeSec() - startTime;
if (retryTime < BIO_INIT_TIMEOUT_TIME) {
isRetry = true;
sleep(BIO_IO_INTERAL_TIME);
}
}
} while (isRetry);
return ret;
}
BResult MirrorClient::AddDiskImpl(const char *diskPath)
{
AddDiskRequest req{};
req.comm = {MESSAGE_MAGIC, 0, 0, mLocalNid.VNodeId(), getpid()};
auto pathLen = strlen(diskPath);
BResult ret = memcpy_s(req.diskPath, FILE_PATH_MAX_LEN, diskPath, pathLen);
if (ret != BIO_OK) {
LOG_ERROR("Req copy disk path failed, ret:" << ret << ", path:" << diskPath << ".");
return ret;
}
req.diskPath[pathLen] = '\0';
ret = SendAddDiskRequest(req);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send add disk request failed, ret:" << ret << ", diskPath:" << req.diskPath << ".");
}
return ret;
}
BResult MirrorClient::SendAddDiskRequest(AddDiskRequest &req)
{
AddDiskResponse rsp;
return agent::BioClientAgent::Instance()->AddDisk(req, rsp);
}
BResult MirrorClient::CheckUpdateReady()
{
auto ret = SendCheckUpdateReadyRequest();
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Check update request failed, ret:" << ret << ".");
}
return ret;
}
BResult MirrorClient::AllocSpaceImpl(uint16_t ptId, CmPtInfo &ptEntry, MirrorPut ¶m, CacheSpaceDesc &spaceInfo)
{
BIO_TRACE_START(SDK_TRACE_PUT_ALLOC_OFF);
auto ret = AllocPutOffset(ptId, ptEntry.version, param.length, param.flowId, param.flowOffset, param.flowIndex);
BIO_TRACE_END(SDK_TRACE_PUT_ALLOC_OFF, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc put offset failed, ret:" << ret << ", ptId:" << ptId << ", ptv:" << ptEntry.version
<< ", length:" << param.length << ".");
return ret;
}
GetSliceResponse *rsp = nullptr;
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE_GET_SLICE);
ret = agent::BioClientAgent::Instance()->PrepareResource(ptEntry, param.flowId, param.flowOffset, param.flowIndex,
param.length, &rsp);
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE_GET_SLICE, BIO_OK);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc put space failed, ret:" << ret << ", flowId:" << param.flowId << ", flowOffset:"
<< param.flowOffset << ", length:" << param.length << ".");
Delete(ptId, param.flowId);
return ret;
}
if (rsp == nullptr) {
Delete(ptId, param.flowId);
return BIO_ERR;
}
spaceInfo.descriptorSize = rsp->sliceLen;
ret = memcpy_s(spaceInfo.descriptorInfo, CACHE_SPACE_DEC_SIZE, rsp->sliceBuf, rsp->sliceLen);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Failed to data copy, sliceLen:" << rsp->sliceLen << ".");
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
Delete(ptId, param.flowId);
return BIO_INNER_ERR;
}
BIO_TP_START(SDK_MIRROR_CLIENT_ADDRNUM_INVALID, &rsp->addrNum, (SLICE_ADDR_MAX_SIZE + 1));
BIO_TP_END;
if (rsp->addrNum > CACHE_SPACE_ADDRESS_SIZE) {
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
Delete(ptId, param.flowId);
return BIO_INNER_ERR;
}
spaceInfo.addressNum = rsp->addrNum;
for (uint32_t idx = 0; idx < spaceInfo.addressNum; idx++) {
if (mMode == CONVERGENCE) {
spaceInfo.address[idx].address = rsp->addr[idx].chunkId + rsp->addr[idx].chunkOffset;
} else {
uint8_t *realAddr =
net::BioClientNet::Instance()->GetShmAddress(rsp->addrOffset[idx], rsp->addr[idx].chunkLen);
if (realAddr == nullptr) {
CLIENT_LOG_ERROR("Invalid response addr offset or chunk len.");
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
Delete(ptId, param.flowId);
return BIO_INNER_ERR;
}
spaceInfo.address[idx].address = reinterpret_cast<uintptr_t>(realAddr);
}
spaceInfo.address[idx].size = rsp->addr[idx].chunkLen;
}
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
return BIO_OK;
}
BResult MirrorClient::AllocSpace(MirrorClient::MirrorPut ¶m, CacheSpaceDesc &spaceInfo)
{
uint16_t ptId = ParseLocation(param.location);
CmPtInfo ptEntry;
bool isRetry = false;
BResult ret = BIO_OK;
uint64_t startTime = Monotonic::TimeSec();
do {
isRetry = false;
if (UNLIKELY((ret = GetPtEntry(ptId, ptEntry)) != BIO_OK)) {
break;
}
static std::atomic<uint64_t> ref(1);
std::string innerKey = "BioAllocSpace" + std::to_string(ref++);
QosApplyParam applyParam{startTime, innerKey.c_str(), param.length};
ret = mBioQos->Apply(QOS_CONCURRENCY | QOS_QUOTA, QUOTA_WRITE, applyParam, &ptEntry);
if (LIKELY(ret == BIO_OK)) {
ret = AllocSpaceImpl(ptId, ptEntry, param, spaceInfo);
mBioQos->Release(QOS_CONCURRENCY, QUOTA_WRITE);
if (LIKELY(ret == BIO_OK)) {
break;
}
}
isRetry = FailHandler(ret, startTime, mTimeOut);
} while (isRetry);
return ret;
}
BResult MirrorClient::AllocPutOffset(uint16_t ptId, uint64_t ptv, uint64_t len, uint64_t &flowId, uint64_t &offset,
uint64_t &index)
{
FlowInstancePtr flowInst = Query(ptId);
if (UNLIKELY(flowInst == nullptr)) {
BResult ret = CreateFlow(ptId);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_WARN("Create flow instance failed, ret: " << ret << ", ptId:" << ptId << ".");
return ret;
}
flowInst = Query(ptId);
if (UNLIKELY(flowInst == nullptr)) {
CLIENT_LOG_WARN("Query flow failed, ptId:" << ptId << ".");
return BIO_INNER_RETRY;
}
}
bool isNormal = false;
BIO_TP_START(SDK_MIRROR_ALLOC_PUT_OFFSET_FAIL, &isNormal, false);
isNormal = flowInst->IsNormal();
BIO_TP_END;
if (UNLIKELY(!isNormal)) {
CLIENT_LOG_WARN("Check flow failed, ptId:" << ptId << ".");
return BIO_INNER_RETRY;
}
if (UNLIKELY(flowInst->Version() != ptv)) {
Delete(ptId, flowInst->FlowId());
BResult ret = CreateFlow(ptId);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Create flow instance failed, need retry, ret: " << ret << ", ptId:" << ptId << ".");
}
return BIO_INNER_RETRY;
}
flowId = flowInst->FlowId();
offset = flowInst->AllocOffset(len, index);
return BIO_OK;
}
void MirrorClient::ConstructPutReq(PutRequest *req, CmPtInfo &ptEntry, MirrorPut ¶m, uint64_t flowId,
uint64_t flowOffset, uint64_t flowIndex, GetSliceResponse *rsp)
{
req->comm = {MESSAGE_MAGIC, ptEntry.ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
req->tenantId = param.attr.mTenantId;
req->affinity = param.attr.affinity;
req->strategy = param.attr.strategy;
CopyKey(req->key, param.key, KEY_MAX_SIZE);
req->length = param.length;
req->flowId = flowId;
req->flowOffset = flowOffset;
req->flowIndex = flowIndex;
req->mrAddress = 0;
req->mrSize = 0;
req->mrKey = net::BioClientNet::Instance()->GetLocalMrKey();
req->sliceLen = rsp->sliceLen;
mBioQos->GetKey(req->quotaNid, req->quotaCid);
if (mIoStrategy[ptEntry.ptId]->expired > Monotonic::TimeSec()) {
req->ioStrategy = mIoStrategy[ptEntry.ptId]->strategy;
} else {
req->ioStrategy = 0;
}
auto ret = memcpy_s(req->sliceBuf, req->sliceLen, rsp->sliceBuf, rsp->sliceLen);
if (UNLIKELY(ret != 0)) {
CLIENT_LOG_ERROR("slice buffer memcpy failed.");
}
}
void MirrorClient::ConstructPutReq(PutRequest *req, CmPtInfo &ptEntry, MirrorPut ¶m, uint64_t flowId,
uint64_t flowOffset, uint64_t flowIndex, NetMrInfo &mr)
{
req->comm = {MESSAGE_MAGIC, ptEntry.ptId, ptEntry.version, mLocalNid.VNodeId(), getpid()};
req->tenantId = param.attr.mTenantId;
req->affinity = param.attr.affinity;
req->strategy = param.attr.strategy;
CopyKey(req->key, param.key, KEY_MAX_SIZE);
req->length = param.length;
req->flowId = flowId;
req->flowOffset = flowOffset;
req->flowIndex = flowIndex;
req->mrAddress = mr.address;
req->mrSize = mr.size;
req->mrKey = mr.key;
req->sliceLen = 0;
mBioQos->GetKey(req->quotaNid, req->quotaCid);
if (mIoStrategy[ptEntry.ptId]->expired > Monotonic::TimeSec()) {
req->ioStrategy = mIoStrategy[ptEntry.ptId]->strategy;
} else {
req->ioStrategy = 0;
}
}
BResult MirrorClient::DataCopy(const char *from, uint32_t fromLen, SliceAddrDesc *addr, uint64_t *offset,
uint32_t addrNum)
{
uint64_t totalLen = 0;
for (uint32_t i = 0; i < addrNum; i++) {
totalLen += addr[i].chunkLen;
}
if (totalLen < fromLen) {
return BIO_INNER_ERR;
}
uint64_t off = 0;
for (uint32_t i = 0; i < addrNum; i++) {
uint8_t *realAddr = nullptr;
if (mMode == WorkerMode::CONVERGENCE) {
realAddr = reinterpret_cast<uint8_t *>(addr[i].chunkId + addr[i].chunkOffset);
} else {
realAddr = net::BioClientNet::Instance()->GetShmAddress(offset[i], addr[i].chunkLen);
if (UNLIKELY(realAddr == nullptr)) {
CLIENT_LOG_ERROR("Get shm addr failed offset:" << offset[i] << ".");
return BIO_INNER_ERR;
}
}
auto ret = memcpy_s(realAddr, addr[i].chunkLen, (from + off), addr[i].chunkLen);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Failed to copy data, len:" << addr[i].chunkLen << ".");
return BIO_INNER_ERR;
}
off += addr[i].chunkLen;
}
return BIO_OK;
}
bool MirrorClient::IsExistLocalCopy(CmPtInfo &ptEntry)
{
BIO_TP_START(SDK_MIRROR_CLIENT_NOT_EXIST_LOCAL_COPY, 0);
for (uint32_t i = 0; i < ptEntry.copys.size(); i++) {
if (ptEntry.copys[i].nodeId == mLocalNid.VNodeId() &&
(ptEntry.copys[i].state == CM_COPY_RUNNING || ptEntry.copys[i].state == CM_COPY_RECOVERY)) {
return true;
}
}
BIO_TP_END;
return false;
}
BResult MirrorClient::PrepareFromServer(CmPtInfo &ptEntry, MirrorPut ¶m, PutRequest *&req)
{
GetSliceResponse *rsp = nullptr;
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE_GET_SLICE);
auto ret = agent::BioClientAgent::Instance()->PrepareResource(ptEntry, param.flowId, param.flowOffset,
param.flowIndex, param.length, &rsp);
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE_GET_SLICE, BIO_OK);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Prepare resource failed, ret:" << ret << ", key:" << param.key << ", flowId:" << param.flowId
<< ", flowOffset:" << param.flowOffset
<< ", length:" << param.length << ".");
return ret;
}
if (rsp == nullptr) {
return BIO_ERR;
}
BIO_TP_START(SDK_MIRROR_RSP_NUM_ERROR, &(rsp->addrNum), (SLICE_ADDR_MAX_SIZE + 1));
BIO_TP_END;
if (UNLIKELY(rsp->addrNum > SLICE_ADDR_MAX_SIZE)) {
CLIENT_LOG_ERROR("rsp addrNum: " << rsp->addrNum << " is invalid.");
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
return BIO_INNER_ERR;
}
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE_COPY_DATA);
ret = DataCopy(param.value, param.length, rsp->addr, rsp->addrOffset, rsp->addrNum);
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE_COPY_DATA, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Copy data failed, ret:" << ret << ", key:" << param.key << ", flowId:" << param.flowId
<< ", flowOffset:" << param.flowOffset << ", length:" << param.length
<< ".");
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
return ret;
}
auto tmp = new (std::nothrow) uint8_t[sizeof(PutRequest) + rsp->sliceLen];
if (UNLIKELY(tmp == nullptr)) {
CLIENT_LOG_ERROR("Alloc put request memory failed, len:" << sizeof(PutRequest) + rsp->sliceLen << ".");
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
return BIO_ALLOC_FAIL;
}
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE_SLICE_SERIALIZATION);
req = static_cast<PutRequest *>(static_cast<void *>(tmp));
ConstructPutReq(req, ptEntry, param, param.flowId, param.flowOffset, param.flowIndex, rsp);
req->memFromServer = true;
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE_SLICE_SERIALIZATION, ret);
delete[] static_cast<uint8_t *>(static_cast<void *>(rsp));
return BIO_OK;
}
BResult MirrorClient::PrepareFromClient(CmPtInfo &ptEntry, MirrorPut ¶m, PutRequest *&req)
{
NetMrInfo mr;
BResult ret = net::BioClientNet::Instance()->Alloc(param.length, mr);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc rdma memory failed, ret:" << ret << ", length:" << param.length << ".");
return BIO_ALLOC_FAIL;
}
ret = memcpy_s(reinterpret_cast<char *>(mr.address), mr.size, param.value, param.length);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Copy data failed, ret:" << ret << ", key:" << param.key << ", flowId:" << param.flowId
<< ", flowOffset:" << param.flowOffset << ", length:" << param.length
<< ".");
net::BioClientNet::Instance()->Free(mr.address);
return BIO_ALLOC_FAIL;
}
uint8_t *tmp = nullptr;
BIO_TP_START(SDK_MIRROR_CLIENT_PREPARE_FAIL, 0);
tmp = new (std::nothrow) uint8_t[sizeof(PutRequest)];
BIO_TP_END;
if (tmp == nullptr) {
CLIENT_LOG_ERROR("Alloc memory failed.");
net::BioClientNet::Instance()->Free(mr.address);
return BIO_ALLOC_FAIL;
}
req = static_cast<PutRequest *>(static_cast<void *>(tmp));
ConstructPutReq(req, ptEntry, param, param.flowId, param.flowOffset, param.flowIndex, mr);
req->memFromServer = false;
return BIO_OK;
}
BResult MirrorClient::Prepare(CmPtInfo &ptEntry, MirrorPut ¶m, PutRequest *&req)
{
if (IsExistLocalCopy(ptEntry)) {
return PrepareFromServer(ptEntry, param, req);
} else {
return PrepareFromClient(ptEntry, param, req);
}
}
void MirrorClient::PutRemote(PutRequest *req, CmPtInfo &ptEntry, std::vector<uint32_t> &indexVec, Callback &callback)
{
for (uint32_t i = 0; i < indexVec.size(); i++) {
uint16_t dstNid = ptEntry.copys[indexVec[i]].nodeId;
BIO_TRACE_START(SDK_TRACE_PUT_REMOTE_SYNC);
net::BioClientNet::Instance()->SendAsyncBuff(static_cast<BioNodeId>(dstNid), BIO_OP_SDK_PUT,
static_cast<void *>(req), sizeof(PutRequest) + req->sliceLen,
callback);
BIO_TRACE_END(SDK_TRACE_PUT_REMOTE_SYNC, BIO_OK);
}
}
void MirrorClient::PutLocal(PutRequest *req, uint32_t localIdx, Callback &callback) const
{
if (UNLIKELY(localIdx == UINT32_MAX)) {
return;
}
agent::BioClientAgent::Instance()->PutLocal(req, callback);
}
void MirrorClient::InitCallbackCtx(ClientCallbackCtx &cbCtx, uint32_t quota)
{
cbCtx.result = BIO_OK;
cbCtx.quota = quota;
sem_init(&cbCtx.sem, 0, 0);
cbCtx.resp = nullptr;
cbCtx.respLen = 0;
}
BResult MirrorClient::SendPutRequestImpl(CmPtInfo &ptEntry, MirrorPut ¶m, PutRequest *req)
{
uint32_t quota = CalcPtQuota(ptEntry);
ClientCallbackCtx cbCtx;
InitCallbackCtx(cbCtx, quota);
std::atomic<uint32_t> ioStrategy(0);
auto cbFunc = [&ioStrategy](void *ctx, void *resp, uint32_t len, int32_t result) {
auto *cbCtx = (ClientCallbackCtx *)ctx;
BIO_TP_START(SDK_MIRROR_PUT_RECV_FAIL, &(cbCtx->result), BIO_INNER_RETRY);
BIO_TP_END;
if (UNLIKELY(result != BIO_OK)) {
cbCtx->result = result;
} else if (resp != nullptr) {
auto rsp = static_cast<PutResponse *>(resp);
if (rsp->ioStrategy > WRITE_UNDERFS_BACK) {
cbCtx->result = BIO_INVALID_PARAM;
} else {
ioStrategy = (rsp->ioStrategy > ioStrategy) ? rsp->ioStrategy : ioStrategy.load();
}
} else {
cbCtx->result = BIO_INVALID_PARAM;
}
if (__sync_sub_and_fetch(&cbCtx->quota, 1) == 0) {
sem_post(&cbCtx->sem);
}
};
Callback callback(cbFunc, static_cast<void *>(&cbCtx));
uint32_t localIdx = UINT32_MAX;
std::vector<uint32_t> remoteIdx;
for (uint32_t idx = 0; idx < ptEntry.copys.size(); idx++) {
if (ptEntry.copys[idx].state != CM_COPY_RUNNING && ptEntry.copys[idx].state != CM_COPY_RECOVERY) {
continue;
}
if (ptEntry.copys[idx].nodeId == mLocalNid.VNodeId()) {
localIdx = idx;
continue;
}
remoteIdx.emplace_back(idx);
}
PutRemote(req, ptEntry, remoteIdx, callback);
PutLocal(req, localIdx, callback);
sem_wait(&cbCtx.sem);
sem_destroy(&cbCtx.sem);
net::BioClientNet::Instance()->Free(req->mrAddress);
if (cbCtx.result == BIO_OK) {
mIoStrategy[ptEntry.ptId]->expired = Monotonic::TimeSec() + IO_EXTRATEGE_TIME;
mIoStrategy[ptEntry.ptId]->strategy = ioStrategy.load();
}
return cbCtx.result;
}
BResult MirrorClient::SendPutRequest(CmPtInfo &ptEntry, MirrorPut ¶m)
{
BIO_TRACE_START(SDK_TRACE_PUT_PREPARE);
PutRequest *req = nullptr;
BResult ret = BIO_OK;
ret = Prepare(ptEntry, param, req);
BIO_TRACE_END(SDK_TRACE_PUT_PREPARE, ret);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Prepare put resource failed, ret:" << ret << ", key:" << param.key << ", length:"
<< param.length << ", flowId:" << param.flowId
<< ", flowOffset:" << param.flowOffset << ".");
return ret;
}
req->dataCrc = mEnableCrc ? BioCrcUtil::Crc32(param.value, param.length) : 0;
BIO_TRACE_START(SDK_TRACE_PUT_SEND);
ret = SendPutRequestImpl(ptEntry, param, req);
BIO_TRACE_END(SDK_TRACE_PUT_SEND, ret);
delete[] static_cast<uint8_t *>(static_cast<void *>(req));
return ret;
}
BResult MirrorClient::GetMasterRemote(GetRequest &req, uint16_t masterNid, char *value, uint64_t &realLen)
{
NetMrInfo mrInfo;
BResult ret = net::BioClientNet::Instance()->Alloc(req.length, mrInfo);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc rdma page failed, ret:" << ret << ", length:" << req.length << ", page size:"
<< net::BioClientNet::Instance()->GetDataPage() << ".");
return BIO_ALLOC_FAIL;
}
req.isMr = 1;
req.address = mrInfo.address;
req.size = mrInfo.size;
req.mrKey = mrInfo.key;
GetResponse rsp;
ret = net::BioClientNet::Instance()->SendSync<GetRequest, GetResponse>(static_cast<BioNodeId>(masterNid),
BIO_OP_SDK_GET, req, rsp);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send sync get request failed, ret:" << ret << ", key:" << req.key << ", offset:" << req.offset
<< ", length:" << req.length << ", dstNid:" << masterNid
<< ".");
} else {
if (rsp.num > SLICE_ADDR_SIZE) {
net::BioClientNet::Instance()->Free(mrInfo.address);
return BIO_INVALID_PARAM;
}
realLen = rsp.realLen;
if (realLen > mrInfo.size) {
net::BioClientNet::Instance()->Free(mrInfo.address);
return BIO_INNER_ERR;
}
BIO_TRACE_START(SDK_TRACE_GET_COPY2U);
ret = memcpy_s(value, req.length, reinterpret_cast<void *>(mrInfo.address), realLen);
BIO_TRACE_END(SDK_TRACE_GET_COPY2U, ret);
if (UNLIKELY(ret != 0)) {
CLIENT_LOG_ERROR("Copy data to user failed, ret:" << ret << ".");
} else if (req.enableCrc) {
uint32_t currentCrc = BioCrcUtil::Crc32(value, realLen);
if (currentCrc != rsp.dataCrc) {
CLIENT_LOG_ERROR("Client Get failed to verify the CRC, key:"
<< req.key << ", origin crc:" << rsp.dataCrc << ", current crc:" << currentCrc);
net::BioClientNet::Instance()->Free(mrInfo.address);
return BIO_CRC_ERR;
}
}
}
net::BioClientNet::Instance()->Free(mrInfo.address);
return ret;
}
BResult MirrorClient::GetMaster(GetRequest &req, uint16_t masterNid, char *value, uint64_t &realLen)
{
CLIENT_LOG_DEBUG("Get master start, masterNid:" << masterNid << ", localNid:" << mLocalNid.VNodeId()
<< ", key:" << req.key << ", offset:" << req.offset
<< ", length:" << req.length << ".");
BResult ret = BIO_INNER_ERR;
BIO_TP_START(SDK_MIRROR_GET_RECV_FAIL, &ret, BIO_INNER_RETRY);
if (masterNid == mLocalNid.VNodeId()) {
BIO_TRACE_START(SDK_TRACE_GET_LOCAL);
ret = agent::BioClientAgent::Instance()->GetLocal(req, value, realLen);
BIO_TRACE_END(SDK_TRACE_GET_LOCAL, ret);
} else {
BIO_TRACE_START(SDK_TRACE_GET_REMOTE);
ret = GetMasterRemote(req, masterNid, value, realLen);
BIO_TRACE_END(SDK_TRACE_GET_REMOTE, ret);
}
BIO_TP_END;
return ret;
}
BResult MirrorClient::SendGetRequest(CmPtInfo &ptEntry, GetRequest &req, char *value, uint64_t &realLen)
{
return GetMaster(req, ptEntry.masterNodeId, value, realLen);
}
void MirrorClient::DeleteRemote(DeleteRequest &req, CmPtInfo &ptEntry, uint32_t index, Callback &callback)
{
uint16_t dstNid = ptEntry.copys[index].nodeId;
net::BioClientNet::Instance()->SendAsync<DeleteRequest>(static_cast<BioNodeId>(dstNid), BIO_OP_SDK_DELETE, req,
callback);
}
void MirrorClient::DeleteLocal(DeleteRequest &req, Callback &callback) const
{
agent::BioClientAgent::Instance()->DeleteLocal(req, callback);
}
BResult MirrorClient::SendDeleteRequest(CmPtInfo &ptEntry, DeleteRequest &req)
{
uint32_t quota = CalcPtQuota(ptEntry);
ClientCallbackCtx cbCtx;
InitCallbackCtx(cbCtx, quota);
auto cbFunc = [](void *ctx, void *resp, uint32_t len, int32_t result) {
if (ctx == nullptr) {
LOG_ERROR("Send delete request callback ctx null");
return;
}
auto cbCtx = (ClientCallbackCtx *)ctx;
BIO_TP_START(SDK_MIRROR_DELETE_RECV_FAIL, &result, BIO_INNER_RETRY);
BIO_TP_END;
if (UNLIKELY(result != BIO_OK)) {
cbCtx->result = result;
} else {
BResult res = (resp != nullptr) ? *(static_cast<BResult *>(resp)) : BIO_INNER_ERR;
if (res != BIO_OK) {
cbCtx->result = res;
}
}
if (__sync_sub_and_fetch(&cbCtx->quota, 1) == 0) {
sem_post(&cbCtx->sem);
}
};
Callback callback(cbFunc, static_cast<void *>(&cbCtx));
for (uint32_t idx = 0; idx < ptEntry.copys.size(); idx++) {
if (ptEntry.copys[idx].state != CM_COPY_RUNNING && ptEntry.copys[idx].state != CM_COPY_RECOVERY) {
continue;
}
if (ptEntry.copys[idx].nodeId == mLocalNid.VNodeId()) {
DeleteLocal(req, callback);
continue;
}
DeleteRemote(req, ptEntry, idx, callback);
}
sem_wait(&cbCtx.sem);
sem_destroy(&cbCtx.sem);
return cbCtx.result;
}
BResult MirrorClient::StatRemote(uint16_t dstNid, StatRequest &req, ObjStat &objInfo)
{
return net::BioClientNet::Instance()->SendSync<StatRequest, ObjStat>(static_cast<BioNodeId>(dstNid),
BIO_OP_SDK_STAT, req, objInfo);
}
BResult MirrorClient::StatLocal(StatRequest &req, ObjStat &objInfo) const
{
return agent::BioClientAgent::Instance()->StatLocal(req, objInfo);
}
BResult MirrorClient::SendStatRequest(CmPtInfo &ptEntry, StatRequest &req, ObjStat &objInfo)
{
uint16_t dstNid = ptEntry.masterNodeId;
BResult ret = BIO_INNER_ERR;
BIO_TP_START(SDK_MIRROR_STAT_RECV_FAIL, &ret, BIO_INNER_RETRY);
if (dstNid == mLocalNid.VNodeId()) {
ret = StatLocal(req, objInfo);
} else {
ret = StatRemote(dstNid, req, objInfo);
}
if (ret == BIO_OK && objInfo.size > BIO_IO_MAX_LEN) {
return BIO_INVALID_PARAM;
}
BIO_TP_END;
return ret;
}
BResult MirrorClient::SendNotifyUpdateRequest(bool &flag)
{
BResult ret = BIO_INNER_ERR;
BIO_TP_START(SDK_MIRROR_NOTIFY_UPDATE_RECV_FAIL, &ret, BIO_INNER_RETRY);
ret = agent::BioClientAgent::Instance()->NotifyUpdate(flag);
BIO_TP_END;
return ret;
}
BResult MirrorClient::SendCheckUpdateReadyRequest()
{
BResult ret = BIO_INNER_ERR;
BIO_TP_START(SDK_MIRROR_CHECK_UPDATE_RECV_FAIL, &ret, BIO_INNER_RETRY);
ret = agent::BioClientAgent::Instance()->CheckUpdateReady();
BIO_TP_END;
return ret;
}
BResult MirrorClient::ListRemote(uint16_t nid, ListRequest &req, std::unordered_map<std::string, ObjStat> &objs)
{
uint64_t maxSize = sizeof(ObjStat) * 1000U;
NetMrInfo mr;
auto ret = net::BioClientNet::Instance()->Alloc(maxSize, mr);
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Alloc rdma memory failed.");
return BIO_ALLOC_FAIL;
}
req.address = mr.address;
req.size = maxSize;
req.mrKey = mr.key;
ListResponse rsp;
BIO_TP_START(LISTALL_REMOTE_RSP_OVER_LIMIT, &rsp.num, 1500U);
ret = net::BioClientNet::Instance()->SendSync<ListRequest, ListResponse>(static_cast<BioNodeId>(nid),
BIO_OP_SDK_LIST, req, rsp);
BIO_TP_END;
if (ret != BIO_OK) {
net::BioClientNet::Instance()->Free(mr.address);
return ret;
}
if (UNLIKELY(rsp.num > 1000U || rsp.buffLen != 0)) {
return BIO_INNER_RETRY;
}
if (rsp.num != 0) {
size_t objSize = 0;
auto statInfo = reinterpret_cast<ObjStat *>(mr.address);
for (uint32_t i = 0; i < rsp.num; i++) {
objSize = objs.size();
BIO_TP_START(LISTALL_REMOTE_OVER_1000, &objSize, 1500U);
BIO_TP_END;
if (objSize >= 1000U) {
break;
}
ObjStat stat;
CopyKey(stat.key, statInfo[i].key, KEY_MAX_SIZE);
stat.size = statInfo[i].size;
stat.time = statInfo[i].time;
objs.insert({stat.key, stat});
}
}
net::BioClientNet::Instance()->Free(mr.address);
return BIO_OK;
}
BResult MirrorClient::ListLocal(ListRequest &req, std::unordered_map<std::string, ObjStat> &objs)
{
return agent::BioClientAgent::Instance()->ListLocal(req, objs);
}
BResult MirrorClient::SendListRequest(ListRequest &req, std::unordered_map<std::string, ObjStat> &objs)
{
BResult ret = BIO_ERR;
uint32_t index = 0;
auto tempPtView = mPtView;
for (auto &ptEntry : tempPtView) {
uint16_t dstNid = ptEntry.second.masterNodeId;
req.isListUnderFs = (index == tempPtView.size() - 1);
req.comm.ptId = ptEntry.second.ptId;
req.comm.ptv = ptEntry.second.version;
BIO_TP_START(SDK_MIRROR_LIST_RECV_FAIL, &ret, BIO_INNER_RETRY);
if (dstNid == mLocalNid.VNodeId()) {
ret = ListLocal(req, objs);
} else {
ret = ListRemote(dstNid, req, objs);
}
BIO_TP_END;
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Send list request failed, ret:" << ret << ", dstNid:" << dstNid
<< ", ptId:" << ptEntry.second.ptId << ".");
objs.clear();
break;
} else if (objs.size() > NO_1000) {
break;
}
index++;
}
return ret;
}
BResult MirrorClient::LoadMaster(LoadRequest &req, uint16_t masterNid, const Bio::LoadCallback &callback, void *context)
{
if (masterNid == mLocalNid.VNodeId()) {
BResult ret = BIO_INNER_ERR;
BIO_TP_START(SDK_MIRROR_LOAD_RECV_FAIL, &ret, BIO_INNER_RETRY);
ret = agent::BioClientAgent::Instance()->LoadLocal(req);
BIO_TP_END;
callback(context, ret);
return BIO_OK;
}
auto cbFunc = [&callback, context](void *ctx, void *resp, uint32_t len, int32_t result) {
BIO_TP_START(SDK_MIRROR_LOAD_RECV_FAIL, &result, BIO_INNER_RETRY);
BIO_TP_END;
if (UNLIKELY(result != BIO_OK)) {
callback(context, result);
return;
}
if (resp == nullptr) {
callback(context, BIO_ERR);
}
BResult hdlRet = *(static_cast<BResult *>(resp));
callback(context, hdlRet);
};
Callback cb(cbFunc, nullptr);
net::BioClientNet::Instance()->SendAsync<LoadRequest>(static_cast<uint32_t>(masterNid), BIO_OP_SDK_LOAD, req, cb);
return BIO_OK;
}
inline BResult MirrorClient::SendLoadRequest(CmPtInfo &ptEntry, LoadRequest &req, const Bio::LoadCallback &callback,
void *context)
{
return LoadMaster(req, ptEntry.masterNodeId, callback, context);
}
BResult MirrorClient::RebuildNodeView()
{
std::map<CmNodeId, CmNodeInfo, CmNodeIdCmp> nodeView;
auto ret = agent::BioClientAgent::Instance()->GetClusterNodeView(mCurNodeTimes, nodeView);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Get cluster node view failed, ret:" << ret << ".");
return ret;
}
if (!nodeView.empty()) {
mLock.LockWrite();
mNodeView.clear();
mNodeView.swap(nodeView);
mLock.UnLock();
}
CLIENT_LOG_INFO("Cur node times:" << mCurNodeTimes << ", nodeview size:" << mNodeView.size());
return BIO_OK;
}
BResult MirrorClient::RebuildPtView()
{
std::map<uint16_t, CmPtInfo> ptView;
auto ret = agent::BioClientAgent::Instance()->GetPtView(mCurPtTimes, ptView);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Get pt view failed, ret:" << ret << ".");
return ret;
}
if (!ptView.empty()) {
mLock.LockWrite();
mPtView.clear();
mPtView.swap(ptView);
mLock.UnLock();
}
CLIENT_LOG_INFO("Cur pt times:" << mCurPtTimes << ", ptview size:" << mPtView.size());
return BIO_OK;
}
BResult MirrorClient::QueryCacheResourceImpl(std::vector<CacheResourcesDesc> &nodeDesc)
{
CacheResourceRequest req;
req.comm = {MESSAGE_MAGIC, 0, 0, mLocalNid.VNodeId(), getpid()};
BResult ret = BIO_ERR;
BIO_TP_START(SDK_MIRROR_CLIENT_QUERY_CACHE_RESOURCE_SEND_FAIL, &ret, BIO_INNER_ERR);
ret = SendCacheResourceRequest(req, nodeDesc);
BIO_TP_END;
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send query cache resource request failed, ret:" << ret);
}
return ret;
}
BResult MirrorClient::SendCacheResourceRequest(CacheResourceRequest &req, std::vector<CacheResourcesDesc> &nodeDesc)
{
uint16_t localId = UINT16_MAX;
std::vector<uint16_t> remoteId;
mUpdateView();
auto nodeView = GetNodeView();
for (const auto &node : nodeView) {
if (node.second.status == CM_NODE_FAULT) {
continue;
}
if (node.first.nodeId == mLocalNid.VNodeId()) {
localId = mLocalNid.VNodeId();
continue;
}
remoteId.emplace_back(node.first.nodeId);
}
CalcCacheResourceLocal(req, localId, nodeDesc);
CalcCacheResourceRemote(req, remoteId, nodeDesc);
return BIO_OK;
}
BResult MirrorClient::GetCacheHitRatioImpl(std::unordered_map<uint16_t, CacheHitDesc> &nodeDesc)
{
CacheHitRequest req;
req.comm = {MESSAGE_MAGIC, 0, 0, mLocalNid.VNodeId(), getpid()};
BResult ret = BIO_ERR;
BIO_TP_START(SDK_MIRROR_CLIENT_QUERY_CACHE_HIT_SEND_FAIL, &ret, BIO_INNER_ERR);
ret = SendCacheHitRequest(req, nodeDesc);
BIO_TP_END;
if (UNLIKELY(ret != BIO_OK)) {
CLIENT_LOG_ERROR("Send get cache hit request failed, ret:" << ret);
}
return ret;
}
BResult MirrorClient::SendCacheHitRequest(CacheHitRequest &req, std::unordered_map<uint16_t, CacheHitDesc> &nodeDesc)
{
uint16_t localId = UINT16_MAX;
std::vector<uint16_t> remoteId;
mUpdateView();
auto nodeView = GetNodeView();
for (const auto &node : nodeView) {
if (node.second.status == CM_NODE_FAULT) {
continue;
}
if (node.first.nodeId == mLocalNid.VNodeId()) {
localId = mLocalNid.VNodeId();
continue;
}
remoteId.emplace_back(node.first.nodeId);
}
GetCacheHitLocal(req, localId, nodeDesc);
GetCacheHitRemote(req, remoteId, nodeDesc);
return BIO_OK;
}
void MirrorClient::GetCacheHitLocal(CacheHitRequest &req, uint16_t localId,
std::unordered_map<uint16_t, CacheHitDesc> &nodeDesc)
{
if (UNLIKELY(localId == UINT16_MAX)) {
return;
}
BResult ret = BIO_OK;
ret = agent::BioClientAgent::Instance()->GetCacheHitLocal(req, nodeDesc);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Send get cache hit request failed, ret: " << ret << ". nodeId: " << localId);
}
}
void MirrorClient::GetCacheHitRemote(CacheHitRequest &req, std::vector<uint16_t> &remoteId,
std::unordered_map<uint16_t, CacheHitDesc> &nodeDesc)
{
for (auto id : remoteId) {
CacheHitResponse rsp;
BResult ret = net::BioClientNet::Instance()->SendSync<CacheHitRequest, CacheHitResponse>(
static_cast<BioNodeId>(id), BIO_OP_SDK_GET_CACHE_HIT, req, rsp);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Send get cache hit request failed, ret: " << ret << ". nodeId: " << id);
continue;
}
nodeDesc[rsp.nodeId].rCacheHitMemCount.store(rsp.rCacheHitMemCount);
nodeDesc[rsp.nodeId].rCacheHitDiskCount.store(rsp.rCacheHitDiskCount);
nodeDesc[rsp.nodeId].rCacheHitCount.store(rsp.rCacheHitCount);
nodeDesc[rsp.nodeId].rCacheTotalCount.store(rsp.rCacheTotalCount);
nodeDesc[rsp.nodeId].wCacheHitMemCount.store(rsp.wCacheHitMemCount);
nodeDesc[rsp.nodeId].wCacheHitDiskCount.store(rsp.wCacheHitDiskCount);
nodeDesc[rsp.nodeId].wCacheHitCount.store(rsp.wCacheHitCount);
nodeDesc[rsp.nodeId].wCacheTotalCount.store(rsp.wCacheTotalCount);
nodeDesc[rsp.nodeId].backendHitCount.store(rsp.backendHitCount);
}
}
void MirrorClient::CalcCacheResourceLocal(CacheResourceRequest &req, uint16_t localId,
std::vector<CacheResourcesDesc> &nodeDesc)
{
if (UNLIKELY(localId == UINT16_MAX)) {
return;
}
BResult ret = agent::BioClientAgent::Instance()->CalcCacheResourceLocal(req, nodeDesc);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Send calc cache resource request failed, ret: " << ret << ". nodeId: " << localId);
}
}
void MirrorClient::CalcCacheResourceRemote(CacheResourceRequest &req, std::vector<uint16_t> &remoteId,
std::vector<CacheResourcesDesc> &nodeDesc)
{
for (auto id : remoteId) {
CacheResourceResponse rsp;
BResult ret = net::BioClientNet::Instance()->SendSync<CacheResourceRequest, CacheResourceResponse>(
static_cast<BioNodeId>(id), BIO_OP_SDK_QUERY_CACHE_RESOURCE, req, rsp);
if (ret != BIO_OK) {
CLIENT_LOG_ERROR("Send calc cache resource request failed, ret: " << ret << ". nodeId: " << id);
continue;
}
CacheResourcesDesc tempDesc;
tempDesc.nodeId = rsp.nodeId;
tempDesc.rCacheMemCapacity = rsp.rCacheMemCapacity;
tempDesc.rCacheDiskCapacity = rsp.rCacheDiskCapacity;
tempDesc.wCacheMemCapacity = rsp.wCacheMemCapacity;
tempDesc.wCacheDiskCapacity = rsp.wCacheDiskCapacity;
tempDesc.rCacheDiskUsedSize = rsp.rCacheDiskUsedSize;
tempDesc.rCacheMemUsedSize = rsp.rCacheMemUsedSize;
tempDesc.wCacheMemUsedSize = rsp.wCacheMemUsedSize;
tempDesc.wCacheDiskUsedSize = rsp.wCacheDiskUsedSize;
nodeDesc.push_back(tempDesc);
}
}