struct data *data_alloc_table(struct data_reg *d_reg) { struct data *d = malloc(sizeof(struct data) * d_reg->data_count); if (!d) { pom_oom(sizeof(struct data) * d_reg->data_count); return NULL; } memset(d, 0, sizeof(struct data) * d_reg->data_count); int i; for (i = 0; i < d_reg->data_count; i++) { if (!(d_reg->items[i].flags & (DATA_REG_FLAG_LIST | DATA_REG_FLAG_NO_ALLOC))) { d[i].value = ptype_alloc_from_type(d_reg->items[i].value_type); if (!d[i].value) goto err; } // Automatically set the non cleanup flag for non allocated data if (d_reg->items[i].flags & DATA_REG_FLAG_NO_ALLOC) d[i].flags = DATA_FLAG_NO_CLEAN; } return d; err: for (i = 0; i < d_reg->data_count && d[i].value; i++) ptype_cleanup(d[i].value); free(d); return NULL; }
struct packet_info *packet_info_pool_get(struct proto *p) { struct packet_info *info = NULL; pom_mutex_lock(&p->pkt_info_pool.lock); if (!p->pkt_info_pool.unused) { // Allocate new packet_info info = malloc(sizeof(struct packet_info)); if (!info) { pom_mutex_unlock(&p->pkt_info_pool.lock); pom_oom(sizeof(struct packet_info)); return NULL; } memset(info, 0, sizeof(struct packet_info)); struct proto_pkt_field *fields = p->info->pkt_fields; int i; for (i = 0; fields[i].name; i++); info->fields_value = malloc(sizeof(struct ptype*) * (i + 1)); memset(info->fields_value, 0, sizeof(struct ptype*) * (i + 1)); for (; i--; ){ info->fields_value[i] = ptype_alloc_from_type(fields[i].value_type); if (!info->fields_value[i]) { i++; for (; fields[i].name; i++) ptype_cleanup(info->fields_value[i]); free(info); pom_mutex_unlock(&p->pkt_info_pool.lock); return NULL; } } debug_info_pool("Allocated info %p for proto %s", info, p->info->name); } else { // Dequeue the packet_info from the unused pool info = p->pkt_info_pool.unused; p->pkt_info_pool.unused = info->pool_next; if (p->pkt_info_pool.unused) p->pkt_info_pool.unused->pool_prev = NULL; debug_info_pool("Used info %p for proto %s", info, p->info->name); } // Queue the packet_info in the used pool info->pool_prev = NULL; info->pool_next = p->pkt_info_pool.used; if (info->pool_next) info->pool_next->pool_prev = info; p->pkt_info_pool.used = info; pom_mutex_unlock(&p->pkt_info_pool.lock); return info; }
struct ptype *data_item_add(struct data *d, struct data_reg *d_reg, unsigned int data_id, const char *key) { struct ptype *value = ptype_alloc_from_type(d_reg->items[data_id].value_type); if (!value) return NULL; if (data_item_add_ptype(d, data_id, key, value) != POM_OK) { ptype_cleanup(value); return NULL; } return value; }
struct packet_info *packet_info_pool_get(struct proto *p) { struct packet_info *info = NULL; struct packet_info **pool = &packet_info_pool[p->id]; if (*pool) { // We can reuse the old one info = *pool; *pool = (*pool)->next; debug_info_pool("Used info %p for proto %s", info, p->info->name); } else { // Allocate new packet_info info = malloc(sizeof(struct packet_info)); if (!info) { pom_oom(sizeof(struct packet_info)); return NULL; } memset(info, 0, sizeof(struct packet_info)); struct proto_pkt_field *fields = p->info->pkt_fields; int i; for (i = 0; fields[i].name; i++); info->fields_value = malloc(sizeof(struct ptype*) * (i + 1)); memset(info->fields_value, 0, sizeof(struct ptype*) * (i + 1)); for (; i--; ) { info->fields_value[i] = ptype_alloc_from_type(fields[i].value_type); if (!info->fields_value[i]) { i++; for (; fields[i].name; i++) ptype_cleanup(info->fields_value[i]); free(info); return NULL; } } debug_info_pool("Allocated info %p for proto %s", info, p->info->name); } return info; }
struct ptype* ptype_alloc_from(struct ptype *pt) { struct ptype *res = ptype_alloc_from_type(pt->type); if (!res) return NULL; res->flags = pt->flags; if (pt->type->info->copy) { if (pt->type->info->copy(res, pt) != POM_OK) { pomlog(POMLOG_ERR "Ptype copy failed while copying from another ptype"); goto err; } } if (pt->unit) { res->unit = strdup(pt->unit); if (!res->unit) { pom_oom(strlen(pt->unit)); goto err; } } return res; err: if (res->type->info->cleanup) res->type->info->cleanup(res); if (pt->unit) free(pt->unit); free(res); return NULL; }