Skip to content

Commit

Permalink
add opt chapter
Browse files Browse the repository at this point in the history
  • Loading branch information
hpyhacking committed Jul 30, 2011
1 parent f370b18 commit 83a0ce9
Show file tree
Hide file tree
Showing 14 changed files with 520 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.db
*.beam
.*
Binary file removed chapter_10/UsrTabFile
Binary file not shown.
34 changes: 34 additions & 0 deletions chapter_12/gensrv.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-module(sample_gensrv).
-export([start/0, stop/0]).
-export([init/1, handle_cast/2, handle_call/3, terminate/2]).
-export([say_hello/1]).

-behavior(gen_server).

start() ->
Name = "Jack",
gen_server:start({local, ?MODULE}, ?MODULE, Name, []).

init(Name) ->
io:format("Init OPT ~p~n", [Name]),
{ok, null}.

say_hello(Name) ->
NewName = gen_server:call(?MODULE, {say_hello, Name}),
io:format("Hello ~p ~n", [NewName]).

stop() ->
gen_server:cast(?MODULE, stop).

handle_cast(stop, LoopData) ->
io:format("Stop OPT~n"),
{stop, normal, LoopData}.

terminate(Reason, LoopData) ->
io:format("Terminate OPT ~p ~p ~n", [Reason, LoopData]).

handle_call({say_hello, Name}, _From, LoopData) ->
io:format("Hello ~p ~n", [Name]),
{reply, "Tommy", LoopData}.


9 changes: 9 additions & 0 deletions chapter_12/usr-1.0/ebin/usr.app
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{application, usr, [
{description, "Mobile Services Database"},
{vsn, "1.0"},
{modules, [usr, usr_db, usr_sup, usr_app]},
{registered, [usr, usr_sup]},
{applications, [kernel, stdlib]},
{env, [{dets_name, "usrDb.db"}]},
{mod, {usr_app, []}}]}.

16 changes: 16 additions & 0 deletions chapter_12/usr-1.0/include/usr.hrl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
%%% File: usr.hrl
%%% Description: Include file for user db

-type(plan() :: prepay | postpay).
-type(status() :: enabled | disabled).
-type(service() :: atom()).

-record(usr,
{
msisdn ::integer(),
id ::integer(),
status = enabled ::status(),
plan ::plan(),
services = [] ::[service()]
}
).
107 changes: 107 additions & 0 deletions chapter_12/usr-1.0/src/usr.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
-module(usr).
-export([start_link/0, start_link/1, stop/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([add_usr/3, delete_usr/1, set_service/3, set_status/2, delete_disabled/0, lookup_id/1]).
-export([lookup_msisdn/1, service_flag/2]).

-behavior(gen_server).

-include("usr.hrl").
-define(TIMEOUT, 30000).

start_link() ->
{ok, FileName} = application:get_env(dets_name),
start_link(FileName).

start_link(FileName) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, FileName, []).

stop() ->
gen_server:cast(?MODULE, stop).

init(FileName) ->
usr_db:create_tables(FileName),
usr_db:restore_backup(),
{ok, null}.

terminate(Reason, LoopData) ->
usr_db:close_tables().

add_usr(PhoneNum, CustId, Plan) when Plan == prepay; Plan == postpay ->
gen_server:call(?MODULE, {add_usr, PhoneNum, CustId, Plan}).

delete_usr(CustId) ->
gen_server:call(?MODULE, {delete_usr, CustId}).

set_service(CustId, Service, Flag) when Flag == true; Flag == false ->
gen_server:call(?MODULE, {set_service, CustId, Service, Flag}).

set_status(CustId, Status) when Status == enabled; Status == disabled ->
gen_server:call(?MODULE, {set_status, CustId, Status}).

delete_disabled() ->
gen_server:call(?MODULE, delete_disabled).

lookup_id(CustId) ->
usr_db:lookup_id(CustId).

lookup_msisdn(PhoneNo) ->
usr_db:lookup_msisdn(PhoneNo).

service_flag(PhoneNo, Service) ->
case usr_db:lookup_msisdn(PhoneNo) of
{ok, #usr{services = Services, status = enabled}} ->
lists:member(Service, Services);
{ok, #usr{status=disabled}} ->
{error, disabled};
{error, Reason} ->
{error, Reason}
end.

handle_call({add_usr, PhoneNo, CustId, Plan}, _From, LoopData) ->
Reply = usr_db:add_usr(
#usr{
msisdn=PhoneNo,
id=CustId,
plan=Plan
}
),
{reply, Reply, LoopData};

handle_call({delete_usr, CustId}, _From, LoopData) ->
Reply = usr_db:delete_usr(CustId),
{reply, Reply, LoopData};

handle_call({set_service, CustId, Service, Flag}, _From, LoopData) ->
Reply = case usr_db:lookup_id(CustId) of
{ok, Usr} ->
Services = lists:delete(Service, Usr#usr.services),
NewServices = case Flag of
true -> [Service | Services];
false -> Services
end,
usr_db:update_usr(Usr#usr{services = NewServices});
{error, instance} ->
{error, instance}
end,
{reply, Reply, LoopData};

handle_call({set_status, CustId, Status}, _From, LoopData) ->
Reply = case usr_db:lookup_id(CustId) of
{ok, Usr} ->
usr_db:update_usr(Usr#usr{status = Status});
{error, instance} ->
{error, instance}
end,
{reply, Reply, LoopData};

handle_call({delete_disabled}, _From, LoopData) ->
Reply = usr_db:delete_disabled(),
{reply, Reply, LoopData}.

handle_cast(stop, LoopData) ->
{stop, normal, LoopData}.

handle_info(Msg, LoopData) ->
io:format("Recive Not OPT Message ~p~n", [Msg]),
{noreply, LoopData}.
10 changes: 10 additions & 0 deletions chapter_12/usr-1.0/src/usr_app.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-module(usr_app).
-behavior(application).

-export([start/2, stop/1]).

start(_Type, StartArgs) ->
usr_sup:start_link().

stop(_State) ->
ok.
89 changes: 89 additions & 0 deletions chapter_12/usr-1.0/src/usr_db.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
%%% File: usr_db.erl
%%% Description: Database API for subscriber DB

-module(usr_db).
-include("usr.hrl").

-export([create_tables/1, close_tables/0]).
-export([add_usr/1, update_usr/1]).
-export([lookup_id/1, lookup_msisdn/1]).
-export([restore_backup/0]).

-export([delete_disabled/0, delete_usr/1]).

create_tables(FileName) ->
ets:new(usrRam, [named_table, {keypos, #usr.msisdn}]),
ets:new(usrIndex, [named_table]),
dets:open_file(usrDisk, [{file, FileName}, {keypos, #usr.msisdn}]).

close_tables() ->
ets:delete(usrRam),
ets:delete(usrIndex),
dets:close(usrDisk).

add_usr(#usr{msisdn=PhoneNo, id=CustId} = Usr) ->
ets:insert(usrIndex, {CustId, PhoneNo}),
update_usr(Usr).

update_usr(Usr) ->
ets:insert(usrRam, Usr),
dets:insert(usrDisk, Usr),
ok.

lookup_id(CustId) ->
case get_index(CustId) of
{ok, PhoneNo} -> lookup_msisdn(PhoneNo);
{error, instance} -> {error, instance}
end.

lookup_msisdn(PhoneNo) ->
case ets:lookup(usrRam, PhoneNo) of
[Usr] -> {ok, Usr};
[] -> {error, instance}
end.

get_index(CustId) ->
case ets:lookup(usrIndex, CustId) of
[{CustId, PhoneNo}] -> {ok, PhoneNo};
[] -> {error, instance}
end.

restore_backup() ->
Insert = fun(#usr{msisdn=PhoneNo, id=Id} = Usr) ->
ets:insert(usrRam, Usr),
ets:insert(usrIndex, {Id, PhoneNo}),
continue
end,
dets:traverse(usrDisk, Insert).

delete_disabled() ->
ets:safe_fixtable(usrRam, true),
catch loop_delete_disabled(ets:first(usrRam)),
ets:safe_fixtable(usrRam, false),
ok.

delete_usr(CustId) ->
case get_index(CustId) of
{ok, PhoneNo} ->
ets:safe_fixtable(usrRam, true),
ets:delete(usrRam, PhoneNo),
ets:safe_fixtable(usrRam, false),
ets:safe_fixtable(usrIndex, true),
ets:delete(usrIndex, CustId),
ets:safe_fixtable(usrIndex, false),

dets:delete(usrDisk, PhoneNo);
{error, instance} -> {error, instance}
end.

loop_delete_disabled('$end_of_table') ->
ok;

loop_delete_disabled(PhoneNo) ->
case ets:lookup(usrRam, PhoneNo) of
[#usr{status=disabled, id=CustId}] ->
delete_usr(CustId);
_ ->
ok
end,
loop_delete_disabled(ets:next(usrRam, PhoneNo)).
16 changes: 16 additions & 0 deletions chapter_12/usr-1.0/src/usr_sup.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
-module(usr_sup).
-behavior(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, null).

init(_) ->
UsrChild = {
usr, {usr, start_link, []},
permanent, 2000, worker, [usr, usr_db]},

{ok, {{one_for_all, 2, 2}, [UsrChild]}}.

107 changes: 107 additions & 0 deletions chapter_12/usr.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
-module(usr).
-export([start_link/0, start_link/1, stop/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2]).
-export([add_usr/3, delete_usr/1, set_service/3, set_status/2, delete_disabled/0, lookup_id/1]).
-export([lookup_msisdn/1, service_flag/2]).

-behavior(gen_server).

-include("usr.hrl").
-define(TIMEOUT, 30000).

start_link() ->
{ok, FileName} = application:get_env(dets_name),
start_link(FileName).

start_link(FileName) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, FileName, []).

stop() ->
gen_server:cast(?MODULE, stop).

init(FileName) ->
usr_db:create_tables(FileName),
usr_db:restore_backup(),
{ok, null}.

terminate(Reason, LoopData) ->
usr_db:close_tables().

add_usr(PhoneNum, CustId, Plan) when Plan == prepay; Plan == postpay ->
gen_server:call(?MODULE, {add_usr, PhoneNum, CustId, Plan}).

delete_usr(CustId) ->
gen_server:call(?MODULE, {delete_usr, CustId}).

set_service(CustId, Service, Flag) when Flag == true; Flag == false ->
gen_server:call(?MODULE, {set_service, CustId, Service, Flag}).

set_status(CustId, Status) when Status == enabled; Status == disabled ->
gen_server:call(?MODULE, {set_status, CustId, Status}).

delete_disabled() ->
gen_server:call(?MODULE, delete_disabled).

lookup_id(CustId) ->
usr_db:lookup_id(CustId).

lookup_msisdn(PhoneNo) ->
usr_db:lookup_msisdn(PhoneNo).

service_flag(PhoneNo, Service) ->
case usr_db:lookup_msisdn(PhoneNo) of
{ok, #usr{services = Services, status = enabled}} ->
lists:member(Service, Services);
{ok, #usr{status=disabled}} ->
{error, disabled};
{error, Reason} ->
{error, Reason}
end.

handle_call({add_usr, PhoneNo, CustId, Plan}, _From, LoopData) ->
Reply = usr_db:add_usr(
#usr{
msisdn=PhoneNo,
id=CustId,
plan=Plan
}
),
{reply, Reply, LoopData};

handle_call({delete_usr, CustId}, _From, LoopData) ->
Reply = usr_db:delete_usr(CustId),
{reply, Reply, LoopData};

handle_call({set_service, CustId, Service, Flag}, _From, LoopData) ->
Reply = case usr_db:lookup_id(CustId) of
{ok, Usr} ->
Services = lists:delete(Service, Usr#usr.services),
NewServices = case Flag of
true -> [Service | Services];
false -> Services
end,
usr_db:update_usr(Usr#usr{services = NewServices});
{error, instance} ->
{error, instance}
end,
{reply, Reply, LoopData};

handle_call({set_status, CustId, Status}, _From, LoopData) ->
Reply = case usr_db:lookup_id(CustId) of
{ok, Usr} ->
usr_db:update_usr(Usr#usr{status = Status});
{error, instance} ->
{error, instance}
end,
{reply, Reply, LoopData};

handle_call({delete_disabled}, _From, LoopData) ->
Reply = usr_db:delete_disabled(),
{reply, Reply, LoopData}.

handle_cast(stop, LoopData) ->
{stop, normal, LoopData}.

handle_info(Msg, LoopData) ->
io:format("Recive Not OPT Message ~p~n", [Msg]),
{noreply, LoopData}.
Loading

0 comments on commit 83a0ce9

Please sign in to comment.