⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mnemosyne_catalog.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 2 页
字号:
    ?insert(exec_stat, Table, S).read_stat(Table, Name) ->    ?read(Name, Table, #stat{}).insert_stat(Table, Name, Value) ->    S = upd_stat(read_stat(Table,Name), Value),    ?insert(Name, Table, S).%%%----parameter_default_value(Name) ->    case lists:keysearch(Name,1,?default_values) of	{value, {Name,Value,Unit}} -> Value;	false -> undefined    end.%%%----upd_stat(S, V) when is_record(S,stat) ->    S#stat{latest = V,	   sum = S#stat.sum+V,	   n = S#stat.n+1};upd_stat(undefined, V) ->    #stat{latest = V,	  sum = V,	  n = 1}.now_in_secs() ->    {MS,S,_} = now(),    MS*1000000 + S.%%%----------------------------------------------------------------select_remote_node(Table, LastResort) ->    select_remote_node1([], [disc_copies,ram_copies], Table, LastResort).select_remote_node1([N|Ns], Types, Table, LastResort) ->    case lists:member(N, mnesia:system_info(running_db_nodes)) of	true -> N;	false -> select_remote_node1(Ns, Types, Table, LastResort)    end;select_remote_node1([], [Type|Types], Table, LastResort) ->    select_remote_node1(mnesia:table_info(Table,Type),			Types, Table, LastResort);select_remote_node1([], [], Table, []) ->    none;    select_remote_node1([], [], Table, LastResort) ->    select_remote_node1(LastResort, [], Table, []).    %%%----------------------------------------------------------------tell_friends(What) ->    tell_friends(What, mnesia:system_info(running_db_nodes)).tell_friends(What, Nodes) ->    gen_server:abcast(lists:delete(node(),Nodes), ?SERVER_NAME, What).%%%----------------------------------------------------------------null_image(Table) -> {0,0,0}.%%%----------------------------------------------------------------mk_insert_time_stamp(Table) ->    insert_time_stamp(Table, {date(),time(),node(),now_in_secs()}).mk_insert_image(Table) ->    NewImage = mk_image_stat(Table),    insert_image(Table, NewImage),    mk_insert_time_stamp(Table),    insert_counter(Table, limit, update_limit(Table,NewImage)),    update_counter(Table, n_upd_local, 1, 1),    tell_friends({remote_data,Table,NewImage,read_time_stamp(Table)}),    NewImage.impatient_mk_insert_image(Table, MaxWait_ms) ->    Pid = spawn(?MODULE,mk_insert_image_send,[Table,self()]),    receive	{image,Image,Pid} ->	    Image    after MaxWait_ms ->	    Pid ! no_msg, % Skip result, but keep calculating an image	    null_image(Table)    end.mk_insert_image_send(Table, Pid) ->    CatalogPid = whereis(?SERVER_NAME),    link(CatalogPid),    Image = mk_insert_image(Table),    receive	no_msg -> ok    after 0 -> Pid ! {image,Image,self()}    end,    subscribe(Table),    unlink(CatalogPid).update_limit(Table) ->    update_limit(Table,read_image(Table)).update_limit(Table,{Nobjs,Sizes,_}) ->    (Nobjs * read_parameter(Table,upd_limit)) div 100;update_limit(Table, none) ->    0.    mk_image_stat(Table) ->    {Ngc0,Recl0,_} = erlang:statistics(garbage_collection),    {Time,NewImage} = timer:tc(?MODULE,mk_image,[Table]),    {Ngc1,Recl1,_} = erlang:statistics(garbage_collection),    insert_exec_stat(Table, Time, Ngc1-Ngc0, Recl1-Recl0),    NewImage.    mk_image(Table) ->    case mnesia:table_info(Table, storage_type) of	disc_only_copies -> mk_image_dets(Table);	unknown -> null_image(Table);	_ -> mk_image_ets(Table)    end.%%%---- etsmk_image_ets(Tab) ->    SizesList = 	lists:map(	  fun(Pos) ->		  one_col(Tab, Pos, ets:info(Tab,type))	  end, lists:seq(2,mnesia:table_info(Tab,arity))),    {ets:info(Tab,size), list_to_tuple(SizesList), product(SizesList)}.    %% TODO: catch exceptions (for example when Key is deleted meanwhile)%% Until we can use fix_table,%% we use match %one_col(Tab, Pos, Type) ->%    TmpTab = ets:new(mnemosyne_tmp,[set,public]),%    fix_table(Tab, true),%    one_col_ets(Type, Tab, ets:first(Tab), Pos, TmpTab),%    fix_table(Tab, false),%    N_objs = ets:info(TmpTab, size),%    ets:delete(TmpTab),%    N_objs.%one_col_ets(_, Table, '$end_of_table', Pos, TmpTab) -> ready;%one_col_ets(Type, Table, Key, Pos, TmpTab) ->%    one_col_ets_elms(Type, ets:lookup_element(Table,Key,Pos), TmpTab),%    one_col_ets(Type, Table, ets:next(Table,Key), Pos, TmpTab).%one_col_ets_elms(set, E, TmpTab) -> ets:insert(TmpTab, {E});%one_col_ets_elms(bag, Es, TmpTab) -> ins_elems(Es, TmpTab).%ins_elems([E|Es], TmpTab) -> ets:insert(TmpTab, {E}), ins_elems(Es,TmpTab);%ins_elems(_, _) -> ready.one_col(Tab, Pos, Type) ->    TmpTab = ets:new(mnemosyne_tmp,[set,public]),    Blank  = mnesia:table_info(Tab, wild_pattern),    Patt   = setelement(Pos, Blank, '$1'),    ResList = ets:match(Tab, Patt),    insert_ets(ResList, TmpTab),    N_objs = ets:info(TmpTab, size),    ets:delete(TmpTab),    N_objs.insert_ets([H|R], Tab) ->    ets:insert(Tab, {H}),    insert_ets(R, Tab);insert_ets([], _) ->    ok.%%%---- detsmk_image_dets(Table) ->    TmpTabs = lists:map(fun(N) -> 				ets:new(tmp,[set,public])			end, lists:seq(2,mnesia:table_info(Table,arity))),    traverse_dets(Table, 0, TmpTabs),    SizesList = lists:map(fun(TmpTab) ->				  S = ets:info(TmpTab,size),				  ets:delete(TmpTab),				  S			  end, TmpTabs),    {dets:info(Table,size), list_to_tuple(SizesList), product(SizesList)}.        traverse_dets(Table, Islot, TmpTabs) ->    case dets:slot(Table,Islot) of	'$end_of_table' -> ready;	Objs -> traverse_dets_objs(Objs, TmpTabs),		traverse_dets(Table, Islot+1, TmpTabs)    end.   traverse_dets_objs([Obj|Objs], TmpTabs) ->    traverse_dets_obj(tl(tuple_to_list(Obj)), TmpTabs),    traverse_dets_objs(Objs, TmpTabs);traverse_dets_objs(_, _) ->    ready.traverse_dets_obj([Val|Vals], [TmpTab|TmpTabs]) ->    ets:insert(TmpTab, {Val}),    traverse_dets_obj(Vals, TmpTabs);traverse_dets_obj(_,_) ->    ready.%%%---- commonproduct(L) when is_list(L) -> lists:foldl(fun(E,Acc) -> E*Acc end, 1, L).%%%================================================================-record(inf,	{name = "",	 image = "",	 limit = "",	 n_upd_local = "",	 n_upd_remote = "",	 subscr = "",	 origin = "",	 latest_upd_sec = "",	 latest_upd_sec_mean = "",	 stat_time_latest = "",	 stat_time_mean = "",	 stat_time_N = ""%%%	 stat_gc_latest = "",%%%	 stat_gc_mean = "",%%%	 stat_gc_N = "",%%%	 stat_recl_latest = "",%%%	 stat_recl_mean = "",%%%	 stat_recl_N = ""	}).	 -define(str(F,A), lists:flatten(io_lib:format(F,A))).tbl_info() ->    Tables = checked_tables(),    Info = collect_info(Tables),    {Hdr1,Hdr2,Fmt,Line,Note} = 	mk_hdr(Info,	       [{1,"Table"}, {3,"Updates"}, {7,"Update History"},		{10,"Calc. Cost"}, %%%		{10,"Number of GCs"},{13,"GC:Reclaimed"},		{13,"Parameters"}],	       #inf{name=" name",		    image="image",		    limit="limit",		    subscr="subscr",		    n_upd_local="Nloc",		    n_upd_remote="Nrem",		    origin="origin",		    latest_upd_sec = "age",		    latest_upd_sec_mean = "mean",		    stat_time_latest="latest",		    stat_time_mean="mean",		    stat_time_N="N"%%%		    stat_gc_latest="latest",%%%		    stat_gc_mean="mean",%%%		    stat_gc_N="N",%%%		    stat_recl_latest="latest",%%%		    stat_recl_mean="mean",%%%		    stat_recl_N="N"		   }),    [io_lib:format("~s~s~s~s", [Line,Hdr1,Hdr2,Line]),     write_info(Info, Fmt),     io_lib:format("~s~s\n", [Line,Note])    ].mk_hdr(Data, Hdr1L, Hdr2Rec) ->    Hdr2L = 	tl(tuple_to_list(Hdr2Rec)) ++ 	element(1, lists:mapfoldl(		     fun(_,N) ->			     {?str("~w)",[N]),N+1}		     end, 1, lists:seq(1,length(?default_values)))),    List_of_lengths =	lists:map(fun(D) -> lists:map(fun(E) -> length(E) end, D)		  end, [Hdr2L|Data]),    MaxL = max_l(tl(List_of_lengths), hd(List_of_lengths)),    Fmt = mk_format(MaxL, Hdr1L),    Hdr1 = mk_hdr1(MaxL,Hdr1L),    TblWidth = length(Hdr1),    Line = lists:map(fun($|) -> $+;			($\n) -> $\n; 			(_) -> $-		     end, Hdr1),     MaxNoteWidth = TblWidth - 20,    Note =	lists:flatten(	  element(1,		  lists:mapfoldl(		    fun({Name,Default,Unit},{N,W}) -> 			    Str = ?str("~w) ~w[~w ~s]   ",				       [N,Name,Default,Unit]),			    Wnew = W+length(Str),			    {if Wnew>MaxNoteWidth -> Str++["\n"];				true -> Str			     end, {N+1,Wnew}}		    end, {1,0}, ?default_values))),    {Hdr1, ?str(Fmt,Hdr2L), Fmt, Line, Note}.mk_format(MaxL, Hdr1Def) ->     case Hdr1Def of	[{N,_}|_] when N>1 -> "| ";	_ -> ""    end ++ lists:concat(mk_format(MaxL,Hdr1Def,1))++"\n".mk_format([W|Ws], [{N1,S}|Ds], N) when N==N1 ->    ["| ~",W,"s "] ++ mk_format(Ws, Ds, N+1);mk_format([W|Ws], [{N1,S}|Ds], N) when N<N1 ->    ["~",W,"s "]  ++ mk_format(Ws, [{N1,S}|Ds], N+1);mk_format([W|Ws], [], N) ->    ["~",W,"s "]  ++ mk_format(Ws, [], N+1);mk_format([], _, _) ->    ["|"].%% mk_hdr1(Maxs, []) -> %%     "| " ++ lists:duplicate(lists:sum(Maxs)+length(Maxs),$ ) ++ "|\n";mk_hdr1(Maxs, Def) ->    mk_hdr1(Maxs, Def, 1) ++ "\n".mk_hdr1([W|Ws], [{N1,S1},{N2,S2}|Ds], N) when N==N1 ->    {W1,WsT} = mk_hdr1_split([W|Ws],N2-N,0),    "| " ++ mk_hdr1_s(W1,S1) ++ mk_hdr1(WsT, [{N2,S2}|Ds], N2);mk_hdr1([W|Ws], [{N1,S}], N) when N==N1 ->    {W1,WsT} = mk_hdr1_split([W|Ws],100,0),    "| " ++ mk_hdr1_s(W1,S) ++ "|";mk_hdr1([W|Ws], [{N1,S}|Ds], N) when N<N1 ->    "|  " ++ lists:duplicate(W,$ ) ++ mk_hdr1(Ws, [{N1,S}|Ds], N+1).%% mk_hdr1(_, [], _) ->%%     "|".mk_hdr1_split([W|Ws], I, Acc) when I>0 -> mk_hdr1_split(Ws,I-1,Acc+W+1);mk_hdr1_split(Ws, _, Acc) -> {Acc,Ws}.mk_hdr1_s(W,S) when length(S)>W ->    lists:duplicate(W, $*);mk_hdr1_s(W,S) ->    Nspaces = W - length(S),    Npfx = Nspaces div 2,    lists:duplicate(Npfx, $ ) ++ S ++ lists:duplicate(Nspaces-Npfx,$ ).    max_l([L|Ls], MaxL) ->    max_l(Ls,	  lists:map(fun(N) ->			    lists:max([lists:nth(N,L), lists:nth(N,MaxL)])		    end, lists:seq(1,length(MaxL))));max_l([], MaxL) ->    MaxL.write_info(Info, Fmt) ->    lists:map(      fun(L) when is_list(L) -> io_lib:format(Fmt, L);	 (X) -> io_lib:format(" ???: ~w\n", [X])      end, Info).	      cntr_info(Tab, Name) ->    case read_counter(Tab,Name) of	undefined -> "";	Cnt -> string(int,Cnt)    end.collect_info(Tables) ->    NowSecs = now_in_secs(),    lists:map(      fun(Tab) ->	      S = read_exec_stat(Tab),	      R = #inf{name = atom_to_list(Tab),		       image = case read_image(Tab) of				   none -> "";				   {Ar,F1,Prod} -> ?str('~W', [{Ar,F1,'_'},8])			       end,		       limit = cntr_info(Tab,limit),		       n_upd_local = cntr_info(Tab,n_upd_local),		       n_upd_remote = cntr_info(Tab,n_upd_remote),		       subscr = case				 lists:member(whereis(?SERVER_NAME),					      mnesia:table_info(Tab,								subscribers))				    of				    true -> "Yes";				    false -> "No"				end,		       origin = case read_time_stamp(Tab) of				    {_,_,Node,_} -> atom_to_list(Node);				    _ -> ""				end,		       		       latest_upd_sec = 		       begin			   MinInterv=read_parameter(Tab,min_upd_interval),			   case read_time_stamp(Tab) of			       {_,_,_,Sec} when Sec+MinInterv>NowSecs -> 				   "("++string(time_s,(NowSecs-Sec))++")";			       {_,_,_,Sec} -> 				   string(time_s,(NowSecs-Sec))++" ";			       _ -> ""			   end		       end,		       latest_upd_sec_mean =string(time_s, 						   stat(mean,							read_stat(Tab,								  upd_stat))),		       stat_time_latest=string(time_us, 					       stat(latest,S#stats.time)),		       stat_time_mean = string(time_us,					       stat(mean,S#stats.time)),		       stat_time_N = string(int, 					    stat(n,S#stats.time))%%%		       stat_gc_latest = string(int, stat(latest,S#stats.gc)),%%%		       stat_gc_mean = string(int, stat(mean,S#stats.gc)),%%%		       stat_gc_N = string(int, stat(n,S#stats.gc)),		       %%%		       stat_recl_latest = string(int,%%%						 stat(latest,S#stats.recl)),%%%		       stat_recl_mean = string(int, stat(mean,S#stats.recl)),%%%		       stat_recl_N = string(int, stat(n,S#stats.recl))		      },	      tl(tuple_to_list(R)) ++ 		  lists:map(		    fun({Name,_,_}) ->			    io_lib:write(read_parameter(Tab,Name))		    end, ?default_values)      end, Tables).stat(latest, S) when is_record(S,stat), is_integer(S#stat.latest) ->    S#stat.latest;stat(mean, S) when is_record(S,stat), is_integer(S#stat.sum), S#stat.n=/=0 ->    S#stat.sum div S#stat.n;stat(n, S) when is_record(S,stat), is_integer(S#stat.n) ->     S#stat.n;stat(_, _) ->    undefined.%% string(clock, {H,M,S}) -> ?str("~2..0w:~2..0w:~2..0w", [H,M,S]);%% string(date, {Y,M,D}) -> ?str("~w-~2..0w-~2..0w", [Y,M,D]);string(time_us, MicroSecs) when is_integer(MicroSecs) ->     if	MicroSecs < 1000 -> ?str("~wus",[MicroSecs]);	MicroSecs < 3000 -> ?str("~4.2fms",[MicroSecs/1000]);	true -> string(time_ms, MicroSecs div 1000)    end;string(time_ms, MilliSecs) when is_integer(MilliSecs) ->    if	MilliSecs < 1000 -> ?str("~wms",[MilliSecs]);	MilliSecs < 9000 -> ?str("~4.2fs",[MilliSecs/1000]);	true -> string(time_s, MilliSecs div 1000)    end;string(time_s, TotSecs) when is_integer(TotSecs) ->    Hrs = TotSecs div 3600,    Mins= (TotSecs div 60) rem 60,    Secs= TotSecs rem 60,    if 	Hrs>24 -> ?str("~wd~2..0wh~2..0wm~2..0ws",		       [Hrs div 24,Hrs rem 24,Mins,Secs]);	Hrs >0 -> ?str("~wh~2..0wm~2..0ws",[Hrs,Mins,Secs]);	Mins>0 -> ?str("~wm~2..0ws",[Mins,Secs]);	true -> ?str("~ws",[Secs])    end;string(int, I) when is_integer(I) -> integer_to_list(I);string(_,_) -> "".

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -