Skip to content

Commit

Permalink
ctl_conversationsdb: buffers
Browse files Browse the repository at this point in the history
  • Loading branch information
brong committed Jan 11, 2025
1 parent bfe3753 commit 94e6d36
Showing 1 changed file with 45 additions and 42 deletions.
87 changes: 45 additions & 42 deletions imap/ctl_conversationsdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,8 @@ struct cursor
{
struct db *db;
struct txn **txnp;
const char *key; size_t keylen;
const char *data; size_t datalen;
struct buf keybuf;
struct buf valbuf;
int err;
};

Expand All @@ -463,24 +463,22 @@ static void cursor_init(struct cursor *c,

static int cursor_next(struct cursor *c)
{
if (!c->err)
if (!c->err) {
const char *key = NULL;
size_t keylen = 0;
const char *val = NULL;
size_t vallen = 0;
c->err = cyrusdb_fetchnext(c->db,
c->key, c->keylen,
&c->key, &c->keylen,
&c->data, &c->datalen,
c->keybuf.s, c->keybuf.len,
&key, &keylen,
&val, &vallen,
c->txnp);
buf_setmap(&c->keybuf, key, keylen);
buf_setmap(&c->valbuf, val, vallen);
}
return c->err;
}

static int blob_compare(const char *a, size_t alen,
const char *b, size_t blen)
{
int d = memcmp(a, b, MIN(alen, blen));
if (!d)
d = alen - blen;
return d;
}

static int next_diffable_record(struct cursor *c)
{
for (;;)
Expand All @@ -490,11 +488,11 @@ static int next_diffable_record(struct cursor *c)

/* skip < records, they won't be in the
* temp database and we don't care so much */
if (c->key[0] == '<')
if (c->keybuf.s[0] == '<')
continue;

/* Subject, not re-calculated */
if (c->key[0] == 'S')
if (c->keybuf.s[0] == 'S')
continue;

return 0;
Expand All @@ -517,13 +515,13 @@ static unsigned int diff_records(struct conversations_state *a,
rb = cursor_next(&cb);

while (!ra || !rb) {
keydelta = blob_compare(ca.key, ca.keylen, cb.key, cb.keylen);
keydelta = buf_cmp(&ca.keybuf, &cb.keybuf);
if (rb || keydelta < 0) {
if (ra) break;
ndiffs++;
if (verbose)
printf("REALONLY: \"%.*s\" data \"%.*s\"\n",
(int)ca.keylen, ca.key, (int)ca.datalen, ca.data);
(int)ca.keybuf.len, ca.keybuf.s, (int)ca.valbuf.len, ca.valbuf.s);
ra = next_diffable_record(&ca);
continue;
}
Expand All @@ -532,26 +530,31 @@ static unsigned int diff_records(struct conversations_state *a,
ndiffs++;
if (verbose)
printf("TEMPONLY: \"%.*s\" data \"%.*s\"\n",
(int)cb.keylen, cb.key, (int)cb.datalen, cb.data);
(int)cb.keybuf.len, cb.keybuf.s, (int)cb.valbuf.len, cb.valbuf.s);
rb = next_diffable_record(&cb);
continue;
}

/* both exist an are the same key */
delta = blob_compare(ca.data, ca.datalen, cb.data, cb.datalen);
delta = buf_cmp(&ca.valbuf, &cb.valbuf);
if (delta) {
ndiffs++;
if (verbose)
printf("REAL: \"%.*s\" data \"%.*s\"\n"
"TEMP: \"%.*s\" data \"%.*s\"\n",
(int)ca.keylen, ca.key, (int)ca.datalen, ca.data,
(int)cb.keylen, cb.key, (int)cb.datalen, cb.data);
(int)ca.keybuf.len, ca.keybuf.s, (int)ca.valbuf.len, ca.valbuf.s,
(int)cb.keybuf.len, cb.keybuf.s, (int)cb.valbuf.len, cb.valbuf.s);
}

ra = next_diffable_record(&ca);
rb = next_diffable_record(&cb);
}

buf_free(&ca.keybuf);
buf_free(&ca.valbuf);
buf_free(&cb.keybuf);
buf_free(&cb.valbuf);

return ndiffs;
}

Expand All @@ -570,20 +573,20 @@ static int fix_modseqs(struct conversations_state *a,
rb = cursor_next(&cb);

while (!ra || !rb) {
keydelta = blob_compare(ca.key, ca.keylen, cb.key, cb.keylen);
keydelta = buf_cmp(&ca.keybuf, &cb.keybuf);
if (rb || keydelta < 0) {
if (ra) break;
if (ca.key[0] == 'F') {
if (ca.keybuf.s[0] == 'F') {
conv_status_t status = CONV_STATUS_INIT;
/* need to add record if it's zero */
r = conversation_parsestatus(ca.data, ca.datalen, &status);
r = conversation_parsestatus(ca.valbuf.s, ca.valbuf.len, &status);
if (r) return r;
if (status.threadexists == 0) {
r = conversation_storestatus(b, ca.key, ca.keylen, &status);
r = conversation_storestatus(b, ca.keybuf.s, ca.keybuf.len, &status);
if (r) {
fprintf(stderr, "Failed to store conversations "
"record \"%.*s\" to %s: %s, giving up\n",
(int)ca.keylen, ca.key,
(int)ca.keybuf.len, ca.keybuf.s,
b->path, error_message(r));
return r;
}
Expand All @@ -600,65 +603,65 @@ static int fix_modseqs(struct conversations_state *a,
}

/* folders? Just modseq check */
if (ca.key[0] == 'F') {
if (ca.keybuf.s[0] == 'F') {
/* check if modseq is higher for real */
conv_status_t statusa = CONV_STATUS_INIT;
conv_status_t statusb = CONV_STATUS_INIT;
/* need to add record if it's zero */
r = conversation_parsestatus(ca.data, ca.datalen, &statusa);
r = conversation_parsestatus(ca.valbuf.s, ca.valbuf.len, &statusa);
if (r) {
fprintf(stderr, "Failed to parse conversations "
"record \"%.*s\" in %s: %s\n",
(int)ca.keylen, ca.key,
(int)ca.keybuf.len, ca.keybuf.s,
a->path, error_message(r));
/* There's no need to report failure to the caller - the
* record diffing passing that occurs after this will
* also pick up the same problem */
goto next;
}
r = conversation_parsestatus(cb.data, cb.datalen, &statusb);
r = conversation_parsestatus(cb.valbuf.s, cb.valbuf.len, &statusb);
if (r) {
fprintf(stderr, "Failed to parse conversations "
"record \"%.*s\" in %s: %s\n",
(int)cb.keylen, cb.key,
(int)cb.keybuf.len, cb.keybuf.s,
b->path, error_message(r));
goto next;
}
if (statusa.threadmodseq > statusb.threadmodseq) {
statusb.threadmodseq = statusa.threadmodseq;
r = conversation_storestatus(b, cb.key, cb.keylen, &statusb);
r = conversation_storestatus(b, cb.keybuf.s, cb.keybuf.len, &statusb);
if (r) {
fprintf(stderr, "Failed to store conversations "
"record \"%.*s\" to %s: %s, giving up\n",
(int)cb.keylen, cb.key,
(int)cb.keybuf.len, cb.keybuf.s,
b->path, error_message(r));
/* If we cannot write to the temp DB, something is
* drastically wrong and we need to report a failure */
return r;
}
}
}
if (ca.key[0] == 'B') {
if (ca.keybuf.s[0] == 'B') {
/* B keys - check all the modseqs, both top level and per folder */
conversation_t conva = CONVERSATION_INIT;
conversation_t convb = CONVERSATION_INIT;
conv_folder_t *foldera;
conv_folder_t *folderb;
conv_sender_t *sendera;

r = conversation_parse(ca.data, ca.datalen, &conva, CONV_WITHALL);
r = conversation_parse(ca.valbuf.s, ca.valbuf.len, &conva, CONV_WITHALL);
if (r) {
fprintf(stderr, "Failed to parse conversations "
"record \"%.*s\" in %s: %s\n",
(int)ca.keylen, ca.key,
(int)ca.keybuf.len, ca.keybuf.s,
a->path, error_message(r));
goto next;
}
r = conversation_parse(cb.data, cb.datalen, &convb, CONV_WITHALL);
r = conversation_parse(cb.valbuf.s, cb.valbuf.len, &convb, CONV_WITHALL);
if (r) {
fprintf(stderr, "Failed to parse conversations "
"record \"%.*s\" in %s: %s\n",
(int)cb.keylen, cb.key,
(int)cb.keybuf.len, cb.keybuf.s,
b->path, error_message(r));
conversation_fini(&conva);
goto next;
Expand Down Expand Up @@ -688,7 +691,7 @@ static int fix_modseqs(struct conversations_state *a,

/* be nice to know if this is needed, but at least twoskip
* will dedup for us */
r = conversation_store(b, cb.key, cb.keylen, &convb);
r = conversation_store(b, cb.keybuf.s, cb.keybuf.len, &convb);

/* free first before checking for errors */
conversation_fini(&conva);
Expand All @@ -697,7 +700,7 @@ static int fix_modseqs(struct conversations_state *a,
if (r) {
fprintf(stderr, "Failed to store conversations "
"record \"%.*s\" to %s: %s, giving up\n",
(int)cb.keylen, cb.key,
(int)cb.keybuf.len, cb.keybuf.s,
b->path, error_message(r));
return r;
}
Expand Down

0 comments on commit 94e6d36

Please sign in to comment.