-module(dynamic_kvs). -define(boot_type_supervisor, supervisor). -define(boot_type_worker, worker). -define(boot_type_simple_worker, simple_worker). -type boot_type() :: ?boot_type_simple_worker | ?boot_type_supervisor | ?boot_type_worker. -define(MATH_INT32_MAX, 4294967296). -record(boot, {module :: atom(), type :: boot_type(), hasname = true :: boolean(), params :: any()}). -export([start/1, start/0, get_name/1, init/1, handle_call/3, new/1, new/2]). %% API -export([set/3, gen/2]). -record(dynamic_kvs, { modules = [] :: [{Mod :: module(), [{Key :: atom(), Val :: any()}]}] }). start(FatherPID) -> boot:start_child(FatherPID, #boot{module = ?MODULE, params = {}, type = ?boot_type_worker}). start() -> boot:start(#boot{module = ?MODULE, params = {}, type = ?boot_type_worker}). get_name(_) -> ?MODULE. init(_) -> {ok, #dynamic_kvs{modules = []}}. new(ModuleName) -> new(ModuleName, []). new(ModuleName, Kvs) -> boot:call(?MODULE, {new, ModuleName, Kvs}). set(ModuleName, Key, Val) -> boot:call(?MODULE, {set, ModuleName, Key, Val}). handle_call({new, ModuleName, Kvs}, _, DynamicKvs) -> gen(ModuleName, Kvs), NewDynamicKvs = case lists:keyfind(ModuleName, 1, DynamicKvs#dynamic_kvs.modules) of false -> DynamicKvs#dynamic_kvs{modules = [{ModuleName, Kvs} | DynamicKvs#dynamic_kvs.modules]}; _ -> DynamicKvs end, {reply, ok, NewDynamicKvs}; handle_call({set, ModuleName, Key, Val}, _, DynamicKvs) -> case lists:keytake(ModuleName, 1, DynamicKvs#dynamic_kvs.modules) of false -> {reply, {error, not_find_module}, DynamicKvs}; {value, {_, Kvs}, RemainMods} -> NewKvs = lists:keyreplace(Key, 1, Kvs, {Key, Val}), gen(ModuleName, NewKvs), {reply, ok, DynamicKvs#dynamic_kvs{modules = [{ModuleName, NewKvs} | RemainMods]}} end. concat(List) -> lists:concat(List). gen(ModuleName, Kvs) -> Meta = meta:new(ModuleName), Fun = fun({K, V}, MetaTemp) -> FunStr = concat([K, "() ->\n\t", utTypeCast:term_to_string(V), ".\n"]), case meta:add_func(MetaTemp, FunStr) of {ok, MetaTemp2} -> MetaTemp2; Error -> io:format("module(~p) define func(~s) error ~p~n", [ModuleName, FunStr, Error]), exit(Error) end end, FinalMeta = lists:foldl(Fun, Meta, Kvs), FinalMeta2 = meta:add_func(FinalMeta, concat(["set(Key, Val) ->\n\tdynamic_kvs:set(", ModuleName, ", Key, Val).\n"])), case meta:compile(FinalMeta2) of {error, Error} -> io:format("error ~p", [Error]), ok; ok -> ok end.