From 1925b94131a5fa5de8d718ae81d86dcca2ae653f Mon Sep 17 00:00:00 2001 From: Evgeniy Khramtsov Date: Wed, 17 May 2017 17:13:34 +0300 Subject: Implement cache for mod_vcard and mod_vcard_xupdate --- src/mod_vcard.erl | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 5 deletions(-) (limited to 'src/mod_vcard.erl') diff --git a/src/mod_vcard.erl b/src/mod_vcard.erl index 00fd4bbc0..495393f72 100644 --- a/src/mod_vcard.erl +++ b/src/mod_vcard.erl @@ -48,11 +48,12 @@ -include("mod_vcard.hrl"). -define(JUD_MATCHES, 30). +-define(VCARD_CACHE, vcard_cache). -callback init(binary(), gen_mod:opts()) -> any(). -callback stop(binary()) -> any(). -callback import(binary(), binary(), [binary()]) -> ok. --callback get_vcard(binary(), binary()) -> [xmlel()] | error. +-callback get_vcard(binary(), binary()) -> {ok, [xmlel()]} | error. -callback set_vcard(binary(), binary(), xmlel(), #vcard_search{}) -> {atomic, any()}. -callback search_fields(binary()) -> [{binary(), binary()}]. @@ -61,6 +62,10 @@ infinity | pos_integer()) -> [{binary(), binary()}]. -callback remove_user(binary(), binary()) -> {atomic, any()}. -callback is_search_supported(binary()) -> boolean(). +-callback use_cache(binary()) -> boolean(). +-callback cache_nodes(binary()) -> [node()]. + +-optional_callbacks([use_cache/1, cache_nodes/1]). -record(state, {host :: binary(), server_host :: binary()}). @@ -80,6 +85,7 @@ init([Host, Opts]) -> process_flag(trap_exit, true), Mod = gen_mod:db_mod(Host, Opts, ?MODULE), Mod:init(Host, Opts), + init_cache(Mod, Host, Opts), ejabberd_hooks:add(remove_user, Host, ?MODULE, remove_user, 50), IQDisc = gen_mod:get_opt(iqdisc, Opts, gen_iq_handler:iqdisc(Host)), @@ -288,7 +294,18 @@ disco_identity(Acc, _From, _To, _Node, _Lang) -> -spec get_vcard(binary(), binary()) -> [xmlel()] | error. get_vcard(LUser, LServer) -> Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:get_vcard(LUser, LServer). + Result = case use_cache(Mod, LServer) of + true -> + ets_cache:lookup( + ?VCARD_CACHE, {LUser, LServer}, + fun() -> Mod:get_vcard(LUser, LServer) end); + false -> + Mod:get_vcard(LUser, LServer) + end, + case Result of + {ok, Els} -> Els; + error -> error + end. -spec make_vcard_search(binary(), binary(), binary(), xmlel()) -> #vcard_search{}. make_vcard_search(User, LUser, LServer, VCARD) -> @@ -366,6 +383,8 @@ set_vcard(User, LServer, VCARD) -> VCardSearch = make_vcard_search(User, LUser, LServer, VCARD), Mod = gen_mod:db_mod(LServer, ?MODULE), Mod:set_vcard(LUser, LServer, VCARD, VCardSearch), + ets_cache:delete(?VCARD_CACHE, {LUser, LServer}, + cache_nodes(Mod, LServer)), ejabberd_hooks:run(vcard_set, LServer, [LUser, LServer, VCARD]) end. @@ -435,12 +454,56 @@ search(LServer, XFields) -> Mod:search(LServer, Data, AllowReturnAll, MaxMatch). %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% --spec remove_user(binary(), binary()) -> any(). +-spec remove_user(binary(), binary()) -> ok. remove_user(User, Server) -> LUser = jid:nodeprep(User), LServer = jid:nameprep(Server), Mod = gen_mod:db_mod(LServer, ?MODULE), - Mod:remove_user(LUser, LServer). + Mod:remove_user(LUser, LServer), + ets_cache:delete(?VCARD_CACHE, {LUser, LServer}, cache_nodes(Mod, LServer)). + +-spec init_cache(module(), binary(), gen_mod:opts()) -> ok. +init_cache(Mod, Host, Opts) -> + case use_cache(Mod, Host) of + true -> + CacheOpts = cache_opts(Host, Opts), + ets_cache:new(?VCARD_CACHE, CacheOpts); + false -> + ets_cache:delete(?VCARD_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(module(), binary()) -> boolean(). +use_cache(Mod, Host) -> + case erlang:function_exported(Mod, use_cache, 1) of + true -> Mod:use_cache(Host); + false -> + gen_mod:get_module_opt( + Host, ?MODULE, use_cache, + ejabberd_config:use_cache(Host)) + end. + +-spec cache_nodes(module(), binary()) -> [node()]. +cache_nodes(Mod, Host) -> + case erlang:function_exported(Mod, cache_nodes, 1) of + true -> Mod:cache_nodes(Host); + false -> ejabberd_cluster:get_nodes() + end. import_info() -> [{<<"vcard">>, 3}, {<<"vcard_search">>, 24}]. @@ -473,6 +536,13 @@ mod_opt_type(search) -> fun (B) when is_boolean(B) -> B end; mod_opt_type(search_all_hosts) -> fun (B) when is_boolean(B) -> B end; +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(_) -> [allow_return_all, db_type, host, iqdisc, matches, - search, search_all_hosts]. + search, search_all_hosts, cache_life_time, cache_size, + use_cache, cache_missed]. -- cgit v1.2.3