1
0
Fork 0
mirror of https://github.com/processone/ejabberd synced 2025-10-03 09:49:18 +02:00

Compare commits

...

2 commits

Author SHA1 Message Date
Pawel Chmielowski
1a9b147baf Report db failures in mod_muc_mnesia:restore_room 2025-07-23 20:27:19 +02:00
Pawel Chmielowski
6214e0385d Report db failures from mod_muc:restore_room 2025-07-23 19:59:32 +02:00
4 changed files with 43 additions and 14 deletions

View file

@ -97,7 +97,7 @@
-callback import(binary(), binary(), [binary()]) -> ok. -callback import(binary(), binary(), [binary()]) -> ok.
-callback store_room(binary(), binary(), binary(), list(), list()|undefined) -> {atomic, any()}. -callback store_room(binary(), binary(), binary(), list(), list()|undefined) -> {atomic, any()}.
-callback store_changes(binary(), binary(), binary(), list()) -> {atomic, any()}. -callback store_changes(binary(), binary(), binary(), list()) -> {atomic, any()}.
-callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error. -callback restore_room(binary(), binary(), binary()) -> muc_room_opts() | error | {error, atom()}.
-callback forget_room(binary(), binary(), binary()) -> {atomic, any()}. -callback forget_room(binary(), binary(), binary()) -> {atomic, any()}.
-callback can_use_nick(binary(), binary(), jid(), binary()) -> boolean(). -callback can_use_nick(binary(), binary(), jid(), binary()) -> boolean().
-callback get_rooms(binary(), binary()) -> [#muc_room{}]. -callback get_rooms(binary(), binary()) -> [#muc_room{}].
@ -591,20 +591,17 @@ extract_password(#iq{} = IQ) ->
false false
end. end.
-spec unhibernate_room(binary(), binary(), binary()) -> {ok, pid()} | error. -spec unhibernate_room(binary(), binary(), binary()) -> {ok, pid()} | {error, notfound | db_failure | term()}.
unhibernate_room(ServerHost, Host, Room) -> unhibernate_room(ServerHost, Host, Room) ->
unhibernate_room(ServerHost, Host, Room, true). unhibernate_room(ServerHost, Host, Room, true).
-spec unhibernate_room(binary(), binary(), binary(), boolean()) -> {ok, pid()} | error. -spec unhibernate_room(binary(), binary(), binary(), boolean()) -> {ok, pid()} | {error, notfound | db_failure | term()}.
unhibernate_room(ServerHost, Host, Room, ResetHibernationTime) -> unhibernate_room(ServerHost, Host, Room, ResetHibernationTime) ->
RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE), RMod = gen_mod:ram_db_mod(ServerHost, ?MODULE),
case RMod:find_online_room(ServerHost, Room, Host) of case RMod:find_online_room(ServerHost, Room, Host) of
error -> error ->
Proc = procname(ServerHost, {Room, Host}), Proc = procname(ServerHost, {Room, Host}),
case ?GEN_SERVER:call(Proc, {unhibernate, Room, Host, ResetHibernationTime}, 20000) of ?GEN_SERVER:call(Proc, {unhibernate, Room, Host, ResetHibernationTime}, 20000);
{ok, _} = R -> R;
_ -> error
end;
{ok, _} = R2 -> R2 {ok, _} = R2 -> R2
end. end.
@ -888,6 +885,8 @@ load_room(RMod, Host, ServerHost, Room, ResetHibernationTime) ->
case restore_room(ServerHost, Host, Room) of case restore_room(ServerHost, Host, Room) of
error -> error ->
{error, notfound}; {error, notfound};
{error, _} = Err ->
Err;
Opts0 -> Opts0 ->
Mod = gen_mod:db_mod(ServerHost, mod_muc), Mod = gen_mod:db_mod(ServerHost, mod_muc),
case proplists:get_bool(persistent, Opts0) of case proplists:get_bool(persistent, Opts0) of

View file

@ -1289,6 +1289,8 @@ create_room_with_opts(Name1, Host1, ServerHost1, CustomRoomOpts) ->
{error, _} -> {error, _} ->
throw({error, "Unable to start room"}) throw({error, "Unable to start room"})
end; end;
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "Room already exists"}) throw({error, "Room already exists"})
end. end.
@ -1307,6 +1309,8 @@ destroy_room(Name1, Service1) ->
case get_room_pid_validate(Name1, Service1, <<"service">>) of case get_room_pid_validate(Name1, Service1, <<"service">>) of
{room_not_found, _, _} -> {room_not_found, _, _} ->
throw({error, "Room doesn't exists"}); throw({error, "Room doesn't exists"});
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
{Pid, _, _} -> {Pid, _, _} ->
mod_muc_room:destroy(Pid), mod_muc_room:destroy(Pid),
ok ok
@ -1698,6 +1702,8 @@ change_room_option(Name, Service, OptionString, ValueString) ->
case get_room_pid_validate(Name, Service, <<"service">>) of case get_room_pid_validate(Name, Service, <<"service">>) of
{room_not_found, _, _} -> {room_not_found, _, _} ->
throw({error, "Room not found"}); throw({error, "Room not found"});
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
{Pid, _, _} -> {Pid, _, _} ->
{Option, Value} = format_room_option(OptionString, ValueString), {Option, Value} = format_room_option(OptionString, ValueString),
change_room_option(Pid, Option, Value) change_room_option(Pid, Option, Value)
@ -1823,25 +1829,29 @@ parse_nodes(_, _) ->
throw({error, "Invalid 'subscribers' - unknown node name used"}). throw({error, "Invalid 'subscribers' - unknown node name used"}).
-spec get_room_pid_validate(binary(), binary(), binary()) -> -spec get_room_pid_validate(binary(), binary(), binary()) ->
{pid() | room_not_found, binary(), binary()}. {pid() | room_not_found | db_failure, binary(), binary()}.
get_room_pid_validate(Name, Service, ServiceArg) -> get_room_pid_validate(Name, Service, ServiceArg) ->
Name2 = validate_room(Name), Name2 = validate_room(Name),
{ServerHost, Service2} = validate_muc2(Service, ServiceArg), {ServerHost, Service2} = validate_muc2(Service, ServiceArg),
case mod_muc:unhibernate_room(ServerHost, Service2, Name2) of case mod_muc:unhibernate_room(ServerHost, Service2, Name2) of
error -> {error, notfound} ->
{room_not_found, Name2, Service2}; {room_not_found, Name2, Service2};
{error, db_failure} ->
{db_failure, Name2, Service2};
{ok, Pid} -> {ok, Pid} ->
{Pid, Name2, Service2} {Pid, Name2, Service2}
end. end.
%% @doc Get the Pid of an existing MUC room, or 'room_not_found'. %% @doc Get the Pid of an existing MUC room, or 'room_not_found'.
-spec get_room_pid(binary(), binary()) -> pid() | room_not_found | invalid_service | unknown_service. -spec get_room_pid(binary(), binary()) -> pid() | room_not_found | db_failure | invalid_service | unknown_service.
get_room_pid(Name, Service) -> get_room_pid(Name, Service) ->
try get_room_serverhost(Service) of try get_room_serverhost(Service) of
ServerHost -> ServerHost ->
case mod_muc:unhibernate_room(ServerHost, Service, Name) of case mod_muc:unhibernate_room(ServerHost, Service, Name) of
error -> {error, notfound} ->
room_not_found; room_not_found;
{error, db_failure} ->
db_failure;
{ok, Pid} -> {ok, Pid} ->
Pid Pid
end end
@ -1954,6 +1964,8 @@ get_room_affiliations(Name, Service) ->
({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)-> ({{Uname, Domain, _Res}, Aff}) when is_atom(Aff)->
{Uname, Domain, Aff, <<>>} {Uname, Domain, Aff, <<>>}
end, Affiliations); end, Affiliations);
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist."}) throw({error, "The room does not exist."})
end. end.
@ -1975,6 +1987,8 @@ get_room_affiliations_v3(Name, Service) ->
Jid = makeencode(Uname, Domain), Jid = makeencode(Uname, Domain),
{Jid, Aff, <<>>} {Jid, Aff, <<>>}
end, Affiliations); end, Affiliations);
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist."}) throw({error, "The room does not exist."})
end. end.
@ -1993,6 +2007,8 @@ get_room_history(Name, Service) ->
_ -> _ ->
throw({error, "Unable to fetch room state."}) throw({error, "Unable to fetch room state."})
end; end;
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist."}) throw({error, "The room does not exist."})
end. end.
@ -2012,6 +2028,8 @@ get_room_affiliation(Name, Service, JID) ->
{ok, StateData} = mod_muc_room:get_state(Pid), {ok, StateData} = mod_muc_room:get_state(Pid),
UserJID = jid:decode(JID), UserJID = jid:decode(JID),
mod_muc_room:get_affiliation(UserJID, StateData); mod_muc_room:get_affiliation(UserJID, StateData);
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist."}) throw({error, "The room does not exist."})
end. end.
@ -2052,6 +2070,8 @@ set_room_affiliation(Name, Service, JID, AffiliationString) ->
{error, _} -> {error, _} ->
throw({error, "Unable to perform change"}) throw({error, "Unable to perform change"})
end; end;
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "Room doesn't exists"}) throw({error, "Room doesn't exists"})
end. end.
@ -2084,6 +2104,8 @@ subscribe_room(User, Nick, Room, NodeList) ->
{error, Reason} -> {error, Reason} ->
throw({error, binary_to_list(Reason)}) throw({error, binary_to_list(Reason)})
end; end;
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist"}) throw({error, "The room does not exist"})
end end
@ -2129,6 +2151,8 @@ unsubscribe_room(User, Room) ->
{error, Reason} -> {error, Reason} ->
throw({error, binary_to_list(Reason)}) throw({error, binary_to_list(Reason)})
end; end;
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist"}) throw({error, "The room does not exist"})
end end
@ -2146,6 +2170,8 @@ get_subscribers(Name, Host) ->
{Pid, _, _} when is_pid(Pid) -> {Pid, _, _} when is_pid(Pid) ->
{ok, JIDList} = mod_muc_room:get_subscribers(Pid), {ok, JIDList} = mod_muc_room:get_subscribers(Pid),
[jid:encode(jid:remove_resource(J)) || J <- JIDList]; [jid:encode(jid:remove_resource(J)) || J <- JIDList];
{db_failure, _Name, _Host} ->
throw({error, "Database error"});
_ -> _ ->
throw({error, "The room does not exist"}) throw({error, "The room does not exist"})
end. end.

View file

@ -76,9 +76,11 @@ store_room(_LServer, Host, Name, Opts, _) ->
mnesia:transaction(F). mnesia:transaction(F).
restore_room(_LServer, Host, Name) -> restore_room(_LServer, Host, Name) ->
case catch mnesia:dirty_read(muc_room, {Name, Host}) of try mnesia:dirty_read(muc_room, {Name, Host}) of
[#muc_room{opts = Opts}] -> Opts; [#muc_room{opts = Opts}] -> Opts;
_ -> error _ -> error
catch
_:_ -> {error, db_failure}
end. end.
forget_room(_LServer, Host, Name) -> forget_room(_LServer, Host, Name) ->

View file

@ -220,10 +220,12 @@ restore_room(LServer, Host, Name) ->
Opts2 = lists:keystore(subscribers, 1, OptsD, {subscribers, SubData}), Opts2 = lists:keystore(subscribers, 1, OptsD, {subscribers, SubData}),
mod_muc:opts_to_binary(Opts2); mod_muc:opts_to_binary(Opts2);
_ -> _ ->
error {error, db_failure}
end; end;
{selected, _} ->
error;
_ -> _ ->
error {error, db_failure}
end. end.
forget_room(LServer, Host, Name) -> forget_room(LServer, Host, Name) ->