summaryrefslogtreecommitdiff |
diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/db/db_node.erl | 4 | ||||
-rw-r--r-- | src/db/logic/db_access.erl | 2 | ||||
-rw-r--r-- | src/db/struct/db_item_ids_manager.erl | 208 | ||||
-rw-r--r-- | src/login/lgn_handler.erl | 44 | ||||
-rw-r--r-- | src/map/map_handler.erl | 24 | ||||
-rw-r--r-- | src/roster/rst_handler.erl | 12 | ||||
-rw-r--r-- | src/special/spe_player.erl | 1 |
7 files changed, 213 insertions, 82 deletions
diff --git a/src/db/db_node.erl b/src/db/db_node.erl index 309adc0..30a29e2 100644 --- a/src/db/db_node.erl +++ b/src/db/db_node.erl @@ -32,5 +32,9 @@ start () -> db_model:add_db(map_db, Mnesia), db_model:add_db(player_db, Mnesia), db_model:add_db(roster_db, Mnesia), + db_model:add_db(inventory_db, Mnesia), + + ok = db_item_ids_manager:start(), + wait_for_stop(), ok. diff --git a/src/db/logic/db_access.erl b/src/db/logic/db_access.erl index d62e4ec..39019a6 100644 --- a/src/db/logic/db_access.erl +++ b/src/db/logic/db_access.erl @@ -88,7 +88,7 @@ insert_at (DB, ID, ReadPerm, WritePerm, Value) -> any()) -> ({'aborted', any()} | {'atomic', {'ok', binary()}}). insert (DB, ReadPerm, WritePerm, Value) -> - ID = <<"?">>, %% TODO [FUNCTION: db][HIGH]: gen new ID. + ID = db_item_ids_manager:allocate(DB), case insert_at(DB, ID, ReadPerm, WritePerm, Value) of {'atomic', 'ok'} -> {'atomic', {'ok', ID}}; {aborted, Val} -> {aborted, Val} diff --git a/src/db/struct/db_item_ids_manager.erl b/src/db/struct/db_item_ids_manager.erl new file mode 100644 index 0000000..999a047 --- /dev/null +++ b/src/db/struct/db_item_ids_manager.erl @@ -0,0 +1,208 @@ +-module(db_item_ids_manager). +-behavior(gen_server). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% TYPES %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-record +( + entry, + { + last_id :: binary(), + freed_ids :: list(binary()) + } +). + +-type entry() :: #entry{}. + +%% FIXME: IDs should be generated in a decentralized fashion. +%% TODO: How to handle IDs management with the redundancy DBs? + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% 'gen_server' Exports +-export +( + [ + init/1, + handle_cast/2, + handle_call/3, %% No reply will ever be given. + terminate/2, + code_change/3, + format_status/2, + handle_info/2 + ] +). + +%%%% Actual Interface +-export +( + [ + allocate/1, + free/2, + start/0 + ] +). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-spec next_char (integer()) -> integer(). +next_char ($9) -> $a; +next_char ($z) -> $A; +next_char ($Z) -> $0; +next_char (C) -> (C + 1). + +-spec next_id_internal + ( + list(integer()), + boolean(), + list(integer()) + ) + -> list(integer()). +next_id_internal ([], true, Result) -> [$0|Result]; +next_id_internal ([], false, Result) -> Result; +next_id_internal ([$Z|Next], true, Result) -> + next_id_internal(Next, true, [$0|Result]); +next_id_internal ([Char|Next], true, Result) -> + next_id_internal(Next, false, [next_char(Char)|Result]); +next_id_internal ([Char|Next], false, Result) -> + next_id_internal(Next, false, [Char|Result]). + +-spec next_id (binary()) -> binary(). +next_id (ID) -> + list_to_binary + ( + next_id_internal + ( + lists:reverse(binary:bin_to_list(ID)), + true, + [] + ) + ). + +-spec new_entry () -> entry(). +new_entry () -> + #entry + { + last_id = <<"">>, + freed_ids = [] + }. + +-spec allocate_id_in_entry (entry()) -> {entry(), binary()}. +allocate_id_in_entry (Entry) -> + case Entry#entry.freed_ids of + [] -> + NewID = next_id(Entry#entry.last_id), + { + Entry#entry{ last_id = NewID }, + NewID + }; + + [OldID|OtherOldIDs] -> + { + Entry#entry{ freed_ids = OtherOldIDs }, + OldID + } + end. + +-spec allocate_id + ( + atom(), + dict:dict(atom(), entry()) + ) + -> {dict:dict(atom(), entry()), binary()}. +allocate_id (DB, State) -> + S0Entry = + case dict:find(DB, State) of + {ok, Value} -> Value; + error -> new_entry() + end, + + {S1Entry, NewID} = allocate_id_in_entry(S0Entry), + + S0State = dict:store(DB, S1Entry, State), + + {S0State, NewID}. + +-spec free_id + ( + binary(), + atom(), + dict:dict(atom(), entry()) + ) + -> dict:dict(atom(), entry()). +free_id (ID, DB, State) -> + Entry = + case dict:find(DB, State) of + {ok, Value} -> Value; + error -> new_entry() + end, + + EntryFreedIDs = Entry#entry.freed_ids, + + case lists:member(ID, EntryFreedIDs) of + true -> State; + false -> + Result = + dict:store + ( + DB, + Entry#entry{ freed_ids = [ID|EntryFreedIDs] }, + State + ), + + Result + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% 'gen_server' functions +init (_) -> {ok, dict:new()}. + +handle_call ({allocate, DB}, _, State) -> + {NewState, NewID} = allocate_id(DB, State), + {reply, {allocated_id, NewID}, NewState}; +handle_call ({free, ID, DB}, _, State) -> + {noreply, free_id(ID, DB, State)}. + +handle_cast ({allocate, _DB}, State) -> + {noreply, State}; +handle_cast ({free, ID, DB}, State) -> + {noreply, free_id(ID, DB, State)}. + +terminate (_, _) -> ok. + +code_change (_, State, _) -> + {ok, State}. + +format_status (_, [_, State]) -> + [{data, [{"State", State}]}]. + +handle_info(_, State) -> + {noreply, State}. + +%%%% Interface Functions +-spec allocate (atom()) -> binary(). +allocate (DB) -> + gen_server:call({global, db_item_ids_manager}, {allocate, DB}), + + receive + {allocated_id, Result} -> + io:format("~n[DB: ~p] Item ID ~p allocated.~n", [DB, Result]), + Result + end. + +-spec free (binary(), atom()) -> 'ok'. +free (ID, DB) -> + gen_server:cast({global, db_item_ids_manager}, {free, ID, DB}), + + ok. + +-spec start () -> 'ok'. +start () -> + {ok, _} = gen_server:start({global, db_item_ids_manager}, ?MODULE, none, []), + + ok. diff --git a/src/login/lgn_handler.erl b/src/login/lgn_handler.erl index d2a6ee2..e14387c 100644 --- a/src/login/lgn_handler.erl +++ b/src/login/lgn_handler.erl @@ -12,55 +12,11 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% LOCAL FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec ensure_player_exists (binary(), binary(), binary(), binary()) -> 'ok'. -ensure_player_exists (ID, Username, Password, Email) -> - case shr_database:fetch(player_db, ID, admin) of - {ok, _} -> ok; - not_found -> - shr_database:insert_at - ( - player_db, - ID, - any, - any, - lgn_shim:generate_random_player(ID, Username, Password, Email) - ) - end, - - UsernameLC = string:lowercase(Username), - EmailLC = string:lowercase(Email), - - case shr_database:fetch(login_db, UsernameLC, admin) of - {ok, _} -> ok; - not_found -> shr_database:insert_at(login_db, UsernameLC, any, any, ID) - end, - - case shr_database:fetch(login_db, EmailLC, admin) of - {ok, _} -> ok; - not_found -> shr_database:insert_at(login_db, EmailLC, any, any, ID) - end, - - ok. - %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% EXPORTED FUNCTIONS %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec start (pid()) -> 'ok'. start (TimedCachesManagerPid) -> - ensure_player_exists - ( - <<"0">>, - <<"Player1">>, - <<"Kalimer0">>, - <<"P1@Tacticians.Online">> - ), - ensure_player_exists - ( - <<"1">>, - <<"Player2">>, - <<"Kalimer1">>, - <<"P2@Tacticians.Online">> - ), shr_timed_caches_manager:new_cache(TimedCachesManagerPid, login_db, none), shr_timed_caches_manager:new_cache(TimedCachesManagerPid, player_db, none), ok. diff --git a/src/map/map_handler.erl b/src/map/map_handler.erl index e4bcb60..eb19e18 100644 --- a/src/map/map_handler.erl +++ b/src/map/map_handler.erl @@ -18,29 +18,5 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec start (pid()) -> 'ok'. start (TimedCachesManagerPid) -> - case shr_database:fetch(map_db, <<"0">>, admin) of - {ok, _} -> ok; - not_found -> - shr_database:insert_at - ( - map_db, - <<"0">>, - any, - any, - map_shim:generate_random_map(0, <<"0">>) - ) - end, - case shr_database:fetch(map_db, <<"1">>, admin) of - {ok, _} -> ok; - not_found -> - shr_database:insert_at - ( - map_db, - <<"1">>, - any, - any, - map_shim:generate_random_map(1, <<"1">>) - ) - end, shr_timed_caches_manager:new_cache(TimedCachesManagerPid, map_db, none), ok. diff --git a/src/roster/rst_handler.erl b/src/roster/rst_handler.erl index 3d6073b..3b23f0c 100644 --- a/src/roster/rst_handler.erl +++ b/src/roster/rst_handler.erl @@ -18,18 +18,6 @@ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -spec start (pid()) -> 'ok'. start (TimedCachesManagerPid) -> - case shr_database:fetch(roster_db, <<"0">>, admin) of - {ok, _} -> ok; - not_found -> - shr_database:insert_at - ( - roster_db, - <<"0">>, - any, - any, - rst_shim:generate_random_character_roster() - ) - end, shr_timed_caches_manager:new_cache(TimedCachesManagerPid, roster_db, none), ok. diff --git a/src/special/spe_player.erl b/src/special/spe_player.erl index 7560a2d..6f0eebc 100644 --- a/src/special/spe_player.erl +++ b/src/special/spe_player.erl @@ -87,7 +87,6 @@ generate (Username, Password, Email) -> {ok, PlayerID} = shr_database:insert(player_db, janitor, janitor, Player), - shr_janitor:new(player_db, PlayerID), InvID = generate_inventory(PlayerID), |