概要:
內置的存儲
描述:
這個模塊是Erlang內置存儲BIFs的接口。這些提供了在Erlang運行時系統中存儲大量數據的能力,而且可以對數據進行持續的訪問時間。(在ordered_set的狀況下,參見下面,訪問時間與存儲的對象數量的對數成正比。)
數據被組織成一組動態表,能夠存儲元組。每一個表都是由一個進程建立的。當進程終止時,表將被自動銷燬。每一個表在建立時都具備訪問權限。
表分爲四種不一樣的類型:set、ordered_set、bag和duplicate_bag。set或ordered_set表只能有一個與每一個鍵相關聯的對象。bag或duplicate_bag能夠有許多與每一個鍵相關聯的對象。
在一個Erlang節點存儲的表的數量是有限的。當前的缺省限制大約是1400個表。在啓動Erlang運行時系統以前,能夠經過設置環境變量 ERL_MAX_ETS_TABLES 來增長上限(例如,使用-env選項到erl/werl)。實際的限制可能比指定的要稍微高一些,但永遠不會下降。
注意,表中沒有自動垃圾收集。即便沒有任何進程的引用,也不會自動銷燬,除非全部者進程終止。它能夠經過 delete/1 顯式地銷燬。默認的全部者是建立表的過程。表全部權能夠經過使用繼承人選項或顯式地調用 give_away/3 來轉移。
一些實現細節:
在當前的實現中,每個對象插入和查找操做都會產生一個對象的副本;
'$end_of_table' 不該該用做鍵,由於在使用first/next時,這個原子被用來標記表的末尾。
一樣值得注意的是匹配和比較相等之間的細微差異,這是由不一樣的表類型 set 和 ordered_set 所演示的。兩個Erlang項匹配,若是它們是相同類型且具備相同的值,那麼1匹配1,而不是1.0(1.0是浮點數而不是整數)。兩個Erlang的項比較相等,要麼它們是相同類型和值的,要麼二者都是數值類型並擴展到相同的值,那麼1比1和1.0都是同樣的。ordered_set在Erlang項順序上工做,在整數和浮點之間沒有定義的順序,它擴展到相同的值,所以鍵1和鍵1.0在ordered_set表中被認爲是相等的。node
故障:
通常來講,若是任何參數的格式是錯誤的,那麼下面的函數將會退出,若是表標識符是無效的,或者因爲表訪問權限而拒絕操做(protected or private)。
併發:
這個模塊爲併發訪問提供了一些有限的支持。對單個對象的全部更新都保證是原子性的和隔離性的。這意味着對單個對象的更新操做要麼成功,要麼徹底失敗,徹底沒有任何影響(原子性)。其餘進程(隔離性)也不能看到更新的中間結果。一些更新了幾個對象的函數代表,它們甚至能夠保證整個操做的原子性和隔離性。在數據庫術語中,隔離級別能夠被看做是「可序列化的」,就好像全部的隔離操做都是串行地執行的,一個接一個地以嚴格的順序執行。
匹配規範:
有些函數使用匹配規範,match_spec。在select/2中給出了一個簡短的解釋。有關詳細描述,請參閱ERTS用戶指南中的「Erlang中的匹配規範」一章。
數據類型:
access() = public | protected | private
continuation()
select/1,3, select_reverse/1,3, match/1,3, and match_object/1,3 使用不透明的 continuation。
match_spec() = [{match_pattern(), [term()], [term()]}]
匹配規範,見上文。
comp_match_spec()
一個編譯的匹配規範。
match_pattern() = atom() | tuple()
tab() = atom() | tid()
tid()
一個表標識符,new/2 返回的。
type() = set | ordered_set | bag | duplicate_bag
導出:
all() -> [Tab]
Types:
Tab = tab()
返回節點上全部表的列表。命名錶由它們的名稱給出,未命名的表由它們的表標識符給出。
delete(Tab) -> true
Types:
Tab = tab()
刪除整個表 Tab。
delete(Tab, Key) -> true
Types:
Tab = tab()
Key = term()
從表 Tab中刪除全部帶有鍵 Key的對象。
delete_all_objects(Tab) -> true
Types:
Tab = tab()
刪除ETS表 Tab中的全部對象。這個操做被保證是原子性的和隔離性的。
delete_object(Tab, Object) -> true
Types:
Tab = tab()
Object = tuple()
從ETS表中刪除確切的對象Object,留下具備相同鍵的對象,但其餘不一樣(對於類型 bag有用)。在duplicate_bag中,對象的全部實例都將被刪除。
file2tab(Filename) -> {ok, Tab} | {error, Reason}
Types:
Filename = file:name()
Tab = tab()
Reason = term()
讀取tab2file/2或tab2file/3生成的文件,並建立相應的表 Tab。
至關於 file2tab(Filename,[])。
file2tab(Filename, Options) -> {ok, Tab} | {error, Reason}
Types:
Filename = file:name()
Tab = tab()
Options = [Option]
Option = {verify, boolean()}
Reason = term()
讀取tab2file/2或tab2file/3生成的文件,並建立相應的表 Tab。
目前惟一受支持的選項是 {verify,boolean()}。若是驗證被打開(經過指定 {verify,true}),該函數將利用文件中存在的任何信息來斷言信息沒有被破壞。這是如何完成的,取決於使用 tab2file/3編寫的 extended_info。
若是文件中沒有 extended_info,而且 {verify,true} 是指定的,當轉儲開始時,所編寫的對象的數量將與原始表的大小進行比較。若是表是 public,而且在表被轉儲到文件時,則會使驗證失敗。爲了不這種類型的問題,要麼在同步更新時不驗證轉儲文件,要麼使用 {extended_info, [object_count]} 選項到 tab2file/3,它將文件中的信息擴展到實際編寫的對象的數量。
若是驗證被打開,而且該文件是用 {extended_info, [md5sum]} 編寫的,那麼讀取文件的速度會更慢,消耗的CPU時間也會大大增長。shell
first(Tab) -> Key | '$end_of_table'
Types:
Tab = tab()
Key = term()
返回表 Tab中的第一個鍵 Key。若是該表是 ordered_set類型,那麼Erlang項順序中的第一個鍵將被返回。若是表是任何其餘類型的,那麼根據該表的內部順序將返回第一個鍵。若是表是空的,則返回 '$end_of_table'。
使用 next/2在表格中找到後續的鍵。
foldl(Function, Acc0, Tab) -> Acc1
Types:
Function = fun((Element :: term(), AccIn) -> AccOut)
Tab = tab()
Acc0 = Acc1 = AccIn = AccOut = term()
若是表是空的,則返回Acc0。這個函數相似於 lists:foldl/3。除了類型ordered_set的表以外,表中元素的順序是不肯定的,它們從頭至尾被遍歷。
若是函數將對象插入到表中,或者另外一個進程將對象插入到表中,那麼這些對象可能(取決於鍵順序)包含在遍歷中。
foldr(Function, Acc0, Tab) -> Acc1
Types:
Function = fun((Element :: term(), AccIn) -> AccOut)
Tab = tab()
Acc0 = Acc1 = AccIn = AccOut = term()
若是表是空的,則返回Acc0。這個函數相似於 lists:foldr/3。表中元素的順序是不肯定的,除了類型ordered_set的表以外,它們從尾到頭被遍歷。
若是函數將對象插入到表中,或者另外一個進程將對象插入到表中,那麼這些對象可能(取決於鍵順序)包含在遍歷中。
from_dets(Tab, DetsTab) -> true
Types:
Tab = tab()
DetsTab = dets:tab_name()
在已經打開的Dets表中,填滿已經建立的ETS表,這個表名爲DetsTab。除非覆蓋,不然ETS表的現有對象將被保留。
若是任何表不存在或dets表不打開,就會拋出一個badarg錯誤。
fun2ms(LiteralFun) -> MatchSpec
Types:
LiteralFun = function()
MatchSpec = match_spec()
僞函數經過 parse_transform的方式將 LiteralFun翻譯成參數,做爲參數轉換成match_spec在函數調用中。「literal」是指,在文本中,須要將其做爲函數的參數來寫,它不能被保存在一個變量中,而這個變量又被傳遞給函數。
解析轉換是在模塊 ms_transform中實現的,源代碼必須包含文件ms_transform.hrl。在STDLIB中爲這個僞函數工做。若是不能在源代碼中包含hrl文件,將致使運行時錯誤,而不是編譯時的錯誤。include文件最容易包括添加行-include(「stdlib/include/ms transform.hrl」).到源代碼。
fun是很是有限的,它只能接受一個單一的參數(匹配的對象):一個惟一的變量或一個元組。它須要使用is_ 關卡測試。在match_spec中不能使用語言結構(例如,if,case,receive等)是不容許的。
返回值是產生的match_spec。
例子:
1> ets:fun2ms(fun({M,N}) when N > 3 -> M end).
[{{'$1','$2'},[{'>','$2',3}],['$1']}]
來自環境的變量能夠被導入,所以它能夠工做:
2> X=3.
3
3> ets:fun2ms(fun({M,N}) when N > X -> M end).
[{{'$1','$2'},[{'>','$2',{const,3}}],['$1
導入的變量將被 match_spec 常量表達式替換,這與Erlang funs的靜態做用域一致。然而,本地或全局的函數調用不能處於fun的關卡或主體中。固然,對構建match_spec函數的內建調用是容許的:
4> ets:fun2ms(fun({M,N}) when N > X, is_atomm(M) -> M end).
Error: fun containing local Erlang function calls
('is_atomm' called in guard) cannot be translated into match_spec
{error,transform_error}
5> ets:fun2ms(fun({M,N}) when N > X, is_atom(M) -> M end).
[{{'$1','$2'},[{'>','$2',{const,3}},{is_atom,'$1'}],['$1']}]
從這個例子中能夠看出,這個函數也能夠從 shell中調用。當從shell中使用時,fun也須要在調用中。在shell案例中使用的其餘方法是使用parse_transform,但或多或少是相同的限制(例外是記錄,由於它們不是由shell處理的)。
警告:
若是 parse_transform沒有被應用到調用這個僞函數的模塊中,那麼調用將在運行時失敗(帶有badarg)。模塊ets實際上導出了一個帶有這個名稱的函數,可是除了在shell中使用函數時,它永遠不該該被調用。若是經過包含 ms_transform.hrl 來正確地應用parse_transform,編譯後的代碼永遠不會調用這個函數,可是函數調用被一個文字匹配規範所取代。
要了解更多信息,請參見mstransform(3)。
give_away(Tab, Pid, GiftData) -> true
Types:
Tab = tab()
Pid = pid()
GiftData = term()
使進程Pid成爲表 Tab的新全部者。若是成功,將消息{「ETS-TRANSFER」,Tab,FromPid,GiftData}發送給新全部者。
進程Pid必須是活的,本地的,而不是表的全部者。調用過程必須是表全部者。
請注意,give_away 並不會影響到表的繼承人選項。例如,表全部者能夠將繼承人設置爲本身,將表放在一邊,而後將其取回,以防接收方終止。
i() -> ok
在tty顯示全部ETS表的信息。
i(Tab) -> ok
Types:
Tab = tab()
在tty上瀏覽表Tab。
info(Tab) -> InfoList | undefined
Types:
Tab = tab()
InfoList = [InfoTuple]
InfoTuple = {compressed, boolean()}
| {heir, pid() | none}
| {keypos, integer() >= 1}
| {memory, integer() >= 0}
| {name, atom()}
| {named_table, boolean()}
| {node, node()}
| {owner, pid()}
| {protection, access()}
| {size, integer() >= 0}
| {type, type()}
將表 Tab的信息返回爲元組列表。若是Tab有正確的表標識符類型,但不引用現有的ETS表,則返回未定義。若是Tab不是正確的類型,那麼這個函數就會由於badarg而失敗。
{compressed, boolean()}
表示表是否被壓縮。
{heir, pid() | none}
表的繼承者的pid,若是沒有繼承者,則爲none。
{keypos, integer() >= 1}
鍵位置。
{memory, integer() >= 0
分配給表的空間(以字爲單位)。
{name, atom()}
表名。
{named_table, boolean()}
代表表是否被命名。
{node, node()}
存放表的節點。這個字段再也不有意義,由於表不能從其餘節點訪問。
{owner, pid()}
表全部者的pid。
{protection, access()}
表訪問的權限。
{size, integer() >= 0
在表中插入的對象的數量。
{type, type()}
表的類型。
info(Tab, Item) -> Value | undefined
Types:
Tab = tab()
Item = compressed
| fixed
| heir
| keypos
| memory
| name
| named_table
| node
| owner
| protection
| safe_fixed
| size
| stats
| type
Value = term()
返回表的相關信息,若是Tab不引用現有的ETS表,則返回未定義的信息。若是Tab不是正確的類型,或者若是Item不是容許的值之一,那麼這個函數就會由於badarg而失敗。
警告:
在R11B和更早的時候,這個函數不會失敗,可是對於條目的無效值返回undefined。
對info/1,除了{Item,Value}定義,下面的項也被容許:
Item=fixed, Value=boolean()
表示表是否由任何進程固定。
Item=safe_fixed, Value={FirstFixed,Info}|false 若是表是使用safe_fixtable/2修復的,那麼調用返回一個元組,其中FirstFixed是表第一次被進程修復的時間,它多是如今修復的進程之一。Info是一個可能的空列表,它是一個元組{Pid,RefCount},一個元組,每一個進程如今都是固定的。RefCount是參考計數器的值,它記錄了進程中表被修復了多少次。
若是表從未被修復,則調用返回false。
Item=stats, Value=tuple()
返回關於OTP測試套件使用的內部格式的set、bag和duplicate_bag表的內部統計信息。不適合生產使用。
init_table(Tab, InitFun) -> true
Types:
Tab = tab()
InitFun = fun((Arg) -> Res)
Arg = read | close
Res = end_of_input | {Objects :: [term()], InitFun} | term()
用調用輸入函數InitFun建立的對象來替換表Tab的現有對象,以下所示。這個函數是爲了與dets模塊兼容而提供的,它並不比使用ets:insert/2來填充表效率更高。
當被調用時,讀取函數InitFun被假定爲返回end_of_input,當沒有更多的輸入,或{Objects,Fun},Objects是一個對象列表,而fun是一個新的輸入函數。任何其餘值的值都做爲錯誤,返回{error,{init_fun,Value}}。每個輸入函數都將被調用一次,若是出現錯誤,最後一個函數會在參數關閉時被調用,它的應答將被忽略。
若是表的類型被設定,而且有多個對象和一個給定的鍵,那麼就會選擇其中一個對象。這並不必定是在輸入函數返回的對象序列中給定鍵的最後一個對象。這也適用於存儲在類型bag表中的重複對象。
insert(Tab, ObjectOrObjects) -> true
Types:
Tab = tab()
ObjectOrObjects = tuple() | [tuple()]
將列表ObjectOrObjects中的對象或全部對象插入到表Tab中。若是表是一個set,而且插入的對象的鍵與表中任何對象的鍵相匹配,那麼舊對象將被替換。若是表是一個ordered_set,而且插入的對象的鍵與表中的任何對象的鍵相等,那麼舊對象也會被替換。若是列表中包含了不止一個帶有匹配鍵的對象,而且該表是一個set,那麼就會插入一個對象,其中一個沒有定義。對於ordered_set也是同樣的,可是若是鍵比較相等,也會發生一樣的事情。
整個操做被保證是原子性的和隔離性的,即便插入了一個對象列表。
insert_new(Tab, ObjectOrObjects) -> boolean()
Types:
Tab = tab()
ObjectOrObjects = tuple() | [tuple()]
這個函數的工做原理與insert/2徹底相同,除了用相同的鍵重寫對象(在set或ordered_set的狀況下),或者在表中已經存在的鍵中添加更多的對象(在bag和duplicate_bag的狀況下),它只是返回false。若是ObjectOrObjects是一個列表,那麼這個函數在插入任何東西以前都會檢查每一個鍵。若是列表中沒有列出全部的鍵,則不會插入任何東西。與insert/2同樣,整個操做都保證是原子性的和隔離性的。
is_compiled_ms(Term) -> boolean()
Types:
Term = term()
這個函數用來檢查一個術語是不是有效編譯的match_spec。編譯的match_spec是一種不透明的數據類型,不能在Erlang節點之間發送,也不能存儲在磁盤上。任何試圖建立一個編譯的match_spec的外部表示的嘗試都會致使一個空的二進制(<<>>)。下面的表達式,做爲一個例子:
ets:is_compiled_ms(ets:match_spec_compile([{'_',[],[true]}])).
會產生true:
MS = ets:match_spec_compile([{'_',[],[true]}]),
Broken = binary_to_term(term_to_binary(MS)),
ets:is_compiled_ms(Broken).
會產生錯誤,由於變量被破壞將包含一個通過編譯的match_spec,它已經經過外部表示。
請注意:
編譯匹配規範沒有外部表示的事實是出於性能考慮。它可能會在未來的版本中發生變化,而這個接口仍然會保持向後兼容的緣由。
last(Tab) -> Key | '$end_of_table'
Types:
Tab = tab()
Key = term()
根據ordered_set類型的表Tab返回最後一個鍵Key。若是表是任何其餘類型的,那麼該函數就是first/2的同義詞。若是表爲空,則返回「$end_of_table」。
使用prev/2來查找表中的前鍵。
lookup(Tab, Key) -> [Object]
Types:
Tab = tab()
Key = term()
Object = tuple()
在表Tab中返回全部帶有鍵key的對象列表。
在set、bag和duplicate_bag的狀況下,只有當給定的鍵與表中對象的鍵相匹配時,纔會返回一個對象。然而,若是表示一個ordered_set,那麼若是給定的鍵比表中的對象的鍵相等,則返回一個對象。區別和=:=和==同樣。做爲一個例子,你能夠在ordered_set中插入一個帶有integer() 1的對象,並將該對象做爲lookup/2的鍵,得到查找的結果;和用float() 1.0 做爲key查找。
若是表是類型set或ordered_set,則函數返回空列表或帶有一個元素的列表,由於不能有多個具備相同鍵的對象。若是表是類型bag或duplicate_bag,則該函數返回任意長度的列表。
注意對象插入的時間順序被保留;用給定的鍵插入的第一個對象將首先出如今結果列表中,以此類推。
在表中插入和查找時間,set、bag和duplicate_bag是常量,無論表的大小。對於ordered_set的數據類型,時間與對象數量的對數成比例。
lookup_element(Tab, Key, Pos) -> Elem
Types:
Tab = tab()
Key = term()
Pos = integer() >= 1
Elem = term() | [term()]
若是表Tab是類型set或ordered_set,則該函數返回帶有鍵key的位置爲Pos的元素。
若是表是bag或duplicate_bag,那麼函數將返回一個列表,其中包含每一個對象的Pos位置的元素。
若是沒有鍵Key的對象,則該函數將以理由badarg退出。
一方面,set、bag和duplicate_bag之間的區別,另外一方面是ordered_set,關於ordered_set的認爲鍵在比較相等時是相等的,而其它表類型只在匹配時才相等,lookup_element和lookup天然適用。
match(Tab, Pattern) -> [Match]
Types:
Tab = tab()
Pattern = match_pattern()
Match = [term()]
將表Tab中的對象與模式Pattern匹配。
模式是一個項,可能包含:
綁定部分(Erlang項),
它與任何Erlang項相匹配,
模式變量:$N,N=0,1,……
該函數爲每個匹配對象返回一個含有其中元素的列表,其中每一個元素都是模式變量綁定的有序列表。一個例子:
6> ets:match(T, '$1'). % Matches every object in the table
[[{rufsen,dog,7}],[{brunte,horse,5}],[{ludde,dog,5}]]
7> ets:match(T, {'_',dog,'$1'}).
[[7],[5]]
8> ets:match(T, {'_',cow,'$1'}).
[]
若是在模式中指定了鍵,那麼匹配是很是有效的。若是沒有指定鍵,也就是說,若是它是一個變量或一個下劃線,那麼必須搜索整個表。若是表很是大,搜索時間可能會很大。
在ordered_set類型的表中,結果與first/next遍歷的順序是相同的。
match(Tab, Pattern, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
Pattern = match_pattern()
Limit = integer() >= 1
Match = [term()]
Continuation = continuation()
跟 ets:match/2 同樣,都是根據匹配模式 Pattern 匹配表 Tab 裏的對象數據,可是 ets:match/3 只返回 Limit 條的匹配數據。返回結果裏還同時返回變量 Continuation,這可做爲下一次調用 ets:match/1 方法的參數來獲取下一批的匹配數據,這比使用 ets:first/1 和 ets:next/2 方法遍歷獲取表裏的對象數據會更快,更有效率。
若是表是空的,則返回$end_of_table。
match(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = [term()]
Continuation = continuation()
繼續從 ets:match/3 方法開始匹配數據,調用 ets:match/3 方法跟匹配數據一塊兒返回的變量 Continuation 可用在下一次調用這個函數來獲取下一批的匹配數據。
當表中沒有更多的對象時,「$end_of_table」就會返回。
match_delete(Tab, Pattern) -> true
Types:
Tab = tab()
Pattern = match_pattern()
從表Tab中刪除與模式Pattern匹配的全部對象。有關模式的描述,請參閱match/2。
match_object(Tab, Pattern) -> [Object]
Types:
Tab = tab()
Pattern = match_pattern()
Object = tuple()
將表Tab中的對象與模式Pattern匹配。有關模式的描述,請參閱match/2。該函數返回與模式匹配的全部對象的列表。
若是在模式中指定了鍵,那麼匹配是很是有效的。若是沒有指定鍵,也就是說,若是它是一個變量或一個下劃線,那麼必須搜索整個表。若是表很是大,搜索時間可能會很大。
在ordered_set類型的表格中,結果與first/next遍歷的順序是相同的。
match_object(Tab, Pattern, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
Pattern = match_pattern()
Limit = integer() >= 1
Match = [term()]
Continuation = continuation()
跟 ets:match_object/2 同樣,都是根據匹配模式 Pattern 匹配表 Tab 裏的對象數據,可是 ets:match_object/3 只返回 Limit 條的匹配數據。返回結果裏還同時返回變量 Continuation,這可做爲下一次調用 ets:match_object/1 方法的參數來獲取下一批的匹配數據,這比使用 ets:first/1 和 ets:next/2 方法遍歷獲取表裏的對象數據更快,更有效率。
若是表是空的,則返回$end_of_table。
match_object(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = [term()]
Continuation = continuation()
繼續從 ets:match_object/3 方法開始匹配數據,調用 ets:match_object/3 方法跟匹配數據一塊兒返回的變量 Continuation 可用在下一次調用這個函數來獲取下一批的匹配數據。
當表中沒有更多的對象時,「$end_of_table」就會返回。
match_spec_compile(MatchSpec) -> CompiledMatchSpec
Types:
MatchSpec = match_spec()
CompiledMatchSpec = comp_match_spec()
這個函數把一個匹配規範 MatchSpec 轉換爲一個可用於被 ets:match_spec_run/2 在後續調用的內部表示形式。轉換後的內部形式"不透明"的一個數據,它並不能轉回爲其原來的外部數據格式,而且無缺無損的轉回(這意味着它不能夠發送到另外一節點的進程上,而且仍然是一個有效的已編譯的匹配規範,或存儲在磁盤上也是不行)。
若是「MatchSpec」這個項不能被編譯(不表明有效的MatchSpec),就會拋出一個badarg錯誤。
注意:
這個函數在普通代碼中使用有限,dets使用它來執行dets:select操做。
match_spec_run(List, CompiledMatchSpec) -> list()
Types:
List = [tuple()]
CompiledMatchSpec = comp_match_spec()
這個函數是用一個已編譯的匹配規範對一個元組形式的列表進行指定匹配,參數 CompiledMatchSpec 是函數 ets:match_spec_compile/1 調用產生的匹配規範,所以是該函數想用的匹配規範的內部表示形式。
該匹配操做會對列表裏的每個元素進行匹配操做,並返回一個包含全部結果的列表。若是列表裏的一個元素並不符合匹配,將不會返回任何數據。所以返回的結果列表的長度有可能會小於參數列表的長度。
下面的兩個調用將給出相同的結果(但確定不是相同的執行時間。)
Table = ets:new...
MatchSpec = ....
% The following call...
ets:match_spec_run(ets:tab2list(Table),
ets:match_spec_compile(MatchSpec)),
% ...will give the same result as the more common (and more efficient)
ets:select(Table,MatchSpec),
注意:
這個函數在普通代碼中使用有限,它被dets用來執行dets:select操做和Mnesia事務中。
member(Tab, Key) -> boolean()
Types:
Tab = tab()
Key = term()
像lookup/2同樣工做,但不返回對象。若是表格中的一個或多個元素有鍵Key,則返回true;反之則返回false。
new(Name, Options) -> tid() | atom()
Types:
Name = atom()
Options = [Option]
Option = Type
| Access
| named_table
| {keypos, Pos}
| {heir, Pid :: pid(), HeirData}
| {heir, none}
| Tweaks
Type = type()
Access = access()
Tweaks = {write_concurrency, boolean()}| {read_concurrency, boolean()}| compressed
Pos = integer() >= 1
HeirData = term()
建立一個新的表並返回一個表標識符,它能夠在後續操做中使用。表格標識符能夠被髮送到其餘進程,以便在一個節點內的不一樣進程之間共享一張表。
參數選項是一個原子列表,它指定表類型、訪問權限、鍵位置,以及表是否被命名。若是遺漏了一個或多個選項,則使用默認值。這意味着不指定任何選項與指定[set, protected, {keypos,1}, {heir,none}, {write_concurrency,false}, {read_concurrency,false}]相同。
set
設置表是一個set表——一個鍵,一個對象,對象之間沒有順序。這是默認的表類型。
ordered_set
表是一個orderedset表——一個鍵,一個對象,在Erlang項順序中排序,這是由<and>操做符所暗示的順序。這種類型的表在某些狀況下的行爲與其餘類型的表有所不一樣。最明顯的是,ordered_set表在比較相等時,將鍵視爲相等,而不只僅是匹配時。這意味着對於ordered_set來講,integer()1和float()1.0被認爲是相等的。這也意味着用於查找元素的鍵不必定與返回的元素中的鍵相匹配,若是float()和integer()的鍵混合在表的鍵中。
bag
這個表是一個bag表,它能夠有不少對象,可是每一個對象只有一個實例,每一個鍵。
duplicate_bag
這個表是一個duplicate_bag表,它能夠有許多對象,包括同一對象的多個副本,每一個鍵。
public
任何進程均可以讀或寫到表中。
protected
全部者進程能夠讀取和寫入表。其餘進程只能讀取表。這是存取權的默認設置。
private
只有全部者進程能夠讀寫表。
named_table
若是這個選項存在,名稱Name與表標識符相關聯。而後,能夠在後續操做中使用名稱代替表標識符。
{keypos,Pos}
在存儲的元組中,應該使用哪一個元素做爲鍵。默認狀況下,它是第一個元素,即Pos=1。然而,這並不老是合適的。特別地,咱們不但願第一個元素成爲鍵,若是咱們想把Erlang記錄存儲在一張表中。
注意,表中存儲的任何元組必須至少有Pos數量的元素。
{heir,Pid,HeirData} | {heir,none}
設定一個進程做爲繼承者。若是全部者終止,繼承者將繼承該表。當這種狀況發生時,將會把消息{'ETS-TRANSFER',tid(),FromPid,HeirData} 發送給繼承者。繼承者必須是一個本地進程。默認的繼承者是none,當全部者終止時,它將破壞表。
{write_concurrency,boolean()}
性能調優。默認爲false,在這種狀況下,一個對錶進行改變(寫入)的操做將得到獨佔訪問,阻塞同一表的任何併發訪問,直到完成爲止。若是設置爲true,該錶針對併發寫訪問進行了優化。同一表的不一樣對象能夠經過併發進程進行改變(和讀取)。這在必定程度上是以犧牲內存消耗和順序訪問和併發讀取的性能爲代價的。write_concurrency選項能夠與write_concurrency選項相結合。一般,當大型併發讀爆發和大型併發寫爆發是常見的(請參閱write_concurrency選項的文檔以得到更多信息),您一般但願將它們組合在一塊兒。注意,這個選項不會改變任何關於原子性和隔離性的保證。在多個對象(如insert/2)中作出這樣的承諾的函數將從這個選項中得到更少(或沒有)。
在當前的實現中,表類型ordered_set不受此選項的影響。此外,write併發性和read併發性所形成的內存消耗是每一個表的一個常量開銷。當兩個選項組合在一塊兒時,這個開銷可能會特別大。
{read_concurrency,boolean()}
性能調優。默認是false。當設置爲true時,該錶針對併發讀操做進行了優化。當在帶有SMP支持的運行時系統上啓用此選項時,讀取操做將變得更加便宜;特別是在有多個物理處理器的系統上。然而,在讀寫操做之間切換變得更加昂貴。當併發讀操做比寫操做要頻繁得多,或者當併發讀和寫出現大的讀和寫時,您一般但願啓用這個選項。不少讀操做都不會被寫,不少的寫操做都不會被讀中斷。當常見的訪問模式是一些讀操做,並重復使用一些寫操做時,您一般不但願啓用這個選項。在這種狀況下,啓用這個選項得到性能降低。read_concurrency選項能夠與write_concurrency選項相結合。一般,當大型併發讀爆發和大型併發寫爆發是常見的時候,您一般須要將它們組合在一塊兒。
compressed
若是存在這個選項,那麼表數據將以更緊湊的格式存儲,以減小內存。缺點是它會使表操做變慢。特別是須要檢查整個對象的操做,例如match和select,將會變得更慢。在當前的實現中,關鍵元素沒有被壓縮。
next(Tab, Key1) -> Key2 | '$end_of_table'
Types:
Tab = tab()
Key1 = Key2 = term()
返回下一個鍵Key2,按照表Tab中的鍵Key1。若是該表是ordered_set類型,那麼Erlang項順序中下一個鍵就會返回。若是表是任何其餘類型的表,那麼根據表的內部順序返回下一個鍵。若是沒有下一個鍵,就會返回「$end_of_table」。
使用first/1來找到表格中的第一個鍵。
除非使用safe_fixtable/2來保護一組類型set、bag或duplicate_bag的表,不然,若是對錶進行併發更新,則遍歷可能會失敗。若是該表是ordered_set的,那麼函數就會按順序返回下一個鍵,即便對象已經不存在了。
prev(Tab, Key1) -> Key2 | '$end_of_table'
Types:
Tab = tab()
Key1 = Key2 = term()
按照ordered_set類型的表Tab中的Erlang項順序返回前面的鍵Key2。若是表是任何其餘類型的,那麼該函數就是next/2的同義詞。若是沒有之前的鍵,則返回「$end_of_table」。
使用last/1來找到表中的最後一個鍵。
rename(Tab, Name) -> Name
Types:
Tab = tab()
Name = atom()
將命名的表Tab從新命名爲新名稱。以後,舊的名稱不能用於訪問表。重命名一個未命名的表沒有效果。
repair_continuation(Continuation, MatchSpec) -> Continuation
Types:
Continuation = continuation()
MatchSpec = match_spec()
這個函數能夠用來恢復ets:select/3或ets:select/1的不透明延續,若是延續已經經過了外部項格式(在節點之間發送或存儲在磁盤上)。
這個函數的緣由是延續項包含了編譯的match_spec,所以若是轉換爲外部項格式,將會失效。考慮到原始的match_spec是完整的,延續能夠被恢復,這意味着它能夠再次被用於後續的ets:select/1調用,即便它已經存儲在磁盤上或另外一個節點上。
做爲一個例子,如下的調用序列將失敗:
T=ets:new(x,[]),
...
{_,C} = ets:select(T,ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 -> A end),10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(Broken).
…下面的順序將會起做用:
T=ets:new(x,[]),
...
MS = ets:fun2ms(fun({N,_}=A)
when (N rem 10) =:= 0 -> A end),
{_,C} = ets:select(T,MS,10),
Broken = binary_to_term(term_to_binary(C)),
ets:select(ets:repair_continuation(Broken,MS)).
…正如對ets:repair_continuation/2的調用將從新創建(謹慎地)失效的延續。
注意:
在應用程序代碼中不多須要這個函數。它被Mnesia用於實現分佈式select/3和select/1序列。一個普通的應用程序要麼使用Mnesia,要麼保持延續不被轉換爲外部格式。
沒有一個編譯的matchspec的外部表示的緣由是性能。它可能會在未來的版本中發生變化,而這個接口將保留向後兼容性。
safe_fixtable(Tab, Fix) -> true
Types:
Tab = tab()
Fix = boolean()
鎖定一個類型是 set,bag 或 duplicate_bag 的表,使其能夠安全遍歷表裏的數據。
一個進程經過調用safe_fixtable(Tab, true)來鎖定一個表。該表保持不變,直到進程經過調用safe_fixtable(Tab, false)釋放它,或者直到進程終止爲止。
若是同時有幾個進程鎖定一個表,那麼表會一直保持鎖定狀態,直到全部進程都釋放它(或崩潰)。有一個引用計數器記錄着每一個進程的操做,有 N 個持續的鎖定操做必須有 N 個釋放操做,表纔會真正被釋放。
當一個表被鎖定,一序列的ets:first/1和ets:next/2的調用都會保證成功執行,而且表裏的每個對象數據只返回一次,即便在遍歷的過程當中,對象數據被刪除或插入。在遍歷過程當中插入到表裏的新數據可能由 ets:next/2 返回(這取決有鍵的內部順序)。
clean_all_with_value(Tab,X) ->
safe_fixtable(Tab,true),
clean_all_with_value(Tab,X,ets:first(Tab)),
safe_fixtable(Tab,false).數據庫
clean_all_with_value(Tab,X,'$end_of_table') ->
true;
clean_all_with_value(Tab,X,Key) ->
case ets:lookup(Tab,Key) of
[{Key,X}] ->
ets:delete(Tab,Key);
_ ->
true
end,
clean_all_with_value(Tab,X,ets:next(Tab,Key)).
一個被鎖定的表是不會有被刪除的對象數據從表裏被實際刪除,直到它被釋放。若是一個進程鎖定一個表,並不釋放它,那些已刪除的對象數據所佔用的內存將永遠不會獲得釋放。對錶操做的性能也會顯著下降。
可使用 ets:info/2 來查看有哪些進程鎖定了表。有不少進程鎖定表的系統須要一個監控來給那些鎖定表很長時間的進程發送警告消息。
對於 ordered_set 類型的表,ets:safe_fixtable/2 是不必的,由於 ets:first/1 和 ets:next/2 將總會調用成功。
select(Tab, MatchSpec) -> [Match]
Types:
Tab = tab()
MatchSpec = match_spec()
Match = term()
使用一個匹配描述從表 Tab 裏匹配對象。此函數調用比 ets:match/2 和 ets:match_object/2 更經常使用。如下是一些最簡單形式的匹配描述:
MatchSpec = [MatchFunction]
MatchFunction = {MatchHead, [Guard], [Result]}
MatchHead = "Pattern as in ets:match"
Guard = {"Guardtest name", ...}
Result = "Term construct"
這意味着匹配描述老是含有一個以上元組元素的列表(含有三個參數的元組元素),元組的第一個元素應是 ets:match/2 的文檔中所描述的模式,第二個元素應是含 0 個或多個斷言測試的列表,第三個元素應是包含關於實際返回值的描述的列表,一般是一個對返回值全描述的列表,即返回匹配對象的全部項目。
返回值的結構使用 MatchHead 所綁定的 "match variables",或者使用特殊的匹配值 '$_'(整個匹配對象)和 '$$'(包含全部匹配值的列表)。安全
ets:match(Tab,{'$1','$2','$3'}) 等同於 ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}])
ets:match_object(Tab,{'$1','$2','$1'}) 等同於 ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}])
複合術語能夠經過簡單地編寫一個列表來構造結果部分,所以下面的代碼:
ets:select(Tab,[{{'$1','$2','$3'},[],['$$']}]) 等同於 ets:select(Tab,[{{'$1','$2','$3'},[],[['$1','$2','$3']]}])
在匹配頭中全部綁定的變量做爲一個列表。若是要構造元組,就必須在元組中編寫一個元組,其中的單個元素是tuple想要構造的元組(由於普通的元組可能被誤認爲是一個守衛)。所以下面的調用:
ets:select(Tab,[{{'$1','$2','$1'},[],['$_']}]) 等同於 ets:select(Tab,[{{'$1','$2','$1'},[],[{{'$1','$2','$3'}}]}])
這種語法至關於跟蹤模式中使用的語法(參見see dbg(3))
這些警衛被構形成元組,其中第一個元素是測試的名稱,其他的元素是測試的參數。要檢查綁定到匹配變量$1的元素的特定類型(好比列表),您能夠將測試寫成{is_list,'$1'}。若是測試失敗,表中的對象將沒法匹配,而且將嘗試下一個MatchFunction(若是有的話)。可使用Erlang中的大多數警衛測試,可是隻有新版本的前綴is_是容許的(如is_float、is_atom等)。
警衛部分還能夠包含邏輯和算術運算,它們使用與警衛測試(前綴表示法)相同的語法編寫,所以在Erlang中編寫的警衛測試是這樣的:
is_integer(X), is_integer(Y), X + Y < 4711
像這樣表示(X換成'$1'和Y換成'$2'):
[{is_integer, '$1'}, {is_integer, '$2'}, {'<', {'+', '$1', '$2'}, 4711}]
在ordered_set類型的表格中,對象的訪問順序與first/next遍歷的順序相同。這意味着匹配規範將在first/next順序中對帶有鍵的物體執行,相應的結果列表將按照該執行的順序執行。
select(Tab, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
MatchSpec = match_spec()
Limit = integer() >= 1
Match = term()
Continuation = continuation()
用法跟 ets:select/2 類似,但只返回限定數量(Limit)的匹配對象數據。Continuation 項可在後續的 ets:select/1 調用中獲取下一組的匹配對象數據。在操做表中對象數據時,這是一種頗有效的操做方式,而且比經過調用 ets:first/1 和 ets:next/1 逐個訪問對象還要快。
若是表是空的,則返回$end_of_table。
select(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Match = term()
Continuation = continuation()
繼續從 ets:select/3 開始的匹配。 下一次匹配到的限定數量 Limit(Limit 由 ets:select/3 初始所得)的對象數據將與新的 Continuation 一塊兒返回,新的 Continuation 將在後續調用該函數時被使用。
若是表中已沒有剩餘的對象,則返回 '$end_of_table'。
select_count(Tab, MatchSpec) -> NumMatched
Types:
Tab = tab()
MatchSpec = match_spec()
NumMatched = integer() >= 0
使用match_spec將表Tab中的對象與之匹配。若是匹配的對象返回true的話,該對象就會被認爲是匹配並被計算在內。對於任何來自match_spec的結果,對象不被認爲是匹配的,所以不被計算在內。
這個函數能夠被描述爲一個matchd_elete/2,它實際上並不刪除任何元素,但只計算它們。
這個函數返回匹配的對象的數量。
select_delete(Tab, MatchSpec) -> NumDeleted
Types:
Tab = tab()
MatchSpec = match_spec()
NumDeleted = integer() >= 0
使用一個匹配規範 MatchSpec 來匹配表 Tab 裏的對象數據。若是對一條對象數據使用匹配規範時返回 true,而且該條對象數據會從表裏移除。對於任何被匹配規範(match_spec)所匹配到的對象數據會被做爲返回值而保留下來。該函數比 ets:match_delete/2 還更通用(ets:match_delete/2 的代碼實現裏還調用到 ets:select_delete/2 方法)。
函數最後會返回一個實際在表裏被刪除的對象的數量值。
select_reverse(Tab, MatchSpec) -> [Match]
Types:
Tab = tab()
MatchSpec = match_spec()
Match = term()
像select/2這樣的工做,可是對於ordered_set表類型返回列表的順序是相反的。對於全部其餘表類型,返回值與select/2的返回值相同。
select_reverse(Tab, MatchSpec, Limit) -> {[Match], Continuation} | '$end_of_table'
Types:
Tab = tab()
MatchSpec = match_spec()
Limit = integer() >= 1
Match = term()
Continuation = continuation()
像select/3這樣的工做,可是對於ordered_set表類型,遍歷是在Erlang項順序的最後一個對象上開始的,並向第一個方向移動。對於全部其餘表類型,返回值與select/3相同。
請注意,這並不等同於反轉select/3調用的結果列表,由於結果列表不只顛倒了,並且還包含了表中最後的Limit匹配對象,而不是第一個。
select_reverse(Continuation) -> {[Match], Continuation} | '$end_of_table'
Types:
Continuation = continuation()
Match = term()
繼續從ets:select_reverse/3開始一個匹配。若是是ordered_set類型的表,表的遍歷將繼續從Erlang數據裏最先的鍵的對象數據開始。返回的列表也將包含跟鍵按相反的順序的對象數據。
若是是其餘類型的的表,那麼該函數的效用跟 ets:select/1 同樣。
例子:
1> T = ets:new(x,[ordered_set]).
2> [ ets:insert(T,{N}) || N <- lists:seq(1,10) ].
...
3> {R0,C0} = ets:select_reverse(T,[{'_',[],['$_']}],4).
...
4> R0.
[{10},{9},{8},{7}]
5> {R1,C1} = ets:select_reverse(C0).
...
6> R1.
[{6},{5},{4},{3}]
7> {R2,C2} = ets:select_reverse(C1).
...
8> R2.
[{2},{1}]
9> '$end_of_table' = ets:select_reverse(C2).
...
setopts(Tab, Opts) -> true
Types:
Tab = tab()
Opts = Opt | [Opt]
Opt = {heir, pid(), HeirData} | {heir, none}
HeirData = term()
設置表選項。目前惟一容許在表被建立以後設置的選項是heir。調用過程必須是表全部者。
slot(Tab, I) -> [Object] | '$end_of_table'
Types:
Tab = tab()
I = integer() >= 0
Object = tuple()
這個函數主要用於調試,一般應該使用first/next或last/prev。
返回表Tab的I:th槽中的全部對象。一個表能夠經過重複調用該函數來遍歷,從第一個槽I=0開始,並在返回「$end_of_table」時結束。若是I參數超出了範圍,那麼這個函數就會失敗。
除非使用safe_fixtable/2來保護類型set、bag或duplicate_bag的表,不然,若是對錶進行併發更新,則遍歷可能會失敗。若是該表是ordered_set的,那麼該函數將返回包含Erlang項順序中的I:th對象的列表。
tab2file(Tab, Filename) -> ok | {error, Reason}
Types:
Tab = tab()
Filename = file:name()
Reason = term()
將表Tab轉儲到文件Filename。
至關於tab2file(Tab, Filename,[])。
tab2file(Tab, Filename, Options) -> ok | {error, Reason}=
Types:
Tab = tab()
Filename = file:name()
Options = [Option]
Option = {extended_info, [ExtInfo]}
ExtInfo = md5sum | object_count
Reason = term()
將表Tab轉儲到文件Filename。
當轉儲表時,關於該表的某些信息會被轉儲到轉儲文件開頭的頭部。這些信息包含關於表類型、名稱、保護、大小、版本的數據,若是它是一個命名錶。它還包含關於擴展信息被添加到文件中的註釋,它能夠是文件中對象的計數,也能夠是文件頭和記錄的MD5和。
若是表是public,而且在轉儲期間從表中添加或刪除記錄,那麼標題中的size字段可能與文件中的實際記錄數不一致。在轉儲期間更新的public表,而且在讀取時須要驗證,至少須要一個擴展信息的字段,以便之後的讀取驗證進程是可靠的。
extended_info選項指定將哪些額外信息寫入錶轉儲:
object_count
實際上寫入文件的對象的數量在文件頁腳中被記錄,爲何即便文件在轉儲期間被更新,也能夠驗證文件截斷。
md5sum
文件中的頭和對象是使用內置的MD5函數來校驗的。全部對象的MD5和都寫在文件頁腳上,這樣在讀取時驗證將檢測到文件數據中最輕微的位翻轉。使用這種方法須要花費至關多的CPU時間。
當使用extended_info選項時,它會致使在stdlib-1.15.1版本以前的ets版本中沒法讀取的文件。
tab2list(Tab) -> [Object]
Types:
Tab = tab()
Object = tuple()
返回表Tab中全部對象的列表。
tabfile_info(Filename) -> {ok, TableInfo} | {error, Reason}
Types:
Filename = file:name()
TableInfo = [InfoItem]
InfoItem = {name, atom()}
| {type, Type}
| {protection, Protection}
| {named_table, boolean()}
| {keypos, integer() >= 0}
| {size, integer() >= 0}
| {extended_info, [ExtInfo]}
| {version,
{Major :: integer() >= 0,
Minor :: integer() >= 0}}
ExtInfo = md5sum | object_count
Type = bag | duplicate_bag | ordered_set | set
Protection = private | protected | public
Reason = term()
返回經過tab2file/2或tab2file3導出到文件的表的信息。
如下項目將返回:
name
導出表的名字。若是表是一個命名錶,那麼當表格使用file2tab/2從文件中加載時,就不可能存在同名的表。若是表沒有被保存爲指定的表,那麼當從文件加載表格時,這個字段根本沒有任何意義。
type
ets導出表的類型(即set、bag、duplicate_bag或ordered_set)。這種類型將在再次載入表時使用。
protection
導出表的保護類型(即private, protected 或 public)。從文件中加載的表將獲得一樣的保護。
named_table
true若是在轉儲文件時該表是一個命名錶,不然false。請注意,當一個具名錶從一個文件中加載時,系統中不能存在同名的表。
keypos
將表的keypos轉儲到文件中,這將在再次加載表格時使用。
size
當錶轉儲到文件時,表中的對象的數量,在公共表的狀況下,不須要對應實際保存到文件的對象的數量,由於在錶轉儲期間,對象可能已經被另外一個進程添加或刪除了。
extended_info
在文件頁腳中寫入的擴展信息,容許在表格加載過程當中進行更強的驗證,如指定爲tab2file/3。注意,這個函數只告訴咱們哪些信息是存在的,而不是文件頁腳中的值。該值是一個包含一個或多個原子object_count和md5sum的列表。
version
{Major,Minor}包含了ets錶轉儲文件格式的主要和次要版本。這個版本字段是由stdlib-1.5.1開始添加的,舊版本的文件在這個字段中會返回{0,0}。
若是文件不可訪問,嚴重損壞,或者沒有使用tab2file/2或tab2file/3生成的文件,則返回錯誤。
table(Tab) -> QueryHandle
table(Tab, Options) -> QueryHandle
Types:
Tab = tab()
QueryHandle = qlc:query_handle()
Options = [Option] | Option
Option = {n_objects, NObjects} | {traverse, TraverseMethod}
NObjects = default | integer() >= 1
TraverseMethod = first_next
| last_prev
| select
| {select, MatchSpec :: match_spec()}
返回QLC(Query List Comprehension)查詢句柄。模塊QLC實現了一種主要針對Mnesia的查詢語言,可是ETS表、Dets表和列表也被QLC識別爲數據的來源。調用ETS:table/1,2是使ETS表Tab可用到QLC的方法。
當在關鍵位置上只有簡單的限制時,QLC使用ets:lookup/2查找鍵,但若是不可能,整個表就會被遍歷。選項遍歷決定了這是如何完成的:
first_next.
表被遍歷一次一個鍵經過調用ets:first/1和ets:next/2。
last_prev.
表被遍歷一次一個鍵經過調用ets:last/1和ets:prev/2。
select.
經過調用ets:select/3和ets:select/1來遍歷表。選項n_object決定返回的對象的數量(select/3的第三個參數);默認狀況下,一次返回100個對象。match_spec(select/3的第二個參數)由QLC組裝:簡單的過濾器被轉換成等價的匹配規範,而更復雜的過濾器必須應用於select/3返回的全部對象,給定匹配全部對象的match_spec。
{select, MatchSpec}.
至於select表,調用ets:select/3和ets:select/1遍歷。不一樣之處在於,match_spec是顯式的。這就是如何在QLC提供的語法中聲明不容易表達的匹配規範。
下面的例子使用一個顯式的match_spec來遍歷表:
9> true = ets:insert(Tab = ets:new(t, []), [{1,a},{2,b},{3,c},{4,d}]),
MS = ets:fun2ms(fun({X,Y}) when (X > 1) or (X < 5) -> {Y} end),
QH1 = ets:table(Tab, [{traverse, {select, MS}}]).
一個帶有隱式match_spec的例子:
10> QH2 = qlc:q([{Y} || {X,Y} <- ets:table(Tab), (X > 1) or (X < 5)]).
後一個例子實際上至關於前者,能夠經過函數qlc:info/1來驗證。
11> qlc:info(QH1) =:= qlc:info(QH2).
true
qlc:info/1 返回關於查詢句柄的信息,在這種狀況下,兩個查詢句柄返回相同的信息。
test_ms(Tuple, MatchSpec) -> {ok, Result} | {error, Errors}
Types:
Tuple = tuple()
MatchSpec = match_spec()
Result = term()
Errors = [{warning | error, string()}]
這個函數是用來測試在調用ets:select/2時使用的match_spec的一個實用程序。這個函數都測試了匹配規範的「語法」正確性,並對對象元組運行Match_Spec。若是匹配規範包含錯誤,那麼元組{error, Errors} 就會返回,Errors是一個天然語言描述的列表,描述了match_spec的錯誤。若是match_spec在語法上是正確的,那麼函數就會返回{ok,Result} ,Result是在真實ets:select/2調用結果:若是匹配規範不匹配對象元組,則返回false。
這是一個有用的調試和測試工具,特別是在編寫複雜的ets:select/2調用時。
to_dets(Tab, DetsTab) -> DetsTab
Types:
Tab = tab()
DetsTab = dets:tab_name()
在已經打開的ETS表格中,填滿已經建立的/打開的Dets表。在插入對象以前,Dets表被清空。
update_counter(Tab, Key, UpdateOp) -> Result
update_counter(Tab, Key, UpdateOp :: [UpdateOp]) -> [Result]
update_counter(Tab, Key, Incr) -> Result
Types:
Tab = tab()
Key = term()
UpdateOp = {Pos, Incr} | {Pos, Incr, Threshold, SetValue}
Pos = Incr = Threshold = SetValue = Result = integer()
這個函數提供了一種有效的方法來更新一個或多個計數器,而沒必要費力地查找一個對象,經過增長一個元素來更新對象,並再次將產生的對象插入到表中。(更新是用原子的方式完成的;也就是說,在操做過程當中,沒有進程能夠訪問ets表。)
它將破壞性地更新表Tab的鍵Key的對象,增長Incr到Pos:th位置的元素。新的計數器值返回。若是沒有指定位置,則會更新下一個鍵(keypos+1)的元素。
若是指定了閾值,則計數器將被重置爲值SetValue,若是下列條件發生:
Incr不是負數(>=0),結果將大於(>)Threshold;
Incr是負的(<0),結果將小於(<)Threshold。
能夠提供UpdateOp的列表,以便在對象中執行幾個更新操做。操做按照列表中指定的順序執行。若是相同的計數器位置在列表中不止一次出現,那麼相應的計數器將會被更新幾回,每次都是基於前面的結果。返回值是每一個更新操做的新計數器值的列表,其順序與操做列表中的順序相同。若是指定了空鏈表,則不會更新任何東西,並返回一個空列表。若是函數失敗,則根本不須要更新。
給定的鍵用來識別對象,經過匹配一個集合表中的對象的鍵,或者與ordered_set表中的物體的鍵進行比較(參見lookup/2和new/2,瞭解差別的詳細信息)。
這個函數將會由於badarg而失敗,若是:
這個表不是類型set或ordered_set;
沒有正確的鍵存在;
對象的參數是錯的;
更新的元素不是整數;
更新的元素也是鍵,或者任何Pos,Incr,閾值或SetValue都不是整數。
update_element(Tab, Key, ElementSpec :: {Pos, Value}) -> boolean()
update_element(Tab, Key, ElementSpec :: [{Pos, Value}]) -> boolean()
Types:
Tab = tab()
Key = term()
Value = term()
Pos = integer() >= 1
這個函數提供了一種有效的方法來更新對象中的一個或多個元素,而沒必要查找、更新和回寫整個對象。
該函數把 ETS 表 Tab 裏鍵爲 Key 的對象數據的第 Pos 個元素數據的值更改成 Value。
一個{Pos,Value}列表能夠更新同一個對象中的幾個元素。若是相同的位置在列表中出現不止一個,那麼列表中的最後一個值將被寫入。若是列表是空的,或者函數失敗,則根本不會進行更新。這個函數也是原子的,由於其餘進程永遠看不到任何中間結果。
若是找到了帶有鍵Key的對象,則該函數返回true;反之則返回false。
給定的鍵用來識別對象,經過匹配一個set表中的對象的鍵,或者與ordered_set表中的對象的鍵進行比較(參見lookup/2和new/2,瞭解差別的詳細信息)。
這個函數將會由於badarg而失敗,若是:
這個表不是類型set或ordered_set,
Pos小於1或大於1,或者,
更新的元素也是鍵。併發