/* * Ouroboros - Copyright (C) 2016 - 2024 * * The IPC Resource Manager - Registry - Flows * * Dimitri Staessens * Sander Vrijders * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., http://www.fsf.org/about/contact/. */ #define _POSIX_C_SOURCE 200809L #define OUROBOROS_PREFIX "reg/flow" #include #include "flow.h" #include #include #include #include struct reg_flow * reg_flow_create(const struct flow_info * info) { struct reg_flow * flow; assert(info != NULL); assert(info->id > 0); assert(info->n_pid != 0); assert(info->n_1_pid == 0); assert(info->mpl == 0); assert(info->state == FLOW_INIT); flow = malloc(sizeof(*flow)); if (flow == NULL) { log_err("Failed to malloc flow."); goto fail_malloc; } memset(flow, 0, sizeof(*flow)); clock_gettime(PTHREAD_COND_CLOCK, &flow->t0); list_head_init(&flow->next); flow->info = *info; return flow; fail_malloc: return NULL; } static void destroy_rbuffs(struct reg_flow * flow) { if (flow->n_rb != NULL) shm_rbuff_destroy(flow->n_rb); flow->n_rb = NULL; if (flow->n_1_rb != NULL) shm_rbuff_destroy(flow->n_1_rb); flow->n_1_rb = NULL; } void reg_flow_destroy(struct reg_flow * flow) { assert(flow != NULL); switch(flow->info.state) { case FLOW_ACCEPT_PENDING: clrbuf(flow->data); /* FALLTHRU */ default: destroy_rbuffs(flow); break; } assert(flow->n_rb == NULL); assert(flow->n_1_rb == NULL); assert(flow->data.data == NULL); assert(flow->data.len == 0); assert(list_is_empty(&flow->next)); free(flow); } static int create_rbuffs(struct reg_flow * flow, struct flow_info * info) { assert(flow != NULL); assert(info != NULL); flow->n_rb = shm_rbuff_create(info->n_pid, info->id); if (flow->n_rb == NULL) goto fail_n_rb; assert(flow->info.n_1_pid == 0); assert(flow->n_1_rb == NULL); flow->info.n_1_pid = info->n_1_pid; flow->n_1_rb = shm_rbuff_create(info->n_1_pid, info->id); if (flow->n_1_rb == NULL) goto fail_n_1_rb; return 0; fail_n_1_rb: shm_rbuff_destroy(flow->n_rb); fail_n_rb: return -ENOMEM; } int reg_flow_update(struct reg_flow * flow, struct flow_info * info) { assert(flow != NULL); assert(info != NULL); assert(flow->info.id == info->id); switch(info->state) { case FLOW_ACCEPT_PENDING: assert(flow->info.state == FLOW_INIT); flow->info.n_pid = info->n_pid; break; case FLOW_ALLOC_PENDING: assert(flow->info.state == FLOW_INIT); assert(info->n_1_pid != 0); if (create_rbuffs(flow, info) < 0) goto fail; break; case FLOW_ALLOCATED: assert(info->n_1_pid != 0); assert(flow->info.state > FLOW_INIT); assert(flow->info.state < FLOW_ALLOCATED); assert(flow->info.n_pid != 0); assert(info->mpl != 0); flow->info.mpl = info->mpl; if (flow->info.state == FLOW_ALLOC_PENDING) break; flow->info.qs = info->qs; if (create_rbuffs(flow, info) < 0) goto fail; break; case FLOW_DEALLOCATED: destroy_rbuffs(flow); break; case FLOW_DEALLOC_PENDING: break; default: assert(false); return -EPERM; } flow->info.state = info->state; *info = flow->info; return 0; fail: return -ENOMEM; } void reg_flow_set_data(struct reg_flow * flow, const buffer_t * buf) { assert(flow != NULL); assert(buf != NULL); assert(flow->data.data == NULL); assert(flow->data.len == 0); flow->data = *buf; } void reg_flow_get_data(struct reg_flow * flow, buffer_t * buf) { assert(flow != NULL); assert(buf != NULL); *buf = flow->data; clrbuf(flow->data); } void reg_flow_free_data(struct reg_flow * flow) { freebuf(flow->data); }