165 lines
4.0 KiB
C
165 lines
4.0 KiB
C
#include "std.h"
|
|
#include "dumpstat.h"
|
|
#include "comm.h"
|
|
#include "file.h"
|
|
|
|
/*
|
|
* Write statistics about objects on file.
|
|
*/
|
|
|
|
static int sumSizes (mapping_t *, mapping_node_t *, void *);
|
|
static int svalue_size (svalue_t *);
|
|
|
|
static int sumSizes (mapping_t * m, mapping_node_t * elt, void * tp)
|
|
{
|
|
int *t = (int *)tp;
|
|
|
|
*t += (svalue_size(&elt->values[0]) + svalue_size(&elt->values[1]));
|
|
*t += sizeof(mapping_node_t);
|
|
return 0;
|
|
}
|
|
|
|
int depth = 0;
|
|
|
|
static int svalue_size (svalue_t * v)
|
|
{
|
|
int i, total;
|
|
|
|
switch (v->type) {
|
|
case T_OBJECT:
|
|
case T_REAL:
|
|
case T_NUMBER:
|
|
return 0;
|
|
case T_STRING:
|
|
return (strlen(v->u.string) + 1);
|
|
case T_ARRAY:
|
|
case T_CLASS:
|
|
if (++depth > 100)
|
|
return 0;
|
|
|
|
/* first svalue is stored inside the array struct */
|
|
total = sizeof(array_t) - sizeof(svalue_t);
|
|
for (i = 0; i < v->u.arr->size; i++) {
|
|
total += svalue_size(&v->u.arr->item[i]) + sizeof(svalue_t);
|
|
}
|
|
depth--;
|
|
return total;
|
|
case T_MAPPING:
|
|
if (++depth > 100)
|
|
return 0;
|
|
total = sizeof(mapping_t);
|
|
mapTraverse(v->u.map, sumSizes, &total);
|
|
depth--;
|
|
return total;
|
|
case T_FUNCTION:
|
|
{
|
|
svalue_t tmp;
|
|
tmp.type = T_ARRAY;
|
|
tmp.u.arr = v->u.fp->hdr.args;
|
|
|
|
if (++depth > 100)
|
|
return 0;
|
|
|
|
if (tmp.u.arr)
|
|
total = sizeof(funptr_hdr_t) + svalue_size(&tmp);
|
|
else
|
|
total = sizeof(funptr_hdr_t);
|
|
switch (v->u.fp->hdr.type) {
|
|
case FP_EFUN:
|
|
total += sizeof(efun_ptr_t);
|
|
break;
|
|
case FP_LOCAL | FP_NOT_BINDABLE:
|
|
total += sizeof(local_ptr_t);
|
|
break;
|
|
case FP_SIMUL:
|
|
total += sizeof(simul_ptr_t);
|
|
break;
|
|
case FP_FUNCTIONAL:
|
|
case FP_FUNCTIONAL | FP_NOT_BINDABLE:
|
|
total += sizeof(functional_t);
|
|
break;
|
|
}
|
|
|
|
depth--;
|
|
return total;
|
|
}
|
|
#ifndef NO_BUFFER_TYPE
|
|
case T_BUFFER:
|
|
/* first byte is stored inside the buffer struct */
|
|
return sizeof(buffer_t) + v->u.buf->size - 1;
|
|
#endif
|
|
default:
|
|
//some freed value or a reference (!) to one (in all my test cases
|
|
//anyway), it will be removed by reclaim_objects later, Wodan
|
|
//fatal("Illegal type: %d\n", v->type);
|
|
;
|
|
}
|
|
/* NOTREACHED */
|
|
return 0;
|
|
}
|
|
|
|
int data_size (object_t * ob)
|
|
{
|
|
int total = 0, i;
|
|
|
|
if (ob->prog) {
|
|
for (i = 0; i < ob->prog->num_variables_total; i++) {
|
|
depth = 0;
|
|
total += svalue_size(&ob->variables[i]) + sizeof(svalue_t);
|
|
}
|
|
}
|
|
return total;
|
|
}
|
|
|
|
void dumpstat (const char * tfn)
|
|
{
|
|
FILE *f;
|
|
object_t *ob;
|
|
const char *fn;
|
|
#ifdef F_SET_HIDE
|
|
int display_hidden;
|
|
#endif
|
|
|
|
fn = check_valid_path(tfn, current_object, "dumpallobj", 1);
|
|
if (!fn) {
|
|
error("Invalid path '/%s' for writing.\n", tfn);
|
|
return;
|
|
}
|
|
f = fopen(fn, "w");
|
|
if (!f) {
|
|
error("Unable to open '/%s' for writing.\n", fn);
|
|
return;
|
|
}
|
|
|
|
#ifdef F_SET_HIDE
|
|
display_hidden = -1;
|
|
#endif
|
|
for (ob = obj_list; ob; ob = ob->next_all) {
|
|
int tmp;
|
|
|
|
#ifdef F_SET_HIDE
|
|
if (ob->flags & O_HIDDEN) {
|
|
if (display_hidden == -1)
|
|
display_hidden = valid_hide(current_object);
|
|
if (!display_hidden)
|
|
continue;
|
|
}
|
|
#endif
|
|
/* FIXME */
|
|
if (ob->prog && (ob->prog->ref == 1 || !(ob->flags & O_CLONE)))
|
|
tmp = ob->prog->total_size;
|
|
else
|
|
tmp = 0;
|
|
fprintf(f, "%-20s %ld ref %2d %s %s (%d)\n", ob->obname,
|
|
tmp + data_size(ob) + sizeof(object_t), ob->ref,
|
|
ob->flags & O_HEART_BEAT ? "HB" : " ",
|
|
#ifndef NO_ENVIRONMENT
|
|
ob->super ? ob->super->obname : "--",
|
|
#else
|
|
"--",
|
|
#endif
|
|
/* ob->cpu */ 0);
|
|
}
|
|
fclose(f);
|
|
}
|