Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions src/base/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -415,3 +415,23 @@ int hash_update(struct hash_table *t,

return 0;
}

size_t hash_get_size(struct hash_table *t, size_t *meta_size, size_t *data_size)
{
struct hash_node *n;
unsigned i;
size_t meta = sizeof(*t) + sizeof(*(t->slots)) * t->num_slots;
size_t data = 0;

for (i = 0; i < t->num_slots; i++) {
for (n = t->slots[i]; n; n = n->next) {
meta += sizeof(*n) + n->key_len;
data += n->data_len;
}
}
if (meta_size)
*meta_size = meta;
if (data_size)
*data_size = data;
return meta + data;
}
1 change: 1 addition & 0 deletions src/include/base/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void *hash_lookup(struct hash_table *t, const void *key, uint32_t key_len, size_
void hash_remove(struct hash_table *t, const void *key, uint32_t key_len);

unsigned hash_get_num_entries(struct hash_table *t);
size_t hash_get_size(struct hash_table *t, size_t *meta_size, size_t *data_size);
void hash_iter(struct hash_table *t, hash_iterate_fn f);

struct hash_node *hash_get_first(struct hash_table *t);
Expand Down
16 changes: 15 additions & 1 deletion src/include/iface/usid.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ typedef enum
USID_CMD_SCAN = 5,
USID_CMD_VERSION = 6,
USID_CMD_DUMP = 7,
_USID_CMD_END = USID_CMD_DUMP,
USID_CMD_STATS = 8,
_USID_CMD_END = USID_CMD_STATS,
} usid_cmd_t;

static const char *const usid_cmd_names[] = {
Expand All @@ -56,6 +57,7 @@ static const char *const usid_cmd_names[] = {
[USID_CMD_SCAN] = "scan",
[USID_CMD_VERSION] = "version",
[USID_CMD_DUMP] = "dump",
[USID_CMD_STATS] = "stats",
};

bool usid_cmd_root_only[] = {
Expand All @@ -67,6 +69,7 @@ bool usid_cmd_root_only[] = {
[USID_CMD_SCAN] = true,
[USID_CMD_VERSION] = false,
[USID_CMD_DUMP] = false,
[USID_CMD_STATS] = false,
};

#define COMMAND_STATUS_MASK_OVERALL UINT64_C(0x0000000000000001)
Expand Down Expand Up @@ -97,8 +100,19 @@ struct usid_dump_header {
uint32_t data_count; /* the number of data iovs */
} __attribute__((packed));

struct usid_stats {
uint64_t key_size;
uint64_t value_int_size;
uint64_t value_int_data_size;
uint64_t value_ext_size;
uint64_t value_ext_data_size;
uint64_t meta_size;
uint32_t nr_kv_pairs;
} __attribute__((packed));

#define USID_MSG_HEADER_SIZE sizeof(struct usid_msg_header)
#define USID_VERSION_SIZE sizeof(struct usid_version)
#define USID_STATS_SIZE sizeof(struct usid_stats)

typedef int (*usid_req_data_fn_t)(struct buffer *buf, void *data);

Expand Down
7 changes: 7 additions & 0 deletions src/include/resource/kv-store.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,16 @@ void *kv_store_get_value(sid_resource_t *kv_store_res, const char *key, size_t *
*/
int kv_store_unset_value(sid_resource_t *kv_store_res, const char *key, kv_store_update_fn_t kv_unset_fn, void *kv_unset_fn_arg);

size_t kv_store_get_size(sid_resource_t *kv_store_res, size_t *meta_size, size_t *data_size);

typedef struct kv_store_iter kv_store_iter_t;

kv_store_iter_t *kv_store_iter_create(sid_resource_t *kv_store_res);
int kv_store_iter_current_size(kv_store_iter_t *iter,
size_t * int_size,
size_t * int_data_size,
size_t * ext_size,
size_t * ext_data_size);
const char * kv_store_iter_current_key(kv_store_iter_t *iter);
void * kv_store_iter_current(kv_store_iter_t *iter, size_t *size, kv_store_value_flags_t *flags);
void * kv_store_iter_next(kv_store_iter_t *iter, size_t *size, kv_store_value_flags_t *flags);
Expand Down
76 changes: 66 additions & 10 deletions src/resource/kv-store.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ static void _destroy_kv_store_value(struct kv_store_value *value)
}

/*
* INPUT OUTPUT (DB RECORD) NOTES
* INPUT OUTPUT (DB RECORD) NOTES
* | |
* ------------------------- --------------------------
* / | \ / | \
Expand All @@ -135,16 +135,21 @@ static void _destroy_kv_store_value(struct kv_store_value *value)
* ---- | ---------- ----- | --------------------
* / \ | / \ / \ | / \
* # VECTOR REF MERGE VALUE SIZE VECTOR REF ALLOC VALUE SIZE
* ---------------------------------------------------------------------------------------------------------------------------------------------------------------
* ----------------------------------------------------------------------------------------------------------------
* A 0 0 0 value ref value size 0 0 1 value copy ref value size
* B 0 0 1 value ref value size 0 0 1 value copy ref value size merge flag has no
* effect: B == A C 0 1 0 value ref value size 0 1 0 value ref value size D 0 1
* 1 value ref value size 0 1 0 value ref value size merge flag has no effect: D == C E 1
* 0 0 iovec ref iovec size 1 0 1 iovec deep copy ref iovec size allocated both iovec copy and value
* parts F 1 0 1 iovec ref iovec size 0 0 1 value merger ref value size iovec members
* merged into single value G 1 1 0 iovec ref iovec size 1 1 0 iovec ref iovec size
* H 1 1 1 iovec ref iovec size 1 1 1 value merger iovec ref iovec size iovec members merged
* into single value, iovec has refs to merged value parts
* B 0 0 1 value ref value size 0 0 1 value copy ref value size 1
* C 0 1 0 value ref value size 0 1 0 value ref value size
* D 0 1 1 value ref value size 0 1 0 value ref value size 1
* E 1 0 0 iovec ref iovec size 1 0 1 iovec deep copy ref iovec size 2
* F 1 0 1 iovec ref iovec size 0 0 1 value merger ref value size 3
* G 1 1 0 iovec ref iovec size 1 1 0 iovec ref iovec size
* H 1 1 1 iovec ref iovec size 1 1 1 value merger iovec ref iovec size 4
*
* NOTES:
* 1: Merge flag has no effect: B == A and D == C
* 2: allocated both iovec copy and value parts
* 3: iovec members merged into a single value
* 4: iovec members merged into a signle value. iovec has refs to merged value parts
*
*
* The AUTOFREE flag may be used together with REF flag (it has no effect otherwise). Then, if the reference to the
Expand Down Expand Up @@ -472,6 +477,51 @@ void *kv_store_iter_current(kv_store_iter_t *iter, size_t *size, kv_store_value_
return _get_data(value);
}

int kv_store_iter_current_size(kv_store_iter_t *iter,
size_t * int_size,
size_t * int_data_size,
size_t * ext_size,
size_t * ext_data_size)
{
size_t iov_size, data_size;
struct kv_store_value *value;

if (!iter || !int_size || !int_data_size || !ext_size || !ext_data_size)
return -1;

if (!(value = iter->current ? hash_get_data(iter->store->ht, iter->current, NULL) : NULL))
return -1;

if (value->ext_flags & KV_STORE_VALUE_VECTOR) {
int i;
struct iovec *iov;

iov = (value->ext_flags & KV_STORE_VALUE_REF)? _get_ptr(value->data) : (struct iovec *) value->data;

iov_size = value->size * sizeof(struct iovec);
for (i = 0, data_size = 0; i < value->size; i++)
data_size += iov[i].iov_len;
} else {
data_size = value->size;
iov_size = 0;
}

if (value->int_flags & KV_STORE_VALUE_INT_ALLOC) {
*int_size = *int_data_size = data_size;
*ext_size = *ext_data_size = 0;
} else {
*int_size = *int_data_size = 0;
*ext_size = *ext_data_size = data_size;
}
if (value->ext_flags & KV_STORE_VALUE_REF) {
*int_size += sizeof(*value) + sizeof(intptr_t);
*ext_size += iov_size;
} else
*int_size += sizeof(*value) + iov_size;

return 0;
}

const char *kv_store_iter_current_key(kv_store_iter_t *iter)
{
return iter->current ? hash_get_key(iter->store->ht, iter->current, NULL) : NULL;
Expand All @@ -494,6 +544,12 @@ void kv_store_iter_destroy(kv_store_iter_t *iter)
free(iter);
}

size_t kv_store_get_size(sid_resource_t *kv_store_res, size_t *meta_size, size_t *data_size)
{
struct kv_store *kv_store = sid_resource_get_data(kv_store_res);
return hash_get_size(kv_store->ht, meta_size, data_size);
}

static int _init_kv_store(sid_resource_t *kv_store_res, const void *kickstart_data, void **data)
{
const struct sid_kv_store_resource_params *params = kickstart_data;
Expand Down
49 changes: 49 additions & 0 deletions src/resource/ubridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,43 @@ static const char *_get_iov_str(struct buffer *buf, bool unset, struct iovec *io
return NULL;
}

static int _write_kv_store_stats(struct usid_stats *stats, sid_resource_t *kv_store_res)
{
kv_store_iter_t * iter;
const char * key;
size_t size;
kv_store_value_flags_t flags;
void * value;
int r;
size_t hash_size, int_size, int_data_size, ext_size, ext_data_size;

memset(stats, 0, sizeof(*stats));
if (!(iter = kv_store_iter_create(kv_store_res))) {
log_error(ID(kv_store_res), INTERNAL_ERROR "%s: failed to create record iterator", __func__);
return -ENOMEM;
}
while ((value = kv_store_iter_next(iter, &size, &flags))) {
stats->nr_kv_pairs++;
key = kv_store_iter_current_key(iter);
kv_store_iter_current_size(iter, &int_size, &int_data_size, &ext_size, &ext_data_size);
stats->key_size += strlen(key) + 1;
stats->value_int_size += int_size;
stats->value_int_data_size += int_data_size;
stats->value_ext_size += ext_size;
stats->value_ext_data_size += ext_data_size;
}
kv_store_get_size(kv_store_res, &hash_size, &int_size);
if (stats->value_int_size != int_size)
log_error(ID(kv_store_res),
INTERNAL_ERROR "%s: kv-store size mismatch: %" PRIu64 " is not equal to %zu",
__func__,
stats->value_int_size,
int_size);
stats->meta_size = hash_size;
kv_store_iter_destroy(iter);
return 0;
}

static int _write_kv_store_dump(struct buffer *buf, sid_resource_t *kv_store_res)
{
kv_store_iter_t * iter;
Expand Down Expand Up @@ -1677,6 +1714,17 @@ static int _cmd_exec_dump(struct cmd_exec_arg *exec_arg)
return r;
}

static int _cmd_exec_stats(struct cmd_exec_arg *exec_arg)
{
int r;
struct sid_ucmd_ctx * ucmd_ctx = sid_resource_get_data(exec_arg->cmd_res);
static struct usid_stats stats;

if ((r = _write_kv_store_stats(&stats, ucmd_ctx->ucmd_mod_ctx.kv_store_res)) == 0)
buffer_add(ucmd_ctx->res_buf, &stats, sizeof(stats), &r);
return r;
}

static int _get_sysfs_value(struct module *mod, const char *path, char *buf, size_t buf_size)
{
FILE * fp;
Expand Down Expand Up @@ -3136,6 +3184,7 @@ static struct cmd_reg _cmd_regs[] = {
[USID_CMD_UNKNOWN] = {.name = NULL, .flags = 0, .exec = _cmd_exec_unknown},
[USID_CMD_VERSION] = {.name = NULL, .flags = 0, .exec = _cmd_exec_version},
[USID_CMD_DUMP] = {.name = NULL, .flags = 0, .exec = _cmd_exec_dump},
[USID_CMD_STATS] = {.name = NULL, .flags = 0, .exec = _cmd_exec_stats},
};

static int _export_kv_store(sid_resource_t *cmd_res)
Expand Down
57 changes: 48 additions & 9 deletions src/tools/sidctl/sidctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void print_uint_field(char *field_name, uint value, output_format_t format, bool
}
}

void print_int64_field(char *field_name, uint64_t value, output_format_t format, bool trailing_comma, int level)
void print_uint64_field(char *field_name, uint64_t value, output_format_t format, bool trailing_comma, int level)
{
if (format == JSON) {
print_indent(level);
Expand Down Expand Up @@ -298,6 +298,37 @@ static int _usid_cmd_dump(struct args *args, output_format_t format)
return r;
}

static int _usid_cmd_stats(struct args *args, output_format_t format)
{
struct buffer * buf = NULL;
struct usid_msg_header *hdr;
size_t size;
struct usid_stats * stats = NULL;
int r;

if ((r = usid_req(LOG_PREFIX, USID_CMD_STATS, 0, NULL, NULL, &buf)) == 0) {
buffer_get_data(buf, (const void **) &hdr, &size);

if (size >= (USID_MSG_HEADER_SIZE + USID_STATS_SIZE) &&
(hdr->status & COMMAND_STATUS_MASK_OVERALL) == COMMAND_STATUS_SUCCESS) {
stats = (struct usid_stats *) hdr->data;
print_start_document(format, 0);
print_uint64_field("KEYS_SIZE", stats->key_size, format, true, 1);
print_uint64_field("VALUES_INTERNAL_SIZE", stats->value_int_size, format, true, 1);
print_uint64_field("VALUES_INTERNAL_DATA_SIZE", stats->value_int_data_size, format, true, 1);
print_uint64_field("VALUES_EXTERNAL_SIZE", stats->value_ext_size, format, true, 1);
print_uint64_field("VALUES_EXTERNAL_DATA_SIZE", stats->value_ext_data_size, format, true, 1);
print_uint64_field("METADATA_SIZE", stats->meta_size, format, true, 1);
print_uint_field("NR_KEY_VALUE_PAIRS", stats->nr_kv_pairs, format, true, 1);
print_end_document(format, 0);
} else
r = -1;

buffer_destroy(buf);
}
return r;
}

static int _usid_cmd_version(struct args *args, output_format_t format)
{
struct buffer * buf = NULL;
Expand All @@ -309,20 +340,20 @@ static int _usid_cmd_version(struct args *args, output_format_t format)

print_start_document(format, 0);

print_uint_field("KEY_SIDCTL_PROTOCOL", USID_PROTOCOL, format, true, 1);
print_uint_field("KEY_SIDCTL_MAJOR", SID_VERSION_MAJOR, format, true, 1);
print_uint_field("KEY_SIDCTL_MINOR", SID_VERSION_MINOR, format, true, 1);
print_uint_field("KEY_SIDCTL_RELEASE", SID_VERSION_RELEASE, format, r == 0, 1);
print_uint_field(KEY_SIDCTL_PROTOCOL, USID_PROTOCOL, format, true, 1);
print_uint_field(KEY_SIDCTL_MAJOR, SID_VERSION_MAJOR, format, true, 1);
print_uint_field(KEY_SIDCTL_MINOR, SID_VERSION_MINOR, format, true, 1);
print_uint_field(KEY_SIDCTL_RELEASE, SID_VERSION_RELEASE, format, r == 0, 1);

if (r == 0) {
buffer_get_data(buf, (const void **) &hdr, &size);

if (size >= (USID_MSG_HEADER_SIZE + USID_VERSION_SIZE)) {
vsn = (struct usid_version *) hdr->data;
print_uint_field("KEY_SID_PROTOCOL", hdr->prot, format, true, 1);
print_uint_field("KEY_SID_MAJOR", vsn->major, format, true, 1);
print_uint_field("KEY_SID_MINOR", vsn->minor, format, true, 1);
print_uint_field("KEY_SID_RELEASE", vsn->release, format, false, 1);
print_uint_field(KEY_SID_PROTOCOL, hdr->prot, format, true, 1);
print_uint_field(KEY_SID_MAJOR, vsn->major, format, true, 1);
print_uint_field(KEY_SID_MINOR, vsn->minor, format, true, 1);
print_uint_field(KEY_SID_RELEASE, vsn->release, format, false, 1);
}

buffer_destroy(buf);
Expand Down Expand Up @@ -356,6 +387,11 @@ static void _help(FILE *f)
" Dump the SID daemon database.\n"
" Input: None.\n"
" Output: Listing of all database entries.\n"
"\n"
" stats\n"
" Show stats for the SID daemon key value store.\n"
" Input: None.\n"
" Output: Key value store stats.\n"
"\n");
}

Expand Down Expand Up @@ -423,6 +459,9 @@ int main(int argc, char *argv[])
case USID_CMD_DUMP:
r = _usid_cmd_dump(&subcmd_args, format);
break;
case USID_CMD_STATS:
r = _usid_cmd_stats(&subcmd_args, format);
break;
default:
_help(stderr);
}
Expand Down