/
mcache2.erl
110 lines (95 loc) · 2.96 KB
/
mcache2.erl
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
%
% wraps memcached_drv
%
-module(mcache2).
-author('echou327@gmail.com').
-export([mget/2, set/5, set/4]).
-define(SEP, ":").
-define(MGET_TIMEOUT, 500).
-define(FMT_RAW, 0).
-define(FMT_NATIVE, 101).
-define(FMT_JSON, 102).
-define(FMT_INT, 103).
mget(Class, [_|_]=Keys) ->
{Pool, _Expiry} = mcache_expires:expire(Class),
RealKeys = lists:map(fun(K) ->
K1 = map_key(Class, K),
erlang:put({'$mcache2_mget$', K1}, K),
K1
end, Keys),
try
{mc_async, 0, {ok, Values}} = memcached_drv:mget(Pool, 0, RealKeys),
lists:foldl(fun({Key, Val, Flag}, Acc) ->
case erlang:get({'$mcache2_mget$', Key}) of
undefined ->
Acc;
K ->
[{K, decode_value({Val, Flag})}|Acc]
end
end, [], Values)
after
lists:foreach(fun({{'$mcache2_mget$',_}=K,V}) ->
erlang:erase(K)
end, erlang:get())
end.
set(Class, Key, Value, Format, Expiry) ->
{Pool, DefaultExpiry} = mcache_expires:expire(Class),
{Value1, Flags} = encode_value(Value, Format),
Expiry1 = encode_expiry(Expiry, DefaultExpiry),
{mc_async, 0, {ok}} = memcached_drv:set(Pool, 0, map_key(Class, Key), Value1, Flags, Expiry1),
ok.
set(Class, Key, Value, Format) ->
set(Class, Key, Value, Format, default).
% internal functions
my_now() ->
erlang:now().
cast([H]) when H>255;is_atom(H) ->
cast(H);
cast([H|L]) when H>255;is_atom(H) ->
[cast(H),":"|cast(L)];
cast(V) when is_tuple(V) ->
cast(tuple_to_list(V));
cast(V) when is_list(V); is_binary(V) ->
V;
cast(V) when is_atom(V) ->
atom_to_list(V);
cast(V) when is_integer(V) ->
integer_to_list(V).
map_key(Class, Key) ->
iolist_to_binary([cast(Class), ":", cast(Key)]).
encode_value(Value, raw) ->
{Value, ?FMT_RAW};
encode_value(Value, native) ->
{term_to_binary(Value), ?FMT_NATIVE};
encode_value(Value, json) ->
{eep0018:encode(Value), ?FMT_JSON};
encode_value(Value, int) ->
{<<Value:32>>, ?FMT_INT}.
decode_value(undefined) ->
undefined;
decode_value(not_found) ->
undefined;
decode_value({Data, ?FMT_RAW}) ->
Data;
decode_value({Data, ?FMT_NATIVE}) ->
binary_to_term(Data);
decode_value({Data, ?FMT_JSON}) ->
eep0018:decode(Data);
decode_value({<<Int:32>>, ?FMT_INT}) ->
Int.
encode_expiry(default, DefaultExpiry) ->
encode_expiry1(DefaultExpiry);
encode_expiry(Expiry, _DefaultExpiry) ->
encode_expiry1(Expiry).
encode_expiry1(infinity) ->
0;
encode_expiry1({X, seconds}) ->
X;
encode_expiry1({X, minutes}) ->
X*60;
encode_expiry1({X, hours}) ->
X*3600;
encode_expiry1({X, days}) when X<30->
X*86400;
encode_expiry1(X) when is_integer(X) ->
X.