當(dāng)前位置:首頁(yè) > 芯聞號(hào) > 充電吧
[導(dǎo)讀]這里的comparator包括抽象類Comparator及其兩個(gè)實(shí)現(xiàn)類:一個(gè)是內(nèi)置的BytewiseComparatorImpl,另一個(gè)是InternalKeyComparator。一.Compara

這里的comparator包括抽象類Comparator及其兩個(gè)實(shí)現(xiàn)類:一個(gè)是內(nèi)置的BytewiseComparatorImpl,另一個(gè)是InternalKeyComparator。
一.Comparator
Comparator只是導(dǎo)出了幾個(gè)接口。

class?Comparator?{
?public:
??virtual?~Comparator();


??//?Three-way?comparison.??Returns?value:
??//???<?0?iff?"a"?<?"b",
??//???==?0?iff?"a"?==?"b",
??//???>?0?iff?"a"?>?"b"
??virtual?int?Compare(const?Slice&?a,?const?Slice&?b)?const?=?0;


??//?The?name?of?the?comparator.??Used?to?check?for?comparator
??//?mismatches?(i.e.,?a?DB?created?with?one?comparator?is
??//?accessed?using?a?different?comparator.
??//
??//?The?client?of?this?package?should?switch?to?a?new?name?whenever
??//?the?comparator?implementation?changes?in?a?way?that?will?cause
??//?the?relative?ordering?of?any?two?keys?to?change.
??//
??//?Names?starting?with?"leveldb."?are?reserved?and?should?not?be?used
??//?by?any?clients?of?this?package.
??//返回comparator的名字
??virtual?const?char*?Name()?const?=?0;


??//?Advanced?functions:?these?are?used?to?reduce?the?space?requirements
??//?for?internal?data?structures?like?index?blocks.


??//?If?*start?<?limit,?changes?*start?to?a?short?string?in?[start,limit).
??//?Simple?comparator?implementations?may?return?with?*start?unchanged,
??//?i.e.,?an?implementation?of?this?method?that?does?nothing?is?correct.
??//?這兩個(gè)函數(shù)作用是減少像index?blocks這樣的內(nèi)部數(shù)據(jù)結(jié)構(gòu)占用的空間。
??//?如果*start?<?limit,就在[start,limit)中找到一個(gè)短字符串,并賦給*start返回。
??//?當(dāng)然返回的*start可能沒(méi)變化(*start==limit),此時(shí)這個(gè)函數(shù)相當(dāng)于啥都沒(méi)干,這也是正確的。
??virtual?void?FindShortestSeparator(
??????std::string*?start,
??????const?Slice&?limit)?const?=?0;


??//?Changes?*key?to?a?short?string?>=?*key.
??//?Simple?comparator?implementations?may?return?with?*key?unchanged,
??//?i.e.,?an?implementation?of?this?method?that?does?nothing?is?correct.
??//?將*key變成一個(gè)比原*key大的短字符串,并賦值給*key返回。
??virtual?void?FindShortSuccessor(std::string*?key)?const?=?0;
};

二.BytewiseComparatorImpl
BytewiseComparatorImpl是按字典逐字節(jié)序進(jìn)行比較的,也就是說(shuō)i>helloworld,因?yàn)橄缺容^i和h,i>h,比較結(jié)束。

class?BytewiseComparatorImpl?:?public?Comparator?{
?public:
??BytewiseComparatorImpl()?{?}


??virtual?const?char*?Name()?const?{
????return?"leveldb.BytewiseComparator";
??}
??//?直接調(diào)用Slice的compare函數(shù)
??virtual?int?Compare(const?Slice&?a,?const?Slice&?b)?const?{
????return?a.compare(b);
??}
??//?FindShortestSeparator找到start、limit之間最短的字符串,如“helloworld”和”hellozoomer”之間最短的key可以是”hellox”。
??virtual?void?FindShortestSeparator(
??????std::string*?start,
??????const?Slice&?limit)?const?{
????//?找到共同前綴的長(zhǎng)度
????size_t?min_length?=?std::min(start->size(),?limit.size());
????size_t?diff_index?=?0;
????while?((diff_index?<?min_length)?&&
???????????((*start)[diff_index]?==?limit[diff_index]))?{
??????diff_index++;
????}
????//?如果一個(gè)字符串是另個(gè)一字符串的前綴,無(wú)需做截短操作,否則進(jìn)入else。
????if?(diff_index?>=?min_length)?{
??????//?Do?not?shorten?if?one?string?is?a?prefix?of?the?other
????}?else?{
??????uint8_t?diff_byte?=?static_cast((*start)[diff_index]);
??????if?(diff_byte?<?static_cast(0xff)?&&
??????????diff_byte?+?1?<?static_cast(limit[diff_index]))?{
????????(*start)[diff_index]++;
????????start->resize(diff_index?+?1);
????????assert(Compare(*start,?limit)?<?0);
??????}
????}
??}
??//?FindShortSuccessor則更極端,用于找到比key大的最短字符串,如傳入“helloworld”,返回的key可能是“i”而已。
??virtual?void?FindShortSuccessor(std::string*?key)?const?{
????//?Find?first?character?that?can?be?incremented
????size_t?n?=?key->size();
????for?(size_t?i?=?0;?i?<?n;?i++)?{
??????const?uint8_t?byte?=?(*key)[i];
??????if?(byte?!=?static_cast(0xff))?{
????????(*key)[i]?=?byte?+?1;
????????key->resize(i+1);
????????return;
??????}
????}
????//?*key?is?a?run?of?0xffs.??Leave?it?alone.
??}
};

三.Internal Key
1.Internal Key的結(jié)構(gòu)。
下面是一個(gè)未編碼前,或者說(shuō)是一個(gè)解碼后的Internal Key結(jié)構(gòu),它由user_key、sequence和type三個(gè)字段組成。

struct?ParsedInternalKey?{
??Slice?user_key;
??SequenceNumber?sequence;
??ValueType?type;


??ParsedInternalKey()?{?}??//?Intentionally?left?uninitialized?(for?speed)
??ParsedInternalKey(const?Slice&?u,?const?SequenceNumber&?seq,?ValueType?t)
??????:?user_key(u),?sequence(seq),?type(t)?{?}
??std::string?DebugString()?const;
};

2.Internal Key的編碼
源碼中通過(guò)InternalKey類封裝了Internal Key的相關(guān)操作。編碼的用到的函數(shù)如下。

void?AppendInternalKey(std::string*?result,?const?ParsedInternalKey&?key)?{
??result->append(key.user_key.data(),?key.user_key.size());
??PutFixed64(result,?PackSequenceAndType(key.sequence,?key.type));
}

static?uint64_t?PackSequenceAndType(uint64_t?seq,?ValueType?t)?{
??assert(seq?<=?kMaxSequenceNumber);
??assert(t?<=?kValueTypeForSeek);
??return?(seq?<<?8)?|?t;
}

AppendInternalKey函數(shù)先把user_key添加到*result中,然后用PackSequenceAndType函數(shù)將sequence和type打包,并將打包的結(jié)果添加到*result中。
PutFixed64函數(shù)只是簡(jiǎn)單的進(jìn)行了拷貝,詳見(jiàn)博客:LevelDB源碼分析之一:coding
PackSequenceAndType函數(shù)的原理是先將seq左移8位,然后和t進(jìn)行或操作,相當(dāng)于把t放到了seq的低8為。為什么seq要小于等于kMaxSequenceNumber呢。
因?yàn)閗MaxSequenceNumber的值如下所示。

typedef?uint64_t?SequenceNumber;
//?We?leave?eight?bits?empty?at?the?bottom?so?a?type?and?sequence#
//?can?be?packed?together?into?64-bits.
//0x1ull:u-unsigned?無(wú)符號(hào);l-long?長(zhǎng)整型,ll就是64位整型。整個(gè)0x1ull代表的含義是無(wú)符號(hào)64位整型常量1,用16進(jìn)制表示。
static?const?SequenceNumber?kMaxSequenceNumber?=?((0x1ull?<<?56)?-?1);

用二進(jìn)制表示就是:0000 0000 1111 1111 1111 1111 1111 1111。如果seq大于kMaxSequenceNumber,左移8位的話會(huì)移出界。
3.Internal key的解碼

inline?bool?ParseInternalKey(const?Slice&?internal_key,
?????????????????????????????ParsedInternalKey*?result)?{
??const?size_t?n?=?internal_key.size();
??if?(n?<?8)?return?false;
??//?DecodeFixed64函數(shù)是PutFixed64函數(shù)的逆過(guò)程,返回sequence和type的打包結(jié)果,并賦值給num。
??uint64_t?num?=?DecodeFixed64(internal_key.data()?+?n?-?8);
??//?截取低8位,賦值給c
??unsigned?char?c?=?num?&?0xff;
??//?右移8位,賦值給sequence
??result->sequence?=?num?>>?8;
??//?將c轉(zhuǎn)換為type
??result->type?=?static_cast(c);
??//?取出user_key
??result->user_key?=?Slice(internal_key.data(),?n?-?8);
??return?(c?<=?static_cast(kTypeValue));
}

通過(guò)上述解碼函數(shù)可以將編碼后的internal_key解碼為* result。為了使用方便,源碼中還專門為解碼user_key和type提供了兩個(gè)函數(shù)。

//?Returns?the?user?key?portion?of?an?internal?key.
inline?Slice?ExtractUserKey(const?Slice&?internal_key)?{
??assert(internal_key.size()?>=?8);
??return?Slice(internal_key.data(),?internal_key.size()?-?8);
}

inline?ValueType?ExtractValueType(const?Slice&?internal_key)?{
??assert(internal_key.size()?>=?8);
??const?size_t?n?=?internal_key.size();
??uint64_t?num?=?DecodeFixed64(internal_key.data()?+?n?-?8);
??unsigned?char?c?=?num?&?0xff;
??return?static_cast(c);
}

四.InternalKeyComparator
InternalKeyComparator是要重點(diǎn)關(guān)注的一個(gè)比較器,它用來(lái)比較內(nèi)部鍵(Internal Key)。內(nèi)部鍵值是為了方便處理,將原普通鍵、序列號(hào)和值類型組成的新鍵。
先看下Compare函數(shù)

int?InternalKeyComparator::Compare(const?Slice&?akey,?const?Slice&?bkey)?const?{
??//?Order?by:
??//????increasing?user?key?(according?to?user-supplied?comparator)
??//????decreasing?sequence?number
??//????decreasing?type?(though?sequence#?should?be?enough?to?disambiguate)
??int?r?=?user_comparator_->Compare(ExtractUserKey(akey),?ExtractUserKey(bkey));
??if?(r?==?0)?{
????const?uint64_t?anum?=?DecodeFixed64(akey.data()?+?akey.size()?-?8);
????const?uint64_t?bnum?=?DecodeFixed64(bkey.data()?+?bkey.size()?-?8);
????if?(anum?>?bnum)?{
??????r?=?-1;
????}?else?if?(anum?<?bnum)?{
??????r?=?+1;
????}
??}
??return?r;
}

1)首先比較user_key,如果user_key不相同,就直接返回比較結(jié)果,否則繼續(xù)進(jìn)行第二步。user_comparator_是用戶指定的比較器,在InternalKeyComparator構(gòu)造時(shí)傳入。
2)在user_key相同的情況下,比較sequence_numer|value type然后返回結(jié)果(注意每個(gè)Internal Key的sequence_number是唯一的,因此不可能出現(xiàn)anum==bnum的情況)
再看看FindShortestSeparator函數(shù)

void?InternalKeyComparator::FindShortestSeparator(
??????std::string*?start,
??????const?Slice&?limit)?const?{
??//?Attempt?to?shorten?the?user?portion?of?the?key
??Slice?user_start?=?ExtractUserKey(*start);
??Slice?user_limit?=?ExtractUserKey(limit);
??std::string?tmp(user_start.data(),?user_start.size());
??user_comparator_->FindShortestSeparator(&tmp,?user_limit);
??if?(tmp.size()?<?user_start.size()?&&
??????user_comparator_->Compare(user_start,?tmp)?<?0)?{
????//?User?key?has?become?shorter?physically,?but?larger?logically.
????//?Tack?on?the?earliest?possible?number?to?the?shortened?user?key.
????PutFixed64(&tmp,?PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
????assert(this->Compare(*start,?tmp)?<?0);
????assert(this->Compare(tmp,?limit)?<?0);
????start->swap(tmp);
??}
}

1)該函數(shù)取出Internal Key中的user_key字段,根據(jù)用戶指定的comparator找到短字符串并替換user_start。此時(shí)user_start物理上是變短了,但是邏輯上卻變大了,原理詳見(jiàn)第二節(jié)的論述。
2)如果user_start被替換了,就用新的user_start更新Internal Key,并使用最大的sequence number。否則start保持不變。
接下來(lái)FindShortSuccessor函數(shù)

void?InternalKeyComparator::FindShortSuccessor(std::string*?key)?const?{
??Slice?user_key?=?ExtractUserKey(*key);
??std::string?tmp(user_key.data(),?user_key.size());
??user_comparator_->FindShortSuccessor(&tmp);
??if?(tmp.size()?<?user_key.size()?&&
??????user_comparator_->Compare(user_key,?tmp)?<?0)?{
????//?User?key?has?become?shorter?physically,?but?larger?logically.
????//?Tack?on?the?earliest?possible?number?to?the?shortened?user?key.
????PutFixed64(&tmp,?PackSequenceAndType(kMaxSequenceNumber,kValueTypeForSeek));
????assert(this->Compare(*key,?tmp)?<?0);
????key->swap(tmp);
??}
}

原理上與FindShortestSeparator相同。


本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉