-module(basedb). -export([start/0,start_base/1,awake/2,asleep/2]). -record(state,{data=dict:new(),proto='SELF'}). -define(dir,"disk/"). start() -> register(?MODULE,spawn(fun() -> init() end)). init() -> Tab = ets:new(?MODULE,[set]), read_dir(?dir,Tab), loop(?dir,Tab). start_base(Id) -> Pid = start_lookup(Id), awake(Id,Pid), Pid. start_lookup(Id) -> case lookup(Id) of {pid,Pid} -> Pid; {data,Data} -> spawn(fun() -> baselib:loop(Data) end); not_found -> spawn(fun() -> baselib:loop(#state{}) end) end. lookup(Id) -> Ref = make_ref(), ?MODULE ! {lookup,Id,Ref,self()}, receive {Ref,Reply} -> Reply end. awake(Id,Pid) -> ?MODULE ! {awake,Id,Pid}, ok. asleep(Id,Data) -> ?MODULE ! {asleep,Id,Data}, ok. loop(Dir,Tab) -> receive {lookup,Id,Ref,From} -> Reply = case ets:lookup(Tab,Id) of [] -> not_found; [{Id,Entry}] -> Entry end, From ! {Ref,Reply}, loop(Dir,Tab); {awake,Id,Pid} -> ets:insert(Tab,{Id,{pid,Pid}}), loop(Dir,Tab); {asleep,Id,Data} -> ets:insert(Tab,{Id,{data,Data}}), loop(Dir,Tab); flush_to_disk -> spawn(fun() -> flush_to_disk(Dir,ets:tab2list(Tab)) end), loop(Dir,Tab) end. flush_to_disk(_Dir,[]) -> ok; flush_to_disk(Dir,[{Id,{data,Data}}|More]) -> file:write_file(Dir++Id++".ob",term_to_binary(Data)), flush_to_disk(Dir,More); flush_to_disk(Dir,[_|More]) -> flush_to_disk(Dir,More). read_dir(Dir,Tab) -> {ok,List} = file:list_dir(Dir), load_dir(List,Dir,Tab). load_dir([],_,_Tab) -> ok; load_dir([F|Files],Dir,Tab) -> case string:tokens(F,".") of [Name,"ob"] -> {ok,Bytes} = file:read_file(Dir++F), Dict = binary_to_term(Bytes), ets:insert(Tab,{Name,{data,Dict}}); _ -> skip end, load_dir(Files,Dir,Tab).