ssb: Add a has_blob command. #89
All checks were successful
Build Tilde Friends / Build-All (push) Successful in 29m14s

This commit is contained in:
Cory McWilliams 2025-01-06 20:46:16 -05:00
parent 7f87714b58
commit d0bbd7f24f
4 changed files with 66 additions and 6 deletions

View File

@ -146,6 +146,7 @@ static int _tf_command_import(const char* file, int argc, char* argv[]);
static int _tf_command_publish(const char* file, int argc, char* argv[]); static int _tf_command_publish(const char* file, int argc, char* argv[]);
static int _tf_command_run(const char* file, int argc, char* argv[]); static int _tf_command_run(const char* file, int argc, char* argv[]);
static int _tf_command_sandbox(const char* file, int argc, char* argv[]); static int _tf_command_sandbox(const char* file, int argc, char* argv[]);
static int _tf_command_has_blob(const char* file, int argc, char* argv[]);
static int _tf_command_store_blob(const char* file, int argc, char* argv[]); static int _tf_command_store_blob(const char* file, int argc, char* argv[]);
static int _tf_command_get_sequence(const char* file, int argc, char* argv[]); static int _tf_command_get_sequence(const char* file, int argc, char* argv[]);
static int _tf_command_get_identity(const char* file, int argc, char* argv[]); static int _tf_command_get_identity(const char* file, int argc, char* argv[]);
@ -170,6 +171,7 @@ const command_t k_commands[] = {
{ "get_sequence", _tf_command_get_sequence, "Get the last sequence number for a feed." }, { "get_sequence", _tf_command_get_sequence, "Get the last sequence number for a feed." },
{ "get_identity", _tf_command_get_identity, "Get the server account identity." }, { "get_identity", _tf_command_get_identity, "Get the server account identity." },
{ "get_profile", _tf_command_get_profile, "Get profile information for the given identity." }, { "get_profile", _tf_command_get_profile, "Get profile information for the given identity." },
{ "has_blob", _tf_command_has_blob, "Check whether a blob is in the blob store." },
{ "store_blob", _tf_command_store_blob, "Write a file to the blob store." }, { "store_blob", _tf_command_store_blob, "Write a file to the blob store." },
{ "verify", _tf_command_verify, "Verify a feed." }, { "verify", _tf_command_verify, "Verify a feed." },
{ "test", _tf_command_test, "Test SSB." }, { "test", _tf_command_test, "Test SSB." },
@ -599,6 +601,64 @@ static int _tf_command_store_blob(const char* file, int argc, char* argv[])
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int _tf_command_has_blob(const char* file, int argc, char* argv[])
{
const char* default_db_path = _get_db_path();
const char* db_path = default_db_path;
const char* blob_id = NULL;
bool show_usage = false;
while (!show_usage)
{
static const struct option k_options[] = {
{ "db-path", required_argument, NULL, 'd' },
{ "blob_id", required_argument, NULL, 'b' },
{ "help", no_argument, NULL, 'h' },
{ 0 },
};
int c = getopt_long(argc, argv, "d:b:h", k_options, NULL);
if (c == -1)
{
break;
}
switch (c)
{
case '?':
case 'h':
default:
show_usage = true;
break;
case 'd':
db_path = optarg;
break;
case 'b':
blob_id = optarg;
break;
}
}
if (show_usage || !blob_id)
{
tf_printf("\n%s has_blob [options]\n\n", file);
tf_printf("options:\n");
tf_printf(" -d, --db-path db_path SQLite database path (default: %s).\n", default_db_path);
tf_printf(" -b, --blob_id blob_id ID of blob to query.\n");
tf_printf(" -h, --help Show this usage information.\n");
tf_free((void*)default_db_path);
return EXIT_FAILURE;
}
sqlite3* db = NULL;
sqlite3_open_v2(db_path, &db, SQLITE_OPEN_READONLY | SQLITE_OPEN_URI, NULL);
tf_ssb_db_init_reader(db);
bool has = tf_ssb_db_blob_has(db, blob_id);
sqlite3_close(db);
tf_free((void*)default_db_path);
tf_printf("%s\n", has ? "true" : "false");
return has ? EXIT_SUCCESS : EXIT_FAILURE;
}
static int _tf_command_get_sequence(const char* file, int argc, char* argv[]) static int _tf_command_get_sequence(const char* file, int argc, char* argv[])
{ {
const char* default_db_path = _get_db_path(); const char* default_db_path = _get_db_path();

View File

@ -603,11 +603,10 @@ bool tf_ssb_db_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_
return result; return result;
} }
bool tf_ssb_db_blob_has(tf_ssb_t* ssb, const char* id) bool tf_ssb_db_blob_has(sqlite3* db, const char* id)
{ {
bool result = false; bool result = false;
sqlite3_stmt* statement; sqlite3_stmt* statement;
sqlite3* db = tf_ssb_acquire_db_reader(ssb);
const char* query = "SELECT COUNT(*) FROM blobs WHERE id = ?1"; const char* query = "SELECT COUNT(*) FROM blobs WHERE id = ?1";
if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK) if (sqlite3_prepare(db, query, -1, &statement, NULL) == SQLITE_OK)
{ {
@ -617,7 +616,6 @@ bool tf_ssb_db_blob_has(tf_ssb_t* ssb, const char* id)
} }
sqlite3_finalize(statement); sqlite3_finalize(statement);
} }
tf_ssb_release_db_reader(ssb, db);
return result; return result;
} }

View File

@ -39,11 +39,11 @@ bool tf_ssb_db_message_content_get(tf_ssb_t* ssb, const char* id, uint8_t** out_
/** /**
** Determine whether a blob is in the database by ID. ** Determine whether a blob is in the database by ID.
** @param ssb The SSB instasnce. ** @param db The SQLite database instance to use.
** @param id The blob identifier. ** @param id The blob identifier.
** @return true If the blob is in the database. ** @return true If the blob is in the database.
*/ */
bool tf_ssb_db_blob_has(tf_ssb_t* ssb, const char* id); bool tf_ssb_db_blob_has(sqlite3* db, const char* id);
/** /**
** Retrieve a blob from the database. ** Retrieve a blob from the database.

View File

@ -139,7 +139,9 @@ static void _tf_ssb_rpc_blobs_has_work(tf_ssb_connection_t* connection, void* us
{ {
blobs_has_work_t* work = user_data; blobs_has_work_t* work = user_data;
tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection); tf_ssb_t* ssb = tf_ssb_connection_get_ssb(connection);
work->found = tf_ssb_db_blob_has(ssb, work->id); sqlite3* db = tf_ssb_acquire_db_reader(ssb);
work->found = tf_ssb_db_blob_has(db, work->id);
tf_ssb_release_db_reader(ssb, db);
} }
static void _tf_ssb_rpc_blobs_has_after_work(tf_ssb_connection_t* connection, int status, void* user_data) static void _tf_ssb_rpc_blobs_has_after_work(tf_ssb_connection_t* connection, int status, void* user_data)