mempool statistics support

git-svn: trunk@4344
0.95
Török Edvin 17 years ago
parent 6a21552ef2
commit deb3031222
  1. 7
      ChangeLog
  2. 7
      clamd/server-th.c
  3. 5
      clamd/session.c
  4. 68
      clamd/thrmgr.c
  5. 2
      clamd/thrmgr.h
  6. 25
      contrib/clamdtop/clamdtop.c
  7. 1
      libclamav/libclamav.map
  8. 21
      libclamav/mpool.c
  9. 5
      libclamav/mpool.h

@ -1,3 +1,10 @@
Thu Nov 6 11:37:08 EET 2008 (edwin)
------------------------------------
* clamd/server-th.c, clamd/session.c, clamd/thrmgr.c,
clamd/thrmgr.h, contrib/clamdtop/clamdtop.c,
libclamav/libclamav.map, libclamav/mpool.c, libclamav/mpool.h:
mempool statistics support
Wed Nov 5 21:49:49 EET 2008 (edwin)
------------------------------------
* clamav-milter/clamav-milter.c, configure.in, libclamav/binhex.c,

@ -160,6 +160,7 @@ static void scanner_thread(void *arg)
shutdown(conn->sd, 2);
closesocket(conn->sd);
thrmgr_setactiveengine(NULL);
cl_free(conn->engine);
free(conn);
return;
@ -240,6 +241,7 @@ static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dbopti
if(!(pua_cats = strdup(engine->pua_cats)))
logg("^Can't make a copy of pua_cats\n");
thrmgr_setactiveengine(NULL);
cl_free(engine);
engine = NULL;
}
@ -279,6 +281,7 @@ static struct cl_engine *reload_db(struct cl_engine *engine, unsigned int dbopti
}
logg("Database correctly reloaded (%u signatures)\n", sigs);
thrmgr_setactiveengine(engine);
return engine;
}
@ -712,8 +715,10 @@ int acceptloop_th(int *socketds, int nsockets, struct cl_engine *engine, unsigne
pthread_join(clamuko_pid, NULL);
}
#endif
if(engine)
if(engine) {
thrmgr_setactiveengine(NULL);
cl_free(engine);
}
if(dbstat)
cl_statfree(dbstat);

@ -131,6 +131,7 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
buff[bread] = 0;
cli_chomp(buff);
thrmgr_setactiveengine(engine);
if(!strncmp(buff, CMD1, strlen(CMD1))) { /* SCAN */
thrmgr_setactivetask(NULL, CMD1);
@ -144,6 +145,10 @@ int command(int desc, const struct cl_engine *engine, const struct cl_limits *li
} else if(!strncmp(buff, CMD4, strlen(CMD4))) { /* RELOAD */
thrmgr_setactivetask(NULL, CMD4);
/* we'll reload, hide the engine, if we are the last
* holding a ref to the engine it'll be freed,
* we don't want STATS command to access it */
thrmgr_setactiveengine(NULL);
mdprintf(desc, "RELOADING\n");
return COMMAND_RELOAD;

@ -30,6 +30,7 @@
#include "thrmgr.h"
#include "others.h"
#include "mpool.h"
#if defined(C_LINUX)
#include <malloc.h>
@ -155,10 +156,14 @@ int thrmgr_printstats(int f)
{
struct threadpool_list *l;
size_t cnt;
size_t pool_used = 0, pool_total = 0, pool_cnt = 0, seen_cnt = 0, error_flag = 0;
float mem_heap = 0, mem_mmap = 0, mem_used = 0, mem_free = 0, mem_releasable = 0;
const struct cl_engine **seen = NULL;
pthread_mutex_lock(&pools_lock);
for(cnt=0,l=pools;l;l=l->nxt) cnt++;
mdprintf(f,"POOLS: %u\n\n", cnt);
for(l= pools;l;l = l->nxt) {
for(l= pools;l && !error_flag;l = l->nxt) {
threadpool_t *pool = l->pool;
const char *state;
work_item_t *q;
@ -172,6 +177,9 @@ int thrmgr_printstats(int f)
continue;
}
pthread_mutex_lock(&pool->pool_mutex);
/* now we can access desc->, knowing that they won't get freed
* because the other tasks can't quit while pool_mutex is taken
*/
switch(pool->state) {
case POOL_INVALID:
state = "INVALID";
@ -216,26 +224,66 @@ int thrmgr_printstats(int f)
mdprintf(f, "\n");
for(task = pool->tasks; task; task = task->nxt) {
long delta;
size_t used, total;
delta = tv_now.tv_usec - task->tv.tv_usec;
delta += (tv_now.tv_sec - task->tv.tv_sec)*1000000;
mdprintf(f,"\t%s %f %s\n",
task->command ? task->command : "N/A",
delta/1e6,
task->filename ? task->filename:"");
if (task->engine) {
/* we usually have at most 2 engines so a linear
* search is good enough */
size_t i;
for (i=0;i<seen_cnt;i++) {
if (seen[i] == task->engine)
break;
}
/* we need to count the memusage from the same
* engine only once */
if (i == seen_cnt) {
const struct cl_engine **s;
/* new engine */
++seen_cnt;
s = realloc(seen, seen_cnt * sizeof(*seen));
if (!s) {
error_flag = 1;
break;
}
seen = s;
seen[seen_cnt - 1] = task->engine;
if (mp_getstats(task->engine, &used, &total) != -1) {
pool_used += used;
pool_total += total;
pool_cnt++;
}
}
}
}
mdprintf(f,"\n");
pthread_mutex_unlock(&pool->pool_mutex);
}
free(seen);
#if defined(C_LINUX)
{
struct mallinfo inf = mallinfo();
mdprintf(f,"MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM\n",
inf.arena/(1024*1024.0), inf.hblkhd/(1024*1024.0),
inf.uordblks/(1024*1024.0), inf.fordblks/(1024*1024.0),
inf.keepcost/(1024*1024.0));
mem_heap = inf.arena/(1024*1024.0);
mem_mmap = inf.hblkhd/(1024*1024.0);
mem_used = inf.uordblks/(1024*1024.0);
mem_free = inf.fordblks/(1024*1024.0);
mem_releasable = inf.keepcost/(1024*1024.0);
/* TODO: figure out how to print these statistics on other OSes */
}
/* TODO: figure out how to print these statistics on other OSes */
#endif
if (error_flag) {
mdprintf(f, "ERROR: error encountered while formatting statistics\n");
} else {
mdprintf(f,"MEMSTATS: heap %.3fM mmap %.3fM used %.3fM free %.3fM releasable %.3fM pools %u pools_used %.3fM pools_total %.3fM\n",
mem_heap, mem_mmap, mem_used, mem_free, mem_releasable, pool_cnt,
pool_used/(1024*1024.0), pool_total/(1024*1024.0));
}
mdprintf(f,"END\n");
pthread_mutex_unlock(&pools_lock);
return 0;
@ -393,6 +441,14 @@ void thrmgr_setactivetask(const char *filename, const char* command)
}
}
void thrmgr_setactiveengine(const struct cl_engine *engine)
{
struct task_desc *desc = pthread_getspecific(stats_tls_key);
if(!desc)
return;
desc->engine = engine;
}
/* thread pool mutex must be held on entry */
static void stats_init(threadpool_t *pool)
{

@ -50,6 +50,7 @@ struct task_desc {
struct timeval tv;
struct task_desc *prv;
struct task_desc *nxt;
const struct cl_engine *engine;
};
typedef struct threadpool_tag {
@ -76,5 +77,6 @@ void thrmgr_destroy(threadpool_t *threadpool);
int thrmgr_dispatch(threadpool_t *threadpool, void *user_data);
int thrmgr_printstats(int outfd);
void thrmgr_setactivetask(const char *filename, const char* command);
void thrmgr_setactiveengine(const struct cl_engine *engine);
#endif

@ -142,7 +142,7 @@ static void init_windows(void)
version_window = subwin(stdscr, 1, maxx, 1, 0);
stats_head_window = subwin(stdscr, 5, maxx-48, 3, 0);
stats_window = subwin(stdscr, maxy-9, maxx, 7, 0);
mem_window = subwin(stdscr, 5, 48, 2, maxx-48);
mem_window = subwin(stdscr, 6, 48, 3, maxx-48);
status_bar_window = subwin(stdscr, 1i, maxx, maxy-1, 0);
touchwin(stdscr);
werase(stdscr);
@ -325,33 +325,44 @@ static void output_memstats(const char* line)
{
char buf[128];
int blink = 0;
double heapu, mmapu, totalu, totalf, releasable;
unsigned long lheapu, lmmapu, ltotalu, ltotalf, lreleasable, totalmem;
double heapu, mmapu, totalu, totalf, releasable, pools_used, pools_total;
unsigned pools_cnt;
unsigned long lheapu, lmmapu, ltotalu, ltotalf, lreleasable, totalmem, lpoolu, lpoolt;
if(sscanf(line, " heap %lfM mmap %lfM used %lfM free %lfM releasable %lfM",
&heapu, &mmapu, &totalu, &totalf, &releasable) != 5)
if(sscanf(line, " heap %lfM mmap %lfM used %lfM free %lfM releasable %lfM pools %u pools_used %lfM pools_total %lfM",
&heapu, &mmapu, &totalu, &totalf, &releasable, &pools_cnt, &pools_used, &pools_total) != 8)
return;
lheapu = heapu*1000;
lmmapu = mmapu*1000;
ltotalu = totalu*1000;
ltotalf = totalf*1000;
lreleasable = releasable*1000;
lpoolu = pools_used*1000;
lpoolt = pools_total*1000;
werase(mem_window);
box(mem_window, 0, 0);
snprintf(buf, sizeof(buf),"heap %4luM mmap %4luM releasable %3luM",
lheapu/1024, lmmapu/1024, lreleasable/1024);
mvwprintw(mem_window, 1, 1, "Memory: ");
print_colored(mem_window, buf);
mvwprintw(mem_window, 2, 1, "Malloc: ");
snprintf(buf, sizeof(buf),"used %4luM free %4luM total %4luM",
ltotalu/1024, ltotalf/1024, (ltotalu+ltotalf)/1024);
print_colored(mem_window, buf);
totalmem = lheapu + lmmapu;
mvwprintw(mem_window, 3, 1, "Mempool: ");
snprintf(buf, sizeof(buf), "count %u used %4luM total %4luM",
pools_cnt, lpoolu/1024, lpoolt/1024);
print_colored(mem_window, buf);
totalmem = lheapu + lmmapu + lpoolt;
if(totalmem > biggest_mem) {
biggest_mem = totalmem;
blink = 1;
}
show_bar(mem_window, 3, totalmem, lmmapu + lreleasable,
show_bar(mem_window, 4, totalmem, lmmapu + lreleasable + lpoolt - lpoolu,
biggest_mem, blink);
wrefresh(mem_window);
}

@ -121,6 +121,7 @@ CLAMAV_PRIVATE {
mp_create;
mp_destroy;
mp_free;
mp_getstats;
local:
*;
};

@ -388,7 +388,26 @@ void mp_flush(struct MP *mp) {
}
used += mp->mpm.size;
spam("Map flushed @ %p, in use: %lu\n", mp, used);
return used;
}
int mp_getstats(const struct cl_engine *eng, size_t *used, size_t *total)
{
size_t sum_used = 0, sum_total = 0;
const struct MPMAP *mpm;
const mp_t *mp;
/* checking refcount is not necessary, but safer */
if (!eng || !eng->refcount)
return -1;
mp = eng->mempool;
if (!mp)
return -1;
for(mpm = &mp->mpm; mpm; mpm = mpm->next) {
sum_used += mpm->usize;
sum_total += mpm->size;
}
*used = sum_used;
*total = sum_total;
return 0;
}
void *mp_malloc(struct MP *mp, size_t size) {

@ -22,7 +22,7 @@
#define MPOOL_H
#ifdef USE_MPOOL
#include "cltypes.h"
typedef struct MP mp_t;
mp_t *mp_create(void);
@ -37,8 +37,10 @@ char *cli_mp_strdup(mp_t *mp, const char *s);
char *cli_mp_virname(mp_t *mp, char *virname, unsigned int official);
uint16_t *cli_mp_hex2ui(mp_t *mp, const char *hex);
void mp_flush(mp_t *mp);
int mp_getstats(const struct cl_engine *engine, size_t *used, size_t *total);
#else /* USE_MPOOL */
typedef void mp_t;
#define mp_malloc(a, b) cli_malloc(b)
#define mp_free(a, b) free(b)
#define mp_calloc(a, b, c) cli_calloc(b, c)
@ -49,6 +51,7 @@ void mp_flush(mp_t *mp);
#define cli_mp_virname(mp, a, b) cli_virname(a, b)
#define cli_mp_hex2ui(mp, hex) cli_hex2ui(hex)
#define mp_flush(val)
#define mp_getstats(mp,used,total) -1
#endif /* USE_MPOOL */
#endif

Loading…
Cancel
Save