Skip to content

Commit c01e4bc

Browse files
grammmikejengelh
authored andcommitted
mbop: add sync_mailbox operation of midb to mbop
References: GXL-630, DESK-3819
1 parent 113facd commit c01e4bc

File tree

8 files changed

+124
-5
lines changed

8 files changed

+124
-5
lines changed

Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ gromox_mbck_SOURCES = tools/mbck.cpp
196196
gromox_mbck_LDADD = ${libHX_LIBS} ${fmt_LIBS} ${sqlite_LIBS} libgromox_common.la
197197
gromox_mbop_SOURCES = tools/genimport.cpp tools/genimport.hpp tools/mbop.hpp tools/mbop.cpp
198198
EXTRA_DIST += tools/mbop_delmsg.cpp tools/mbop_emptyfld.cpp tools/mbop_foreach.cpp tools/mbop_freebusy.cpp tools/mbop_locale.cpp tools/mbop_main.cpp tools/mbop_purge.cpp tools/staticnpmap.cpp
199-
gromox_mbop_LDADD = ${libHX_LIBS} ${mysql_LIBS} libgromox_common.la libgromox_exrpc.la libgromox_mapi.la libgxs_mysql_adaptor.la
199+
gromox_mbop_LDADD = ${libHX_LIBS} ${mysql_LIBS} libgromox_common.la libgromox_exrpc.la libgromox_mapi.la libgxs_mysql_adaptor.la libgxs_midb_agent.la
200200
gromox_mbsize_SOURCES = tools/mbsize.cpp
201201
gromox_mbsize_LDADD = ${sqlite_LIBS} libgromox_common.la
202202
gromox_mkmidb_SOURCES = tools/mkmidb.cpp tools/mkshared.cpp tools/mkshared.hpp

doc/changelog.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Enhancements:
3737
* dscli: try all oxdisco URLs until one succeeds
3838
* exmdb: support repeated import of permission data (e.g. from kdb2mt)
3939
* ews: create calendar item after accepting a MR with MacMail
40+
* mbop: new `sync-midb` subcommand to prebuild midb caches ahead of the first IMAP login
4041

4142
Fixes:
4243

doc/gromox-mbop.8

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ set\-photo: read user image from stdin and save to store
6969
set\-websettings, set\-websettings\-persistent, set\-websettings\-recipients:
7070
read new grommunio-web settings from stdin and save to store
7171
.IP \(bu 4
72+
sync\-midb: trigger a midb synchronization run
73+
.IP \(bu 4
7274
thaw: unfreeze a mailbox
7375
.IP \(bu 4
7476
unload: issue the "unload_store" RPC for a mailbox
@@ -323,6 +325,21 @@ Reads various grommunio-web settings from the store and dumps it to stdout.
323325
Causes the respective mailbox to be opened by the server. (Any request to the
324326
information storage server causes the respective mailbox to be opened; and ping
325327
is technically just a no-op request type.)
328+
.SH sync\-midb
329+
.SS Synopsis
330+
\fBsync-midb\fP [\fB\-f\fP \fIfolder_spec\fP]
331+
.SS Description
332+
Sends a request to midb for opening the mailbox and updating the midb-specific
333+
folder indices, as well as potentially building RFC5322 representations for
334+
newly-appeared messages. (Once the mailbox is open in midb, it uses
335+
asynchronous notifications to stay up to date.) Due to implementation details
336+
of the midb connector, requests will time out after 60 second, even if sync
337+
procedure inside the midb daemon keeps running in the background.
338+
.SS Options
339+
.TP
340+
\fB\-f\fP \fIfolder_spec\fP
341+
Forcibly rerun the sync routine for a single specific folder. See section
342+
"Folder specification". In addition, the special keyword "all" is recognized.
326343
.SH purge\-datafiles
327344
The "purge\-datafiles" RPC makes exmdb_provider remove attachment and content
328345
files from disk that are no longer referenced by any message.

exch/midb/mail_engine.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3550,12 +3550,20 @@ static int me_xunld(int argc, char **argv, int sockd)
35503550
* Request:
35513551
* X-RSYM <store-dir>
35523552
* Response:
3553-
* TRUE <0|1|2>
3553+
* TRUE 0: synchro failure
3554+
* TRUE 1: was loaded before (tracking changes live), now is synchronized
3555+
* TRUE 2: was unloaded before (not tracking), now is synchronized
35543556
*/
35553557
static int me_xrsym(int argc, char **argv, int sockd)
35563558
{
35573559
auto idb = me_peek_idb(argv[1]);
35583560
if (idb == nullptr) {
3561+
/*
3562+
* There is a time between me_peek_idb and me_get_idb that
3563+
* another thread may have invoked me_get_idb and already
3564+
* triggered an initial sync. Therefore, we are passing `true`
3565+
* here to force resync in any case.
3566+
*/
35593567
me_get_idb(argv[1], true);
35603568
return cmd_write(sockd, "TRUE 2\r\n");
35613569
} else if (!me_sync_mailbox(idb.get(), true)) {

include/gromox/midb_agent.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ extern GX_EXPORT int summary_folder(const char *path, const std::string &folder,
4646
extern GX_EXPORT int make_folder(const char *path, const std::string &folder, int *perrno);
4747
extern GX_EXPORT int remove_folder(const char *path, const std::string &folder, int *perrno);
4848
extern GX_EXPORT int ping_mailbox(const char *path, int *perrno);
49+
extern GX_EXPORT int sync_mailbox(const char *path, uint64_t folder_id, int *err);
4950
extern GX_EXPORT int rename_folder(const char *path, const std::string &src_name, const std::string &dst_name, int *perrno);
5051
extern GX_EXPORT int subscribe_folder(const char *path, const std::string &folder, int *perrno);
5152
extern GX_EXPORT int unsubscribe_folder(const char *path, const std::string &folder, int *perrno);

mra/midb_agent.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,33 @@ int ping_mailbox(const char *path, int *perrno)
745745
return MIDB_RDWR_ERROR;
746746
}
747747

748+
int sync_mailbox(const char *path, uint64_t folder_id, int *err)
749+
{
750+
auto conn = get_connection(path);
751+
if (conn == nullptr)
752+
return MIDB_NO_SERVER;
753+
char buf[1024];
754+
int len;
755+
if (folder_id == 0)
756+
len = gx_snprintf(buf, std::size(buf), "X-RSYM %s\r\n", path);
757+
else
758+
len = gx_snprintf(buf, std::size(buf), "X-RSYF %s %llu\r\n",
759+
path, static_cast<unsigned long long>(folder_id));
760+
auto ret = rw_command(conn->sockd, buf, len, std::size(buf));
761+
if (ret != 0)
762+
return ret;
763+
if (strncmp(buf, "TRUE", 4) == 0) {
764+
conn.reset();
765+
return MIDB_RESULT_OK;
766+
} else if (strncmp(buf, "FALSE ", 6) == 0) {
767+
conn.reset();
768+
if (err != nullptr)
769+
*err = strtol(&buf[6], nullptr, 0);
770+
return MIDB_RESULT_ERROR;
771+
}
772+
return MIDB_RDWR_ERROR;
773+
}
774+
748775
int rename_folder(const char *path, const std::string &src_name,
749776
const std::string &dst_name, int *perrno)
750777
{

tools/mbop.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace foreach_wrap { extern int main(int, char **); }
2121
namespace getfreebusy { extern int main(int, char **); }
2222
namespace purgesoftdel { extern int main(int, char **); }
2323
namespace set_locale { extern int main(int, char **); }
24+
namespace sync_midb { extern int main(int, char **); }
2425

2526
namespace global {
2627

tools/mbop_main.cpp

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <gromox/exmdb_rpc.hpp>
1818
#include <gromox/freebusy.hpp>
1919
#include <gromox/mapidefs.h>
20+
#include <gromox/midb_agent.hpp>
2021
#include <gromox/mysql_adaptor.hpp>
2122
#include <gromox/process.hpp>
2223
#include <gromox/svc_loader.hpp>
@@ -211,6 +212,65 @@ static int freeze_main(int argc, char **argv)
211212

212213
}
213214

215+
namespace sync_midb {
216+
217+
static const char *g_folder_spec;
218+
static constexpr HXoption g_options_table[] = {
219+
{{}, 'f', HXTYPE_STRP, &g_folder_spec, {}, {}, {}, "Forcibly rescan this folder", "SPEC"},
220+
MBOP_AUTOHELP,
221+
HXOPT_TABLEEND,
222+
};
223+
224+
int main(int argc, char **argv)
225+
{
226+
HXopt6_auto_result argp;
227+
228+
if (HX_getopt6(g_options_table, argc, argv, nullptr,
229+
HXOPT_USAGEONERR) != HXOPT_ERR_SUCCESS || g_exit_after_optparse)
230+
return EXIT_PARAM;
231+
232+
int err = 0, ret;
233+
if (g_folder_spec == nullptr) {
234+
ret = midb_agent::ping_mailbox(g_storedir, &err);
235+
} else if (strcasecmp(g_folder_spec, "all") == 0) {
236+
ret = midb_agent::sync_mailbox(g_storedir, 0, &err);
237+
} else {
238+
eid_t eid = gi_lookup_eid_by_name(g_storedir, g_folder_spec);
239+
if (eid == 0) {
240+
mbop_fprintf(stderr, "Not recognized/found: \"%s\"\n", g_folder_spec);
241+
return EXIT_FAILURE;
242+
}
243+
ret = midb_agent::sync_mailbox(g_storedir, eid.gcv(), &err);
244+
}
245+
switch (ret) {
246+
case MIDB_RESULT_OK:
247+
if (global::g_verbose_mode)
248+
printf("midb sync triggered\n");
249+
return EXIT_SUCCESS;
250+
case MIDB_RESULT_ERROR:
251+
mbop_fprintf(stderr, "midb sync failed: backend returned %d\n", err);
252+
break;
253+
case MIDB_NO_SERVER:
254+
mbop_fprintf(stderr, "midb sync failed: midb backend unavailable\n");
255+
break;
256+
case MIDB_RDWR_ERROR:
257+
mbop_fprintf(stderr, "midb sync failed: protocol error while talking to midb\n");
258+
break;
259+
case MIDB_LOCAL_ENOMEM:
260+
mbop_fprintf(stderr, "midb sync failed: local memory exhausted\n");
261+
break;
262+
case MIDB_TOO_MANY_RESULTS:
263+
mbop_fprintf(stderr, "midb sync failed: backend returned too much data\n");
264+
break;
265+
default:
266+
mbop_fprintf(stderr, "midb sync failed: unexpected midb agent status %d\n", ret);
267+
break;
268+
}
269+
return EXIT_FAILURE;
270+
}
271+
272+
}
273+
214274
static errno_t resolvename(const GUID &guid, const char *name, bool create,
215275
uint16_t *out)
216276
{
@@ -426,8 +486,10 @@ static int single_user_wrap(int argc, char **argv)
426486
return ret;
427487
}
428488

429-
static constexpr generic_module g_dfl_svc_plugins[] =
430-
{{"libgxs_mysql_adaptor.so", SVC_mysql_adaptor}};
489+
static constexpr generic_module g_dfl_svc_plugins[] = {
490+
{"libgxs_mysql_adaptor.so", SVC_mysql_adaptor},
491+
{"libgxs_midb_agent.so", SVC_midb_agent},
492+
};
431493

432494
int main(int argc, char **argv)
433495
{
@@ -447,7 +509,7 @@ int main(int argc, char **argv)
447509
argv = result.uarg;
448510
if (argc == 0)
449511
return global::help();
450-
service_init({nullptr, g_dfl_svc_plugins, 1});
512+
service_init({nullptr, g_dfl_svc_plugins, 2});
451513
auto cl_1 = HX::make_scope_exit(service_stop);
452514
if (service_run_early() != 0 || service_run() != 0) {
453515
fprintf(stderr, "service_run: failed\n");
@@ -535,6 +597,8 @@ int cmd_parser(int argc, char **argv)
535597
return set_locale::main(argc, argv);
536598
else if (strcmp(argv[0], "get-freebusy") == 0 || strcmp(argv[0], "gfb") == 0)
537599
return getfreebusy::main(argc, argv);
600+
else if (strcmp(argv[0], "sync-midb") == 0)
601+
return sync_midb::main(argc, argv);
538602

539603
if (strcmp(argv[0], "clear-profile") == 0) {
540604
auto ret = delstoreprop(argc, argv, PSETID_Gromox, "zcore_profsect", PT_BINARY);

0 commit comments

Comments
 (0)