Refactor "rhizome list" command

Move output formatting into commandline.c, leave database query in
rhizome_database.c
This commit is contained in:
Andrew Bettison 2013-11-07 10:21:11 +10:30
parent e00c945fd1
commit 9606b4b1b8
3 changed files with 111 additions and 107 deletions

View File

@ -1818,25 +1818,94 @@ int app_rhizome_list(const struct cli_parsed *parsed, struct cli_context *contex
{
if (config.debug.verbose)
DEBUG_cli_parsed(parsed);
const char *service, *name, *sender_sid, *recipient_sid, *offset, *limit;
const char *service = NULL, *name = NULL, *sender_hex = NULL, *recipient_hex = NULL, *offset_ascii = NULL, *limit_ascii = NULL;
cli_arg(parsed, "service", &service, NULL, "");
cli_arg(parsed, "name", &name, NULL, "");
cli_arg(parsed, "sender_sid", &sender_sid, cli_optional_sid, "");
cli_arg(parsed, "recipient_sid", &recipient_sid, cli_optional_sid, "");
cli_arg(parsed, "offset", &offset, cli_uint, "0");
cli_arg(parsed, "limit", &limit, cli_uint, "0");
cli_arg(parsed, "sender_sid", &sender_hex, cli_optional_sid, "");
cli_arg(parsed, "recipient_sid", &recipient_hex, cli_optional_sid, "");
cli_arg(parsed, "offset", &offset_ascii, cli_uint, "0");
cli_arg(parsed, "limit", &limit_ascii, cli_uint, "0");
/* Create the instance directory if it does not yet exist */
if (create_serval_instance_dir() == -1)
return -1;
if (!(keyring = keyring_open_instance_cli(parsed)))
return -1;
int r=-1;
if (rhizome_opendb() != -1){
r=rhizome_list_manifests(context, service, name, sender_sid, recipient_sid, atoi(offset), atoi(limit), 0);
if (rhizome_opendb() == -1) {
keyring_free(keyring);
return -1;
}
size_t rowlimit = atoi(limit_ascii);
size_t rowoffset = atoi(offset_ascii);
struct rhizome_list_cursor cursor;
bzero(&cursor, sizeof cursor);
cursor.service = service && service[0] ? service : NULL;
cursor.name = name && name[0] ? name : NULL;
if (sender_hex && sender_hex[0]) {
if (str_to_sid_t(&cursor.sender, sender_hex) == -1)
return WHYF("Invalid <sender>: %s", sender_hex);
cursor.is_sender_set = 1;
}
if (recipient_hex && recipient_hex[0]) {
if (str_to_sid_t(&cursor.recipient, recipient_hex) == -1)
return WHYF("Invalid <recipient: %s", recipient_hex);
cursor.is_recipient_set = 1;
}
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
if (rhizome_list_open(&retry, &cursor) == -1) {
keyring_free(keyring);
return -1;
}
const char *headers[]={
"_id",
"service",
"id",
"version",
"date",
".inserttime",
".author",
".fromhere",
"filesize",
"filehash",
"sender",
"recipient",
"name"
};
cli_columns(context, NELS(headers), headers);
while (rhizome_list_next(&retry, &cursor) == 1) {
rhizome_manifest *m = cursor.manifest;
assert(m->filesize != RHIZOME_SIZE_UNSET);
if (cursor.rowcount < rowoffset)
continue;
if (rowlimit != 0 && cursor.rowcount > rowlimit)
break;
rhizome_lookup_author(m);
cli_put_long(context, cursor.rowid, ":");
cli_put_string(context, m->service, ":");
cli_put_hexvalue(context, m->cryptoSignPublic.binary, sizeof m->cryptoSignPublic.binary, ":");
cli_put_long(context, m->version, ":");
cli_put_long(context, m->has_date ? m->date : 0, ":");
cli_put_long(context, m->inserttime, ":");
switch (m->authorship) {
case AUTHOR_LOCAL:
case AUTHOR_AUTHENTIC:
cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":");
cli_put_long(context, 1, ":");
break;
default:
cli_put_string(context, NULL, ":");
cli_put_long(context, 0, ":");
break;
}
cli_put_long(context, m->filesize, ":");
cli_put_hexvalue(context, m->filesize ? m->filehash.binary : NULL, sizeof m->filehash.binary, ":");
cli_put_hexvalue(context, m->has_sender ? m->sender.binary : NULL, sizeof m->sender.binary, ":");
cli_put_hexvalue(context, m->has_recipient ? m->recipient.binary : NULL, sizeof m->recipient.binary, ":");
cli_put_string(context, m->name, "\n");
}
rhizome_list_release(&cursor);
cli_row_count(context, cursor.rowcount);
keyring_free(keyring);
return r;
return 0;
}
int app_keyring_create(const struct cli_parsed *parsed, struct cli_context *context)

View File

@ -564,9 +564,6 @@ int64_t rhizome_bar_version(const unsigned char *bar);
uint64_t rhizome_bar_bidprefix_ll(unsigned char *bar);
int rhizome_is_bar_interesting(unsigned char *bar);
int rhizome_is_manifest_interesting(rhizome_manifest *m);
int rhizome_list_manifests(struct cli_context *context, const char *service, const char *name,
const char *sender_sid, const char *recipient_sid,
size_t rowlimit, size_t rowoffset, char count_rows);
int rhizome_retrieve_manifest(const rhizome_bid_t *bid, rhizome_manifest *m);
int rhizome_retrieve_manifest_by_prefix(const unsigned char *prefix, unsigned prefix_len, rhizome_manifest *m);
int rhizome_advertise_manifest(struct subscriber *dest, rhizome_manifest *m);
@ -613,6 +610,29 @@ int rhizome_verify_bundle_privatekey(const unsigned char *sk, const unsigned cha
int rhizome_queue_ignore_manifest(unsigned char *bid_prefix, int prefix_len, int timeout);
int rhizome_ignore_manifest_check(unsigned char *bid_prefix, int prefix_len);
/* Rhizome list cursor for iterating over all or a subset of manifests in the store.
*/
struct rhizome_list_cursor {
// Query parameters that narrow the set of listed bundles.
const char *service;
const char *name;
bool_t is_sender_set;
bool_t is_recipient_set;
sid_t sender;
sid_t recipient;
// Set by calling the next() function.
int64_t rowid;
rhizome_manifest *manifest;
size_t rowcount;
// Private state.
sqlite3_stmt *_statement;
unsigned _offset;
};
int rhizome_list_open(sqlite_retry_state *, struct rhizome_list_cursor *);
int rhizome_list_next(sqlite_retry_state *, struct rhizome_list_cursor *);
void rhizome_list_release(struct rhizome_list_cursor *);
/* one manifest is required per candidate, plus a few spare.
so MAX_RHIZOME_MANIFESTS must be > MAX_CANDIDATES.
*/

View File

@ -1407,27 +1407,12 @@ rollback:
return -1;
}
struct rhizome_list_cursor {
// Query parameters that narrow the set of listed bundles.
const char *service;
const char *name;
sid_t sender;
sid_t recipient;
// Set by calling the next() function.
int64_t rowid;
rhizome_manifest *manifest;
size_t rowcount;
// Private state.
sqlite3_stmt *_statement;
unsigned _offset;
};
/* The cursor struct must be zerofilled and the query parameters optionally filled in prior to
* calling this function.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor)
int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor)
{
IN();
strbuf b = strbuf_alloca(1024);
@ -1436,9 +1421,9 @@ static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_curs
strbuf_puts(b, " AND service = @service");
if (cursor->name)
strbuf_puts(b, " AND name like @name");
if (!is_sid_t_any(cursor->sender))
if (cursor->is_sender_set)
strbuf_puts(b, " AND sender = @sender");
if (!is_sid_t_any(cursor->recipient))
if (cursor->is_recipient_set)
strbuf_puts(b, " AND recipient = @recipient");
strbuf_puts(b, " ORDER BY inserttime DESC LIMIT -1 OFFSET @offset");
if (strbuf_overrun(b))
@ -1452,9 +1437,9 @@ static int rhizome_list_open(sqlite_retry_state *retry, struct rhizome_list_curs
goto failure;
if (cursor->name && sqlite_bind(retry, cursor->_statement, NAMED|STATIC_TEXT, "@name", cursor->name, END) == -1)
goto failure;
if (!is_sid_t_any(cursor->sender) && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@sender", &cursor->sender, END) == -1)
if (cursor->is_sender_set && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@sender", &cursor->sender, END) == -1)
goto failure;
if (!is_sid_t_any(cursor->recipient) && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@recipient", &cursor->recipient, END) == -1)
if (cursor->is_recipient_set && sqlite_bind(retry, cursor->_statement, NAMED|SID_T, "@recipient", &cursor->recipient, END) == -1)
goto failure;
cursor->manifest = NULL;
RETURN(0);
@ -1466,7 +1451,7 @@ failure:
OUT();
}
static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor)
int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_cursor *cursor)
{
IN();
if (cursor->_statement == NULL && rhizome_list_open(retry, cursor) == -1)
@ -1516,9 +1501,9 @@ static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_curs
rhizome_manifest_set_inserttime(m, q_inserttime);
if (cursor->service && !(m->service && strcasecmp(cursor->service, m->service) == 0))
continue;
if (!is_sid_t_any(cursor->sender) && !(m->has_sender && cmp_sid_t(&cursor->sender, &m->sender) == 0))
if (cursor->is_sender_set && !(m->has_sender && cmp_sid_t(&cursor->sender, &m->sender) == 0))
continue;
if (!is_sid_t_any(cursor->recipient) && !(m->has_recipient && cmp_sid_t(&cursor->recipient, &m->recipient) == 0))
if (cursor->is_recipient_set && !(m->has_recipient && cmp_sid_t(&cursor->recipient, &m->recipient) == 0))
continue;
// Don't do rhizome_verify_author(m); too CPU expensive for a listing. Save that for when
// the bundle is extracted or exported.
@ -1529,7 +1514,7 @@ static int rhizome_list_next(sqlite_retry_state *retry, struct rhizome_list_curs
OUT();
}
static void rhizome_list_release(struct rhizome_list_cursor *cursor)
void rhizome_list_release(struct rhizome_list_cursor *cursor)
{
if (cursor->manifest) {
rhizome_manifest_free(cursor->manifest);
@ -1541,76 +1526,6 @@ static void rhizome_list_release(struct rhizome_list_cursor *cursor)
}
}
int rhizome_list_manifests(struct cli_context *context, const char *service, const char *name,
const char *sender_hex, const char *recipient_hex,
size_t rowlimit, size_t rowoffset, char count_rows)
{
IN();
struct rhizome_list_cursor cursor;
bzero(&cursor, sizeof cursor);
cursor.service = service && service[0] ? service : NULL;
cursor.name = name && name[0] ? name : NULL;
if (sender_hex && *sender_hex && str_to_sid_t(&cursor.sender, sender_hex) == -1)
RETURN(WHYF("Invalid sender SID: %s", sender_hex));
if (recipient_hex && *recipient_hex && str_to_sid_t(&cursor.recipient, recipient_hex) == -1)
RETURN(WHYF("Invalid recipient SID: %s", recipient_hex));
sqlite_retry_state retry = SQLITE_RETRY_STATE_DEFAULT;
if (rhizome_list_open(&retry, &cursor) == -1)
RETURN(-1);
const char *names[]={
"_id",
"service",
"id",
"version",
"date",
".inserttime",
".author",
".fromhere",
"filesize",
"filehash",
"sender",
"recipient",
"name"
};
cli_columns(context, NELS(names), names);
while (rhizome_list_next(&retry, &cursor) == 1) {
rhizome_manifest *m = cursor.manifest;
assert(m->filesize != RHIZOME_SIZE_UNSET);
if (cursor.rowcount < rowoffset)
continue;
if (rowlimit == 0 || cursor.rowcount <= rowlimit) {
rhizome_lookup_author(m);
cli_put_long(context, cursor.rowid, ":");
cli_put_string(context, m->service, ":");
cli_put_hexvalue(context, m->cryptoSignPublic.binary, sizeof m->cryptoSignPublic.binary, ":");
cli_put_long(context, m->version, ":");
cli_put_long(context, m->has_date ? m->date : 0, ":");
cli_put_long(context, m->inserttime, ":");
switch (m->authorship) {
case AUTHOR_LOCAL:
case AUTHOR_AUTHENTIC:
cli_put_hexvalue(context, m->author.binary, sizeof m->author.binary, ":");
cli_put_long(context, 1, ":");
break;
default:
cli_put_string(context, NULL, ":");
cli_put_long(context, 0, ":");
break;
}
cli_put_long(context, m->filesize, ":");
cli_put_hexvalue(context, m->filesize ? m->filehash.binary : NULL, sizeof m->filehash.binary, ":");
cli_put_hexvalue(context, m->has_sender ? m->sender.binary : NULL, sizeof m->sender.binary, ":");
cli_put_hexvalue(context, m->has_recipient ? m->recipient.binary : NULL, sizeof m->recipient.binary, ":");
cli_put_string(context, m->name, "\n");
} else if (!count_rows)
break;
}
rhizome_list_release(&cursor);
cli_row_count(context, cursor.rowcount);
RETURN(0);
OUT();
}
void rhizome_bytes_to_hex_upper(unsigned const char *in, char *out, int byteCount)
{
(void) tohex(out, byteCount * 2, in);