Rhizome list cursor 'rowid_since' semantics

Setting 'rowid_since' now causes the cursor to iterate over bundles
in chronological order (oldest first) from that rowid upward.
This commit is contained in:
Andrew Bettison 2013-11-19 15:41:12 +10:30
parent 1acfff6ab5
commit 21b10b2cb7
2 changed files with 40 additions and 9 deletions

View File

@ -631,6 +631,10 @@ struct rhizome_list_cursor {
bool_t is_recipient_set;
sid_t sender;
sid_t recipient;
// If set, then the cursor moves in ascending (chronological) order starting
// from the first bundle with rowid > rowid_since. If zero, then the cursor
// moves in descending (reverse chronological) order starting from the most
// recent bundle.
uint64_t rowid_since;
// Set by calling the next() function.
rhizome_manifest *manifest;

View File

@ -1483,6 +1483,16 @@ rollback:
*/
int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
{
if (config.debug.rhizome)
DEBUGF("c=%p c->service=%s c->name=%s c->sender=%s c->recipient=%s c->rowid_since=%"PRIu64" c->_rowid_last=%"PRIu64,
c,
alloca_str_toprint(c->service),
alloca_str_toprint(c->name),
c->is_sender_set ? alloca_tohex_sid_t(c->sender) : "UNSET",
c->is_recipient_set ? alloca_tohex_sid_t(c->recipient) : "UNSET",
c->rowid_since,
c->_rowid_last
);
IN();
strbuf b = strbuf_alloca(1024);
strbuf_sprintf(b, "SELECT id, manifest, version, inserttime, author, rowid FROM manifests WHERE 1=1");
@ -1494,11 +1504,15 @@ int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
strbuf_puts(b, " AND sender = @sender");
if (c->is_recipient_set)
strbuf_puts(b, " AND recipient = @recipient");
if (c->rowid_since)
strbuf_puts(b, " AND rowid > @since");
if (c->_rowid_last)
strbuf_puts(b, " AND rowid < @last");
strbuf_puts(b, " ORDER BY rowid DESC"); // most recent first
if (c->rowid_since) {
strbuf_puts(b, " AND rowid > @last ORDER BY rowid ASC"); // oldest first
if (c->_rowid_last < c->rowid_since)
c->_rowid_last = c->rowid_since;
} else {
if (c->_rowid_last)
strbuf_puts(b, " AND rowid < @last");
strbuf_puts(b, " ORDER BY rowid DESC"); // most recent first
}
if (strbuf_overrun(b))
RETURN(WHYF("SQL command too long: %s", strbuf_str(b)));
c->_statement = sqlite_prepare(retry, strbuf_str(b));
@ -1512,8 +1526,6 @@ int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
goto failure;
if (c->is_recipient_set && sqlite_bind(retry, c->_statement, NAMED|SID_T, "@recipient", &c->recipient, END) == -1)
goto failure;
if (c->rowid_since && sqlite_bind(retry, c->_statement, NAMED|INT64, "@since", c->rowid_since, END) == -1)
goto failure;
if (c->_rowid_last && sqlite_bind(retry, c->_statement, NAMED|INT64, "@last", c->_rowid_last, END) == -1)
goto failure;
c->manifest = NULL;
@ -1537,6 +1549,16 @@ failure:
*/
int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
{
if (config.debug.rhizome)
DEBUGF("c=%p c->service=%s c->name=%s c->sender=%s c->recipient=%s c->rowid_since=%"PRIu64" c->_rowid_last=%"PRIu64,
c,
alloca_str_toprint(c->service),
alloca_str_toprint(c->name),
c->is_sender_set ? alloca_tohex_sid_t(c->sender) : "UNSET",
c->is_recipient_set ? alloca_tohex_sid_t(c->recipient) : "UNSET",
c->rowid_since,
c->_rowid_last
);
IN();
if (c->_statement == NULL && rhizome_list_open(retry, c) == -1)
RETURN(-1);
@ -1556,7 +1578,7 @@ int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
assert(sqlite3_column_type(c->_statement, 4) == SQLITE_TEXT || sqlite3_column_type(c->_statement, 4) == SQLITE_NULL);
assert(sqlite3_column_type(c->_statement, 5) == SQLITE_INTEGER);
uint64_t q_rowid = sqlite3_column_int64(c->_statement, 5);
if (c->_rowid_current && q_rowid >= c->_rowid_current) {
if (c->_rowid_current && (c->rowid_since ? q_rowid >= c->_rowid_current : q_rowid <= c->_rowid_current)) {
WHYF("Query returned rowid=%"PRIu64" out of order (last was %"PRIu64") -- skipped", q_rowid, c->_rowid_current);
continue;
}
@ -1613,13 +1635,18 @@ int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *c)
void rhizome_list_commit(struct rhizome_list_cursor *c)
{
if (config.debug.rhizome)
DEBUGF("c=%p c->rowid_since=%"PRIu64" c->_rowid_current=%"PRIu64" c->_rowid_last=%"PRIu64,
c, c->rowid_since, c->_rowid_current, c->_rowid_last);
assert(c->_rowid_current != 0);
if (c->_rowid_last == 0 || c->_rowid_current < c->_rowid_last)
if (c->_rowid_last == 0 || (c->rowid_since ? c->_rowid_current > c->_rowid_last : c->_rowid_current < c->_rowid_last))
c->_rowid_last = c->_rowid_current;
}
void rhizome_list_release(struct rhizome_list_cursor *c)
{
if (config.debug.rhizome)
DEBUGF("c=%p", c);
if (c->manifest) {
rhizome_manifest_free(c->manifest);
c->_rowid_current = 0;