#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); }