diff --git a/pool/page_ckp.php b/pool/page_ckp.php
index aa59fb97..dcb54636 100644
--- a/pool/page_ckp.php
+++ b/pool/page_ckp.php
@@ -31,7 +31,7 @@ function dockp($data, $user)
$pg .= '
Name | ';
$pg .= 'Initial | ';
$pg .= 'Allocated | ';
- $pg .= 'Store | ';
+ $pg .= 'In Store | ';
$pg .= 'RAM | ';
$pg .= 'RAM2 | ';
$pg .= 'Cull | ';
@@ -50,7 +50,7 @@ function dockp($data, $user)
$pg .= ''.$ans['name:'.$i].' | ';
$pg .= ''.stnum($ans['initial:'.$i]).' | ';
$pg .= ''.stnum($ans['allocated:'.$i]).' | ';
- $pg .= ''.stnum($ans['store:'.$i]).' | ';
+ $pg .= ''.stnum($ans['instore:'.$i]).' | ';
$pg .= ''.stnum($ans['ram:'.$i]).' | ';
$pg .= ''.stnum($ans['ram2:'.$i]).' | ';
$pg .= ''.stnum($ans['cull:'.$i]).' | ';
diff --git a/src/ckdb.h b/src/ckdb.h
index 077baf00..caee1fe2 100644
--- a/src/ckdb.h
+++ b/src/ckdb.h
@@ -51,7 +51,7 @@
#define DB_VLOCK "1"
#define DB_VERSION "1.0.4"
-#define CKDB_VERSION DB_VERSION"-1.801"
+#define CKDB_VERSION DB_VERSION"-1.900"
#define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__
diff --git a/src/ckdb_cmd.c b/src/ckdb_cmd.c
index 0b75e90d..e6e22796 100644
--- a/src/ckdb_cmd.c
+++ b/src/ckdb_cmd.c
@@ -5631,73 +5631,71 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
__maybe_unused tv_t *notcd, __maybe_unused K_TREE *trf_root)
{
char tmp[1024], *buf;
+ const char *name;
size_t len, off;
uint64_t ram, ram2, tot = 0;
K_LIST *klist;
+ K_LISTS *klists;
int rows = 0;
+ bool istree;
LOGDEBUG("%s(): cmd '%s'", __func__, cmd);
APPEND_REALLOC_INIT(buf, off, len);
APPEND_REALLOC(buf, off, len, "ok.");
-// FYI average transactiontree length of the ~119k I have is ~28k (>3.3GB)
-#define USEINFO(_obj, _stores, _trees) \
- klist = _obj ## _free; \
- ram = sizeof(K_LIST) + _stores * sizeof(K_STORE) + \
- klist->allocate * klist->item_mem_count * klist->siz + \
- sizeof(K_TREE) * (klist->total - klist->count) * _trees; \
- ram2 = klist->ram; \
- snprintf(tmp, sizeof(tmp), \
- "name:%d=" #_obj "%cinitial:%d=%d%callocated:%d=%d%c" \
- "store:%d=%d%ctrees:%d=%d%cram:%d=%"PRIu64"%c" \
- "ram2:%d=%"PRIu64"%ccull:%d=%d%c", \
- rows, FLDSEP, \
- rows, klist->allocate, FLDSEP, \
- rows, klist->total, FLDSEP, \
- rows, klist->total - klist->count, FLDSEP, \
- rows, _trees, FLDSEP, \
- rows, ram, FLDSEP, \
- rows, ram2, FLDSEP, \
- rows, klist->cull_count, FLDSEP); \
- APPEND_REALLOC(buf, off, len, tmp); \
- tot += ram + ram2; \
- rows++;
-
- USEINFO(users, 1, 2);
- USEINFO(useratts, 1, 1);
- USEINFO(workers, 1, 1);
- USEINFO(paymentaddresses, 1, 2);
- USEINFO(payments, 1, 1);
- USEINFO(accountbalance, 1, 1);
- USEINFO(idcontrol, 1, 0);
- USEINFO(optioncontrol, 1, 1);
- USEINFO(workinfo, 1, 1);
- // Trees don't share items so count as 1 tree
- USEINFO(shares, 2, 1);
- // Trees don't share items so count as 1 tree
- USEINFO(shareerrors, 2, 1);
- // _pool doesn't share items so is included
- USEINFO(sharesummary, 1, 2);
- USEINFO(workmarkers, 1, 2);
- // _pool doesn't share items so is included
- USEINFO(markersummary, 1, 2);
- USEINFO(marks, 1, 1);
- USEINFO(blocks, 1, 1);
- USEINFO(miningpayouts, 1, 1);
- USEINFO(payouts, 1, 3);
- USEINFO(auths, 1, 1);
- USEINFO(poolstats, 1, 1);
- USEINFO(userstats, 2, 1);
- USEINFO(workerstatus, 1, 1);
- USEINFO(userinfo, 1, 1);
- USEINFO(msgline, 1, 0);
- USEINFO(workqueue, 3, 0);
- USEINFO(transfer, 0, 0);
- USEINFO(heartbeatqueue, 1, 0);
- USEINFO(logqueue, 1, 0);
- USEINFO(seqset, 1, 0);
- USEINFO(seqtrans, 0, 0);
+ /* All but temporary lists are in klist_all
+ * All trees are there also since all trees have a node klist */
+ ck_wlock(&lock_check_lock);
+ klists = all_klists;
+ while (klists) {
+ klist = klists->klist;
+
+ ram = sizeof(*klist);
+ if (klist->name == tree_node_list_name) {
+ ram += sizeof(K_TREE);
+ istree = true;
+ name = klist->name2;
+ } else {
+ istree = false;
+ name = klist->name;
+ }
+ if (klist->lock)
+ ram += sizeof(*(klist->lock));
+ // List of item lists
+ ram += klist->item_mem_count * sizeof(*(klist->item_memory));
+ // items
+ ram += klist->total * sizeof(K_ITEM);
+ // List of data lists
+ ram += klist->data_mem_count * sizeof(*(klist->data_memory));
+ // data
+ ram += klist->total * klist->siz;
+
+ // stores
+ ram += klist->stores * sizeof(K_STORE);
+
+ ram2 = klist->ram;
+
+ snprintf(tmp, sizeof(tmp),
+ "name:%d=%s%s%s%cinitial:%d=%d%callocated:%d=%d%c"
+ "instore:%d=%d%cram:%d=%"PRIu64"%c"
+ "ram2:%d=%"PRIu64"%ccull:%d=%d%c",
+ rows, name, istree ? " (tree)" : "",
+ klist->is_lock_only ? " (lock)" : "", FLDSEP,
+ rows, klist->allocate, FLDSEP,
+ rows, klist->total, FLDSEP,
+ rows, klist->total - klist->count, FLDSEP,
+ rows, ram, FLDSEP,
+ rows, ram2, FLDSEP,
+ rows, klist->cull_count, FLDSEP);
+ APPEND_REALLOC(buf, off, len, tmp);
+
+ tot += ram + ram2;
+ rows++;
+
+ klists = klists->next;
+ }
+ ck_wunlock(&lock_check_lock);
snprintf(tmp, sizeof(tmp), "totalram=%"PRIu64"%c", tot, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
@@ -5705,7 +5703,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp),
"rows=%d%cflds=%s%c",
rows, FLDSEP,
- "name,initial,allocated,store,trees,ram,cull", FLDSEP);
+ "name,initial,allocated,instore,ram,cull", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Stats", FLDSEP, "");
diff --git a/src/klist.c b/src/klist.c
index 9340dfcd..68da30b7 100644
--- a/src/klist.c
+++ b/src/klist.c
@@ -16,8 +16,6 @@ const char *tree_node_list_name = "TreeNodes";
bool check_locks = true;
const char *thread_noname = "UNSET";
int next_thread_id = 0;
-bool lock_check_init = false;
-cklock_t lock_check_lock;
__thread int my_thread_id = -1;
__thread char *my_thread_name = NULL;
__thread bool my_check_locks = true;
@@ -32,8 +30,11 @@ __thread const char *my_locks_f[MAX_LOCKDEPTH];
__thread int my_locks_l[MAX_LOCKDEPTH];
__thread int my_lock_level = 0;
__thread bool my_check_deadlocks = true;
-K_LISTS *all_klists;
#endif
+// Required for cmd_stats
+bool lock_check_init = false;
+cklock_t lock_check_lock;
+K_LISTS *all_klists;
#define _CHKLIST(_list, _name) do {\
if (!_list) { \
@@ -61,6 +62,7 @@ K_LISTS *all_klists;
static void k_alloc_items(K_LIST *list, KLIST_FFL_ARGS)
{
K_ITEM *item;
+ void *data;
int allocate, i;
CHKLIST(list);
@@ -90,10 +92,6 @@ static void k_alloc_items(K_LIST *list, KLIST_FFL_ARGS)
}
list->item_memory[list->item_mem_count - 1] = (void *)item;
- list->total += allocate;
- list->count = allocate;
- list->count_up = allocate;
-
item[0].name = list->name;
item[0].prev = NULL;
item[0].next = &(item[1]);
@@ -110,21 +108,29 @@ static void k_alloc_items(K_LIST *list, KLIST_FFL_ARGS)
if (list->do_tail)
list->tail = &(item[allocate-1]);
+ list->data_mem_count++;
+ if (!(list->data_memory = realloc(list->data_memory,
+ list->data_mem_count * sizeof(*(list->data_memory))))) {
+ quithere(1, "List %s data_memory failed to realloc count=%d",
+ list->name, list->data_mem_count);
+ }
+ data = calloc(allocate, list->siz);
+ if (!data) {
+ quithere(1, "List %s failed to calloc %d new data - total was %d, limit was %d",
+ list->name, allocate, list->total, list->limit);
+ }
+ list->data_memory[list->data_mem_count - 1] = data;
+
item = list->head;
while (item) {
- list->data_mem_count++;
- if (!(list->data_memory = realloc(list->data_memory,
- list->data_mem_count *
- sizeof(*(list->data_memory))))) {
- quithere(1, "List %s data_memory failed to realloc count=%d",
- list->name, list->data_mem_count);
- }
- item->data = calloc(1, list->siz);
- if (!(item->data))
- quithere(1, "List %s failed to calloc item data", list->name);
- list->data_memory[list->data_mem_count - 1] = (void *)(item->data);
+ item->data = data;
+ data += list->siz;
item = item->next;
}
+
+ list->total += allocate;
+ list->count = allocate;
+ list->count_up = allocate;
}
K_STORE *_k_new_store(K_LIST *list, KLIST_FFL_ARGS)
@@ -142,6 +148,7 @@ K_STORE *_k_new_store(K_LIST *list, KLIST_FFL_ARGS)
store->lock = list->lock;
store->name = list->name;
store->do_tail = list->do_tail;
+ list->stores++;
return store;
}
@@ -187,7 +194,6 @@ K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit,
if (!(list->is_lock_only))
k_alloc_items(list, KLIST_FFL_PASS);
-#if LOCK_CHECK
/* Don't want to keep track of short lived (tree) lists
* since they wont use locking anyway */
if (!list->local_list) {
@@ -210,7 +216,6 @@ K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit,
all_klists = klists;
ck_wunlock(&lock_check_lock);
}
-#endif
return list;
}
@@ -541,7 +546,6 @@ K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS)
free(list->lock);
}
-#if LOCK_CHECK
// local_list lists are not stored in all_klists
if (!list->local_list) {
K_LISTS *klists, *klists_prev = NULL;
@@ -572,7 +576,6 @@ K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS)
}
ck_wunlock(&lock_check_lock);
}
-#endif
free(list);
@@ -588,6 +591,8 @@ K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS)
store->name, __func__, KLIST_FFL_PASS);
}
+ store->master->stores--;
+
free(store);
return NULL;
diff --git a/src/klist.h b/src/klist.h
index ec59cbea..5f4f303e 100644
--- a/src/klist.h
+++ b/src/klist.h
@@ -87,8 +87,6 @@ extern bool check_locks;
#define MAX_THREADS 128
extern const char *thread_noname;
extern int next_thread_id;
-extern bool lock_check_init;
-extern cklock_t lock_check_lock;
extern __thread int my_thread_id;
extern __thread char *my_thread_name;
extern __thread bool my_check_locks;
@@ -152,6 +150,7 @@ typedef struct k_list {
void (*dsp_func)(K_ITEM *, FILE *); // optional data display to a file
int cull_count;
int ram; // ram allocated for data pointers - code must manage it
+ int stores; // how many stores it currently has
#if LOCK_CHECK
// Since each thread has it's own k_lock no locking is required on this
K_LOCK k_lock[MAX_THREADS];
@@ -160,13 +159,14 @@ typedef struct k_list {
#endif
} K_LIST;
-#if LOCK_CHECK
+// Required for cmd_stats
+extern bool lock_check_init;
+extern cklock_t lock_check_lock;
typedef struct k_lists {
K_LIST *klist;
struct k_lists *next;
} K_LISTS;
extern K_LISTS *all_klists;
-#endif
/*
* K_STORE is for a list of items taken from a K_LIST
@@ -526,7 +526,14 @@ static inline K_ITEM *list_rtail(K_LIST *list)
#else
#define LOCK_MAYBE __maybe_unused
#define LOCK_INIT(_name)
-#define FIRST_LOCK_INIT(_name)
+#define FIRST_LOCK_INIT(_ignore) do { \
+ if (lock_check_init) { \
+ quithere(1, "lock_check_lock has already been " \
+ "initialised!"); \
+ } \
+ cklock_init(&lock_check_lock); \
+ lock_check_init = true; \
+ } while (0)
#define CHECK_WLOCK(_list) ck_wlock((_list)->lock)
#define CHECK_WUNLOCK(_list) ck_wunlock((_list)->lock)
#define CHECK_RLOCK(_list) ck_rlock((_list)->lock)