/** * \brief This function handle node_unsubscribe command */ int vs_handle_node_unsubscribe(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *node_unsubscribe) { struct VSNode *node; struct VSNodeSubscriber *node_subscriber; uint32 node_id = UINT32(node_unsubscribe->data[0]); uint32 version = UINT32(node_unsubscribe->data[UINT32_SIZE]); /*uint32 crc32 = UINT32(node_unsubscribe->data[UINT32_SIZE + UINT32_SIZE]);*/ /* Try to find node */ if((node = vs_node_find(vs_ctx, node_id)) == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n", __FUNCTION__, node_id); return 0; } /* TODO: when versing will be supported, then compute crc32, save data to * the disk and send node_unsubscribe command to the client with version number * and crc32 */ if(version != 0) { v_print_log(VRS_PRINT_WARNING, "Version: %d != 0, versing is not supported yet\n", version); } /* Node has to be created */ if(node->state == ENTITY_CREATED || node->state == ENTITY_CREATING) { /* Is client subscribed to this node? */ node_subscriber = node->node_subs.first; while(node_subscriber != NULL) { if(node_subscriber->session->session_id == vsession->session_id) { break; } node_subscriber = node_subscriber->next; } if(node_subscriber!= NULL) { return vs_node_unsubscribe(node, node_subscriber, 0); } else { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() client not subscribed to this node (id: %d)\n", __FUNCTION__, node_id); return 0; } } else { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) is not in NODE_CREATED state: %d\n", __FUNCTION__, node->id, node->state); return 0; } return 0; }
/** * \brief This function do recursive unsubscribing from node */ static int vs_node_unsubscribe(struct VSNode *node, struct VSNodeSubscriber *node_subscriber, int level) { struct VSNode *child_node; struct VSLink *link; struct VBucket *tg_bucket, *layer_bucket; struct VSTagGroup *tg; struct VSLayer *layer; struct VSNodeSubscriber *_node_subscriber, *_next_node_subscriber; struct VSEntityFollower *node_follower; struct VSEntityFollower *taggroup_follower; struct VSEntityFollower *layer_follower; /* Unsubscribe from all child nodes */ link = node->children_links.first; while(link != NULL) { child_node = link->child; _node_subscriber = child_node->node_subs.first; while(_node_subscriber != NULL) { _next_node_subscriber = _node_subscriber->next; if(_node_subscriber->session->session_id == node_subscriber->session->session_id) { /* Unsubscribe from child node */ vs_node_unsubscribe(child_node, _node_subscriber, level+1); break; } _node_subscriber = _next_node_subscriber; } link = link->next; } /* Unsubscribe client from all tag groups */ tg_bucket = node->tag_groups.lb.first; while(tg_bucket != NULL) { tg = (struct VSTagGroup*)tg_bucket->data; /* Remove client from the list of TagGroup subscribers */ vs_taggroup_unsubscribe(tg, node_subscriber->session); /* Remove client from the list of TagGroup followers */ taggroup_follower = tg->tg_folls.first; while(taggroup_follower != NULL) { if(taggroup_follower->node_sub->session->session_id == node_subscriber->session->session_id) { v_list_free_item(&tg->tg_folls, taggroup_follower); break; } taggroup_follower = taggroup_follower->next; } tg_bucket = tg_bucket->next; } /* Unsubscribe client from all layers */ layer_bucket = node->layers.lb.first; while(layer_bucket != NULL) { layer = (struct VSLayer*)layer_bucket->data; /* Remove client from the list of Layer subscribers */ vs_layer_unsubscribe(layer, node_subscriber->session); /* Remove client from the list of Layer followers */ layer_follower = layer->layer_folls.first; while(layer_follower != NULL) { if(layer_follower->node_sub->session->session_id == node_subscriber->session->session_id) { v_list_free_item(&layer->layer_folls, layer_follower); break; } layer_follower = layer_follower->next; } layer_bucket = layer_bucket->next; } if(level > 0) { /* Remove this session from list of followers too */ node_follower = node->node_folls.first; while(node_follower != NULL) { if(node_follower->node_sub->session->session_id == node_subscriber->session->session_id) { /* Remove client from list of clients, that knows about this node */ v_print_log(VRS_PRINT_DEBUG_MSG, "Removing session: %d from the list of node: %d followers\n", node_subscriber->session->session_id, node->id); v_list_free_item(&node->node_folls, node_follower); break; } node_follower = node_follower->next; } } /* Finally remove this session from list of node subscribers */ v_list_free_item(&node->node_subs, node_subscriber); return 1; }