本篇內(nèi)容介紹了“GlusterFS Translator API怎么使用”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比西林網(wǎng)站開(kāi)發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式西林網(wǎng)站制作公司更省心,省錢(qián),快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋西林地區(qū)。費(fèi)用合理售后完善,十多年實(shí)體公司更值得信賴。
在深入translator api前,我們必須理解關(guān)于此api所在上下文的兩個(gè)概念。
一個(gè)是文件系統(tǒng)api,主要通過(guò)分配表xlator_fops,來(lái)展露大多數(shù)文件系統(tǒng)功能。xlator_fops,就是組合linux vfs的file_operations, inode_operations, and super_operations三類操作在一個(gè)數(shù)組。要理解xlator如何工作,必須理解這些調(diào)用做什么,相互關(guān)系是什么,比如open/lookup/close,read/write,opendir/readdir,truncate,symlink等。
一個(gè)是xlator api的基礎(chǔ):是異步的并是基于回調(diào)的。意思是處理某個(gè)請(qǐng)求的代碼必須分為兩部分,一部分是在進(jìn)入下一個(gè)xlator前的處理,一部分是待下一個(gè)xlator處理完成請(qǐng)求后。用另一種方式解說(shuō),就是你的分配函數(shù)(xlator_fops的前半部分)調(diào)用下一個(gè)xlator的分配函數(shù),然后直接返回,并不阻塞。你的回調(diào)函數(shù)(后半部分)也許當(dāng)你調(diào)用下一個(gè)xlator的分配函數(shù)時(shí)就很快被調(diào)用,或者后面某個(gè)時(shí)間從某個(gè)完全不同的線程中被調(diào)用(常常是網(wǎng)絡(luò)傳輸?shù)膒oll線程)。在兩種情況下,回調(diào)都不能僅僅是從棧中取得上下文。Glusterfs確實(shí)提供了多種方式來(lái)在分配函數(shù)和回調(diào)函數(shù)間保持和傳遞上下文,但是不能僅僅依靠棧,需要我們編碼處理一些事情。
一個(gè)xlator的主要的分配表常常是fops(xlator動(dòng)態(tài)庫(kù)加載代碼利用dlsym查找操作op名)。fops包含指向所有正常文件系統(tǒng)的操作的指針。僅僅需要填充在本xlator我們感興趣的操作。任何其他的操作在運(yùn)行時(shí)基于默認(rèn)值來(lái)填充,并確定個(gè)回調(diào)函數(shù),并直接把此請(qǐng)求發(fā)到下一個(gè)xlator。
默認(rèn)函數(shù)和回調(diào)函數(shù)除了提供默認(rèn)功能,也有其他目的。當(dāng)我們需要添加某個(gè)新函數(shù)時(shí)到一個(gè)xlator時(shí),我們可以拷貝和修改那些相同操作的默認(rèn)函數(shù)等。這保證了正確的參數(shù)列表和合理的默認(rèn)行為。每個(gè)xlator也許有另外的分配表,比如cbk表,此表用來(lái)管理inode和文件描述子的生命周期(看inode和file descriptor context部分)
STACK_WIND and STACK_UNWIND是基于回調(diào)機(jī)制來(lái)實(shí)現(xiàn)的。這兩個(gè)函數(shù)不作用于gdb里類似的調(diào)用棧,而是一個(gè)獨(dú)立維護(hù)的棧,每個(gè)棧幀表示對(duì)xlators的調(diào)用。當(dāng)某個(gè)fop從內(nèi)核傳遞過(guò)來(lái)要調(diào)用時(shí),這個(gè)調(diào)用就作為一個(gè)request請(qǐng)求,從FUSE xlator 經(jīng)過(guò)DHT/AFR等到client xlator 直到server xlator 最后到posix xlator。 我們可以在用戶空間fop入口點(diǎn)做任何需要的處理(這里應(yīng)該就是fuse xlator),然后使用STACK_WIND沿著volume 文件設(shè)置的xlator 路徑,傳遞此請(qǐng)求。
define STACK_WIND(frame, rfn, obj, fn, params …)
STACK_WIND (frame, default_setxattr_cbk, FIRST_CHILD(this), FIRST_CHILD(this)→fops→setxattr, loc, dict, flags, xdata);
此函數(shù)的參數(shù)解釋如下:
frame:表示此請(qǐng)求的棧幀 stack frame。
rfn:當(dāng)下一個(gè)xlator或者其他xlator完成了此請(qǐng)求(包括前半部分和后半部分)后,要調(diào)用的回調(diào)函數(shù)。
obj:要傳遞到的那個(gè)xlator對(duì)象,也即下一個(gè)xlator,不是調(diào)用STACK_WIND的本xlator。多個(gè)子的情況如何處理?
fn:要調(diào)用的具體的xlator的操作,來(lái)自下一個(gè)xlator的fops分配表。
params …任何其他的入口點(diǎn)相關(guān)的參數(shù)(比如針對(duì)此fop的inodes, file descriptors, offsets, data buffers等)如前敘,rfn回調(diào)函數(shù)也許在STACK_WIND的調(diào)用內(nèi)部被調(diào)用,也或者后來(lái)在另一個(gè)環(huán)境中被調(diào)用。不調(diào)用下一個(gè)xlator就完成請(qǐng)求比如從cache中讀數(shù)據(jù),或者當(dāng)本xlator層完成對(duì)req的處理,要從本層的回調(diào)中把請(qǐng)求傳回上一個(gè)xlator時(shí),我們使用STACK_UNWIND。實(shí)際上,我們最好使用 STACK_UNWIND_STRICT。這個(gè)函數(shù)允許我們確定請(qǐng)求的種類,比如是open還是close等。
#define STACK_UNWIND_STRICT(op, frame, params …)
STACK_UNWIND_STRICT (symlink, frame, op_ret, op_errno, inode, buf, preparent, postparent, xdata);
參數(shù)解釋
參數(shù)op:操作類型,是open/還是其他。用來(lái)檢查額外參數(shù)是否匹配此fop。
params …:此請(qǐng)求的一些額外的參數(shù)
另外,在op和params直接,還有兩個(gè)參數(shù)op_ret和op_errno.雖然沒(méi)有在宏定義中出現(xiàn)。但在調(diào)用時(shí)還是要有的。
op_ret:fop的到目前的狀態(tài)(讀的字節(jié)數(shù)或者寫(xiě)的字節(jié)數(shù),常常0表示fop成功,-1表示失敗)
op_errno:標(biāo)準(zhǔn)錯(cuò)誤碼,在fop失敗的情況下
具體fop相關(guān)的參數(shù)有其他特殊的參數(shù),我們可以在params …中實(shí)現(xiàn)。但是我們也經(jīng)常需要這兩個(gè)參數(shù)
frame:當(dāng)前請(qǐng)求的stack frame。
this:表示此xlator實(shí)例的xlator對(duì)象
回調(diào)函數(shù)跟分配函數(shù)類似,除了在這兩個(gè)參數(shù)間有一個(gè)額外的參數(shù)cookie。是一個(gè)未定義數(shù)據(jù)類型的指針,由相應(yīng)的STACK_WIND存儲(chǔ)。默認(rèn)情況下,這是一個(gè)由STACK_WIND生成的stack frame的指針,但是STACK_WIND_COOKIE可以允許我們確定一個(gè)不同的值。在這種情況下,這個(gè)處于rfn和obj直接的額外參數(shù),可以從分配函數(shù)到其回調(diào)函數(shù)傳遞某些上下文。注意這個(gè)指針不能指向棧上的任何內(nèi)容,因?yàn)楫?dāng)回調(diào)函數(shù)調(diào)用時(shí),stack可能已經(jīng)不存在了。
另一個(gè)需要注意的:STACK_UNWIND也許會(huì)導(dǎo)致整個(gè)調(diào)用棧退出,此時(shí),最后的那個(gè)STACK_UNWIND調(diào)用將會(huì)釋放所有的frames。因此,永遠(yuǎn)不要期望在調(diào)用STACK_UNWIND后,當(dāng)前的frame內(nèi)容還是完好的。
每個(gè)xlator 棧幀有一個(gè)local 指針,是用來(lái)保存xlator相關(guān)的上下文。這是最基本的機(jī)制,用來(lái)在分配函數(shù)和回調(diào)間保存上下文。因此我們應(yīng)該習(xí)慣如下代碼模式
/* in dispatch function */
local = (my_locals_t *)GF_CALLOC(1,sizeof(*local),...);
if (!local) {
/* STACK_UNWIND with ENOMEM eror */
}
/* fill in my_locals_t fields */
frame->local = local;
/* in callback */
local = frame->local;
要記?。好總€(gè)幀frame的非NULL的local域當(dāng)要?dú)r(shí)要用GF_FREE來(lái)釋放,不用做其他的清理工作。如果local結(jié)構(gòu)里包含指針或?qū)ζ渌麑?duì)象的引用,需要我們自己進(jìn)行這些資源的清理。在毀棧前,內(nèi)存或者其他資源先清理是個(gè)好的習(xí)慣,為此就不能依靠GF_FREE來(lái)自動(dòng)清理。最安全的方式是定義我們自己的xlator相關(guān)的destructor,在調(diào)用STACK_UNWIND前手動(dòng)調(diào)用。
大多數(shù)分配函數(shù)和回調(diào)以文件描述子或節(jié)點(diǎn)inode為參數(shù)。file descriptor (fd_t) or an inode (inode_t)。常常,xlator需要保存一些這些對(duì)象的一些關(guān)于此xlator的一些上下文,以此,在一個(gè)請(qǐng)求的完整生命周期內(nèi)信息可以保持。例如,DHT xlator需要保存目錄的layout map和某些inode的已知的位置。有一套函數(shù)來(lái)存儲(chǔ)操作此類上下文。在每個(gè)函數(shù)中,第二個(gè)參數(shù)是此value相關(guān)的xlator對(duì)象的指針。value是64位無(wú)符號(hào)×××。
inode_ctx_put (inode, xlator, value) /* NB: put, not set */把value放到inode里?
inode_ctx_get (inode, xlator, &value)從inode中獲取值到value。
inode_ctx_del (inode, xlator, &value)
fd_ctx_set (fd, xlator, value) /* NB: set, not put */
fd_ctx_get (fd, xlator, &value)
fd_ctx_del (fd, xlator, &value)
_del函數(shù)實(shí)際是破壞性get,先返回然后刪除值。inode函數(shù)有兩個(gè)value的形式,比如inode_ctx_put2,操作兩個(gè)值。使用xlator指針作為key/index并不僅僅是為了好看。當(dāng)要?jiǎng)h除inode_t or fd_t時(shí), 刪除代碼要瀏覽上下文槽(估計(jì)就是遍歷所有xlator)。對(duì)于每個(gè)使用inode_t or fd_t的xlator的上下文槽,查看xlator的cbk表,調(diào)用其forget 或者release。如果上下文是個(gè)指針,需要手動(dòng)釋放資源。傳遞到分配函數(shù)和回調(diào)的inode_t or fd_t pointer參數(shù),僅僅是個(gè) borrowed reference。如果需要保證以后對(duì)象還在,需要調(diào)用inode_ref or fd_ref,來(lái)達(dá)到permanent reference。當(dāng)不再需要引用時(shí)可以 inode_unref or fd_unref。
另一個(gè)常見(jiàn)的參數(shù)類型dict _t,是一種通用詞典或者h(yuǎn)ash-map的數(shù)據(jù)結(jié)構(gòu),用來(lái)以字符串key/索引的方式保存任意值。例如,值可以是可變大小的有無(wú)符號(hào)的×××,字符串,二進(jìn)制blob。字符串,二進(jìn)制blob也許可以用GLusterfs函數(shù)free,也可以用glibc free?;蛘卟挥胒ree。保存引用計(jì)數(shù)的值的dict_t* 和the *data_t 對(duì)象,在引用數(shù)為0的情況下釋放資源。和inode和文件描述子一樣,如果想在以后使用接受到dict_t的對(duì)象,需要使用add _ref and _unref來(lái)管理其生命周期。詞典不僅僅用于分配函數(shù)和回調(diào)函數(shù)。也用于傳遞options到模塊,比如xlator的init函數(shù)所用的options。事實(shí)上,目前的xlator的init函數(shù)主體大部分是來(lái)解釋包含在詞典里的options。要給xlator添加一個(gè)option,也需要向xlator的options 數(shù)組里添加一項(xiàng)。每個(gè)option可以是個(gè)boolean/整型/字符串/路徑/xlator 名字/其他類型。如果是個(gè)字符串,可以確定一個(gè)正確的值的列表。解析后的options,加上其他xlator級(jí)別的信息,將存儲(chǔ)在xlator_t structure結(jié)構(gòu)(在大多數(shù)上下中用this表示)的private的成員變量中。
在一個(gè)xlator里的代碼,經(jīng)常需要枚舉其子xlator。要不找到一個(gè)滿足要求的子xlator的或者操作所有的子xlator。例如,對(duì)于DHT xlator,需要從所有的子xlator收集 hash-layout 映射,以確定文件應(yīng)該放到哪個(gè)子xlator;對(duì)于 AFR xlator,需要從子xlator中提取同一文件將要執(zhí)行的操作個(gè)數(shù)以便確定replication復(fù)制狀態(tài)。代碼范例如下: xlator_list_t *trav; xlator_t *xl;
for (trav = this->children; trav; trav = trav->next) { xl = trav->xlator; do_something(xl); }
如果目的是扇出一個(gè)請(qǐng)求到所有的子xlator,則需要一些努力。在一個(gè)分配函數(shù)里最常用的方式是如下 local→call_count = priv→num_children;
for (trav = this->children; trav; trav = trav->next) { xl = trav->xlator; STACK_WIND(frame,my_callback,xl,xl->fops->whatever,...); } 然后在回調(diào)函數(shù)中執(zhí)行 LOCK(&frame->lock); call_cnt = --local->call_count; UNLOCK(&frame->lock);
/* Do whatever you do for every call */
if (!call_cnt) { /* Do last-call processing. */ STACK_UNWIND(frame,op_ret,op_errno,...); }
return 0; 在某些情況下,可以使用STACK_WIND_COOKIE,這樣可以在回調(diào)中知道具體哪個(gè)調(diào)用返回了。可以查看AFR。
所有的xlator 函數(shù)使用類似SEDA和AT&T的STREAMS的異步調(diào)用規(guī)范。需要的調(diào)用幀和調(diào)用棧數(shù)據(jù)結(jié)構(gòu)功能上幾乎與Windows NT里的I/O requst packets 和irp 棧相同。許多xlator函數(shù)類似與fuse對(duì)應(yīng)的函數(shù),但是修改了或者添加了其他參數(shù)。
在xlator api里這是最基本的數(shù)據(jù)結(jié)構(gòu),call_frame_t and call_stack_txlators環(huán)境可以看作是個(gè)線程庫(kù),每個(gè)請(qǐng)求有自己一個(gè)輕量級(jí)線程。這個(gè)線程有自己的棧,但是這些調(diào)用棧比c棧更加結(jié)構(gòu)化,同時(shí)常常偏離棧的嚴(yán)格的FIFO語(yǔ)義。每個(gè)調(diào)用幀表示一個(gè)函數(shù)調(diào)用,函數(shù)調(diào)用也許是嵌套的。但是這些函數(shù)在c里實(shí)際上兩個(gè)調(diào)用--初始部分執(zhí)行并在進(jìn)行任何嵌套調(diào)用前返回。收尾部分在嵌套的調(diào)用完成后執(zhí)行。
call_frame_t的成員如下:
root:指向內(nèi)嵌在call_stack_t里的假幀,不像其他單獨(dú)分配的frame。在stack里對(duì)所有的frame都相同。
parent指向調(diào)用此frame的那個(gè)frame。用c說(shuō)就是調(diào)用函數(shù) calling 函數(shù)。
next /prev指向下一個(gè)/前一個(gè)要完成的frame。注意不是要調(diào)用的那個(gè)幀,
local 私有數(shù)據(jù),針對(duì)此幀調(diào)用的私有數(shù)據(jù)。是xlagor函數(shù)的本地變量,保存在此,可以在分配函數(shù)和回調(diào)間保持。
this 指向xlator的私有全局狀態(tài)。
ret 指向調(diào)用者(上層xlator)的回調(diào)函數(shù),當(dāng)本xlator的req完成后執(zhí)行。
ref_count and complete 調(diào)度器用來(lái)跟蹤那個(gè)frame是active,哪個(gè)完成了,哪個(gè)需要恢復(fù)執(zhí)行。
lock and cookie:
正常情況下,新frame push到棧后,next就跟parent就相同了。但是,一個(gè)frame(幀)可以分支。例如,stripe_writev請(qǐng)求的幀,在每個(gè)子xlator返回前生成一個(gè)新幀。假設(shè)有3個(gè)子xlator,即3個(gè)子卷。next就只與第一個(gè)新幀相同。
根據(jù)線程庫(kù)模型,call_stack_t對(duì)應(yīng)的就是線程控制塊。
有用的成員變量有:
uid 和gid表示調(diào)用幀來(lái)自誰(shuí),用來(lái)鑒權(quán)和認(rèn)證。
pid表示發(fā)起此請(qǐng)求的進(jìn)程pid。
trans 指向請(qǐng)求相關(guān)的transport 結(jié)構(gòu)。在服務(wù)器端用來(lái)實(shí)現(xiàn)基于節(jié)點(diǎn)的存取控制,或者用來(lái)沿著失敗的連接跟蹤請(qǐng)求。在client用作啥用?
frames:假幀,指向請(qǐng)求的第一個(gè)真正的frame。
op /type?
call_pool_t?
STACK_WIND and STACK_UNWIND等價(jià)與函數(shù)的調(diào)用和返回。在本xlator的請(qǐng)求的執(zhí)行,分配表先執(zhí)行,wind后就停止只ing了。當(dāng)函數(shù)rfn回調(diào)函數(shù)執(zhí)行時(shí),此操作就開(kāi)始恢復(fù)執(zhí)行了。rfn也許被調(diào)用多次。(多個(gè)子卷)。
todo
call stack
call stub
Version 1.0
Last updated 2014-04-30 12:28:09 CST
“GlusterFS Translator API怎么使用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!