這篇文章主要介紹Ceph中RGW是如何向底層OSD發送Message的,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!
在src/cls/rgw/cls_rgw_client.cc可以看到如下函數:
int cls_rgw_lc_set_entry(IoCtx& io_ctx, string& oid, pair<string, int>& entry)
{
bufferlist in, out;
cls_rgw_lc_set_entry_op call;
call.entry = entry;
::encode(call, in);
int r = io_ctx.exec(oid, "rgw", "lc_set_entry", in, out);
return r;
}繼續跟蹤io_ctx.exec()這個函數調用, 在src/librados/librados.cc可以查看到相應的函數實現如下:
int librados::IoCtx::exec(const std::string& oid, const char *cls, const char *method,
bufferlist& inbl, bufferlist& outbl)
{
object_t obj(oid);
return io_ctx_impl->exec(obj, cls, method, inbl, outbl);
}繼續跟蹤io_ctx_impl->exec()這個函數調用,在librados/IoCtxImpl.cc中看到如下實現:
int librados::IoCtxImpl::exec(const object_t& oid,
const char *cls, const char *method,
bufferlist& inbl, bufferlist& outbl)
{
::ObjectOperation rd;
prepare_assert_ops(&rd);
rd.call(cls, method, inbl);
return operate_read(oid, &rd, &outbl);
}rd.call()此函數將該操作封裝成OSDOp,放入ObjectOperation對象的vector集合中。 在最后的operate_read(oid, &rd, &outbl)函數中發起讀寫請求操作:
int librados::IoCtxImpl::operate_read(const object_t& oid,
::ObjectOperation *o,
bufferlist *pbl,
int flags)
{
if (!o->size())
return 0;
Mutex mylock("IoCtxImpl::operate_read::mylock");
Cond cond;
bool done;
int r;
version_t ver;
Context *onack = new C_SafeCond(&mylock, &cond, &done, &r);
int op = o->ops[0].op.op;
ldout(client->cct, 10) << ceph_osd_op_name(op) << " oid=" << oid << " nspace=" << oloc.nspace << dendl;
Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc,
*o, snap_seq, pbl, flags,
onack, &ver);
lock->Lock();
objecter->op_submit(objecter_op);
lock->Unlock();
mylock.Lock();
while (!done)
cond.Wait(mylock);
mylock.Unlock();
ldout(client->cct, 10) << "Objecter returned from "
<< ceph_osd_op_name(op) << " r=" << r << dendl;
set_sync_op_version(ver);
return r;
}需要說明的是operate_read(oid, &rd, &outbl)可以分解為一下三個步驟:
創建一個Op實例,數據結構變成了Objecter::Op
Objecter::Op *objecter_op = objecter->prepare_read_op(oid, oloc, *o, snap_seq, pbl, flags, onack, &ver);
操作提交到objecter層,操作對象類型變為Objecter::Op, 函數實現在osdc/Objecter.cc:
objecter->op_submit(objecter_op)
繼續調用ceph_tid_t Objecter::_op_submit()函數,函數實現在osdc/Objecter.cc: 省略了部分代碼,重點關注send_op(op)
ceph_tid_t Objecter::_op_submit(Op *op)
{
// pick tid if we haven't got one yet
if (op->tid == ceph_tid_t(0)) {
ceph_tid_t mytid = ++last_tid;
op->tid = mytid;
}
assert(client_inc >= 0);
// pick target
num_homeless_ops++; // initially; recalc_op_target() will decrement if it finds a target
int r = recalc_op_target(op);
bool check_for_latest_map = (r == RECALC_OP_TARGET_POOL_DNE);
............
else if (op->session) {
send_op(op);
}
.............
}這里的send_op(op)就是我們要關注的重點了. 從這里開始就會用到網絡層提供的各種操作將消息,也就是這里的op發送出去. 這里可以看成是調用網絡層的一個起點.
下面的代碼就和網絡層有關系了。
在網絡層中,需要注意的是類Messenger是核心的數據結構。同時也是個抽象基類,在Firefly版本中,由于網絡通信類型只實現了SimpleMessenger這一單一類型。在后面,就會看到SimpleMessenger是繼承自Messenger類,很多方法最終都是調用的是SimpleMessenger(在此也可以體會到多態思想)。 首先,看一下Objecter類的聲明(其他部分已省略):
class Objecter : public md_config_obs_t {
...........
public:
Messenger *messenger;
........
}在這個類中聲明了messenger. 從ceph_tid_t Objecter::_op_submit(Op *op) 中可以看到,最后調用了send_op()函數。 這個函數末尾:
messenger->send_message(m, op->session->con);
可以看出,需要發送的消息是: m。 發送到哪里去呢? 通過**op->session->con**可以獲取到相應的連接。
以上是“Ceph中RGW是如何向底層OSD發送Message的”這篇文章的所有內容,感謝各位的閱讀!希望分享的內容對大家有幫助,更多相關知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。