Skip to content

Commit b72b92c

Browse files
committed
Add commands for new dataabase export/import
1 parent c9e3f0b commit b72b92c

File tree

4 files changed

+383
-184
lines changed

4 files changed

+383
-184
lines changed

src/ejabberd_admin.erl

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,70 @@ get_commands_spec() ->
457457
result_desc = "Status text",
458458
result_example = "Operation aborted"},
459459

460+
#ejabberd_commands{name = export_db, tags = [db],
461+
desc = "Export database records for host to files",
462+
note = "added in 25.XX",
463+
module = ejabberd_db_serialize, function = export,
464+
args_desc = ["Name of host that should be exported",
465+
"Directory name where exported files should be created"],
466+
args_example = [<<"localhost">>, <<"/home/ejabberd/export">>],
467+
args = [{host, binary}, {dir, binary}],
468+
result = {res, restuple},
469+
result_desc = "Result tuple",
470+
result_example = {ok, <<"Export started">>}},
471+
#ejabberd_commands{name = export_db_status, tags = [db],
472+
desc = "Return current status of export operation",
473+
note = "added in 22.XX",
474+
module = ejabberd_db_serialize, function = export_status,
475+
args_desc = ["Name of host where export is performed"],
476+
args_example = [<<"localhost">>],
477+
args = [{host, binary}],
478+
result = {status, binary},
479+
result_desc = "Current operation status",
480+
result_example = "Operation in progress: 'Exporting mod_mam', exported 5000 records so far"},
481+
#ejabberd_commands{name = export_db_abort, tags = [db],
482+
desc = "Abort currently running export peration",
483+
note = "added in 22.XX",
484+
module = ejabberd_db_serialize, function = export_abort,
485+
args_desc = ["Name of host where export is performed"],
486+
args_example = [<<"localhost">>],
487+
args = [{host, binary}],
488+
result = {status, binary},
489+
result_desc = "Operation status",
490+
result_example = "Operation aborted"},
491+
492+
#ejabberd_commands{name = import_db, tags = [db],
493+
desc = "Import database records for host to files",
494+
note = "added in 25.XX",
495+
module = ejabberd_db_serialize, function = import,
496+
args_desc = ["Name of host that should be imported",
497+
"Directory name where imported files should be created"],
498+
args_example = [<<"localhost">>, <<"/home/ejabberd/export">>],
499+
args = [{host, binary}, {dir, binary}],
500+
result = {res, restuple},
501+
result_desc = "Result tuple",
502+
result_example = {ok, <<"Import started">>}},
503+
#ejabberd_commands{name = import_db_status, tags = [db],
504+
desc = "Return current status of import operation",
505+
note = "added in 22.XX",
506+
module = ejabberd_db_serialize, function = import_status,
507+
args_desc = ["Name of host where import is performed"],
508+
args_example = [<<"localhost">>],
509+
args = [{host, binary}],
510+
result = {status, binary},
511+
result_desc = "Current operation status",
512+
result_example = "Operation in progress: 'Importing mod_mam', imported 5000 records so far"},
513+
#ejabberd_commands{name = import_db_abort, tags = [db],
514+
desc = "Abort currently running import peration",
515+
note = "added in 22.XX",
516+
module = ejabberd_db_serialize, function = import_abort,
517+
args_desc = ["Name of host where import is performed"],
518+
args_example = [<<"localhost">>],
519+
args = [{host, binary}],
520+
result = {status, binary},
521+
result_desc = "Operation status",
522+
result_example = "Operation aborted"},
523+
460524
#ejabberd_commands{name = export2sql, tags = [mnesia],
461525
desc = "Export virtual host information from Mnesia tables to SQL file",
462526
longdesc = "Configure the modules to use SQL, then call this command. "
@@ -1027,13 +1091,13 @@ delete_old_messages_batch(Server, Days, BatchSize, Rate) ->
10271091
{true, _} ->
10281092
case Mod:remove_old_messages_batch(L, Da, B) of
10291093
{ok, Count} ->
1030-
{ok, S, Count};
1094+
{ok, S, Count, undefined};
10311095
{error, _} = E ->
10321096
E
10331097
end;
10341098
{_, true} ->
10351099
case Mod:remove_old_messages_batch(L, Da, B, IS) of
1036-
{ok, IS2, Count} ->
1100+
{ok, IS2, Count, undefined} ->
10371101
{ok, {L, Da, B, IS2}, Count};
10381102
{error, _} = E ->
10391103
E
@@ -1056,13 +1120,13 @@ delete_old_messages_status(Server) ->
10561120
{failed, Steps, Error} ->
10571121
io_lib:format("Operation failed after deleting ~p messages with error ~p",
10581122
[Steps, misc:format_val(Error)]);
1059-
{aborted, Steps} ->
1123+
{aborted, Steps, _} ->
10601124
io_lib:format("Operation was aborted after deleting ~p messages",
10611125
[Steps]);
1062-
{working, Steps} ->
1126+
{working, Steps, _} ->
10631127
io_lib:format("Operation in progress, deleted ~p messages",
10641128
[Steps]);
1065-
{completed, Steps} ->
1129+
{completed, Steps, _} ->
10661130
io_lib:format("Operation was completed after deleting ~p messages",
10671131
[Steps])
10681132
end,

src/ejabberd_batch.erl

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
-define(SERVER, ?MODULE).
4242

4343
-record(state, {tasks = #{}}).
44-
-record(task, {state = not_started, pid, steps, done_steps}).
44+
-record(task, {state = not_started, pid, steps, done_steps, last_message}).
4545

4646
%%%===================================================================
4747
%%% API
@@ -99,14 +99,14 @@ handle_call({task_status, Type}, _From, #state{tasks = Tasks} = State) ->
9999
{reply, not_started, State};
100100
#task{state = not_started} ->
101101
{reply, not_started, State};
102-
#task{state = failed, done_steps = Steps, pid = Error} ->
102+
#task{state = failed, done_steps = Steps, last_message = Error} ->
103103
{reply, {failed, Steps, Error}, State};
104-
#task{state = aborted, done_steps = Steps} ->
105-
{reply, {aborted, Steps}, State};
106-
#task{state = working, done_steps = Steps} ->
107-
{reply, {working, Steps}, State};
108-
#task{state = completed, done_steps = Steps} ->
109-
{reply, {completed, Steps}, State}
104+
#task{state = aborted, done_steps = Steps, last_message = Msg} ->
105+
{reply, {aborted, Steps, Msg}, State};
106+
#task{state = working, done_steps = Steps, last_message = Msg} ->
107+
{reply, {working, Steps, Msg}, State};
108+
#task{state = completed, done_steps = Steps, last_message = Msg} ->
109+
{reply, {completed, Steps, Msg}, State}
110110
end;
111111
handle_call({abort_task, Type}, _From, #state{tasks = Tasks} = State) ->
112112
case maps:get(Type, Tasks, none) of
@@ -126,26 +126,26 @@ handle_call(_Request, _From, State = #state{}) ->
126126
{noreply, NewState :: #state{}} |
127127
{noreply, NewState :: #state{}, timeout() | hibernate} |
128128
{stop, Reason :: term(), NewState :: #state{}}).
129-
handle_cast({task_finished, Type, Pid}, #state{tasks = Tasks} = State) ->
129+
handle_cast({task_finished, Type, Pid, Msg}, #state{tasks = Tasks} = State) ->
130130
case maps:get(Type, Tasks, none) of
131131
#task{state = working, pid = Pid2} = T when Pid == Pid2 ->
132-
Tasks2 = maps:put(Type, T#task{state = completed, pid = none}, Tasks),
132+
Tasks2 = maps:put(Type, T#task{state = completed, pid = none, last_message = Msg}, Tasks),
133133
{noreply, State#state{tasks = Tasks2}};
134134
_ ->
135135
{noreply, State}
136136
end;
137-
handle_cast({task_progress, Type, Pid, Count}, #state{tasks = Tasks} = State) ->
137+
handle_cast({task_progress, Type, Pid, Count, Msg}, #state{tasks = Tasks} = State) ->
138138
case maps:get(Type, Tasks, none) of
139139
#task{state = working, pid = Pid2, done_steps = Steps} = T when Pid == Pid2 ->
140-
Tasks2 = maps:put(Type, T#task{done_steps = Steps + Count}, Tasks),
140+
Tasks2 = maps:put(Type, T#task{done_steps = Steps + Count, last_message = Msg}, Tasks),
141141
{noreply, State#state{tasks = Tasks2}};
142142
_ ->
143143
{noreply, State}
144144
end;
145145
handle_cast({task_error, Type, Pid, Error}, #state{tasks = Tasks} = State) ->
146146
case maps:get(Type, Tasks, none) of
147147
#task{state = working, pid = Pid2} = T when Pid == Pid2 ->
148-
Tasks2 = maps:put(Type, T#task{state = failed, pid = Error}, Tasks),
148+
Tasks2 = maps:put(Type, T#task{state = failed, last_message = Error}, Tasks),
149149
{noreply, State#state{tasks = Tasks2}};
150150
_ ->
151151
{noreply, State}
@@ -186,20 +186,24 @@ code_change(_OldVsn, State = #state{}, _Extra) ->
186186

187187
work_loop(Task, JobState, JobFun, Rate, StartDate, CurrentProgress) ->
188188
try JobFun(JobState) of
189-
{ok, _NewState, 0} ->
190-
gen_server:cast(?MODULE, {task_finished, Task, self()});
191-
{ok, NewState, Count} ->
192-
gen_server:cast(?MODULE, {task_progress, Task, self(), Count}),
189+
{ok, _NewState, 0, Msg} ->
190+
gen_server:cast(?MODULE, {task_finished, Task, self(), Msg});
191+
{ok, NewState, Count, Msg} ->
192+
gen_server:cast(?MODULE, {task_progress, Task, self(), Count, Msg}),
193193
NewProgress = CurrentProgress + Count,
194-
TimeSpent = erlang:monotonic_time(second) - StartDate,
195-
SleepTime = max(0, NewProgress/Rate*60 - TimeSpent),
194+
SleepTime = case Rate of
195+
infinity -> 0;
196+
_ ->
197+
TimeSpent = erlang:monotonic_time(second) - StartDate,
198+
max(0, NewProgress/Rate*60 - TimeSpent)
199+
end,
196200
receive
197201
abort -> ok
198202
after round(SleepTime*1000) ->
199203
work_loop(Task, NewState, JobFun, Rate, StartDate, NewProgress)
200204
end;
201205
{error, Error} ->
202206
gen_server:cast(?MODULE, {task_error, Task, self(), Error})
203-
catch _:_ ->
204-
gen_server:cast(?MODULE, {task_error, Task, self(), internal_error})
207+
catch T:E:S ->
208+
gen_server:cast(?MODULE, {task_error, Task, self(), {internal_error, T, E, S}})
205209
end.

0 commit comments

Comments
 (0)