diff --git a/doc/Makefile b/doc/Makefile index 9b105d89f..8fc3d7db7 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -32,6 +32,7 @@ MANPAGES := doc/lightning-cli.1 \ doc/lightning-createinvoice.7 \ doc/lightning-createrune.7 \ doc/lightning-datastore.7 \ + doc/lightning-datastoreusage.7 \ doc/lightning-decodepay.7 \ doc/lightning-decode.7 \ doc/lightning-deldatastore.7 \ diff --git a/doc/index.rst b/doc/index.rst index 061f56d45..373968528 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -38,6 +38,7 @@ Core Lightning Documentation lightning-createonion lightning-createrune lightning-datastore + lightning-datastoreusage lightning-decode lightning-decodepay lightning-deldatastore diff --git a/doc/lightning-datastore.7.md b/doc/lightning-datastore.7.md index b442ac35b..68168e964 100644 --- a/doc/lightning-datastore.7.md +++ b/doc/lightning-datastore.7.md @@ -60,7 +60,7 @@ Rusty Russell <> is mainly responsible. SEE ALSO -------- -lightning-listdatastore(7), lightning-deldatastore(7) +lightning-listdatastore(7), lightning-deldatastore(7), lightning-datastoreusage(7) RESOURCES --------- diff --git a/doc/lightning-datastoreusage.7.md b/doc/lightning-datastoreusage.7.md new file mode 100644 index 000000000..5ab2ed57d --- /dev/null +++ b/doc/lightning-datastoreusage.7.md @@ -0,0 +1,43 @@ +lightning-datastoreusage -- Command for listing datastore usage info +============================================================ + +SYNOPSIS +-------- + +**datastoreusage** + +DESCRIPTION +----------- + +The **datastoreusage** RPC command allows the caller to fetch the +total bytes that are stored under a certain *key* (or from the root), +including the size of the *key*. + +All descendants of the *key* (or root) are taken into account. +RETURN VALUE +------------ + +[comment]: # (GENERATE-FROM-SCHEMA-START) +On success, an object containing **datastoreusage** is returned. It is an object containing: + +- **key** (string): The key from which the database was traversed. +- **total\_bytes** (u64): The total bytes that are stored under the *key*, including the all descendants data and the size of the keys themselves. + +[comment]: # (GENERATE-FROM-SCHEMA-END) + +AUTHOR +------ + +Peter Neuroth <> is mainly responsible. + +SEE ALSO +-------- + +lightning-datastore(7), lightning-deldatastore(7), lightning-listdatastore(7) + +RESOURCES +--------- + +Main web site: + +[comment]: # ( SHA256STAMP:743b3308974872f191362fcd0b1af647ea1efd28ae30ea04f6deb22418871a17) diff --git a/doc/lightning-deldatastore.7.md b/doc/lightning-deldatastore.7.md index 1bfe45581..b6df33e83 100644 --- a/doc/lightning-deldatastore.7.md +++ b/doc/lightning-deldatastore.7.md @@ -43,7 +43,7 @@ Rusty Russell <> is mainly responsible. SEE ALSO -------- -lightning-listdatastore(7), lightning-datastore(7) +lightning-listdatastore(7), lightning-datastore(7), lightning-datastoreusage(7) RESOURCES --------- diff --git a/doc/lightning-listdatastore.7.md b/doc/lightning-listdatastore.7.md index e92a17d24..22c66d283 100644 --- a/doc/lightning-listdatastore.7.md +++ b/doc/lightning-listdatastore.7.md @@ -41,7 +41,7 @@ Rusty Russell <> is mainly responsible. SEE ALSO -------- -lightning-datastore(7), lightning-deldatastore(7) +lightning-datastore(7), lightning-deldatastore(7), lightning-datastoreusage(7) RESOURCES --------- diff --git a/doc/schemas/datastoreusage.request.json b/doc/schemas/datastoreusage.request.json new file mode 100644 index 000000000..6ff72bcb9 --- /dev/null +++ b/doc/schemas/datastoreusage.request.json @@ -0,0 +1,23 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": false, + "required": [], + "added": "v23.11", + "properties": { + "key": { + "oneOf": [ + { + "type": "array", + "description": "key is an array of values (though a single value is treated as a one-element array). Used as the starting point to traverse the datastore.", + "items": { + "type": "string" + } + }, + { + "type": "string" + } + ] + } + } +} diff --git a/doc/schemas/datastoreusage.schema.json b/doc/schemas/datastoreusage.schema.json new file mode 100644 index 000000000..19bcd3165 --- /dev/null +++ b/doc/schemas/datastoreusage.schema.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "additionalProperties": false, + "required": [ + "datastoreusage" + ], + "properties": { + "datastoreusage": { + "type": "object", + "additionalProperties": false, + "required": [ + "key", + "total_bytes" + ], + "properties": { + "key": { + "type": "string", + "description": "The key from which the database was traversed." + }, + "total_bytes": { + "type": "u64", + "description": "The total bytes that are stored under the *key*, including the all descendants data and the size of the keys themselves." + } + } + } + } +} diff --git a/lightningd/datastore.c b/lightningd/datastore.c index 1e845e741..d26a047e1 100644 --- a/lightningd/datastore.c +++ b/lightningd/datastore.c @@ -289,6 +289,54 @@ static struct command_result *json_deldatastore(struct command *cmd, return command_success(cmd, response); } +static struct command_result *json_datastoreusage(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + struct json_stream *response; + const char **k, **key; + struct db_stmt *stmt; + const u8 *data; + u64 gen, total_bytes = 0; + + if (!param(cmd, buffer, params, + p_opt("key", param_list_or_string, &key), + NULL)) + return command_param_failed(); + + // We ignore an empty key string or key array. + if (key && *key[0] == '\0') + key = NULL; + + response = json_stream_success(cmd); + json_object_start(response, "datastoreusage"); + json_add_string(response, "key", datastore_key_fmt(tmpctx, key)); + + for (stmt = wallet_datastore_first(cmd, cmd->ld->wallet, key, + &k, &data, &gen); + stmt; + stmt = wallet_datastore_next(cmd, key, stmt, + &k, &data, &gen)) { + + u64 self_bytes = tal_bytelen(data); + /* The key is stored as a binary blob where each string is separated by + * a '\0'. Therefore we add an additional `len(k) - 1`. k is the primary + * key of the table and can not be NULL */ + self_bytes += tal_count(k) - 1; + for (size_t i = 0; i < tal_count(k); i++) { + self_bytes += strlen(k[i]); + }; + total_bytes += self_bytes; + }; + tal_free(stmt); + + json_add_u64(response, "total_bytes", total_bytes); + json_object_end(response); + + return command_success(cmd, response); +} + static const struct json_command datastore_command = { "datastore", "utility", @@ -312,3 +360,11 @@ static const struct json_command listdatastore_command = { "List the datastore, optionally only {key}", }; AUTODATA(json_command, &listdatastore_command); + +static const struct json_command datastoreusage_command = { + "datastoreusage", + "utility", + json_datastoreusage, + "List the datastore usage, starting from an optional {key}", +}; +AUTODATA(json_command, &datastoreusage_command);