-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkvs_gen_tcp.erl
More file actions
90 lines (82 loc) · 2.36 KB
/
kvs_gen_tcp.erl
File metadata and controls
90 lines (82 loc) · 2.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
-module(kvs_server).
-export([start/0,stop/1]).
-include_lib("eunit/include/eunit.hrl").
-define(PORT, 12321).
-define(STORE, store).
start() ->
Options = [binary, {packet, raw}, {active, true}, {reuseaddr, true}],
ets:new(?STORE, [set, public, named_table]),
case gen_tcp:listen(?PORT, Options) of
{ok, Listen} -> spawn(fun() -> acceptor_loop(Listen) end),
{ok, Listen};
{error, _} ->
stop
end.
stop(Listen) ->
gen_tcp:close(Listen),
ok.
acceptor_loop(Listen) ->
case gen_tcp:accept(Listen) of
{ok, Client} ->
Pid = spawn(fun() -> server_loop(Client) end),
gen_tcp:controlling_process(Client, Pid),
acceptor_loop(Listen);
{error, closed} ->
stop;
{error, timeout} ->
io:format("accept failed: timeout~n"),
stop;
{error, Reason} ->
io:format("accept failed: ~p~n", [Reason]),
stop
end.
server_loop(Client) ->
receive
{tcp, Client, Data} ->
gen_tcp:send(Client, handle_request(parse_request(Data))),
inet:setopts(Client, [{active, once}]),
server_loop(Client);
{tcp_closed, _} ->
gen_tcp:close(Client),
ok;
_ ->
gen_tcp:close(Client),
error
end.
% Exercise 1. Complete implementation of the handlers for set and get requests
% Exercise 1. Implement a handler for delete requests
handle_request([<<"help">>]) ->
<<"command list\n set <key> <value>\n get <key>\n delete <key>\n">>;
handle_request([<<"set">>, Key, Val]) ->
?debugVal(Key),
?debugVal(Val),
try ets:insert(?STORE, {Key, Val}) of
true ->
<< "ok\n" >>
catch
_ : _ ->
<< "failed\n" >>
end;
%<<"set request!\n">>;
handle_request([<<"get">>, Key]) ->
?debugVal(Key),
Ret = ets:lookup(?STORE, Key),
case Ret of
[{Key, Val}] ->
?debugVal(Val),
<< Val/binary , "\n">>;
_ ->
<< "not found\n" >>
end;
% <<"get request!\n">>;
handle_request([<<"delete">>, Key]) ->
?debugVal(Key),
ets:delete(?STORE, Key),
<< "ok\n" >>;
handle_request(Req) ->
?debugVal(Req),
<<"parse error\n">>.
parse_request(Data) ->
% remove the last newline characters
Data2 = re:replace(Data, <<"\\s+$">>, <<"">>, [{newline, any}, {return, binary}]),
re:split(Data2, "\\s+").