-module(mnesia_frag).%% Callback functions when accessed within an activity-export([lock/4,write/5,delete/5,delete_object/5,read/5,match_object/5,all_keys/4,select/5,select/6,select_cont/3,index_match_object/6,index_read/6,foldl/6,foldr/6,table_info/4,first/3,next/4,prev/4,last/3,clear_table/4]).%% Callback functions which provides transparent%% access of fragmented tables from any activity%% access context.lock(ActivityId,Opaque,{table,Tab},LockKind)->casefrag_names(Tab)of[Tab]->mnesia:lock(ActivityId,Opaque,{table,Tab},LockKind);Frags->DeepNs=[mnesia:lock(ActivityId,Opaque,{table,F},LockKind)||F<-Frags],mnesia_lib:uniq(lists:append(DeepNs))end;lock(ActivityId,Opaque,LockItem,LockKind)->mnesia:lock(ActivityId,Opaque,LockItem,LockKind).write(ActivityId,Opaque,Tab,Rec,LockKind)->Frag=record_to_frag_name(Tab,Rec),mnesia:write(ActivityId,Opaque,Frag,Rec,LockKind).delete(ActivityId,Opaque,Tab,Key,LockKind)->Frag=key_to_frag_name(Tab,Key),mnesia:delete(ActivityId,Opaque,Frag,Key,LockKind).delete_object(ActivityId,Opaque,Tab,Rec,LockKind)->Frag=record_to_frag_name(Tab,Rec),mnesia:delete_object(ActivityId,Opaque,Frag,Rec,LockKind).read(ActivityId,Opaque,Tab,Key,LockKind)->Frag=key_to_frag_name(Tab,Key),mnesia:read(ActivityId,Opaque,Frag,Key,LockKind).match_object(ActivityId,Opaque,Tab,HeadPat,LockKind)->MatchSpec=[{HeadPat,[],['$_']}],select(ActivityId,Opaque,Tab,MatchSpec,LockKind).select(ActivityId,Opaque,Tab,MatchSpec,LockKind)->do_select(ActivityId,Opaque,Tab,MatchSpec,LockKind).select(ActivityId,Opaque,Tab,MatchSpec,Limit,LockKind)->init_select(ActivityId,Opaque,Tab,MatchSpec,Limit,LockKind).select_cont(_Tid,_,{frag_cont,'$end_of_table',[],_})->'$end_of_table';select_cont(Tid,Ts,{frag_cont,'$end_of_table',[{Tab,Node,Type}|Rest],Args})->{Spec,LockKind,Limit}=Args,InitFun=fun(FixedSpec)->mnesia:dirty_sel_init(Node,Tab,FixedSpec,Limit,Type)end,Res=mnesia:fun_select(Tid,Ts,Tab,Spec,LockKind,Tab,InitFun,Limit,Node,Type),frag_sel_cont(Res,Rest,Args);select_cont(Tid,Ts,{frag_cont,Cont,TabL,Args})->frag_sel_cont(mnesia:select_cont(Tid,Ts,Cont),TabL,Args);select_cont(Tid,Ts,Else)->mnesia:select_cont(Tid,Ts,Else).all_keys(ActivityId,Opaque,Tab,LockKind)->Match=[mnesia:all_keys(ActivityId,Opaque,Frag,LockKind)||Frag<-frag_names(Tab)],lists:append(Match).clear_table(ActivityId,Opaque,Tab,Obj)->[mnesia:clear_table(ActivityId,Opaque,Frag,Obj)||Frag<-frag_names(Tab)],ok.index_match_object(ActivityId,Opaque,Tab,Pat,Attr,LockKind)->Match=[mnesia:index_match_object(ActivityId,Opaque,Frag,Pat,Attr,LockKind)||Frag<-frag_names(Tab)],lists:append(Match).index_read(ActivityId,Opaque,Tab,Key,Attr,LockKind)->Match=[mnesia:index_read(ActivityId,Opaque,Frag,Key,Attr,LockKind)||Frag<-frag_names(Tab)],lists:append(Match).foldl(ActivityId,Opaque,Fun,Acc,Tab,LockKind)->Fun2=fun(Frag,A)->mnesia:foldl(ActivityId,Opaque,Fun,A,Frag,LockKind)end,lists:foldl(Fun2,Acc,frag_names(Tab)).foldr(ActivityId,Opaque,Fun,Acc,Tab,LockKind)->Fun2=fun(Frag,A)->mnesia:foldr(ActivityId,Opaque,Fun,A,Frag,LockKind)end,lists:foldr(Fun2,Acc,frag_names(Tab)).table_info(ActivityId,Opaque,{Tab,Key},Item)->Frag=key_to_frag_name(Tab,Key),table_info2(ActivityId,Opaque,Tab,Frag,Item);table_info(ActivityId,Opaque,Tab,Item)->table_info2(ActivityId,Opaque,Tab,Tab,Item).table_info2(ActivityId,Opaque,Tab,Frag,Item)->caseItemofsize->SumFun=fun({_,Size},Acc)->Acc+Sizeend,lists:foldl(SumFun,0,frag_size(ActivityId,Opaque,Tab));memory->SumFun=fun({_,Size},Acc)->Acc+Sizeend,lists:foldl(SumFun,0,frag_memory(ActivityId,Opaque,Tab));base_table->lookup_prop(Tab,base_table);node_pool->lookup_prop(Tab,node_pool);n_fragments->FH=lookup_frag_hash(Tab),FH#frag_state.n_fragments;foreign_key->FH=lookup_frag_hash(Tab),FH#frag_state.foreign_key;foreigners->lookup_foreigners(Tab);n_ram_copies->length(val({Tab,ram_copies}));n_disc_copies->length(val({Tab,disc_copies}));n_disc_only_copies->length(val({Tab,disc_only_copies}));n_external_copies->length(val({Tab,external_copies}));frag_names->frag_names(Tab);frag_dist->frag_dist(Tab);frag_size->frag_size(ActivityId,Opaque,Tab);frag_memory->frag_memory(ActivityId,Opaque,Tab);_->mnesia:table_info(ActivityId,Opaque,Frag,Item)end.first(ActivityId,Opaque,Tab)->case?catch_val({Tab,frag_hash})of{'EXIT',_}->mnesia:first(ActivityId,Opaque,Tab);FH->FirstFrag=Tab,casemnesia:first(ActivityId,Opaque,FirstFrag)of'$end_of_table'->search_first(ActivityId,Opaque,Tab,1,FH);Next->Nextendend.search_first(ActivityId,Opaque,Tab,N,FH)whenN<FH#frag_state.n_fragments->NextN=N+1,NextFrag=n_to_frag_name(Tab,NextN),casemnesia:first(ActivityId,Opaque,NextFrag)of'$end_of_table'->search_first(ActivityId,Opaque,Tab,NextN,FH);Next->Nextend;search_first(_ActivityId,_Opaque,_Tab,_N,_FH)->'$end_of_table'.last(ActivityId,Opaque,Tab)->case?catch_val({Tab,frag_hash})of{'EXIT',_}->mnesia:last(ActivityId,Opaque,Tab);FH->LastN=FH#frag_state.n_fragments,search_last(ActivityId,Opaque,Tab,LastN,FH)end.search_last(ActivityId,Opaque,Tab,N,FH)whenN>=1->Frag=n_to_frag_name(Tab,N),casemnesia:last(ActivityId,Opaque,Frag)of'$end_of_table'->PrevN=N-1,search_last(ActivityId,Opaque,Tab,PrevN,FH);Prev->Prevend;search_last(_ActivityId,_Opaque,_Tab,_N,_FH)->'$end_of_table'.prev(ActivityId,Opaque,Tab,Key)->case?catch_val({Tab,frag_hash})of{'EXIT',_}->mnesia:prev(ActivityId,Opaque,Tab,Key);FH->N=key_to_n(FH,Key),Frag=n_to_frag_name(Tab,N),casemnesia:prev(ActivityId,Opaque,Frag,Key)of'$end_of_table'->search_prev(ActivityId,Opaque,Tab,N);Prev->Prevendend.search_prev(ActivityId,Opaque,Tab,N)whenN>1->PrevN=N-1,PrevFrag=n_to_frag_name(Tab,PrevN),casemnesia:last(ActivityId,Opaque,PrevFrag)of'$end_of_table'->search_prev(ActivityId,Opaque,Tab,PrevN);Prev->Prevend;search_prev(_ActivityId,_Opaque,_Tab,_N)->'$end_of_table'.next(ActivityId,Opaque,Tab,Key)->case?catch_val({Tab,frag_hash})of{'EXIT',_}->mnesia:next(ActivityId,Opaque,Tab,Key);FH->N=key_to_n(FH,Key),Frag=n_to_frag_name(Tab,N),casemnesia:next(ActivityId,Opaque,Frag,Key)of'$end_of_table'->search_next(ActivityId,Opaque,Tab,N,FH);Prev->Prevendend.search_next(ActivityId,Opaque,Tab,N,FH)whenN<FH#frag_state.n_fragments->NextN=N+1,NextFrag=n_to_frag_name(Tab,NextN),casemnesia:first(ActivityId,Opaque,NextFrag)of'$end_of_table'->search_next(ActivityId,Opaque,Tab,NextN,FH);Next->Nextend;search_next(_ActivityId,_Opaque,_Tab,_N,_FH)->'$end_of_table'.