Browse Source

ckdb - handle culling in the klist code

master
kanoi 8 years ago
parent
commit
ed9a9aae3d
  1. 12
      pool/page_ckp.php
  2. 54
      src/ckdb.c
  3. 16
      src/ckdb.h
  4. 7
      src/ckdb_cmd.c
  5. 7
      src/ckdb_data.c
  6. 109
      src/klist.c
  7. 16
      src/klist.h

12
pool/page_ckp.php

@ -16,7 +16,7 @@ function stnum($num)
# #
function dockp($data, $user) function dockp($data, $user)
{ {
$pg = '<h1>CKPool</h1>'; $pg = '<h1>CKDB</h1>';
$msg = msgEncode('stats', 'stats', array(), $user); $msg = msgEncode('stats', 'stats', array(), $user);
$rep = sendsockreply('stats', $msg); $rep = sendsockreply('stats', $msg);
@ -33,10 +33,11 @@ function dockp($data, $user)
$pg .= "<td class=dl><span class=nb>Name:<$r id=srtname data-sf=s0></span></td>"; $pg .= "<td class=dl><span class=nb>Name:<$r id=srtname data-sf=s0></span></td>";
$pg .= '<td class=dr>Initial</td>'; $pg .= '<td class=dr>Initial</td>';
$pg .= '<td class=dr>Allocated</td>'; $pg .= '<td class=dr>Allocated</td>';
$pg .= "<td class=dr><span class=nb><$r id=srtname data-sf=r3>:In&nbsp;Store</span></td>"; $pg .= "<td class=dr><span class=nb><$r id=srtstore data-sf=r3>:In&nbsp;Store</span></td>";
$pg .= "<td class=dr><span class=nb><$r id=srtname data-sf=r4>:RAM</span></td>"; $pg .= "<td class=dr><span class=nb><$r id=srtram data-sf=r4>:RAM</span></td>";
$pg .= "<td class=dr><span class=nb><$r id=srtname data-sf=r5>:RAM2</span></td>"; $pg .= "<td class=dr><span class=nb><$r id=srtram2 data-sf=r5>:RAM2</span></td>";
$pg .= '<td class=dr>Cull</td>'; $pg .= '<td class=dr>Cull</td>';
$pg .= '<td class=dr>Limit</td>';
$pg .= "</tr></thead>\n"; $pg .= "</tr></thead>\n";
if ($ans['STATUS'] == 'ok') if ($ans['STATUS'] == 'ok')
{ {
@ -57,11 +58,14 @@ function dockp($data, $user)
$pg .= "<td class=dr data-srt='".$ans['ram:'.$i]."'>".stnum($ans['ram:'.$i]).'</td>'; $pg .= "<td class=dr data-srt='".$ans['ram:'.$i]."'>".stnum($ans['ram:'.$i]).'</td>';
$pg .= "<td class=dr data-srt='".$ans['ram2:'.$i]."'>".stnum($ans['ram2:'.$i]).'</td>'; $pg .= "<td class=dr data-srt='".$ans['ram2:'.$i]."'>".stnum($ans['ram2:'.$i]).'</td>';
$pg .= '<td class=dr>'.stnum($ans['cull:'.$i]).'</td>'; $pg .= '<td class=dr>'.stnum($ans['cull:'.$i]).'</td>';
$pg .= '<td class=dr>'.stnum($ans['cull_limit:'.$i]).'</td>';
$pg .= "</tr>\n"; $pg .= "</tr>\n";
} }
$pg .= '</tbody>'; $pg .= '</tbody>';
} }
$pg .= "</table>\n"; $pg .= "</table>\n";
$pg .= "<script type='text/javascript'>\n";
$pg .= "sotc('ckpsrt','srtram');</script>\n";
return $pg; return $pg;
} }

54
src/ckdb.c

@ -1962,8 +1962,9 @@ static void alloc_storage()
ALLOC_LOGQUEUE, LIMIT_LOGQUEUE, true); ALLOC_LOGQUEUE, LIMIT_LOGQUEUE, true);
logqueue_store = k_new_store(logqueue_free); logqueue_store = k_new_store(logqueue_free);
breakqueue_free = k_new_list("BreakQueue", sizeof(BREAKQUEUE), breakqueue_free = k_new_list_cull("BreakQueue", sizeof(BREAKQUEUE),
ALLOC_BREAKQUEUE, LIMIT_BREAKQUEUE, true); ALLOC_BREAKQUEUE, LIMIT_BREAKQUEUE,
true, CULL_BREAKQUEUE);
reload_breakqueue_store = k_new_store(breakqueue_free); reload_breakqueue_store = k_new_store(breakqueue_free);
reload_done_breakqueue_store = k_new_store(breakqueue_free); reload_done_breakqueue_store = k_new_store(breakqueue_free);
cmd_breakqueue_store = k_new_store(breakqueue_free); cmd_breakqueue_store = k_new_store(breakqueue_free);
@ -2017,16 +2018,19 @@ static void alloc_storage()
} }
} }
seqtrans_free = k_new_list("SeqTrans", sizeof(SEQTRANS), seqtrans_free = k_new_list_cull("SeqTrans", sizeof(SEQTRANS),
ALLOC_SEQTRANS, LIMIT_SEQTRANS, true); ALLOC_SEQTRANS, LIMIT_SEQTRANS, true,
CULL_SEQTRANS);
msgline_free = k_new_list("MsgLine", sizeof(MSGLINE), msgline_free = k_new_list_cull("MsgLine", sizeof(MSGLINE),
ALLOC_MSGLINE, LIMIT_MSGLINE, true); ALLOC_MSGLINE, LIMIT_MSGLINE, true,
CULL_MSGLINE);
msgline_store = k_new_store(msgline_free); msgline_store = k_new_store(msgline_free);
msgline_free->dsp_func = dsp_msgline; msgline_free->dsp_func = dsp_msgline;
workqueue_free = k_new_list("WorkQueue", sizeof(WORKQUEUE), workqueue_free = k_new_list_cull("WorkQueue", sizeof(WORKQUEUE),
ALLOC_WORKQUEUE, LIMIT_WORKQUEUE, true); ALLOC_WORKQUEUE, LIMIT_WORKQUEUE,
true, CULL_WORKQUEUE);
pool0_workqueue_store = k_new_store(workqueue_free); pool0_workqueue_store = k_new_store(workqueue_free);
pool_workqueue_store = k_new_store(workqueue_free); pool_workqueue_store = k_new_store(workqueue_free);
cmd_workqueue_store = k_new_store(workqueue_free); cmd_workqueue_store = k_new_store(workqueue_free);
@ -2045,8 +2049,9 @@ static void alloc_storage()
LIMIT_HEARTBEATQUEUE, true); LIMIT_HEARTBEATQUEUE, true);
heartbeatqueue_store = k_new_store(heartbeatqueue_free); heartbeatqueue_store = k_new_store(heartbeatqueue_free);
transfer_free = k_new_list(Transfer, sizeof(TRANSFER), transfer_free = k_new_list_cull(Transfer, sizeof(TRANSFER),
ALLOC_TRANSFER, LIMIT_TRANSFER, true); ALLOC_TRANSFER, LIMIT_TRANSFER, true,
CULL_TRANSFER);
transfer_free->dsp_func = dsp_transfer; transfer_free->dsp_func = dsp_transfer;
users_free = k_new_list("Users", sizeof(USERS), users_free = k_new_list("Users", sizeof(USERS),
@ -3097,9 +3102,6 @@ static void trans_seq(tv_t *now)
if (store->count) { if (store->count) {
K_WLOCK(seqtrans_free); K_WLOCK(seqtrans_free);
k_list_transfer_to_head(store, seqtrans_free); k_list_transfer_to_head(store, seqtrans_free);
if (seqtrans_free->count == seqtrans_free->total &&
seqtrans_free->total >= ALLOC_SEQTRANS * CULL_SEQTRANS)
k_cull_list(seqtrans_free);
K_WUNLOCK(seqtrans_free); K_WUNLOCK(seqtrans_free);
} }
} }
@ -3878,9 +3880,6 @@ setitemdata:
} }
K_WLOCK(seqtrans_free); K_WLOCK(seqtrans_free);
k_list_transfer_to_head(lost, seqtrans_free); k_list_transfer_to_head(lost, seqtrans_free);
if (seqtrans_free->count == seqtrans_free->total &&
seqtrans_free->total >= ALLOC_SEQTRANS * CULL_SEQTRANS)
k_cull_list(seqtrans_free);
K_WUNLOCK(seqtrans_free); K_WUNLOCK(seqtrans_free);
} }
@ -4772,10 +4771,6 @@ static void *breaker(void *arg)
pthread_cond_signal(&process_socket_waitcond); pthread_cond_signal(&process_socket_waitcond);
mutex_unlock(&process_socket_waitlock); mutex_unlock(&process_socket_waitlock);
} }
if (breakqueue_free->count == breakqueue_free->total &&
breakqueue_free->total >= ALLOC_BREAKQUEUE * CULL_BREAKQUEUE)
k_cull_list(breakqueue_free);
K_WUNLOCK(breakqueue_free); K_WUNLOCK(breakqueue_free);
} }
@ -6083,7 +6078,7 @@ static void process_sockd(PGconn *conn, K_ITEM *wq_item, enum reply_type reply_t
K_WUNLOCK(breakqueue_free); K_WUNLOCK(breakqueue_free);
FREENULL(ans); FREENULL(ans);
free_msgline_data(ml_item, true, true); free_msgline_data(ml_item, true);
K_WLOCK(msgline_free); K_WLOCK(msgline_free);
msgline_free->ram -= msgline->msgsiz; msgline_free->ram -= msgline->msgsiz;
k_add_head(msgline_free, ml_item); k_add_head(msgline_free, ml_item);
@ -6091,9 +6086,6 @@ static void process_sockd(PGconn *conn, K_ITEM *wq_item, enum reply_type reply_t
K_WLOCK(workqueue_free); K_WLOCK(workqueue_free);
k_add_head(workqueue_free, wq_item); k_add_head(workqueue_free, wq_item);
if (workqueue_free->count == workqueue_free->total &&
workqueue_free->total >= ALLOC_WORKQUEUE * CULL_WORKQUEUE)
k_cull_list(workqueue_free);
K_WUNLOCK(workqueue_free); K_WUNLOCK(workqueue_free);
tick(); tick();
@ -6755,7 +6747,7 @@ static void *process_socket(__maybe_unused void *arg)
K_ITEM *ml_item = wq->msgline_item; K_ITEM *ml_item = wq->msgline_item;
MSGLINE *ml; MSGLINE *ml;
DATA_MSGLINE(ml, ml_item); DATA_MSGLINE(ml, ml_item);
free_msgline_data(ml_item, true, false); free_msgline_data(ml_item, true);
K_WLOCK(msgline_free); K_WLOCK(msgline_free);
msgline_free->ram -= ml->msgsiz; msgline_free->ram -= ml->msgsiz;
k_add_head(msgline_free, ml_item); k_add_head(msgline_free, ml_item);
@ -6798,7 +6790,7 @@ skippy:
if (bq->ml_item) { if (bq->ml_item) {
MSGLINE *ml; MSGLINE *ml;
DATA_MSGLINE(ml, bq->ml_item); DATA_MSGLINE(ml, bq->ml_item);
free_msgline_data(bq->ml_item, true, true); free_msgline_data(bq->ml_item, true);
K_WLOCK(msgline_free); K_WLOCK(msgline_free);
msgline_free->ram -= ml->msgsiz; msgline_free->ram -= ml->msgsiz;
k_add_head(msgline_free, bq->ml_item); k_add_head(msgline_free, bq->ml_item);
@ -7158,7 +7150,7 @@ static void process_reload_item(PGconn *conn, K_ITEM *bq_item)
if (bq->ml_item) { if (bq->ml_item) {
DATA_MSGLINE(msgline, bq->ml_item); DATA_MSGLINE(msgline, bq->ml_item);
free_msgline_data(bq->ml_item, true, true); free_msgline_data(bq->ml_item, true);
K_WLOCK(msgline_free); K_WLOCK(msgline_free);
msgline_free->ram -= msgline->msgsiz; msgline_free->ram -= msgline->msgsiz;
k_add_head(msgline_free, bq->ml_item); k_add_head(msgline_free, bq->ml_item);
@ -7797,7 +7789,7 @@ static void process_queued(PGconn *conn, K_ITEM *wq_item)
break; break;
} }
free_msgline_data(ml_item, true, true); free_msgline_data(ml_item, true);
K_WLOCK(msgline_free); K_WLOCK(msgline_free);
msgline_free->ram -= msgline->msgsiz; msgline_free->ram -= msgline->msgsiz;
k_add_head(msgline_free, ml_item); k_add_head(msgline_free, ml_item);
@ -7805,9 +7797,6 @@ static void process_queued(PGconn *conn, K_ITEM *wq_item)
K_WLOCK(workqueue_free); K_WLOCK(workqueue_free);
k_add_head(workqueue_free, wq_item); k_add_head(workqueue_free, wq_item);
if (workqueue_free->count == workqueue_free->total &&
workqueue_free->total >= ALLOC_WORKQUEUE * CULL_WORKQUEUE)
k_cull_list(workqueue_free);
K_WUNLOCK(workqueue_free); K_WUNLOCK(workqueue_free);
} }
@ -7816,9 +7805,6 @@ static void free_lost(SEQDATA *seqdata)
if (seqdata->reload_lost) { if (seqdata->reload_lost) {
K_WLOCK(seqtrans_free); K_WLOCK(seqtrans_free);
k_list_transfer_to_head(seqdata->reload_lost, seqtrans_free); k_list_transfer_to_head(seqdata->reload_lost, seqtrans_free);
if (seqtrans_free->count == seqtrans_free->total &&
seqtrans_free->total >= ALLOC_SEQTRANS * CULL_SEQTRANS)
k_cull_list(seqtrans_free);
K_WUNLOCK(seqtrans_free); K_WUNLOCK(seqtrans_free);
seqdata->reload_lost = NULL; seqdata->reload_lost = NULL;
} }

16
src/ckdb.h

@ -58,7 +58,7 @@
#define DB_VLOCK "1" #define DB_VLOCK "1"
#define DB_VERSION "1.0.7" #define DB_VERSION "1.0.7"
#define CKDB_VERSION DB_VERSION"-2.513" #define CKDB_VERSION DB_VERSION"-2.514"
#define WHERE_FFL " - from %s %s() line %d" #define WHERE_FFL " - from %s %s() line %d"
#define WHERE_FFL_HERE __FILE__, __func__, __LINE__ #define WHERE_FFL_HERE __FILE__, __func__, __LINE__
@ -1370,7 +1370,7 @@ typedef struct msgline {
#define ALLOC_MSGLINE 8192 #define ALLOC_MSGLINE 8192
#define LIMIT_MSGLINE 0 #define LIMIT_MSGLINE 0
#define CULL_MSGLINE 8 #define CULL_MSGLINE (8 * ALLOC_MSGLINE)
#define INIT_MSGLINE(_item) INIT_GENERIC(_item, msgline) #define INIT_MSGLINE(_item) INIT_GENERIC(_item, msgline)
#define DATA_MSGLINE(_var, _item) DATA_GENERIC(_var, _item, msgline, true) #define DATA_MSGLINE(_var, _item) DATA_GENERIC(_var, _item, msgline, true)
#define DATA_MSGLINE_NULL(_var, _item) DATA_GENERIC(_var, _item, msgline, false) #define DATA_MSGLINE_NULL(_var, _item) DATA_GENERIC(_var, _item, msgline, false)
@ -1396,7 +1396,7 @@ typedef struct breakqueue {
#define ALLOC_BREAKQUEUE 16384 #define ALLOC_BREAKQUEUE 16384
#define LIMIT_BREAKQUEUE 0 #define LIMIT_BREAKQUEUE 0
#define CULL_BREAKQUEUE 4 #define CULL_BREAKQUEUE (4 * ALLOC_BREAKQUEUE)
#define INIT_BREAKQUEUE(_item) INIT_GENERIC(_item, breakqueue) #define INIT_BREAKQUEUE(_item) INIT_GENERIC(_item, breakqueue)
#define DATA_BREAKQUEUE(_var, _item) DATA_GENERIC(_var, _item, breakqueue, true) #define DATA_BREAKQUEUE(_var, _item) DATA_GENERIC(_var, _item, breakqueue, true)
@ -1463,7 +1463,7 @@ typedef struct workqueue {
#define ALLOC_WORKQUEUE 1024 #define ALLOC_WORKQUEUE 1024
#define LIMIT_WORKQUEUE 0 #define LIMIT_WORKQUEUE 0
#define CULL_WORKQUEUE 32 #define CULL_WORKQUEUE (32 * ALLOC_WORKQUEUE)
#define INIT_WORKQUEUE(_item) INIT_GENERIC(_item, workqueue) #define INIT_WORKQUEUE(_item) INIT_GENERIC(_item, workqueue)
#define DATA_WORKQUEUE(_var, _item) DATA_GENERIC(_var, _item, workqueue, true) #define DATA_WORKQUEUE(_var, _item) DATA_GENERIC(_var, _item, workqueue, true)
@ -1563,7 +1563,9 @@ typedef struct transfer {
// Suggest malloc use MMAP = largest under 2MB // Suggest malloc use MMAP = largest under 2MB
#define ALLOC_TRANSFER ((int)(2*1024*1024/sizeof(TRANSFER))) #define ALLOC_TRANSFER ((int)(2*1024*1024/sizeof(TRANSFER)))
#define LIMIT_TRANSFER 0 #define LIMIT_TRANSFER 0
#define CULL_TRANSFER 16 /* ALLOC_TRANSFER is ~14k, but it should only ever get this big during a reload
* so set it a bit above that */
#define CULL_TRANSFER 32768
#define INIT_TRANSFER(_item) INIT_GENERIC(_item, transfer) #define INIT_TRANSFER(_item) INIT_GENERIC(_item, transfer)
#define DATA_TRANSFER(_var, _item) DATA_GENERIC(_var, _item, transfer, true) #define DATA_TRANSFER(_var, _item) DATA_GENERIC(_var, _item, transfer, true)
@ -1787,7 +1789,7 @@ extern K_LIST *seqtrans_free;
#define ALLOC_SEQTRANS 1024 #define ALLOC_SEQTRANS 1024
#define LIMIT_SEQTRANS 0 #define LIMIT_SEQTRANS 0
#define CULL_SEQTRANS 64 #define CULL_SEQTRANS (16 * ALLOC_SEQTRANS)
#define INIT_SEQTRANS(_item) INIT_GENERIC(_item, seqtrans) #define INIT_SEQTRANS(_item) INIT_GENERIC(_item, seqtrans)
#define DATA_SEQTRANS(_var, _item) DATA_GENERIC(_var, _item, seqtrans, true) #define DATA_SEQTRANS(_var, _item) DATA_GENERIC(_var, _item, seqtrans, true)
#define DATA_SEQTRANS_NULL(_var, _item) DATA_GENERIC(_var, _item, seqtrans, false) #define DATA_SEQTRANS_NULL(_var, _item) DATA_GENERIC(_var, _item, seqtrans, false)
@ -3227,7 +3229,7 @@ extern void sequence_report(bool lock);
#define FREE_ITEM(item) do { } while(0) #define FREE_ITEM(item) do { } while(0)
// TODO: make a macro for all other to use above macro // TODO: make a macro for all other to use above macro
extern void free_transfer_data(TRANSFER *transfer); extern void free_transfer_data(TRANSFER *transfer);
extern void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull); extern void free_msgline_data(K_ITEM *item, bool t_lock);
extern void free_users_data(K_ITEM *item); extern void free_users_data(K_ITEM *item);
extern void free_workinfo_data(K_ITEM *item); extern void free_workinfo_data(K_ITEM *item);
#define free_sharesummary_data(_i) FREE_ITEM(_i) #define free_sharesummary_data(_i) FREE_ITEM(_i)

7
src/ckdb_cmd.c

@ -6032,7 +6032,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), snprintf(tmp, sizeof(tmp),
"name:%d=%s%s%s%cinitial:%d=%d%callocated:%d=%d%c" "name:%d=%s%s%s%cinitial:%d=%d%callocated:%d=%d%c"
"instore:%d=%d%cram:%d=%"PRIu64"%c" "instore:%d=%d%cram:%d=%"PRIu64"%c"
"ram2:%d=%"PRIu64"%ccull:%d=%d%c", "ram2:%d=%"PRIu64"%ccull:%d=%d%ccull_limit:%d=%d%c",
rows, name, istree ? " (tree)" : "", rows, name, istree ? " (tree)" : "",
klist->is_lock_only ? " (lock)" : "", FLDSEP, klist->is_lock_only ? " (lock)" : "", FLDSEP,
rows, klist->allocate, FLDSEP, rows, klist->allocate, FLDSEP,
@ -6040,7 +6040,8 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
rows, klist->total - klist->count, FLDSEP, rows, klist->total - klist->count, FLDSEP,
rows, ram, FLDSEP, rows, ram, FLDSEP,
rows, ram2, FLDSEP, rows, ram2, FLDSEP,
rows, klist->cull_count, FLDSEP); rows, klist->cull_count, FLDSEP,
rows, klist->cull_limit, FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
tot += ram + ram2; tot += ram + ram2;
@ -6056,7 +6057,7 @@ static char *cmd_stats(__maybe_unused PGconn *conn, char *cmd, char *id,
snprintf(tmp, sizeof(tmp), snprintf(tmp, sizeof(tmp),
"rows=%d%cflds=%s%c", "rows=%d%cflds=%s%c",
rows, FLDSEP, rows, FLDSEP,
"name,initial,allocated,instore,ram,cull", FLDSEP); "name,initial,allocated,instore,ram,cull,cull_limit", FLDSEP);
APPEND_REALLOC(buf, off, len, tmp); APPEND_REALLOC(buf, off, len, tmp);
snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Stats", FLDSEP, ""); snprintf(tmp, sizeof(tmp), "arn=%s%carp=%s", "Stats", FLDSEP, "");

7
src/ckdb_data.c

@ -18,7 +18,7 @@ void free_transfer_data(TRANSFER *transfer)
FREENULL(transfer->mvalue); FREENULL(transfer->mvalue);
} }
void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull) void free_msgline_data(K_ITEM *item, bool t_lock)
{ {
K_ITEM *t_item = NULL; K_ITEM *t_item = NULL;
TRANSFER *transfer; TRANSFER *transfer;
@ -40,11 +40,6 @@ void free_msgline_data(K_ITEM *item, bool t_lock, bool t_cull)
K_WLOCK(transfer_free); K_WLOCK(transfer_free);
transfer_free->ram -= ram2; transfer_free->ram -= ram2;
k_list_transfer_to_head(msgline->trf_store, transfer_free); k_list_transfer_to_head(msgline->trf_store, transfer_free);
if (t_cull) {
if (transfer_free->count == transfer_free->total &&
transfer_free->total >= ALLOC_TRANSFER * CULL_TRANSFER)
k_cull_list(transfer_free);
}
if (t_lock) if (t_lock)
K_WUNLOCK(transfer_free); K_WUNLOCK(transfer_free);
msgline->trf_store = k_free_store(msgline->trf_store); msgline->trf_store = k_free_store(msgline->trf_store);

109
src/klist.c

@ -213,7 +213,8 @@ K_STORE *_k_new_store(K_LIST *list, KLIST_FFL_ARGS)
K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit, K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit,
bool do_tail, bool lock_only, bool without_lock, bool do_tail, bool lock_only, bool without_lock,
bool local_list, const char *name2, KLIST_FFL_ARGS) bool local_list, const char *name2, int cull_limit,
KLIST_FFL_ARGS)
{ {
K_LIST *list; K_LIST *list;
@ -223,6 +224,11 @@ K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit,
if (limit < 0) if (limit < 0)
quithere(1, "Invalid new list %s with limit %d must be >= 0", name, limit); quithere(1, "Invalid new list %s with limit %d must be >= 0", name, limit);
/* after culling, the first block of items are again allocated,
* so there's no point culling a single block of items */
if (cull_limit > 0 && cull_limit <= allocate)
quithere(1, "Invalid new list %s with cull_limit %d must be > allocate (%d)", name, cull_limit, allocate);
list = calloc(1, sizeof(*list)); list = calloc(1, sizeof(*list));
if (!list) if (!list)
quithere(1, "Failed to calloc list %s", name); quithere(1, "Failed to calloc list %s", name);
@ -248,6 +254,7 @@ K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit,
list->allocate = allocate; list->allocate = allocate;
list->limit = limit; list->limit = limit;
list->do_tail = do_tail; list->do_tail = do_tail;
list->cull_limit = cull_limit;
if (!(list->is_lock_only)) if (!(list->is_lock_only))
k_alloc_items(list, KLIST_FFL_PASS); k_alloc_items(list, KLIST_FFL_PASS);
@ -360,6 +367,58 @@ K_ITEM *_k_unlink_tail(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS)
return item; return item;
} }
#define CHKCULL(_list) \
do { \
if (!((_list)->is_store) && !((_list)->is_lock_only) && \
(_list)->cull_limit > 0 && \
(_list)->count == (_list)->total && \
(_list)->total >= (_list)->cull_limit) { \
k_cull_list(_list, file, func, line); \
} \
} while(0);
static void k_cull_list(K_LIST *list, KLIST_FFL_ARGS)
{
int i;
CHKLIST(list);
_LIST_WRITE(list, true, file, func, line);
if (list->is_store) {
quithere(1, "List %s can't %s() a store" KLIST_FFL,
list->name, __func__, KLIST_FFL_PASS);
}
if (list->is_lock_only) {
quithere(1, "List %s can't %s() a lock_only" KLIST_FFL,
list->name, __func__, KLIST_FFL_PASS);
}
if (list->count != list->total) {
quithere(1, "List %s can't %s() a list in use" KLIST_FFL,
list->name, __func__, KLIST_FFL_PASS);
}
for (i = 0; i < list->item_mem_count; i++)
free(list->item_memory[i]);
free(list->item_memory);
list->item_memory = NULL;
list->item_mem_count = 0;
for (i = 0; i < list->data_mem_count; i++)
free(list->data_memory[i]);
free(list->data_memory);
list->data_memory = NULL;
list->data_mem_count = 0;
list->total = list->count = list->count_up = 0;
list->head = list->tail = NULL;
list->cull_count++;
k_alloc_items(list, KLIST_FFL_PASS);
}
void _k_add_head(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS) void _k_add_head(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS)
{ {
CHKLS(list); CHKLS(list);
@ -390,6 +449,8 @@ void _k_add_head(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_
list->count++; list->count++;
list->count_up++; list->count_up++;
CHKCULL(list);
} }
/* slows it down (of course) - only for debugging /* slows it down (of course) - only for debugging
@ -437,6 +498,8 @@ void _k_add_tail(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_
list->count++; list->count++;
list->count_up++; list->count_up++;
CHKCULL(list);
} }
// Insert item into the list next after 'after' // Insert item into the list next after 'after'
@ -475,6 +538,8 @@ void _k_insert_after(K_LIST *list, K_ITEM *item, K_ITEM *after, LOCK_MAYBE bool
list->count++; list->count++;
list->count_up++; list->count_up++;
// no point checking cull since this wouldn't be an _free list
} }
void _k_unlink_item(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS) void _k_unlink_item(K_LIST *list, K_ITEM *item, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS)
@ -541,6 +606,8 @@ void _k_list_transfer_to_head(K_LIST *from, K_LIST *to, LOCK_MAYBE bool chklock,
from->count = 0; from->count = 0;
to->count_up += from->count_up; to->count_up += from->count_up;
from->count_up = 0; from->count_up = 0;
CHKCULL(to);
} }
void _k_list_transfer_to_tail(K_LIST *from, K_LIST *to, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS) void _k_list_transfer_to_tail(K_LIST *from, K_LIST *to, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS)
@ -577,6 +644,8 @@ void _k_list_transfer_to_tail(K_LIST *from, K_LIST *to, LOCK_MAYBE bool chklock,
from->count = 0; from->count = 0;
to->count_up += from->count_up; to->count_up += from->count_up;
from->count_up = 0; from->count_up = 0;
CHKCULL(to);
} }
K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS) K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS)
@ -655,41 +724,3 @@ K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS)
return NULL; return NULL;
} }
// Must be locked and none in use and/or unlinked
void _k_cull_list(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS)
{
int i;
CHKLIST(list);
_LIST_WRITE(list, chklock, file, func, line);
if (list->is_store) {
quithere(1, "List %s can't %s() a store" KLIST_FFL,
list->name, __func__, KLIST_FFL_PASS);
}
if (list->count != list->total) {
quithere(1, "List %s can't %s() a list in use" KLIST_FFL,
list->name, __func__, KLIST_FFL_PASS);
}
for (i = 0; i < list->item_mem_count; i++)
free(list->item_memory[i]);
free(list->item_memory);
list->item_memory = NULL;
list->item_mem_count = 0;
for (i = 0; i < list->data_mem_count; i++)
free(list->data_memory[i]);
free(list->data_memory);
list->data_memory = NULL;
list->data_mem_count = 0;
list->total = list->count = list->count_up = 0;
list->head = list->tail = NULL;
list->cull_count++;
k_alloc_items(list, KLIST_FFL_PASS);
}

16
src/klist.h

@ -151,7 +151,8 @@ typedef struct k_list {
int data_mem_count; // how many item data memory buffers have been allocated int data_mem_count; // how many item data memory buffers have been allocated
void **data_memory; // allocated item data memory buffers void **data_memory; // allocated item data memory buffers
void (*dsp_func)(K_ITEM *, FILE *); // optional data display to a file void (*dsp_func)(K_ITEM *, FILE *); // optional data display to a file
int cull_count; int cull_limit; // <1 means don't cull, otherwise total to cull at
int cull_count; // number of times culled
uint64_t ram; // ram allocated for data pointers - code must manage it uint64_t ram; // ram allocated for data pointers - code must manage it
int stores; // how many stores it currently has int stores; // how many stores it currently has
#if LOCK_CHECK #if LOCK_CHECK
@ -670,13 +671,15 @@ extern K_STORE *_k_new_store(K_LIST *list, KLIST_FFL_ARGS);
extern K_LIST *_k_new_list(const char *name, size_t siz, int allocate, extern K_LIST *_k_new_list(const char *name, size_t siz, int allocate,
int limit, bool do_tail, bool lock_only, int limit, bool do_tail, bool lock_only,
bool without_lock, bool local_list, bool without_lock, bool local_list,
const char *name2, KLIST_FFL_ARGS); const char *name2, int cull_limit, KLIST_FFL_ARGS);
#define k_new_list(_name, _siz, _allocate, _limit, _do_tail) \ #define k_new_list(_name, _siz, _allocate, _limit, _do_tail) \
_k_new_list(_name, _siz, _allocate, _limit, _do_tail, false, false, false, NULL, KLIST_FFL_HERE) _k_new_list(_name, _siz, _allocate, _limit, _do_tail, false, false, false, NULL, 0, KLIST_FFL_HERE)
#define k_lock_only_list(_name) \ #define k_lock_only_list(_name) \
_k_new_list(_name, 1, 1, 1, true, true, false, false, NULL, KLIST_FFL_HERE) _k_new_list(_name, 1, 1, 1, true, true, false, false, NULL, 0, KLIST_FFL_HERE)
#define k_new_tree_list(_name, _siz, _allocate, _limit, _do_tail, _local_tree, _name2) \ #define k_new_tree_list(_name, _siz, _allocate, _limit, _do_tail, _local_tree, _name2) \
_k_new_list(_name, _siz, _allocate, _limit, _do_tail, false, true, _local_tree, _name2, KLIST_FFL_HERE) _k_new_list(_name, _siz, _allocate, _limit, _do_tail, false, true, _local_tree, _name2, 0, KLIST_FFL_HERE)
#define k_new_list_cull(_name, _siz, _allocate, _limit, _do_tail, _cull) \
_k_new_list(_name, _siz, _allocate, _limit, _do_tail, false, false, false, NULL, _cull, KLIST_FFL_HERE)
extern K_ITEM *_k_unlink_head(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS); extern K_ITEM *_k_unlink_head(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS);
#define k_unlink_head(_list) _k_unlink_head(_list, true, KLIST_FFL_HERE) #define k_unlink_head(_list) _k_unlink_head(_list, true, KLIST_FFL_HERE)
#define k_unlink_head_nolock(_list) _k_unlink_head(_list, false, KLIST_FFL_HERE) #define k_unlink_head_nolock(_list) _k_unlink_head(_list, false, KLIST_FFL_HERE)
@ -711,8 +714,5 @@ extern K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS);
#define k_free_list(_list) _k_free_list(_list, KLIST_FFL_HERE) #define k_free_list(_list) _k_free_list(_list, KLIST_FFL_HERE)
extern K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS); extern K_STORE *_k_free_store(K_STORE *store, KLIST_FFL_ARGS);
#define k_free_store(_store) _k_free_store(_store, KLIST_FFL_HERE) #define k_free_store(_store) _k_free_store(_store, KLIST_FFL_HERE)
extern void _k_cull_list(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS);
#define k_cull_list(_list) _k_cull_list(_list, true, KLIST_FFL_HERE)
//#define k_cull_list_nolock(_list) _k_cull_list(_list, false, KLIST_FFL_HERE)
#endif #endif

Loading…
Cancel
Save