国产精品久久久久久久久久久久久久_国产肉体ⅹxxx137大胆_国产精品mv_国产日韩中文字幕_国产福利一区二区三区在线视频_中文字幕www_久草最新_日韩av第一页在线播放_青青草在线视频网站_少妇淫片aaaaa毛片叫床爽_成人精品在线视频_超碰97免费观看_毛片一级视频_他掀开裙子把舌头伸进去添视频_天堂一区二区三区在线_黑人日比视频_一区在线看_一区日本_亚洲中文字幕无码中文字_国产一级视频免费看

hbase查詢一條數(shù)據(jù)的過程

系統(tǒng) 4792 0

HBase中的Client如何路由到正確的RegionServer

在HBase中,大部分的操作都是在RegionServer完成的,Client端想要插入,刪除,查詢數(shù)據(jù)都需要先找到相應(yīng)的RegionServer。什么叫相應(yīng)的RegionServer?就是管理你要操作的那個Region的RegionServer。Client本身并不知道哪個RegionServer管理哪個Region,那么它是如何找到相應(yīng)的RegionServer的?本文就是在研究源碼的基礎(chǔ)上揭秘這個過程。

在前面的文章“HBase存儲架構(gòu)”中我們已經(jīng)討論了HBase基本的存儲架構(gòu)。在此基礎(chǔ)上我們引入兩個特殊的概念:-ROOT-和.META.。這是什么?它們是HBase的兩張內(nèi)置表,從存儲結(jié)構(gòu)和操作方法的角度來說,它們和其他HBase的表沒有任何區(qū)別,你可以認(rèn)為這就是兩張普通的表,對于普通表的操作對它們都適用。它們與眾不同的地方是HBase用它們來存貯一個重要的系統(tǒng)信息——Region的分布情況以及每個Region的詳細(xì)信息。

好了,既然我們前面說到-ROOT-和.META.可以被看作是兩張普通的表,那么它們和其他表一樣就應(yīng)該有自己的表結(jié)構(gòu)。沒錯,它們有自己的表結(jié)構(gòu),并且這兩張表的表結(jié)構(gòu)是相同的,在分析源碼之后我將這個表結(jié)構(gòu)大致的畫了出來:

我們來仔細(xì)分析一下這個結(jié)構(gòu),每條Row記錄了一個Region的信息。

首先是RowKey,RowKey由三部分組成:TableName, StartKey 和 TimeStamp。RowKey存儲的內(nèi)容我們又稱之為Region的Name。哦,還記得嗎?我們在前面的文章中提到的,用來存放Region的文件夾的名字是RegionName的Hash值,因為RegionName可能包含某些非法字符。現(xiàn)在你應(yīng)該知道為什么RegionName會包含非法字符了吧,因為StartKey是被允許包含任何值的。將組成RowKey的三個部分用逗號連接就構(gòu)成了整個RowKey,這里TimeStamp使用十進(jìn)制的數(shù)字字符串來表示的。這里有一個RowKey的例子:

Table1,RK10000,12345678

然后是表中最主要的Family:info,info里面包含三個Column:regioninfo, server, serverstartcode。其中regioninfo就是Region的詳細(xì)信息,包括StartKey, EndKey 以及每個Family的信息等等。server存儲的就是管理這個Region的RegionServer的地址。

所以當(dāng)Region被拆分、合并或者重新分配的時候,都需要來修改這張表的內(nèi)容。

到目前為止我們已經(jīng)學(xué)習(xí)了必須的背景知識,下面我們要正式開始介紹Client端尋找RegionServer的整個過程。我打算用一個假想的例子來學(xué)習(xí)這個過程,因此我先構(gòu)建了假想的-ROOT-表和.META.表。

我們先來看.META.表,假設(shè)HBase中只有兩張用戶表:Table1和Table2,Table1非常大,被劃分成了很多Region,因此在.META.表中有很多條Row用來記錄這些Region。而Table2很小,只是被劃分成了兩個Region,因此在.META.中只有兩條Row用來記錄。這個表的內(nèi)容看上去是這個樣子的:

.META.

現(xiàn)在假設(shè)我們要從Table2里面插尋一條RowKey是RK10000的數(shù)據(jù)。那么我們應(yīng)該遵循以下步驟:

1. 從.META.表里面查詢哪個Region包含這條數(shù)據(jù)。

2. 獲取管理這個Region的RegionServer地址。

3. 連接這個RegionServer, 查到這條數(shù)據(jù)。

好,我們先來第一步。問題是.META.也是一張普通的表,我們需要先知道哪個RegionServer管理了.META.表,怎么辦?有一個方法,我們把管理.META.表的RegionServer的地址放到ZooKeeper上面不久行了,這樣大家都知道了誰在管理.META.。

貌似問題解決了,但對于這個例子我們遇到了一個新問題。因為Table1實在太大了,它的Region實在太多了,.META.為了存儲這些Region信息,花費了大量的空間,自己也需要劃分成多個Region。這就意味著可能有多個RegionServer在管理.META.。怎么辦?在ZooKeeper里面存儲所有管理.META.的RegionServer地址讓Client自己去遍歷?HBase并不是這么做的。

HBase的做法是用另外一個表來記錄.META.的Region信息,就和.META.記錄用戶表的Region信息一模一樣。這個表就是-ROOT-表。這也解釋了為什么-ROOT-和.META.擁有相同的表結(jié)構(gòu),因為他們的原理是一模一樣的。

假設(shè).META.表被分成了兩個Region,那么-ROOT-的內(nèi)容看上去大概是這個樣子的:

-ROOT-

hbase查詢一條數(shù)據(jù)的過程

hbase查詢一條數(shù)據(jù)的過程

這么一來Client端就需要先去訪問-ROOT-表。所以需要知道管理-ROOT-表的RegionServer的地址。這個地址被存在ZooKeeper中。默認(rèn)的路徑是:

/hbase/root-region-server

等等,如果-ROOT-表太大了,要被分成多個Region怎么辦?嘿嘿,HBase認(rèn)為-ROOT-表不會大到那個程度,因此-ROOT-只會有一個Region,這個Region的信息也是被存在HBase內(nèi)部的。

現(xiàn)在讓我們從頭來過,我們要查詢Table2中RowKey是RK10000的數(shù)據(jù)。整個路由過程的主要代碼在org.apache.hadoop.hbase.client.HConnectionManager.TableServers中:

private HRegionLocation locateRegion(final byte [] tableName,

final byte [] row, boolean useCache)

throws IOException{

if (tableName == null || tableName.length == 0) {

throw new IllegalArgumentException(

“table name cannot be null or zero length”);

}

if (Bytes.equals(tableName, ROOT_TABLE_NAME)) {

synchronized (rootRegionLock) {

// This block guards against two threads trying to find the root

// region at the same time. One will go do the find while the

// second waits. The second thread will not do find.

if (!useCache || rootRegionLocation == null) {

this.rootRegionLocation = locateRootRegion();

}

return this.rootRegionLocation;

}

} else if (Bytes.equals(tableName, META_TABLE_NAME)) {

return locateRegionInMeta(ROOT_TABLE_NAME, tableName, row, useCache,

metaRegionLock);

} else {

// Region not in the cache – have to go to the meta RS

return locateRegionInMeta(META_TABLE_NAME, tableName, row, useCache,userRegionLock);

}

}

這是一個遞歸調(diào)用的過程:

獲取Table2,RowKey為RK10000的RegionServer

=>

獲取.META.,RowKey為Table2,RK10000, 99999999999999的RegionServer

=>

獲取-ROOT-,RowKey為.META.,Table2,RK10000,99999999999999,99999999999999的RegionServer

=>

獲取-ROOT-的RegionServer

=>

從ZooKeeper得到-ROOT-的RegionServer

=>

從-ROOT-表中查到RowKey最接近(小于)

.META.,Table2,RK10000,99999999999999,99999999999999的一條Row,并得到.META.的RegionServer

=>

從.META.表中查到RowKey最接近(小于)Table2,RK10000, 99999999999999的一條Row,并得到Table2的RegionServer

=>

從Table2中查到RK10000的Row

到此為止Client完成了路由RegionServer的整個過程,在整個過程中使用了添加“99999999999999”后綴并查找最接近(小于)RowKey的方法。對于這個方法大家可以仔細(xì)揣摩一下,并不是很難理解。

最后要提醒大家注意兩件事情:

  1. 在整個路由過程中并沒有涉及到MasterServer,也就是說HBase日常的數(shù)據(jù)操作并不需要MasterServer,不會造成MasterServer的負(fù)擔(dān)。
  2. Client端并不會每次數(shù)據(jù)操作都做這整個路由過程,很多數(shù)據(jù)都會被Cache起來。至于如何Cache,則不在本文的討論范圍之內(nèi)。

hbase查詢一條數(shù)據(jù)的過程


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |