%%遍歷表並回寫數據 %%do_update_data/2裏面做了ets:instert/2更新的操作和其它處理 handle_call({update_data,Request}, _From, State) -> [begin do_update_data(Item,Request)end|| Item<-ets:tab2list(?TABLE_NAME)], {reply, ok, State};
handle_call({update_data,Func}, _From, State) -> ets:safe_fixtable(?TABLE_NAME, true), update_data(ets:first(?TABLE_NAME), Func), ets:safe_fixtable(?TABLE_NAME, false), {reply, ok, State}. update_data('$end_of_table',_) -> ok; update_data({key, Value1, Value2, _, _, _}=Idx,Func) when Value1 == "test"; value1 == '_' -> case ets:lookup(?TABLE_NAME, Idx) of [Ele] -> Func(Ele); [] -> ok end, update_data(ets:next(?TABLE_NAME, Idx),Func); update_data(Idx,Func) -> update_data(ets:next(?TABLE_NAME, Idx), Func).
鎖定一個類型是 set,bag 或 duplicate_bag 的表,使其可以安全遍歷表裏的數據;
在一個進程裏調用 ets:safe_fixtable(Tab, true) 可以鎖定一個表,直到在進程裏調用 ets:safe_fixtable(Tab, false) 纔會解鎖,或進程崩潰。
如果同時有幾個進程鎖定一個表,那麼表會一直保持鎖定狀態,直到所有進程都釋放它(或崩潰)。有一個引用計數器記錄着每個進程的操作,有 N 個持續的鎖定操作必須有 N 個釋放操作,表纔會真正被釋放。
handle_call({update_data,Func}, _From, State) -> ets:safe_fixtable(?TABLE_NAME, true), update_data(ets:first(?TABLE_NAME), Func,0), ets:safe_fixtable(?TABLE_NAME, false), {reply, ok, State}. update_data('$end_of_table',_,_) -> ok; update_data({key, Value1, Value2, _, _, _}=Idx,Func,Counter) when Value1 == "test"; value1 == '_' -> case ets:lookup(?TABLE_NAME, Idx) of [Ele] -> Func(Ele); [] -> ok end, NewCounter = if Counter >=50 -> timer:sleep(10),1; true -> Counter+1 end, update_data(ets:next(?TABLE_NAME, Idx),Func,NewCounter); update_data(Idx,Func,Counter) -> update_data(ets:next(?TABLE_NAME, Idx), Func,Counter).