ceph:bufferlist實現(xiàn)

bufferlist是ceph的底層組件旭从,用于存儲二進制數(shù)據(jù),其存儲的數(shù)據(jù)可以直接寫入磁盤场仲,在代碼中有很廣泛的使用和悦。

bufflist對應(yīng)的類為buffer::list(using bufferlist = buffer::list;),而buffer::list又基于buffer::ptr和buffer::raw實現(xiàn)渠缕,探討buffer::list的實現(xiàn)鸽素,不能跳過它們。

buffer::raw

raw的數(shù)據(jù)成員部分代碼如下:

class buffer::raw
{
public:
  char *data;
  unsigned len;
  std::atomic<unsigned> nref{0};
  int mempool;

  mutable ceph::spinlock crc_spinlock;
  map<pair<size_t, size_t>, pair<uint32_t, uint32_t>> crc_map;
  ......
};

最基本的成員:data是指向具體數(shù)據(jù)的指針亦鳞,len是數(shù)據(jù)的長度馍忽,nref是引用計數(shù)。而mempool是其對應(yīng)的內(nèi)存池的index燕差,這個和data空間的分配有關(guān)遭笋,暫時不去管它。

data指向的數(shù)據(jù)有很多來源谁不,直接通過malloc從內(nèi)存分配只是最基礎(chǔ)的一種坐梯,可能還來自mmap內(nèi)存映射的空間等等。對于每一種數(shù)據(jù)來源刹帕,需要不同邏輯的數(shù)據(jù)分配和釋放函數(shù)吵血,所以raw對應(yīng)了很多子類谎替,分別表示不同的數(shù)據(jù)。

舉個例子蹋辅,對應(yīng)于malloc的raw子類為buffer::raw_malloc钱贯,構(gòu)造和析構(gòu)函數(shù)中實現(xiàn)了使用malloc進行數(shù)據(jù)分配和釋放的邏輯:

class buffer::raw_malloc : public buffer::raw
{
public:
  MEMPOOL_CLASS_HELPERS();

  explicit raw_malloc(unsigned l) : raw(l)
  {
    if (len)
    {
      data = (char *)malloc(len);
      if (!data)
        throw bad_alloc();
    }
    else
    {
      data = 0;
    }
    inc_total_alloc(len);
    inc_history_alloc(len);
    bdout << "raw_malloc " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl;
  }
  raw_malloc(unsigned l, char *b) : raw(b, l)
  {
    inc_total_alloc(len);
    bdout << "raw_malloc " << this << " alloc " << (void *)data << " " << l << " " << buffer::get_total_alloc() << bendl;
  }
  ~raw_malloc() override
  {
    free(data);
    dec_total_alloc(len);
    bdout << "raw_malloc " << this << " free " << (void *)data << " " << buffer::get_total_alloc() << bendl;
  }
  raw *clone_empty() override
  {
    return new raw_malloc(len);
  }
};

buffer::ptr

ptr是基于raw的,成員部分如下:

class CEPH_BUFFER_API ptr
{
  raw *_raw;
  unsigned _off, _len;
  ......
};

ptr和raw的關(guān)系和golang中splice和array的關(guān)系有點像侦另。raw是真正存儲數(shù)據(jù)的地方秩命,而ptr只是指向某個raw中的一段的指針。其數(shù)據(jù)成員 _raw為指向raw的指針褒傅,_off表示數(shù)據(jù)起始偏移弃锐,_len表示數(shù)據(jù)長度。

這邊還有提一下ptr的append函數(shù)殿托,直觀上ptr不應(yīng)該提供append函數(shù)霹菊,事實上ptr的append確實很局限,只有當(dāng)ptr對應(yīng)的raw區(qū)域后方有空閑空間的時候支竹,才能append成功旋廷,至于空間不夠的情況,應(yīng)該是交給list等高層類來處理礼搁。代碼如下:

unsigned buffer::ptr::append(const char *p, unsigned l)
{
  assert(_raw);
  assert(l <= unused_tail_length());
  char *c = _raw->data + _off + _len;
  maybe_inline_memcpy(c, p, l, 32);
  _len += l;
  return _len + _off;
}

buffer::list

簡單來說饶碘,list就是一個ptr組成的鏈表:

class CEPH_BUFFER_API list
{
  // my private bits
  std::list<ptr> _buffers;
  unsigned _len;
  unsigned _memcopy_count; //the total of memcopy using rebuild().
  ptr append_buffer;       // where i put small appends.
  ......
};

_buffers是一個ptr的鏈表,_len是整個_buffers中所有的ptr的數(shù)據(jù)的總長度馒吴,_memcopy_count用于統(tǒng)計memcopy的字節(jié)數(shù)扎运,append_buffer是用于優(yōu)化append操作的緩沖區(qū),可以看出bufferlist將數(shù)據(jù)以不連續(xù)鏈表的方式存儲饮戳。

在說具體函數(shù)之前绪囱,先說一下bufferlist的迭代器:

  template <bool is_const>
  class CEPH_BUFFER_API iterator_impl
      : public std::iterator<std::forward_iterator_tag, char>
  {
  protected:
    bl_t *bl;
    list_t *ls;   // meh.. just here to avoid an extra pointer dereference..
    unsigned off; // in bl
    list_iter_t p;
    unsigned p_off; // in *p
    ......
  };

其數(shù)據(jù)成員的含義如下:

  • bl:指針,指向bufferlist
  • ls:指針莹捡,指向bufferlist的成員 _buffers
  • p: 類型是std::list::iterator,用來迭代遍歷bufferlist中的bufferptr
  • p_off:當(dāng)前位置在對應(yīng)的bufferptr中的偏移量
  • off:當(dāng)前位置在整個bufferlist中的偏移量

迭代器中提供的seek(unsigned o)advance(int o)等函數(shù)中的o都是指bufferlist的偏移扣甲,而不是單個ptr內(nèi)的偏移篮赢。

下面對bufferlist中我遇到的一些函數(shù)進行分析,其他函數(shù)遇到再說琉挖。

clear()

清空bufferlist中的內(nèi)容

push_front(raw* / ptr &)

push_back(raw* / ptr &)

在_buffers的前面或后面增加新的ptr

rebuild()

rebuild(ptr &nb)

將bufferlist中buffers鏈表中所有的ptr中的數(shù)據(jù)存到一個ptr中启泣,并將_buffers原有數(shù)據(jù)clear,然后將新的單個ptr push到_buffers中示辈。
帶參數(shù)時使用參數(shù)傳入的ptr作為目標ptr寥茫,不帶參數(shù)時自己創(chuàng)建一個ptr。

claim(list &bl, unsigned int flags = CLAIM_DEFAULT);

將bl的數(shù)據(jù)拿過來矾麻,替換原有的數(shù)據(jù)纱耻。調(diào)用后bl數(shù)據(jù)被清空芭梯。

claim_append(list &bl, unsigned int flags = CLAIM_DEFAULT);

claim_prepend(list &bl, unsigned int flags = CLAIM_DEFAULT);

將bl的數(shù)據(jù)拿過來,splice到_buffers的尾部/頭部弄喘。

append(...)

將數(shù)據(jù)追加到_buffers尾部玖喘,已有ptr空間不夠時,會自動分配新的ptr蘑志。

splice(unsigned off, unsigned len, list *claim_by = 0)

_buffers中總偏移off處長度為len的數(shù)據(jù)累奈,move到claim_by對應(yīng)的bufferlist的尾部。注意是move不是copy急但。

write(int off, int len, std::ostream &out)

_buffers中總偏移量off處長度為len的數(shù)據(jù)澎媒,寫入到ostream。注意是copy波桩,不是move戒努。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市突委,隨后出現(xiàn)的幾起案子柏卤,更是在濱河造成了極大的恐慌,老刑警劉巖匀油,帶你破解...
    沈念sama閱讀 210,914評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件缘缚,死亡現(xiàn)場離奇詭異,居然都是意外死亡敌蚜,警方通過查閱死者的電腦和手機桥滨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評論 2 383
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弛车,“玉大人齐媒,你說我怎么就攤上這事》柞耍” “怎么了喻括?”我有些...
    開封第一講書人閱讀 156,531評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贫奠。 經(jīng)常有香客問我唬血,道長,這世上最難降的妖魔是什么唤崭? 我笑而不...
    開封第一講書人閱讀 56,309評論 1 282
  • 正文 為了忘掉前任拷恨,我火速辦了婚禮,結(jié)果婚禮上谢肾,老公的妹妹穿的比我還像新娘腕侄。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,381評論 5 384
  • 文/花漫 我一把揭開白布冕杠。 她就那樣靜靜地躺著微姊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拌汇。 梳的紋絲不亂的頭發(fā)上柒桑,一...
    開封第一講書人閱讀 49,730評論 1 289
  • 那天,我揣著相機與錄音噪舀,去河邊找鬼魁淳。 笑死,一個胖子當(dāng)著我的面吹牛与倡,可吹牛的內(nèi)容都是我干的界逛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼纺座,長吁一口氣:“原來是場噩夢啊……” “哼息拜!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起净响,我...
    開封第一講書人閱讀 37,643評論 0 266
  • 序言:老撾萬榮一對情侶失蹤少欺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后馋贤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赞别,經(jīng)...
    沈念sama閱讀 44,095評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,448評論 2 325
  • 正文 我和宋清朗相戀三年配乓,在試婚紗的時候發(fā)現(xiàn)自己被綠了仿滔。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,566評論 1 339
  • 序言:一個原本活蹦亂跳的男人離奇死亡犹芹,死狀恐怖崎页,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腰埂,我是刑警寧澤飒焦,帶...
    沈念sama閱讀 34,253評論 4 328
  • 正文 年R本政府宣布,位于F島的核電站屿笼,受9級特大地震影響荒给,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜刁卜,卻給世界環(huán)境...
    茶點故事閱讀 39,829評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望曙咽。 院中可真熱鬧蛔趴,春花似錦、人聲如沸例朱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至箫荡,卻和暖如春魁亦,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背羔挡。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評論 1 264
  • 我被黑心中介騙來泰國打工洁奈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人绞灼。 一個月前我還...
    沈念sama閱讀 46,248評論 2 360
  • 正文 我出身青樓利术,卻偏偏與公主長得像,于是被迫代替她去往敵國和親低矮。 傳聞我的和親對象是個殘疾皇子印叁,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,440評論 2 348

推薦閱讀更多精彩內(nèi)容

  • android 為了高效的 IPC 通信做了很多工作,內(nèi)存管理就屬于其中之一军掂。傳統(tǒng)的 IPC 傳遞數(shù)據(jù)轮蜕,至少需要2...
    zjfclimin閱讀 4,036評論 0 4
  • 本篇文章是基于谷歌有關(guān)Graphic的一篇概覽文章的翻譯:http://source.android.com/de...
    lee_3do閱讀 7,107評論 2 21
  • 教程一:視頻截圖(Tutorial 01: Making Screencaps) 首先我們需要了解視頻文件的一些基...
    90后的思維閱讀 4,676評論 0 3
  • 決定離開上海了,自己回家學(xué)習(xí)一下順便旅游一下蝗锥,可是為什么好多人說我草率跃洛,沒堅持,堅持什么呢玛追?自己還都不夠優(yōu)秀税课,沒有...
    子晴瑄純閱讀 249評論 0 0
  • 自媒體時代為什么我不開公眾號了 現(xiàn)在,公眾號以新的形式影響著人們痊剖,公眾號取代了許多新聞韩玩,取代了許多雜志,取代了許多...
    舟?閱讀 547評論 2 3