int proto_unregister(char *name) { struct proto *proto; for (proto = proto_head; proto && strcmp(proto->info->name, name); proto = proto->next); if (!proto) return POM_OK; proto_number_unregister(proto); if (proto->info->cleanup && proto->info->cleanup(proto->priv)) { pomlog(POMLOG_ERR "Error while cleaning up the protocol %s", name); return POM_ERR; } if (proto->reg_instance) registry_remove_instance(proto->reg_instance); conntrack_table_cleanup(proto->ct); if (proto->next) proto->next->prev = proto->prev; if (proto->prev) proto->prev->next = proto->next; else proto_head = proto->next; mod_refcount_dec(proto->info->mod); free(proto); return POM_OK; }
int event_unregister(struct event_reg *evt) { if (evt->next) evt->next->prev = evt->prev; if (evt->prev) evt->prev->next = evt->next; else event_reg_head = evt->next; registry_remove_instance(evt->reg_instance); free(evt); return POM_OK; }
struct event_reg *event_register(struct event_reg_info *reg_info) { struct event_reg *evt; // Check if an event with the same name has already been registered for (evt = event_reg_head; evt && strcmp(evt->info->name, reg_info->name); evt = evt->next); if (evt) { pomlog(POMLOG_ERR "An event named %s has already been registered", reg_info->name); return NULL; } // Allocate the event_reg evt = malloc(sizeof(struct event_reg)); if (!evt) { pom_oom(sizeof(struct event_reg)); return NULL; } memset(evt, 0, sizeof(struct event_reg)); evt->reg_instance = registry_add_instance(event_registry_class, reg_info->name); if (!evt->reg_instance) { free(evt); return NULL; } evt->perf_listeners = registry_instance_add_perf(evt->reg_instance, "listeners", registry_perf_type_gauge, "Number of event listeners", "listeners"); evt->perf_ongoing = registry_instance_add_perf(evt->reg_instance, "ongoing", registry_perf_type_gauge, "Number of ongoing events", "events"); evt->perf_processed = registry_instance_add_perf(evt->reg_instance, "processed", registry_perf_type_counter, "Number of events fully processed", "events"); if (!evt->perf_listeners || !evt->perf_ongoing || !evt->perf_processed) { registry_remove_instance(evt->reg_instance); free(evt); return NULL; } evt->info = reg_info; evt->next = event_reg_head; if (evt->next) evt->next->prev = evt; event_reg_head = evt; pomlog(POMLOG_DEBUG "Event %s registered", reg_info->name); return evt; }
int output_instance_add(char *type, char *name) { struct output_reg *reg; for (reg = output_reg_head; reg && strcmp(reg->reg_info->name, type); reg = reg->next); if (!reg) { pomlog(POMLOG_ERR "Output type %s does not exists", type); return POM_ERR; } struct output *res = malloc(sizeof(struct output)); if (!res) { pom_oom(sizeof(struct output)); return POM_ERR; } memset(res, 0, sizeof(struct output)); res->info = reg; res->name = strdup(name); if (!res->name) { pom_oom(strlen(name) + 1); goto err; } res->reg_instance = registry_add_instance(output_registry_class, name); if (!res->reg_instance) goto err; res->reg_instance->priv = res; res->perf_runtime = registry_instance_add_perf(res->reg_instance, "runtime", registry_perf_type_timeticks, "Runtime", NULL); if (!res->perf_runtime) goto err; struct ptype *param_running_val = ptype_alloc("bool"); if (!param_running_val) goto err; struct registry_param *param_running = registry_new_param("running", "no", param_running_val, "Running state of the output", REGISTRY_PARAM_FLAG_CLEANUP_VAL); if (!param_running) { ptype_cleanup(param_running_val); goto err; } if (registry_param_set_callbacks(param_running, res, NULL, output_instance_start_stop_handler) != POM_OK) { registry_cleanup_param(param_running); ptype_cleanup(param_running_val); goto err; } if (registry_instance_add_param(res->reg_instance, param_running) != POM_OK) { registry_cleanup_param(param_running); ptype_cleanup(param_running_val); goto err; } struct ptype *output_type = ptype_alloc("string"); if (!output_type) goto err; struct registry_param *type_param = registry_new_param("type", type, output_type, "Type of the output", REGISTRY_PARAM_FLAG_CLEANUP_VAL | REGISTRY_PARAM_FLAG_IMMUTABLE); if (!type_param) { ptype_cleanup(output_type); goto err; } if (registry_instance_add_param(res->reg_instance, type_param) != POM_OK) { registry_cleanup_param(type_param); ptype_cleanup(output_type); goto err; } if (registry_uid_create(res->reg_instance) != POM_OK) goto err; if (reg->reg_info->init) { if (reg->reg_info->init(res) != POM_OK) { pomlog(POMLOG_ERR "Error while initializing the output %s", name); goto err; } } res->next = output_head; if (res->next) res->next->prev = res; output_head = res; return POM_OK; err: if (res->reg_instance) { registry_remove_instance(res->reg_instance); } else { if (res->name) free(res->name); free(res); } return POM_ERR; }
int proto_register(struct proto_reg_info *reg_info) { if (reg_info->api_ver != PROTO_API_VER) { pomlog(POMLOG_ERR "Cannot register proto as API version differ : expected %u got %u", PROTO_API_VER, reg_info->api_ver); return POM_ERR; } // Check if the protocol already exists struct proto *proto; for (proto = proto_head; proto && strcmp(proto->info->name, reg_info->name); proto = proto->next); if (proto) return POM_ERR; // Allocate the protocol proto = malloc(sizeof(struct proto)); if (!proto) { pom_oom(sizeof(struct proto)); return POM_ERR; } memset(proto, 0, sizeof(struct proto)); proto->info = reg_info; proto->id = proto_count; proto_count++; if (reg_info->number_class) { proto->number_class = proto_number_class_get(reg_info->number_class); if (!proto->number_class) goto err_proto; } int res = pthread_rwlock_init(&proto->expectation_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing the proto_expectation rwlock : %s", pom_strerror(res)); goto err_proto; } res = pthread_rwlock_init(&proto->listeners_lock, NULL); if (res) { pomlog(POMLOG_ERR "Error while initializing the proto_listeners rwlock : %s", pom_strerror(res)); goto err_lock1; } proto->reg_instance = registry_add_instance(proto_registry_class, reg_info->name); if (!proto->reg_instance) { pomlog(POMLOG_ERR "Error while adding the registry instanc for protocol %s", reg_info->name); goto err_lock; } // Allocate the conntrack table if (reg_info->ct_info) { proto->ct = conntrack_table_alloc(reg_info->ct_info->default_table_size, (reg_info->ct_info->rev_pkt_field_id == -1 ? 0 : 1)); if (!proto->ct) { pomlog(POMLOG_ERR "Error while allocating conntrack tables"); goto err_registry; } proto->perf_conn_cur = registry_instance_add_perf(proto->reg_instance, "conn_cur", registry_perf_type_gauge, "Current number of monitored connection", "connections"); proto->perf_conn_tot = registry_instance_add_perf(proto->reg_instance, "conn_tot", registry_perf_type_counter, "Total number of connections", "connections"); proto->perf_conn_hash_col = registry_instance_add_perf(proto->reg_instance, "conn_hash_col", registry_perf_type_counter, "Total number of conntrack hash collisions", "collisions"); if (!proto->perf_conn_cur || !proto->perf_conn_tot || !proto->perf_conn_hash_col) goto err_conntrack; } proto->perf_pkts = registry_instance_add_perf(proto->reg_instance, "pkts", registry_perf_type_counter, "Number of packets processed", "pkts"); proto->perf_bytes = registry_instance_add_perf(proto->reg_instance, "bytes", registry_perf_type_counter, "Number of bytes processed", "bytes"); proto->perf_expt_pending = registry_instance_add_perf(proto->reg_instance, "expectations_pending", registry_perf_type_gauge, "Number of expectations pending", "expectations"); proto->perf_expt_matched = registry_instance_add_perf(proto->reg_instance, "expectations_matched", registry_perf_type_counter, "Number of expectations matched", "expectations"); if (!proto->perf_pkts || !proto->perf_bytes || !proto->perf_expt_pending || !proto->perf_expt_matched) goto err_conntrack; if (reg_info->init) { if (reg_info->init(proto, proto->reg_instance) == POM_ERR) { pomlog(POMLOG_ERR "Error while registering proto %s", reg_info->name); goto err_conntrack; } } mod_refcount_inc(reg_info->mod); proto->next = proto_head; if (proto->next) proto->next->prev = proto; proto_head = proto; pomlog(POMLOG_DEBUG "Proto %s registered", reg_info->name); return POM_OK; err_conntrack: // Remove proto number if any proto_number_unregister(proto); conntrack_table_cleanup(proto->ct); err_registry: registry_remove_instance(proto->reg_instance); err_lock: pthread_rwlock_destroy(&proto->listeners_lock); err_lock1: pthread_rwlock_destroy(&proto->expectation_lock); err_proto: free(proto); return POM_ERR; }
int registry_remove_class(struct registry_class *c) { if (!c) return POM_OK; registry_lock(); if (c->prev) c->prev->next = c->next; else registry_head = c->next; if (c->next) c->next->prev = c->prev; while (c->types) { struct registry_instance_type *t = c->types; c->types = c->types->next; free(t->name); free(t); } while (c->instances) { if (registry_remove_instance(c->instances) != POM_OK) { pomlog(POMLOG_WARN "Some error occured while removing an instance"); break; } } registry_unlock(); while (c->global_params) { struct registry_param *p = c->global_params; c->global_params = p->next; free(p->name); if (p->default_value) free(p->default_value); free(p->description); if (p->flags & REGISTRY_PARAM_FLAG_CLEANUP_VAL) ptype_cleanup(p->value); free(p); } while (c->perfs) { struct registry_perf *p = c->perfs; c->perfs = p->next; if (p->update_hook) { int res = pthread_mutex_destroy(&p->hook_lock); if (res) { pomlog(POMLOG_ERR "Error while destroying perf hook lock : %s", pom_strerror(errno)); abort(); } } free(p->name); free(p->description); free(p->unit); free(p); } free(c->name); free(c); return POM_OK; }
int registry_config_reset() { registry_lock(); // Reset the UID table size_t old_uid_table_size = registry_uid_table_size; registry_uid_table_size = 0; struct datastore *sys_dstore = system_datastore(); int restore_sys_dstore = 0; struct registry_class *cls; for (cls = registry_head; cls; cls = cls->next) { /* TODO : registry parameters */ if (cls->instance_remove) { // If we can, remove the instances while (cls->instances) { // Do not remove the system datastore ! if (cls->instances == sys_dstore->reg_instance) { cls->instances = cls->instances->next; if (cls->instances) cls->instances->prev = NULL; restore_sys_dstore = 1; continue; } if (registry_remove_instance(cls->instances) != POM_OK) { // cls->instances might be invalid at this point so don't reference it pomlog(POMLOG_ERR "Unable to remove an instance from class %s", cls->name); if (restore_sys_dstore) { cls->instances = sys_dstore->reg_instance; cls->instances->prev = NULL; cls->instances->next = NULL; restore_sys_dstore = 0; } goto err; } } if (restore_sys_dstore) { cls->instances = sys_dstore->reg_instance; cls->instances->prev = NULL; cls->instances->next = NULL; restore_sys_dstore = 0; } } else { // Else reset all the parameters of each instance struct registry_instance *inst; for (inst = cls->instances; inst; inst = inst->next) { struct registry_param *param; for (param = inst->params; param; param = param->next) { if (registry_set_param_value(param, param->default_value) != POM_OK) { pomlog(POMLOG_ERR "Unable to reset the default value of parameter %s.%s.%s", cls->name, inst->name, param->name); goto err; } } } } } registry_classes_serial_inc(); registry_unlock(); return POM_OK; err: registry_uid_table_size = old_uid_table_size; return POM_ERR; }