Skip to content

Commit

Permalink
Merge pull request cyrusimap#4811 from cyrusimap/replicaonly-raclmodseq
Browse files Browse the repository at this point in the history
replicaonly: add silent RACL updates and batch them to sync
  • Loading branch information
brong committed Feb 22, 2024
2 parents bbb852a + 9dd2e06 commit 80606b3
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 25 deletions.
6 changes: 6 additions & 0 deletions imap/cyr_expire.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
#include "mboxevent.h"
#include "mboxlist.h"
#include "conversations.h"
#include "user.h"
#include "util.h"
#include "xmalloc.h"
#include "strarray.h"
Expand Down Expand Up @@ -322,6 +323,11 @@ static int noexpire_mailbox(const mbentry_t *mbentry)
goto done;
}

if (user_isreplicaonly(mbname_userid(mbname))) {
ret = 1;
goto done;
}

// Determine user inbox name
if (mbname_isdeleted(mbname)) {
mbname_t *tmp = mbname_from_userid(mbname_userid(mbname));
Expand Down
50 changes: 30 additions & 20 deletions imap/mboxlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -1032,7 +1032,7 @@ static int mboxlist_update_raclmodseq(const char *acluser)
}

static int mboxlist_update_racl(const char *dbname, const mbentry_t *oldmbentry,
const mbentry_t *newmbentry, struct txn **txn)
const mbentry_t *newmbentry, struct txn **txn, int silent)
{
static strarray_t *admins = NULL;
struct buf buf = BUF_INITIALIZER;
Expand Down Expand Up @@ -1063,7 +1063,7 @@ static int mboxlist_update_racl(const char *dbname, const mbentry_t *oldmbentry,
mboxlist_racl_key(!!userid, acluser, dbname, &buf);
r = cyrusdb_delete(mbdb, buf.s, buf.len, txn, /*force*/1);
if (r) goto done;
mboxlist_update_raclmodseq(acluser);
if (!silent) mboxlist_update_raclmodseq(acluser);
}
}

Expand All @@ -1077,7 +1077,7 @@ static int mboxlist_update_racl(const char *dbname, const mbentry_t *oldmbentry,
mboxlist_racl_key(!!userid, acluser, dbname, &buf);
r = cyrusdb_store(mbdb, buf.s, buf.len, "", 0, txn);
if (r) goto done;
mboxlist_update_raclmodseq(acluser);
if (!silent) mboxlist_update_raclmodseq(acluser);
}
}

Expand Down Expand Up @@ -1155,22 +1155,27 @@ static void assert_namespacelocked(const char *mboxname)
* DELETED --> {NULL} : Expire
* DELETED --> RESERVE : Create again (should never happen ideally, but undo/restore)
*/
static int mboxlist_update_entry(const char *name,
const mbentry_t *mbentry, struct txn **txn)
#define mboxlist_update_entry(n, m, t) mboxlist_update_entry_full(n, m, t, 0)
static int mboxlist_update_entry_full(const char *name, const mbentry_t *mbentry,
struct txn **txn, int silent)
{
char *dbname = mboxname_to_dbname(name);
mbname_t *mbname = mbname_from_intname(name);
struct buf key = BUF_INITIALIZER;
mbentry_t *old = NULL;
mbentry_t *oldi = NULL;
int r = 0;
struct txn *mytid = NULL;
const char *dbname = mbname_dbname(mbname);

/* make sure the name is locked first - NOTE, this doesn't guarantee ordering
* on the I key since we can't tell to lock that (and may be accessing two) so
* make sure you have all the related name keys locked before entering this
* function if renaming */
assert_namespacelocked(name);

if (!silent && !(mbentry && (mbentry->mbtype & MBTYPE_DELETED)))
mboxname_assert_canadd(mbname);

/* take a local transaction if there isn't one already - we definitely
* want all these updates in a single transaction so the mboxlist is
* always consistent */
Expand All @@ -1183,7 +1188,7 @@ static int mboxlist_update_entry(const char *name,

// if we have RACLs, let's update them first
if (have_racl) {
r = mboxlist_update_racl(dbname, old, mbentry, txn);
r = mboxlist_update_racl(dbname, old, mbentry, txn, silent);
if (r) goto done;
}

Expand Down Expand Up @@ -1305,7 +1310,7 @@ static int mboxlist_update_entry(const char *name,
mboxlist_entry_free(&old);
mboxlist_entry_free(&oldi);
buf_free(&key);
free(dbname);
mbname_free(&mbname);
return r;
}

Expand All @@ -1322,14 +1327,14 @@ EXPORTED int mboxlist_deletelock(const mbentry_t *mbentry)
return r;
}

EXPORTED int mboxlist_update(const mbentry_t *mbentry, int localonly)
EXPORTED int mboxlist_update_full(const mbentry_t *mbentry, int localonly, int silent)
{
int r = 0, r2 = 0;
struct txn *tid = NULL;

init_internal();

r = mboxlist_update_entry(mbentry->name, mbentry, &tid);
r = mboxlist_update_entry_full(mbentry->name, mbentry, &tid, silent);

/* commit the change to mupdate */
if (!r && !localonly && config_mupdate_server) {
Expand Down Expand Up @@ -1759,6 +1764,7 @@ EXPORTED int mboxlist_update_intermediaries(const char *frommboxname,
newmbentry.createdmodseq = modseq;
newmbentry.foldermodseq = modseq;
int flags = MBOXLIST_CREATE_KEEP_INTERMEDIARIES; // avoid infinite looping!
flags |= MBOXLIST_CREATE_SYNC; /* for silent */
r = mboxlist_createmailbox(&newmbentry, 0/*options*/, 0/*highestmodseq*/,
1/*isadmin*/, NULL/*userid*/, NULL/*authstate*/,
flags, NULL/*mailboxptr*/);
Expand Down Expand Up @@ -1856,6 +1862,7 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
struct mailbox *newmailbox = NULL;
int isremote = mbtype & MBTYPE_REMOTE;
mbentry_t *usermbentry = NULL, *newmbentry = NULL;
int silent = 0;

init_internal();

Expand All @@ -1865,7 +1872,10 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,

assert_namespacelocked(mboxname);

if (!(flags & MBOXLIST_CREATE_SYNC)) {
if ((flags & MBOXLIST_CREATE_SYNC)) {
silent = 1;
}
else {
options |= config_getint(IMAPOPT_MAILBOX_DEFAULT_OPTIONS)
| OPT_POP3_NEW_UIDL;

Expand Down Expand Up @@ -1928,15 +1938,15 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
the uniqueid in the record is required to open
user metadata files (conversations, counters) */
newmbentry->mbtype |= MBTYPE_INTERMEDIATE;
r = mboxlist_update_entry(mboxname, newmbentry, NULL);
r = mboxlist_update_entry_full(mboxname, newmbentry, NULL, silent);
newmbentry->mbtype &= ~MBTYPE_INTERMEDIATE;
if (r) goto done;
}

/* Filesystem Operations */
r = mailbox_create(mboxname, mbtype, newpartition, acl, newmbentry->uniqueid,
options, uidvalidity, createdmodseq, highestmodseq, &newmailbox);
if (!r) r = mailbox_add_conversations(newmailbox, /*silent*/0);
if (!r) r = mailbox_add_conversations(newmailbox, silent);
if (r) {
/* CREATE failed - remove mbentry */
mboxlist_delete(newmbentry);
Expand All @@ -1950,7 +1960,7 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
newmbentry->createdmodseq = newmailbox->i.createdmodseq;
newmbentry->foldermodseq = foldermodseq ? foldermodseq : newmailbox->i.highestmodseq;
}
r = mboxlist_update_entry(mboxname, newmbentry, NULL);
r = mboxlist_update_entry_full(mboxname, newmbentry, NULL, silent);

if (!r && !(flags & MBOXLIST_CREATE_KEEP_INTERMEDIARIES)) {
/* create any missing intermediaries */
Expand All @@ -1975,7 +1985,7 @@ EXPORTED int mboxlist_createmailbox(const mbentry_t *mbentry,
if (r) {
syslog(LOG_ERR, "MUPDATE: can't commit mailbox entry for '%s'",
mboxname);
mboxlist_update_entry(mboxname, NULL, 0);
mboxlist_update_entry_full(mboxname, NULL, 0, silent);
}
if (mupdate_h) mupdate_disconnect(&mupdate_h);
free(loc);
Expand Down Expand Up @@ -2348,7 +2358,7 @@ EXPORTED int mboxlist_deletemailbox(const char *name, int isadmin,
mboxlist_entry_free(&newmbentry);
}
else {
r = mboxlist_update_entry(name, NULL, 0);
r = mboxlist_update_entry_full(name, NULL, 0, silent);
if (r) {
xsyslog(LOG_ERR, "DBERROR: error deleting",
"mailbox=<%s> error=<%s>",
Expand Down Expand Up @@ -2857,13 +2867,13 @@ EXPORTED int mboxlist_renamemailbox(const mbentry_t *mbentry,
oldmbentry->createdmodseq = mbentry->createdmodseq;
oldmbentry->foldermodseq = newmbentry->foldermodseq;

r = mboxlist_update_entry(oldname, oldmbentry, &tid);
r = mboxlist_update_entry_full(oldname, oldmbentry, &tid, silent);

mboxlist_entry_free(&oldmbentry);

/* create a new entry */
if (!r) {
r = mboxlist_update_entry(newname, newmbentry, &tid);
r = mboxlist_update_entry_full(newname, newmbentry, &tid, silent);
}

switch (r) {
Expand Down Expand Up @@ -3371,7 +3381,7 @@ mboxlist_sync_setacls(const char *name, const char *newacl, modseq_t foldermodse
if (mbentry->foldermodseq < foldermodseq)
mbentry->foldermodseq = foldermodseq;

r = mboxlist_update_entry(name, mbentry, NULL);
r = mboxlist_update_entry_full(name, mbentry, NULL, /*silent*/1);

if (r) {
xsyslog(LOG_ERR, "DBERROR: error updating acl",
Expand Down Expand Up @@ -3750,7 +3760,7 @@ static int racls_add_cb(const mbentry_t *mbentry, void *rock)
struct txn **txn = (struct txn **)rock;
char *dbname = mboxname_to_dbname(mbentry->name);

int r = mboxlist_update_racl(dbname, NULL, mbentry, txn);
int r = mboxlist_update_racl(dbname, NULL, mbentry, txn, /*silent*/1);

free(dbname);
return r;
Expand Down
4 changes: 3 additions & 1 deletion imap/mboxlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ int mboxlist_insertremote(mbentry_t *mbentry, struct txn **rettid);
int mboxlist_deleteremote(const char *name, struct txn **in_tid);

/* Update a mailbox's entry */
int mboxlist_update(const mbentry_t *mbentry, int localonly);
#define mboxlist_update(m, l) mboxlist_update_full(m, l, 0)
int mboxlist_update_full(const mbentry_t *mbentry, int localonly,
int silent);
/* Update but take the usernamespace lock first */
int mboxlist_updatelock(const mbentry_t *mbentry, int localonly);

Expand Down
2 changes: 1 addition & 1 deletion imap/mboxname.c
Original file line number Diff line number Diff line change
Expand Up @@ -3154,7 +3154,7 @@ static modseq_t mboxname_domodseq(const char *fname,
return counters.highestmodseq;
}

static void mboxname_assert_canadd(mbname_t *mbname)
EXPORTED void mboxname_assert_canadd(const mbname_t *mbname)
{
assert(!config_getswitch(IMAPOPT_REPLICAONLY));
// add code for suppressing particular users by filename
Expand Down
1 change: 1 addition & 0 deletions imap/mboxname.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ struct mboxname_counters {
int mboxname_read_counters(const char *mboxname, struct mboxname_counters *vals);
#define MBOXMODSEQ_ISFOLDER (1<<0)
#define MBOXMODSEQ_ISDELETE (1<<1)
void mboxname_assert_canadd(const mbname_t *mbname);
modseq_t mboxname_nextmodseq(const char *mboxname, modseq_t last, int mbtype, int flags);
modseq_t mboxname_setmodseq(const char *mboxname, modseq_t val, int mbtype, int flags);
uint32_t mboxname_readuidvalidity(const char *mboxname);
Expand Down
6 changes: 4 additions & 2 deletions imap/sync_reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,8 +154,10 @@ static int reset_single(const char *userid)

for (i = mblist->count; i; i--) {
const char *name = strarray_nth(mblist, i-1);
r = mboxlist_deletemailbox(name, 1, sync_userid, sync_authstate, NULL,
MBOXLIST_DELETE_LOCALONLY|MBOXLIST_DELETE_FORCE);
int delflags = MBOXLIST_DELETE_FORCE | MBOXLIST_DELETE_SILENT |
MBOXLIST_DELETE_LOCALONLY;
r = mboxlist_deletemailbox(name, 1, sync_userid, sync_authstate,
NULL, delflags);
if (r == IMAP_MAILBOX_NONEXISTENT) {
printf("skipping already removed mailbox %s\n", name);
}
Expand Down
5 changes: 4 additions & 1 deletion imap/sync_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -2706,7 +2706,10 @@ int sync_apply_mailbox(struct dlist *kin,
newmbentry->foldermodseq = highestmodseq;
newmbentry->createdmodseq = createdmodseq;

r = mboxlist_updatelock(newmbentry, /*localonly*/1);
struct mboxlock *namespacelock = mboxname_usernamespacelock(mboxname);
r = mboxlist_update_full(newmbentry, /*localonly*/1, /*silent*/1);
mboxname_release(&namespacelock);

mboxlist_entry_free(&newmbentry);

return r;
Expand Down

0 comments on commit 80606b3

Please sign in to comment.