#include "services/outside_network.h"
#include "services/outbound_list.h"
#include "services/cache/rrset.h"
+#include "services/cache/infra.h"
#include "services/mesh.h"
#include "util/data/msgparse.h"
#include "util/data/msgencode.h"
/** Size of an UDP datagram */
#define NORMAL_UDP_SIZE 512 /* bytes */
+/** Report on memory usage by this thread and global */
+static void
+worker_mem_report(struct worker* worker)
+{
+ size_t total, front, back, mesh, msg, rrset, infra, ac, superac;
+ size_t me;
+ if(verbosity < VERB_ALGO)
+ return;
+ front = listen_get_mem(worker->front);
+ back = outnet_get_mem(worker->back);
+ msg = slabhash_get_mem(worker->env.msg_cache);
+ rrset = slabhash_get_mem(&worker->env.rrset_cache->table);
+ infra = slabhash_get_mem(worker->env.infra_cache->hosts);
+ mesh = mesh_get_mem(worker->env.mesh);
+ ac = alloc_get_mem(&worker->alloc);
+ superac = alloc_get_mem(&worker->daemon->superalloc);
+ me = sizeof(*worker) + sizeof(*worker->base) + sizeof(*worker->comsig)
+ + comm_point_get_mem(worker->cmd_com) +
+ sizeof(worker->rndstate) + region_get_mem(worker->scratchpad);
+ total = front+back+mesh+msg+rrset+infra+ac+superac+me;
+ log_info("Memory conditions: %u front=%u back=%u mesh=%u msg=%u "
+ "rrset=%u infra=%u alloccache=%u globalalloccache=%u me=%u",
+ (unsigned)total, (unsigned)front, (unsigned)back,
+ (unsigned)mesh, (unsigned)msg, (unsigned)rrset,
+ (unsigned)infra, (unsigned)ac, (unsigned)superac,
+ (unsigned)me);
+}
+
void
worker_send_cmd(struct worker* worker, ldns_buffer* buffer,
enum worker_commands cmd)
if(error != 0) {
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
+ worker_mem_report(worker);
return 0;
}
/* sanity check. */
/* error becomes timeout for the module as if this reply
* never arrived. */
mesh_report_reply(worker->env.mesh, &e, 0, reply_info);
+ worker_mem_report(worker);
return 0;
}
mesh_report_reply(worker->env.mesh, &e, 1, reply_info);
+ worker_mem_report(worker);
return 0;
}
verbose(VERB_ALGO, "worker scvd callback for qstate %p", e->qstate);
if(error != 0) {
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
+ worker_mem_report(worker);
return 0;
}
/* sanity check. */
* never arrived. */
verbose(VERB_ALGO, "worker: bad reply handled as timeout");
mesh_report_reply(worker->env.mesh, e, 0, reply_info);
+ worker_mem_report(worker);
return 0;
}
mesh_report_reply(worker->env.mesh, e, 1, reply_info);
+ worker_mem_report(worker);
return 0;
}
/* the max request number has been reached, stop accepting */
listen_pushback(worker->front);
}
+ worker_mem_report(worker);
return 0;
}
worker_delete(worker);
return 0;
}
+ worker_mem_report(worker);
return 1;
}
return;
mesh_stats(worker->env.mesh, "mesh has");
server_stats_log(&worker->stats, worker->thread_num);
+ worker_mem_report(worker);
mesh_delete(worker->env.mesh);
listen_delete(worker->front);
outside_network_delete(worker->back);
- TODO items from forgery-resilience draft.
and on memory handling improvements.
- renamed module_event_timeout to module_event_noreply.
+ - memory reporting code; reports on memory usage after handling
+ a network packet (not on cache replies).
19 July 2007: Wouter
- shuffle NS selection when getting nameserver target addresses.
list = nx;
}
}
+
+size_t listen_get_mem(struct listen_dnsport* listen)
+{
+ size_t s = sizeof(*listen) + sizeof(*listen->base) +
+ sizeof(*listen->udp_buff) +
+ ldns_buffer_capacity(listen->udp_buff);
+ struct listen_list* p;
+ for(p = listen->cps; p; p = p->next) {
+ s += sizeof(*p);
+ s += comm_point_get_mem(p->com);
+ }
+ return s;
+}
/**
* delete the listening structure
+ * @param listen: listening structure.
*/
void listen_delete(struct listen_dnsport* listen);
+/**
+ * get memory size used by the listening structs
+ * @param listen: listening structure.
+ * @return: size in bytes.
+ */
+size_t listen_get_mem(struct listen_dnsport* listen);
+
/**
* Create and bind nonblocking UDP socket
* @param addr: address info ready to make socket.
timehist_log(mesh->histogram);
}
}
+
+size_t
+mesh_get_mem(struct mesh_area* mesh)
+{
+ struct mesh_state* m;
+ size_t s = sizeof(*mesh) + sizeof(struct timehist) +
+ sizeof(struct th_buck)*mesh->histogram->num;
+ RBTREE_FOR(m, struct mesh_state*, &mesh->all) {
+ /* all, including m itself allocated in qstate region */
+ s += region_get_mem(m->s.region);
+ }
+ return s;
+}
*/
void mesh_stats(struct mesh_area* mesh, const char* str);
+/**
+ * Calculate memory size in use by mesh and all queries inside it.
+ * @param mesh: the mesh to examine.
+ * @return size in bytes.
+ */
+size_t mesh_get_mem(struct mesh_area* mesh);
+
#endif /* SERVICES_MESH_H */
serviced_delete(sq);
}
}
+
+/** get memory used by waiting tcp entry (in use or not) */
+static size_t
+waiting_tcp_get_mem(struct waiting_tcp* w)
+{
+ size_t s;
+ if(!w) return 0;
+ s = sizeof(*w) + w->pkt_len;
+ if(w->timer)
+ s += comm_timer_get_mem(w->timer);
+ return s;
+}
+
+size_t outnet_get_mem(struct outside_network* outnet)
+{
+ size_t i;
+ struct waiting_tcp* w;
+ struct serviced_query* sq;
+ struct service_callback* sb;
+ size_t s = sizeof(*outnet) + sizeof(*outnet->base) +
+ sizeof(*outnet->udp_buff) +
+ ldns_buffer_capacity(outnet->udp_buff);
+ /* second buffer is not ours */
+ s += sizeof(struct comm_point*)*outnet->num_udp4;
+ for(i=0; i<outnet->num_udp4; i++)
+ s += comm_point_get_mem(outnet->udp4_ports[i]);
+ s += sizeof(struct comm_point*)*outnet->num_udp6;
+ for(i=0; i<outnet->num_udp6; i++)
+ s += comm_point_get_mem(outnet->udp6_ports[i]);
+ s += sizeof(struct pending_tcp*)*outnet->num_tcp;
+ for(i=0; i<outnet->num_tcp; i++) {
+ s += sizeof(struct pending_tcp);
+ s += comm_point_get_mem(outnet->tcp_conns[i]->c);
+ if(outnet->tcp_conns[i]->query)
+ s += waiting_tcp_get_mem(outnet->tcp_conns[i]->query);
+ }
+ for(w=outnet->tcp_wait_first; w; w = w->next_waiting)
+ s += waiting_tcp_get_mem(w);
+ s += sizeof(*outnet->pending);
+ s += sizeof(struct pending) * outnet->pending->count;
+ s += sizeof(*outnet->serviced);
+ RBTREE_FOR(sq, struct serviced_query*, outnet->serviced) {
+ s += sizeof(*sq) + sq->qbuflen;
+ for(sb = sq->cblist; sb; sb = sb->next)
+ s += sizeof(*sb);
+ }
+ return s;
+}
*/
void outnet_serviced_query_stop(struct serviced_query* sq, void* cb_arg);
+/**
+ * Get memory size in use by outside network.
+ * Counts buffers and outstanding query (serviced queries) malloced data.
+ * @param outnet: outside network structure.
+ * @return size in bytes.
+ */
+size_t outnet_get_mem(struct outside_network* outnet);
+
#endif /* OUTSIDE_NETWORK_H */
free(c);
}
+size_t listen_get_mem(struct listen_dnsport* ATTR_UNUSED(listen))
+{
+ return 0;
+}
+
+size_t outnet_get_mem(struct outside_network* ATTR_UNUSED(outnet))
+{
+ return 0;
+}
+
+size_t comm_point_get_mem(struct comm_point* ATTR_UNUSED(c))
+{
+ return 0;
+}
+
/*********** End of Dummy routines ***********/
log_info("%salloc: %d in cache.", alloc->super?"":"sup",
(int)alloc->num_quar);
}
+
+size_t alloc_get_mem(struct alloc_cache* alloc)
+{
+ size_t s = sizeof(*alloc);
+ if(!alloc->super) {
+ lock_quick_lock(&alloc->lock); /* superalloc needs locking */
+ }
+ s += sizeof(alloc_special_t) * alloc->num_quar;
+ if(!alloc->super) {
+ lock_quick_unlock(&alloc->lock);
+ }
+ return s;
+}
*/
void alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem);
+/**
+ * Get memory size of alloc cache, alloc structure including special types.
+ * @param alloc: on what alloc.
+ * @return size in bytes.
+ */
+size_t alloc_get_mem(struct alloc_cache* alloc);
+
/**
* Print debug information (statistics).
* @param alloc: on what alloc.
}
}
+size_t comm_point_get_mem(struct comm_point* c)
+{
+ size_t s;
+ if(!c)
+ return 0;
+ s = sizeof(*c) + sizeof(*c->ev);
+ if(c->timeout)
+ s += sizeof(*c->timeout);
+ if(c->type == comm_tcp || c->type == comm_local)
+ s += sizeof(*c->buffer) + ldns_buffer_capacity(c->buffer);
+ if(c->type == comm_tcp_accept) {
+ int i;
+ for(i=0; i<c->max_tcp_count; i++)
+ s += comm_point_get_mem(c->tcp_handlers[i]);
+ }
+ return s;
+}
+
struct comm_timer*
comm_timer_create(struct comm_base* base, void (*cb)(void*), void* cb_arg)
{
return (int)timer->ev_timer->enabled;
}
+size_t
+comm_timer_get_mem(struct comm_timer* timer)
+{
+ return sizeof(*timer) + sizeof(struct internal_timer);
+}
+
struct comm_signal*
comm_signal_create(struct comm_base* base,
void (*callback)(int, void*), void* cb_arg)
*/
void comm_point_start_listening(struct comm_point* c, int newfd, int sec);
+/**
+ * Get size of memory used by comm point.
+ * For TCP handlers this includes subhandlers.
+ * For UDP handlers, this does not include the (shared) UDP buffer.
+ * @param c: commpoint.
+ * @return size in bytes.
+ */
+size_t comm_point_get_mem(struct comm_point* c);
+
/**
* create timer. Not active upon creation.
* @param base: event handling base.
*/
int comm_timer_is_set(struct comm_timer* timer);
+/**
+ * Get size of memory used by comm timer.
+ * @param timer: the timer to examine.
+ * @return size in bytes.
+ */
+size_t comm_timer_get_mem(struct comm_timer* timer);
+
/**
* Create a signal handler. Call signal_bind() later to bind to a signal.
* @param base: communication base to use.
}
log_info("memory: %s", buf);
}
+
+size_t
+region_get_mem(region_type* region)
+{
+ size_t s = sizeof(*region);
+ s += region->total_allocated + region->chunk_size - region->allocated;
+ s += region->maximum_cleanup_count * sizeof(cleanup_type);
+ if(region->recycle_bin)
+ s += sizeof(struct recycle_elem*)*region->large_object_size;
+ return s;
+}
/** Debug print REGION statistics to LOG */
void region_log_stats(region_type *region);
+/** get total memory size in use by region */
+size_t region_get_mem(region_type* region);
+
#endif /* _REGION_ALLOCATOR_H_ */
return total;
}
+size_t slabhash_get_mem(struct slabhash* sl)
+{
+ size_t i, total = sizeof(*sl);
+ for(i=0; i<sl->size; i++) {
+ lock_quick_lock(&sl->array[i]->lock);
+ total += sizeof(struct lruhash) + sl->array[i]->space_used +
+ sizeof(struct lruhash_bin)*sl->array[i]->size;
+ lock_quick_unlock(&sl->array[i]->lock);
+ }
+ return total;
+}
+
struct lruhash* slabhash_gettable(struct slabhash* sl, hashvalue_t hash)
{
return sl->array[slab_idx(sl, hash)];
/**
* Retrieve slab hash total size.
* @param table: hash table.
+ * @return size configured as max.
*/
size_t slabhash_get_size(struct slabhash* table);
+/**
+ * Retrieve slab hash current memory use.
+ * @param table: hash table.
+ * @return memory in use.
+ */
+size_t slabhash_get_mem(struct slabhash* table);
+
/**
* Get lruhash table for a given hash value
* @param table: slabbed hash table.