/** * \brief This function removes all tag groups and tags from the VSNode. This * function doesn't check, if any client is subscribed to tag groups or not. * This function should be called only in situation, when node is destroyed. */ int vs_node_taggroups_destroy(struct VSNode *node) { struct VBucket *tg_bucket, *tg_bucket_next, *bucket; struct VSTagGroup *tg; struct VSTag *tag; tg_bucket = node->tag_groups.lb.first; while(tg_bucket != NULL) { tg_bucket_next = tg_bucket->next; tg = (struct VSTagGroup*)tg_bucket->data; /* Free all data allocated in tags at the first time */ bucket = tg->tags.lb.first; while(bucket != NULL) { tag = (struct VSTag*)bucket->data; if(tag->value) { free(tag->value); tag->value = NULL; } free(tag); bucket = bucket->next; } /* Destroy all tags in this taggroup */ v_hash_array_destroy(&tg->tags); /* Free list of followers and subscribers */ v_list_free(&tg->tg_folls); v_list_free(&tg->tg_subs); /* Destroy this tag group itself */ v_hash_array_remove_item(&node->tag_groups, tg); free(tg); tg_bucket = tg_bucket_next; } return 1; }
/** * \brief This function destroys layer stored at verse server */ void vs_layer_destroy(struct VSNode *node, struct VSLayer *layer) { struct VSLayer *child_layer; struct VSLayerValue *item; struct VBucket *vbucket; /* Free values in all items */ vbucket = (struct VBucket*)layer->values.lb.first; while(vbucket != NULL) { item = (struct VSLayerValue*)vbucket->data; free(item->value); vbucket = vbucket->next; } /* Destroy hashed array with items */ v_hash_array_destroy(&layer->values); /* Set references to parent layer in all child layers to NULL */ child_layer = layer->child_layers.first; while(child_layer != NULL) { child_layer->parent = NULL; child_layer = child_layer->next; } layer->child_layers.first = NULL; layer->child_layers.last = NULL; /* If this layer has parent layer, then remove this layer from * parent linked list of child layers */ if(layer->parent != NULL) { v_list_rem_item(&layer->parent->child_layers, layer); } /* Free list of followers and subscribers */ v_list_free(&layer->layer_folls); v_list_free(&layer->layer_subs); v_print_log(VRS_PRINT_DEBUG_MSG, "Layer: %d destroyed\n", layer->id); /* Destroy this layer itself */ v_hash_array_remove_item(&node->layers, layer); free(layer); }
/** * \brief This function will try to remove node from the server. The node can't * have any child node or subscriber. */ static int vs_node_destroy(struct VS_CTX *vs_ctx, struct VSNode *node) { /* Node can't have any followers. The VSNode can be destroyed, when server * receive ack of node_destroy command from all clients */ if(node->node_folls.first == NULL) { /* Node can't have any child node */ if(node->children_links.first == NULL) { /* Remove node permissions */ if(node->permissions.first != NULL) { v_list_free(&node->permissions); } /* Remove link on this node from parent node */ if(node->parent_link != NULL) { struct VSNode *parent_node = node->parent_link->parent; v_list_free_item(&parent_node->children_links, node->parent_link); } /* Remove all tag groups and tags */ if(node->tag_groups.lb.first != NULL) { vs_node_taggroups_destroy(node); } v_hash_array_destroy(&node->tag_groups); /* Remove all layers */ if(node->layers.lb.first != NULL) { vs_node_layers_destroy(node); } v_hash_array_destroy(&node->layers); v_print_log(VRS_PRINT_DEBUG_MSG, "Node: %d destroyed\n", node->id); /* Remove node from the hashed linked list of nodes */ v_hash_array_remove_item(&vs_ctx->data.nodes, node); free(node); return 1; } else { /* This should never happen */ v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): node (id: %d) with child nodes can't be destroyed\n", __FUNCTION__, node->id); return 0; } } else { /* This should never happen */ v_print_log(VRS_PRINT_WARNING, "%(): node (id: %d) with followers can't be destroyed\n", __FUNCTION__, node->id); return 0; } }
/** * \brief Destroy Verse server context * * \param[in] vs_ctx The Verse server context. */ static void vs_destroy_ctx(struct VS_CTX *vs_ctx) { struct VSUser *user; int i; /* Free all data shared at verse server */ vs_node_destroy_branch(vs_ctx, vs_ctx->data.root_node, 0); /* Destroy hashed array of nodes */ v_hash_array_destroy(&vs_ctx->data.nodes); /* Destroy list of connections */ for (i=0; i<vs_ctx->max_sessions; i++) { if(vs_ctx->vsessions[i] != NULL) { v_destroy_session(vs_ctx->vsessions[i]); free(vs_ctx->vsessions[i]); vs_ctx->vsessions[i] = NULL; } } free(vs_ctx->vsessions); vs_ctx->vsessions = NULL; free(vs_ctx->port_list); vs_ctx->port_list = NULL; free(vs_ctx->tcp_io_ctx.buf); vs_ctx->tcp_io_ctx.buf = NULL; free(vs_ctx->private_cert_file); vs_ctx->private_cert_file = NULL; if(vs_ctx->ca_cert_file != NULL) { free(vs_ctx->ca_cert_file); vs_ctx->ca_cert_file = NULL; } free(vs_ctx->public_cert_file); vs_ctx->public_cert_file = NULL; free(vs_ctx->hostname); vs_ctx->hostname = NULL; free(vs_ctx->ded); vs_ctx->ded = NULL; if(vs_ctx->csv_user_file != NULL) { free(vs_ctx->csv_user_file); vs_ctx->csv_user_file = NULL; } user = (struct VSUser*)vs_ctx->users.first; while(user != NULL) { vs_user_free(user); user = user->next; } v_list_free(&vs_ctx->users); #ifdef WITH_OPENSSL vs_destroy_stream_ctx(vs_ctx); #endif }
/** * \brief This function destroy tag group and all tags included in this tag * group. This function should be called only in situation, when all clients * received command 'TagGroup Destroy'. */ int vs_taggroup_destroy(struct VSNode *node, struct VSTagGroup *tg) { struct VBucket *bucket; struct VSTag *tag; /* All clients had to received TagGroup_Destroy command */ assert(tg->tg_folls.first == NULL); /* Free all data allocated in tags at the first time */ bucket = tg->tags.lb.first; while(bucket != NULL) { tag = (struct VSTag*)bucket->data; if(tag->value != NULL) { free(tag->value); tag->value = NULL; } free(tag); bucket = bucket->next; } /* Destroy all tags in this taggroup */ v_hash_array_destroy(&tg->tags); /* Free list of followers and subscribers */ v_list_free(&tg->tg_folls); v_list_free(&tg->tg_subs); v_print_log(VRS_PRINT_DEBUG_MSG, "TagGroup: %d destroyed\n", tg->id); /* Destroy this tag group itself */ v_hash_array_remove_item(&node->tag_groups, tg); free(tg); vs_node_inc_version(node); return 1; }
/** * \brief This function destroy history of sent packets. It free linked list of * sent packets and all hashed linked lists of commands. * \param[in] *history The history of sent packets. */ void v_packet_history_destroy(struct VPacket_History *history) { struct VSent_Packet *sent_packet; int cmd_id; /* Free all pointer at commands in all sent packet */ sent_packet = history->packets.first; while(sent_packet != NULL) { v_list_free(&sent_packet->cmds); sent_packet = sent_packet->next; } /* Free linked list of sent packets */ v_list_free(&history->packets); /* Free commands in hashed linked lists */ for(cmd_id=0; cmd_id <= MAX_CMD_ID; cmd_id++) { if(history->cmd_hist[cmd_id] != NULL) { v_cmd_queue_destroy(history->cmd_hist[cmd_id]); free(history->cmd_hist[cmd_id]); history->cmd_hist[cmd_id] = NULL; } } }
/** * \brief This function free all commands in linked list of priority queue */ static void _v_out_prio_queue_destroy(struct VPrioOutQueue *prio_queu) { v_list_free(&prio_queu->cmds); }
/** * \brief This function removes packet with id from history of sent packets. * It removes all its commands from the command history too. * * \param[in] *C The verse context. * \param[in] id The ID of packet, the will be removed from the history. * * \return This function returns 1, then packet with id was found in the history * and it returns 0 otherwise. */ int v_packet_history_rem_packet(struct vContext *C, uint32 id) { struct VS_CTX *vs_ctx = CTX_server_ctx(C); struct VDgramConn *dgram_conn = CTX_current_dgram_conn(C); struct VPacket_History *history = &dgram_conn->packet_history; struct VPacket *r_packet = CTX_r_packet(C); struct VSent_Packet *sent_packet; int ret = 0, is_fake_cmd_received = 0; sent_packet = v_packet_history_find_packet(history, id); if(sent_packet != NULL) { struct VSent_Command *sent_cmd; v_print_log(VRS_PRINT_DEBUG_MSG, "Removing packet: %d from history\n", sent_packet->id); /* Go through the whole list of sent commands and free them from the * hashed linked list */ sent_cmd = sent_packet->cmds.first; while(sent_cmd != NULL) { /* Remove own command from hashed linked list if it wasn't already * removed, when command was obsoleted by some newer packet */ if(sent_cmd->vbucket!=NULL) { struct Generic_Cmd *cmd = (struct Generic_Cmd*)sent_cmd->vbucket->data; /* Bucket has to include some data */ assert(sent_cmd->vbucket->data!=NULL); /* Decrease total size of commands that were sent and wasn't acknowladged yet*/ dgram_conn->sent_size -= v_cmd_size(cmd); /* Put fake command for create/destroy commands at verse server */ if(vs_ctx != NULL) { struct VSession *vsession = CTX_current_session(C); struct Generic_Cmd *fake_cmd = NULL; switch(cmd->id) { case CMD_NODE_CREATE: fake_cmd = v_fake_node_create_ack_create(UINT32(cmd->data[UINT16_SIZE + UINT32_SIZE])); break; case CMD_NODE_DESTROY: fake_cmd = v_fake_node_destroy_ack_create(UINT32(cmd->data[0])); break; case CMD_TAGGROUP_CREATE: fake_cmd = v_fake_taggroup_create_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE])); break; case CMD_TAGGROUP_DESTROY: fake_cmd = v_fake_taggroup_destroy_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE])); break; case CMD_TAG_CREATE: fake_cmd = v_tag_create_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE]), UINT16(cmd->data[UINT32_SIZE + UINT16_SIZE])); break; case CMD_TAG_DESTROY: fake_cmd = v_tag_destroy_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE]), UINT16(cmd->data[UINT32_SIZE + UINT16_SIZE])); break; case CMD_LAYER_CREATE: fake_cmd = v_fake_layer_create_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE + UINT16_SIZE])); break; case CMD_LAYER_DESTROY: fake_cmd = v_fake_layer_destroy_ack_create(UINT32(cmd->data[0]), UINT16(cmd->data[UINT32_SIZE])); break; default: break; } if(fake_cmd != NULL) { is_fake_cmd_received = 1; /* Push command to the queue of incomming commands */ v_in_queue_push(vsession->in_queue, fake_cmd); /* Print content of fake command */ v_fake_cmd_print(VRS_PRINT_DEBUG_MSG, fake_cmd); } } /* Remove command from the history of sent commands */ ret = v_hash_array_remove_item(&history->cmd_hist[sent_cmd->id]->cmds, sent_cmd->vbucket->data); if(ret == 1) { /* Destroy command */ v_cmd_destroy(&cmd); } else { v_print_log(VRS_PRINT_ERROR, "Unable to remove command id: %d\n", sent_cmd->id); ret = 0; } } sent_cmd = sent_cmd->next; } /* Free linked list of sent commands */ v_list_free(&sent_packet->cmds); /* Remove packet itself from the linked list of sent packet */ v_list_rem_item(&history->packets, sent_packet); free(sent_packet); ret = 1; } else { /* When acknowledged payload packet is not found in history, then it * is OK, because it is probably keep alive packet without any node * commands */ v_print_log(VRS_PRINT_DEBUG_MSG, "Packet with id: %d, not found in history\n", id); } /* When pure ack packet caused adding some fake commands to the queue, then * poke server data thread */ if( (vs_ctx != NULL) && (is_fake_cmd_received == 1) && (r_packet->data == NULL)) { sem_post(vs_ctx->data.sem); } return ret; }