datastore: Add datastoreusage command

datastoreusage returns the total_bytes that are stored under a given
{Key} or from root. {Key} is the entry point from which we begin to
traverse the datastore.

Changelog-Added: JSON-RPC: `datastoreusage`: returns the total bytes that are stored under a given key.

Signed-off-by: Peter Neuroth <pet.v.ne@gmail.com>
This commit is contained in:
Peter Neuroth
2023-07-24 20:47:46 +02:00
committed by Rusty Russell
parent 5aea5fff2f
commit aab948e538
9 changed files with 155 additions and 3 deletions

View File

@@ -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 \

View File

@@ -38,6 +38,7 @@ Core Lightning Documentation
lightning-createonion <lightning-createonion.7.md>
lightning-createrune <lightning-createrune.7.md>
lightning-datastore <lightning-datastore.7.md>
lightning-datastoreusage <lightning-datastoreusage.7.md>
lightning-decode <lightning-decode.7.md>
lightning-decodepay <lightning-decodepay.7.md>
lightning-deldatastore <lightning-deldatastore.7.md>

View File

@@ -60,7 +60,7 @@ Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible.
SEE ALSO
--------
lightning-listdatastore(7), lightning-deldatastore(7)
lightning-listdatastore(7), lightning-deldatastore(7), lightning-datastoreusage(7)
RESOURCES
---------

View File

@@ -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 <<pet.v.ne@gmail.com>> is mainly responsible.
SEE ALSO
--------
lightning-datastore(7), lightning-deldatastore(7), lightning-listdatastore(7)
RESOURCES
---------
Main web site: <https://github.com/ElementsProject/lightning>
[comment]: # ( SHA256STAMP:743b3308974872f191362fcd0b1af647ea1efd28ae30ea04f6deb22418871a17)

View File

@@ -43,7 +43,7 @@ Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible.
SEE ALSO
--------
lightning-listdatastore(7), lightning-datastore(7)
lightning-listdatastore(7), lightning-datastore(7), lightning-datastoreusage(7)
RESOURCES
---------

View File

@@ -41,7 +41,7 @@ Rusty Russell <<rusty@rustcorp.com.au>> is mainly responsible.
SEE ALSO
--------
lightning-datastore(7), lightning-deldatastore(7)
lightning-datastore(7), lightning-deldatastore(7), lightning-datastoreusage(7)
RESOURCES
---------

View File

@@ -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"
}
]
}
}
}

View File

@@ -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."
}
}
}
}
}

View File

@@ -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);