diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-05-17 17:13:34 +0300 |
---|---|---|
committer | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2017-05-17 17:13:34 +0300 |
commit | 1925b94131a5fa5de8d718ae81d86dcca2ae653f (patch) | |
tree | 820124866d9e4bb4592eacb7441635269b88a4cb /src/mod_vcard_xupdate.erl | |
parent | Add cache options to the validator (diff) |
Implement cache for mod_vcard and mod_vcard_xupdate
Diffstat (limited to 'src/mod_vcard_xupdate.erl')
-rw-r--r-- | src/mod_vcard_xupdate.erl | 153 |
1 files changed, 92 insertions, 61 deletions
diff --git a/src/mod_vcard_xupdate.erl b/src/mod_vcard_xupdate.erl index e31b3049..0da8198d 100644 --- a/src/mod_vcard_xupdate.erl +++ b/src/mod_vcard_xupdate.erl @@ -30,52 +30,39 @@ %% gen_mod callbacks -export([start/2, stop/1, reload/3]). --export([update_presence/1, vcard_set/3, export/1, - import_info/0, import/5, import_start/2, +-export([update_presence/1, vcard_set/3, remove_user/2, mod_opt_type/1, depends/2]). -include("ejabberd.hrl"). -include("logger.hrl"). -include("xmpp.hrl"). --callback init(binary(), gen_mod:opts()) -> any(). --callback import(binary(), binary(), [binary()]) -> ok. --callback add_xupdate(binary(), binary(), binary()) -> {atomic, any()}. --callback get_xupdate(binary(), binary()) -> binary() | undefined. --callback remove_xupdate(binary(), binary()) -> {atomic, any()}. +-define(VCARD_XUPDATE_CACHE, vcard_xupdate_cache). %%==================================================================== %% gen_mod callbacks %%==================================================================== start(Host, Opts) -> - Mod = gen_mod:db_mod(Host, Opts, ?MODULE), - Mod:init(Host, Opts), + init_cache(Host, Opts), ejabberd_hooks:add(c2s_self_presence, Host, ?MODULE, update_presence, 100), ejabberd_hooks:add(vcard_set, Host, ?MODULE, vcard_set, 100), - ok. + ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50). stop(Host) -> ejabberd_hooks:delete(c2s_self_presence, Host, ?MODULE, update_presence, 100), ejabberd_hooks:delete(vcard_set, Host, ?MODULE, vcard_set, 100), - ok. - -reload(Host, NewOpts, OldOpts) -> - NewMod = gen_mod:db_mod(Host, NewOpts, ?MODULE), - OldMod = gen_mod:db_mod(Host, OldOpts, ?MODULE), - if NewMod /= OldMod -> - NewMod:init(Host, NewOpts); - true -> - ok - end, - ok. + ejabberd_hooks:delete(remove_user, Host, ?MODULE, remove_user, 50). + +reload(Host, NewOpts, _OldOpts) -> + init_cache(Host, NewOpts). depends(_Host, _Opts) -> - []. + [{mod_vcard, hard}]. %%==================================================================== %% Hooks @@ -91,51 +78,95 @@ update_presence(Acc) -> Acc. -spec vcard_set(binary(), binary(), xmlel()) -> ok. -vcard_set(LUser, LServer, VCARD) -> - US = {LUser, LServer}, - case fxml:get_path_s(VCARD, - [{elem, <<"PHOTO">>}, {elem, <<"BINVAL">>}, cdata]) - of - <<>> -> remove_xupdate(LUser, LServer); - BinVal -> - add_xupdate(LUser, LServer, - str:sha(misc:decode_base64(BinVal))) - end, - ejabberd_sm:force_update_presence(US). +vcard_set(LUser, LServer, _VCARD) -> + ets_cache:delete(?VCARD_XUPDATE_CACHE, {LUser, LServer}), + ejabberd_sm:force_update_presence({LUser, LServer}). + +-spec remove_user(binary(), binary()) -> ok. +remove_user(User, Server) -> + LUser = jid:nodeprep(User), + LServer = jid:nameprep(Server), + ets_cache:delete(?VCARD_XUPDATE_CACHE, {LUser, LServer}). %%==================================================================== %% Storage %%==================================================================== - -add_xupdate(LUser, LServer, Hash) -> - Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:add_xupdate(LUser, LServer, Hash). - +-spec get_xupdate(binary(), binary()) -> binary() | undefined. get_xupdate(LUser, LServer) -> - Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:get_xupdate(LUser, LServer). - -remove_xupdate(LUser, LServer) -> - Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_xupdate(LUser, LServer). - -import_info() -> - [{<<"vcard_xupdate">>, 3}]. - -import_start(LServer, DBType) -> - Mod = gen_mod:db_mod(DBType, ?MODULE), - Mod:init(LServer, []). - -import(LServer, {sql, _}, DBType, Tab, [LUser, Hash, TimeStamp]) -> - Mod = gen_mod:db_mod(DBType, ?MODULE), - Mod:import(LServer, Tab, [LUser, Hash, TimeStamp]). - -export(LServer) -> - Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:export(LServer). + Result = case use_cache(LServer) of + true -> + ets_cache:lookup( + ?VCARD_XUPDATE_CACHE, {LUser, LServer}, + fun() -> db_get_xupdate(LUser, LServer) end); + false -> + db_get_xupdate(LUser, LServer) + end, + case Result of + {ok, Hash} -> Hash; + error -> undefined + end. + +-spec db_get_xupdate(binary(), binary()) -> {ok, binary()} | error. +db_get_xupdate(LUser, LServer) -> + case mod_vcard:get_vcard(LUser, LServer) of + [VCard] -> + {ok, compute_hash(VCard)}; + _ -> + error + end. + +-spec init_cache(binary(), gen_mod:opts()) -> ok. +init_cache(Host, Opts) -> + case use_cache(Host) of + true -> + CacheOpts = cache_opts(Host, Opts), + ets_cache:new(?VCARD_XUPDATE_CACHE, CacheOpts); + false -> + ets_cache:delete(?VCARD_XUPDATE_CACHE) + end. + +-spec cache_opts(binary(), gen_mod:opts()) -> [proplists:property()]. +cache_opts(Host, Opts) -> + MaxSize = gen_mod:get_opt( + cache_size, Opts, + ejabberd_config:cache_size(Host)), + CacheMissed = gen_mod:get_opt( + cache_missed, Opts, + ejabberd_config:cache_missed(Host)), + LifeTime = case gen_mod:get_opt( + cache_life_time, Opts, + ejabberd_config:cache_life_time(Host)) of + infinity -> infinity; + I -> timer:seconds(I) + end, + [{max_size, MaxSize}, {cache_missed, CacheMissed}, {life_time, LifeTime}]. + +-spec use_cache(binary()) -> boolean(). +use_cache(Host) -> + gen_mod:get_module_opt( + Host, ?MODULE, use_cache, + ejabberd_config:use_cache(Host)). + +-spec compute_hash(xmlel()) -> binary(). +compute_hash(VCard) -> + case fxml:get_path_s(VCard, + [{elem, <<"PHOTO">>}, + {elem, <<"BINVAL">>}, + cdata]) of + <<>> -> + <<>>; + BinVal -> + str:sha(misc:decode_base64(BinVal)) + end. %%==================================================================== %% Options %%==================================================================== -mod_opt_type(db_type) -> fun(T) -> ejabberd_config:v_db(?MODULE, T) end; -mod_opt_type(_) -> [db_type]. +mod_opt_type(O) when O == cache_life_time; O == cache_size -> + fun (I) when is_integer(I), I > 0 -> I; + (infinity) -> infinity + end; +mod_opt_type(O) when O == use_cache; O == cache_missed -> + fun (B) when is_boolean(B) -> B end; +mod_opt_type(_) -> + [cache_life_time, cache_size, use_cache, cache_missed]. |