Compare commits

...

5 Commits

Author SHA1 Message Date
Holger Weiß 65aeb1d553
Merge 79ab6bb47c into c5437235f3 2024-03-21 03:31:29 +01:00
Paweł Chmielowski c5437235f3 Make mod_vcard_xupdate send hash after avatar get set for first time
We need to remove info about empty photo in session stored presence after
avatar get set, otherwise as we don't modify presences like that in
mod_vcard_xupdate, we will send presence with updated hash.

This fixes issue #4182
2024-03-20 10:57:12 +01:00
Paweł Chmielowski 537aac24f7 Improve detection of types in odbc
This should fix issue with dialyzer on erlang 26.2.3+
2024-03-18 14:54:32 +01:00
Paweł Chmielowski 8f20dd8425 Test retractons in mam_tests 2024-03-18 12:42:03 +01:00
Holger Weiss 79ab6bb47c PubSub: Use integer type for timestamps (SQL)
Store PubSub item creation/modification timestamps as integers instead
of "$megasec:$sec:$microsec" strings.  This can improve the performance
of certain SQL queries significantly.

Thanks to Ammonit Measurement GmbH for sponsoring this work.
2021-08-24 07:07:44 +02:00
17 changed files with 114 additions and 45 deletions

17
mix.exs
View File

@ -80,6 +80,20 @@ defmodule Ejabberd.MixProject do
end
end
defp if_type_exported(module, typeDef, okResult) do
try do
{:ok, concrete} = :dialyzer_utils.get_core_from_beam(:code.which(module))
{:ok, types} = :dialyzer_utils.get_record_and_type_info(concrete)
if Maps.has_key(types, typeDef) do
okResult
else
[]
end
rescue
_ -> []
end
end
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include", deps_include()]
@ -97,7 +111,8 @@ defmodule Ejabberd.MixProject do
if_version_below(~c"24", [{:d, :COMPILER_REPORTS_ONLY_LINES}]) ++
if_version_below(~c"24", [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) ++
if_version_below(~c"24", [{:d, :OTP_BELOW_24}]) ++
if_version_below(~c"25", [{:d, :OTP_BELOW_25}])
if_version_below(~c"25", [{:d, :OTP_BELOW_25}]) ++
if_type_exported(:odbc, {:opaque, :connection_reference, 0}, [{:d, :ODBC_HAS_TYPES}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end

View File

@ -152,6 +152,7 @@
{if_var_true, roster_gateway_workaround, {d, 'ROSTER_GATEWAY_WORKAROUND'}},
{if_var_true, sip, {d, 'SIP'}},
{if_var_true, stun, {d, 'STUN'}},
{if_type_exported, {odbc, {opaque, connection_reference, 0}}, {d, 'ODBC_HAS_TYPES'}},
{src_dirs, [src,
{if_rebar3, sql},
{if_var_true, tools, tools}]}]}.

View File

@ -151,6 +151,30 @@ ProcessVars = fun F([], Acc) ->
false ->
F(Tail, Acc)
end;
F([{Type, {Mod, TypeDef}, Value} | Tail], Acc) when
Type == if_type_exported orelse
Type == if_type_not_exported ->
try
{ok, Concrete} = dialyzer_utils:get_core_from_beam(code:which(Mod)),
{ok, Types} = dialyzer_utils:get_record_and_type_info(Concrete),
maps:get(TypeDef, Types, undefined)
of
undefined when Type == if_type_not_exported ->
F(Tail, ProcessSingleVar(F, Value, Acc));
undefined ->
F(Tail, Acc);
_ when Type == if_type_exported ->
F(Tail, ProcessSingleVar(F, Value, Acc));
_ ->
F(Tail, Acc)
catch _:_ ->
if
Type == if_type_not_exported ->
F(Tail, ProcessSingleVar(F, Value, Acc));
true ->
F(Tail, Acc)
end
end;
F([Other1 | Tail1], Acc) ->
F(Tail1, [F(Other1, []) | Acc]);
F(Val, Acc) when is_tuple(Val) ->

View File

@ -262,8 +262,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT UNSIGNED NOT NULL,
modification BIGINT UNSIGNED NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);

View File

@ -240,8 +240,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT UNSIGNED NOT NULL,
modification BIGINT UNSIGNED NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item (itemid);

View File

@ -209,8 +209,8 @@ CREATE TABLE [dbo].[pubsub_item] (
[nodeid] [bigint] NULL,
[itemid] [varchar] (255) NOT NULL,
[publisher] [varchar] (250) NOT NULL,
[creation] [varchar] (32) NOT NULL,
[modification] [varchar] (32) NOT NULL,
[creation] [bigint] NOT NULL,
[modification] [bigint] NOT NULL,
[payload] [text] NOT NULL DEFAULT ''
) TEXTIMAGE_ON [PRIMARY];

View File

@ -280,8 +280,8 @@ CREATE TABLE pubsub_item (
nodeid bigint,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT UNSIGNED NOT NULL,
modification BIGINT UNSIGNED NOT NULL,
payload mediumtext NOT NULL
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));

View File

@ -256,8 +256,8 @@ CREATE TABLE pubsub_item (
nodeid bigint,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT UNSIGNED NOT NULL,
modification BIGINT UNSIGNED NOT NULL,
payload mediumtext NOT NULL
) ENGINE=InnoDB CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE INDEX i_pubsub_item_itemid ON pubsub_item(itemid(36));

View File

@ -433,8 +433,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT NOT NULL,
modification BIGINT NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);

View File

@ -259,8 +259,8 @@ CREATE TABLE pubsub_item (
nodeid bigint REFERENCES pubsub_node(nodeid) ON DELETE CASCADE,
itemid text NOT NULL,
publisher text NOT NULL,
creation varchar(32) NOT NULL,
modification varchar(32) NOT NULL,
creation BIGINT NOT NULL,
modification BIGINT NOT NULL,
payload text NOT NULL DEFAULT ''
);
CREATE INDEX i_pubsub_item_itemid ON pubsub_item USING btree (itemid);

View File

@ -52,7 +52,8 @@
-export([get_presence/1, set_presence/2, resend_presence/1, resend_presence/2,
open_session/1, call/3, cast/2, send/2, close/1, close/2, stop_async/1,
reply/2, copy_state/2, set_timeout/2, route/2, format_reason/2,
host_up/1, host_down/1, send_ws_ping/1, bounce_message_queue/2]).
host_up/1, host_down/1, send_ws_ping/1, bounce_message_queue/2,
reset_vcard_xupdate_resend_presence/1]).
-include_lib("xmpp/include/xmpp.hrl").
-include("logger.hrl").
@ -108,6 +109,10 @@ resend_presence(Pid) ->
resend_presence(Pid, To) ->
route(Pid, {resend_presence, To}).
-spec reset_vcard_xupdate_resend_presence(pid()) -> boolean().
reset_vcard_xupdate_resend_presence(Pid) ->
route(Pid, reset_vcard_xupdate_resend_presence).
-spec close(pid()) -> ok;
(state()) -> state().
close(Ref) ->
@ -246,6 +251,13 @@ process_info(#{lserver := LServer} = State, {route, Packet}) ->
true ->
State1
end;
process_info(State, reset_vcard_xupdate_resend_presence) ->
case maps:get(pres_last, State, error) of
error -> State;
Pres ->
Pres2 = xmpp:remove_subtag(Pres, #vcard_xupdate{}),
process_self_presence(State#{pres_last => Pres2}, Pres2)
end;
process_info(#{jid := JID} = State, {resend_presence, To}) ->
case maps:get(pres_last, State, error) of
error -> State;

View File

@ -56,6 +56,7 @@
get_vh_session_number/1,
get_vh_by_backend/1,
force_update_presence/1,
reset_vcard_xupdate_resend_presence/1,
connected_users/0,
connected_users_number/0,
user_resources/2,
@ -926,6 +927,15 @@ force_update_presence({LUser, LServer}) ->
end,
Ss).
-spec reset_vcard_xupdate_resend_presence({binary(), binary()}) -> ok.
reset_vcard_xupdate_resend_presence({LUser, LServer}) ->
Mod = get_sm_backend(LServer),
Ss = get_sessions(Mod, LUser, LServer),
lists:foreach(
fun(#session{sid = {_, Pid}}) ->
ejabberd_c2s:reset_vcard_xupdate_resend_presence(Pid)
end, Ss).
-spec get_sm_backend(binary()) -> module().
get_sm_backend(Host) ->

View File

@ -67,12 +67,8 @@
-export([connecting/2, connecting/3,
session_established/2, session_established/3]).
-ifdef(OTP_RELEASE).
-if(?OTP_RELEASE >= 27).
-type(odbc_connection_reference() :: odbc:connection_reference()).
-else.
-type(odbc_connection_reference() :: pid()).
-endif.
-ifdef(ODBC_HAS_TYPES).
-type(odbc_connection_reference() :: odbc:connection_reference()).
-else.
-type(odbc_connection_reference() :: pid()).
-endif.

View File

@ -97,7 +97,7 @@ user_send_packet(Acc) ->
-spec vcard_set(iq()) -> iq().
vcard_set(#iq{from = #jid{luser = LUser, lserver = LServer}} = IQ) ->
ets_cache:delete(?VCARD_XUPDATE_CACHE, {LUser, LServer}, ejabberd_cluster:get_nodes()),
ejabberd_sm:force_update_presence({LUser, LServer}),
ejabberd_sm:reset_vcard_xupdate_resend_presence({LUser, LServer}),
IQ;
vcard_set(Acc) ->
Acc.

View File

@ -844,16 +844,16 @@ set_item(Item) ->
P = encode_jid(JID),
Payload = Item#pubsub_item.payload,
XML = str:join([fxml:element_to_binary(X) || X<-Payload], <<>>),
SM = encode_now(M),
SC = encode_now(C),
SM = misc:now_to_usec(M),
SC = misc:now_to_usec(C),
?SQL_UPSERT_T(
"pubsub_item",
["!nodeid=%(Nidx)d",
"!itemid=%(ItemId)s",
"publisher=%(P)s",
"modification=%(SM)s",
"modification=%(SM)d",
"payload=%(XML)s",
"-creation=%(SC)s"
"-creation=%(SC)d"
]),
ok.
@ -1087,20 +1087,27 @@ rsm_page(Count, Index, Offset, Items) ->
first = #rsm_first{index = Offset, data = First},
last = Last}.
%% Convert <<"2021-08-22T19:25:52.817368Z">> to <<"1629660352817368">>.
-spec encode_stamp(binary()) -> binary().
encode_stamp(Stamp) ->
try xmpp_util:decode_timestamp(Stamp) of
Now ->
encode_now(Now)
catch _:{bad_timestamp, _} ->
Stamp % We should return a proper error to the client instead.
<<"0">> % We should return a proper error to the client instead.
end.
%% Convert <<"1629660352817368">> to <<"2021-08-22T19:25:52.817368Z">>.
-spec decode_stamp(binary()) -> binary().
decode_stamp(Stamp) ->
xmpp_util:encode_timestamp(decode_now(Stamp)).
encode_now({T1, T2, T3}) ->
<<(misc:i2l(T1, 6))/binary, ":",
(misc:i2l(T2, 6))/binary, ":",
(misc:i2l(T3, 6))/binary>>.
decode_now(NowStr) ->
[MS, S, US] = binary:split(NowStr, <<":">>, [global]),
{binary_to_integer(MS), binary_to_integer(S), binary_to_integer(US)}.
%% Convert {1629, 660352, 817368} to <<"1629660352817368">>.
-spec encode_now(erlang:timestamp()) -> binary().
encode_now(Now) ->
integer_to_binary(misc:now_to_usec(Now)).
%% Convert <<"1629660352817368">> to {1629, 660352, 817368}.
-spec decode_now(binary()) -> erlang:timestamp().
decode_now(Str) ->
misc:usec_to_now(binary_to_integer(Str)).

View File

@ -184,15 +184,10 @@ export(_Server) ->
payload = Payload}) ->
P = jid:encode(JID),
XML = str:join([fxml:element_to_binary(X) || X<-Payload], <<>>),
SM = encode_now(M),
SC = encode_now(C),
SM = misc:now_to_usec(M),
SC = misc:now_to_usec(C),
[?SQL("insert into pubsub_item(itemid,nodeid,creation,modification,publisher,payload)"
" values (%(ItemId)s, %(Nidx)d, %(SC)s, %(SM)s, %(P)s, %(XML)s);")];
" values (%(ItemId)s, %(Nidx)d, %(SC)d, %(SM)d, %(P)s, %(XML)s);")];
(_Host, _R) ->
[]
end}].
encode_now({T1, T2, T3}) ->
<<(misc:i2l(T1, 6))/binary, ":",
(misc:i2l(T2, 6))/binary, ":",
(misc:i2l(T3, 6))/binary>>.

View File

@ -431,12 +431,21 @@ set_default(Config, Default) ->
send_messages(Config, Range) ->
Peer = ?config(peer, Config),
send_message_extra(Config, 0, <<"to-retract-1">>, []),
lists:foreach(
fun(N) ->
fun
(1) ->
send_message_extra(Config, 1, <<"retraction-1">>, [#message_retract{id = <<"to-retract-1">>}]);
(N) ->
Body = xmpp:mk_text(integer_to_binary(N)),
send(Config, #message{to = Peer, body = Body})
end, Range).
send_message_extra(Config, N, Id, Sub) ->
Peer = ?config(peer, Config),
Body = xmpp:mk_text(integer_to_binary(N)),
send(Config, #message{id = Id, to = Peer, body = Body, sub_els = Sub}).
recv_messages(Config, Range) ->
Peer = ?config(peer, Config),
lists:foreach(
@ -448,7 +457,7 @@ recv_messages(Config, Range) ->
xmpp:get_subtag(Msg, #mam_archived{}),
#stanza_id{by = BareMyJID} =
xmpp:get_subtag(Msg, #stanza_id{})
end, Range).
end, [0 | Range]).
recv_archived_messages(Config, From, To, QID, Range) ->
MyJID = my_jid(Config),