/** * \brief This function create new tag group */ struct VSTagGroup *vs_taggroup_create(struct VSNode *node, uint16 tg_id, uint16 custom_type) { struct VSTagGroup *tg = NULL; struct VBucket *tg_bucket; if ( !(v_hash_array_count_items(&node->tag_groups) < MAX_TAGGROUPS_COUNT) ) { v_print_log(VRS_PRINT_DEBUG_MSG, "Maximal number of tag groups in node: %d reached.\n", node->id); return NULL; } /* Try to create new tag group */ tg = (struct VSTagGroup*)calloc(1, sizeof(VSTagGroup)); if(tg == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "Out of memory.\n"); return NULL; } /* Initialize new tag group */ vs_taggroup_init(tg); if(tg_id == VRS_RESERVED_TAGGROUP_ID) { /* Try to find first free taggroup_id */ tg->id = node->last_tg_id; while( v_hash_array_find_item(&node->tag_groups, tg) != NULL) { /* When not found, then try higher value */ tg->id++; /* Skip IDs with special purpose */ if(tg->id > LAST_TAGGROUP_ID) { tg->id = FIRST_TAGGROUP_ID; } } } else { tg->id = tg_id; } node->last_tg_id = tg->id; /* Try to add TagGroup to the hashed linked list */ tg_bucket = v_hash_array_add_item(&node->tag_groups, tg, sizeof(struct VSTagGroup)); if(tg_bucket == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "Tag group could not be added to node: %d.\n", node->id); free(tg); return NULL; } /* Copy type */ tg->custom_type = custom_type; vs_node_inc_version(node); return tg; }
/** * \brief This function creates new VSNode at Verse server */ struct VSNode *vs_node_create(struct VS_CTX *vs_ctx, struct VSNode *parent_node, struct VSUser *owner, uint32 node_id, uint16 custom_type) { struct VSNode *node; struct VSLink *link; struct VBucket *bucket; if(! (v_hash_array_count_items(&vs_ctx->data.nodes) < VRS_MAX_COMMON_NODE_COUNT) ) { v_print_log(VRS_PRINT_DEBUG_MSG, "max number: %d of nodes reached\n", VRS_MAX_COMMON_NODE_COUNT); return NULL; } node = (struct VSNode*)calloc(1, sizeof(struct VSNode)); if(node == NULL) { v_print_log(VRS_PRINT_ERROR, "Out of memory\n"); return NULL; } vs_node_init(node); if(node_id == VRS_RESERVED_NODE_ID) { /* Try to find first free node_id. It is fast and easy, When * VRS_LAST_COMMON_NODE_ID did not reach 0xFFFFFFFF-1 value yet and not used * node_id are not reused.*/ node->id = vs_ctx->data.last_common_node_id + 1; while( v_hash_array_find_item(&vs_ctx->data.nodes, &node) != NULL) { node->id++; /* Node id 0xFFFFFFFF has special purpose and node IDs in range <0, 65535> * have special purposes too (skip them) */ if(node->id > VRS_LAST_COMMON_NODE_ID) node->id = VRS_FIRST_COMMON_NODE_ID; /* TODO: implement faster finding of free node id */ } vs_ctx->data.last_common_node_id = node->id; } else { node->id = node_id; } /* Create link to the parent node */ if(parent_node != NULL) { link = vs_link_create(parent_node, node); if(link == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "link between nodes %d %d could not be created\n", parent_node->id, node->id); free(node); return NULL; } } else { /* This can happen only for root node */ assert(node_id == VRS_ROOT_NODE_ID); node->parent_link = NULL; node->level = 0; } /* Add node to the hashed array of all verse nodes */ bucket = v_hash_array_add_item(&vs_ctx->data.nodes, node, sizeof(struct VSNode)); if(bucket == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "node %d could not be added to the hashed list of nodes\n", node->id); if(node->parent_link != NULL) { v_list_free_item(&parent_node->children_links, node->parent_link); } free(node); return NULL; } node->owner = owner; node->type = custom_type; return node; }
/** * \brief This function tries to handle Tag_Create command */ int vs_handle_tag_create(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *tag_create) { struct VSNode *node; struct VSTagGroup *tg; struct VSTag *tag; struct VBucket *vbucket; struct VSEntitySubscriber *tg_subscriber; uint32 node_id = UINT32(tag_create->data[0]); uint16 taggroup_id = UINT16(tag_create->data[UINT32_SIZE]); uint16 tag_id = UINT16(tag_create->data[UINT32_SIZE + UINT16_SIZE]); uint8 data_type = UINT8(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]); uint8 count = UINT8(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + UINT8_SIZE]); uint16 type = UINT16(tag_create->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE + UINT8_SIZE + UINT8_SIZE]); int ret = 0; /* 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; } pthread_mutex_lock(&node->mutex); /* Node has to be created */ if(vs_node_is_created(node) != 1) { goto end; } /* User has to have permission to write to the node */ if(vs_node_can_write(vsession, node) != 1) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): user: %s can't write to node: %d\n", __FUNCTION__, ((struct VSUser *)vsession->user)->username, node->id); goto end; } /* Try to find TagGroup */ if( (tg = vs_taggroup_find(node, taggroup_id)) == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag_group (id: %d) in node (id: %d) not found\n", __FUNCTION__, taggroup_id, node_id); goto end; } /* Tag Group has to be created too (it can't be in DELETING or DELETED state ) */ if(!(tg->state == ENTITY_CREATED || tg->state == ENTITY_CREATING)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag group (id: %d) from node (id: %d) is not in CREATING or CREATED state: %d\n", __FUNCTION__, tg->id, node->id, tg->state); goto end; } /* Client has to send tag_create command with tag_id equal to * the value 0xFFFF */ if(tag_id != RESERVED_TAG_ID) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag_id: %d is not 0xFFFF\n", __FUNCTION__, tag_id); goto end; } /* Is type of Tag supported? */ if(!(data_type>VRS_VALUE_TYPE_RESERVED && data_type<=VRS_VALUE_TYPE_STRING8)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag_type: %d is not supported\n", __FUNCTION__, data_type); goto end; } vbucket = tg->tags.lb.first; /* Check, if there isn't tag with the same type */ while(vbucket != NULL) { tag = vbucket->data; if(tag->custom_type == type) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag type: %d is already used in taggroup: %d\n", __FUNCTION__, type, tg->id); goto end; } vbucket = vbucket->next; } if (v_hash_array_count_items(&tg->tags) > MAX_TAGS_COUNT) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() max number of tags in node: %d tag_group: %d was reached\n", tg->id); goto end; } /* Try to create new tag */ tag = vs_tag_create(tg, RESERVED_TAG_ID, data_type, count, type); if(tag == NULL) { goto end; } ret = 1; tag->state = ENTITY_CREATING; /* Send TagCreate to all subscribers of tag group */ tg_subscriber = tg->tg_subs.first; while(tg_subscriber != NULL) { if(vs_tag_send_create(tg_subscriber, node, tg, tag) != 1) { ret = 0; } tg_subscriber = tg_subscriber->next; } end: pthread_mutex_unlock(&node->mutex); return ret; }
/** * \brief This function is called, when server receives command layer_create * * \param[in] *vs_ctx The pointer at verse server context * \param[in] *vsession The pointer at session of client that sent this command * \param[in] *layer_create_cmd The pointer at received command * * \return This function returns 0, when parameters of received command are * wrong. When all parameters are right, then it returns 1. */ int vs_handle_layer_create(struct VS_CTX *vs_ctx, struct VSession *vsession, struct Generic_Cmd *layer_create_cmd) { struct VSNode *node; struct VSUser *user; struct VSLayer *parent_layer; struct VSLayer *layer; struct VBucket *vbucket; struct VSNodeSubscriber *node_subscriber; uint32 node_id = UINT32(layer_create_cmd->data[0]); uint16 parent_layer_id = UINT16(layer_create_cmd->data[UINT32_SIZE]); uint16 layer_id = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE]); uint8 data_type = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE]); uint8 count = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE+UINT8_SIZE]); uint16 type = UINT16(layer_create_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT16_SIZE+UINT8_SIZE+UINT8_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; } /* When parent layer id is not -1, then try to find this parent layer */ if(parent_layer_id == RESERVED_LAYER_ID) { parent_layer = NULL; } else { parent_layer = vs_layer_find(node, parent_layer_id); if(parent_layer == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() parent layer (id: %d) in node (id: %d) not found\n", __FUNCTION__, parent_layer_id, node_id); return 0; } } /* Node has to be created */ if(!(node->state == ENTITY_CREATED || node->state == ENTITY_CREATING)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) is not in CREATING or CREATED state: %d\n", __FUNCTION__, node->id, node->state); return 0; } /* Try to find user */ if((user = vs_user_find(vs_ctx, vsession->user_id)) == NULL) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() vsession->user_id: %d not found\n", __FUNCTION__, vsession->user_id); return 0; } /* User has to have permission to write to the node */ if(vs_node_can_write(vs_ctx, vsession, node) != 1) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): user: %s can't write to node: %d\n", __FUNCTION__, user->username, node->id); return 0; } /* Client has to send layer_create command with layer_id equal to * the value 0xFFFF */ if(layer_id != RESERVED_LAYER_ID) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer_id: %d is not 0xFFFF\n", __FUNCTION__, layer_id); return 0; } /* Is type of Layer supported? */ if(!(data_type>VRS_VALUE_TYPE_RESERVED && data_type<=VRS_VALUE_TYPE_REAL64)) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() data_type: %d is not supported\n", __FUNCTION__, data_type); return 0; } vbucket = node->layers.lb.first; /* Check, if there isn't tag with the same type */ while(vbucket != NULL) { layer = vbucket->data; if(layer->type == type) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer type: %d is already used in layer: %d\n", __FUNCTION__, type, layer->id); return 0; } vbucket = vbucket->next; } if (v_hash_array_count_items(&node->layers) > MAX_LAYERS_COUNT) { v_print_log(VRS_PRINT_DEBUG_MSG, "%s() max number of layers in node: %d was reached\n", node->id); return 0; } layer = vs_layer_create(node, parent_layer, data_type, count, type); /* Try to find first free id for layer */ /* TODO: this could be more effective */ layer->id = node->last_layer_id; while( v_hash_array_find_item(&node->layers, layer) != NULL ) { layer->id++; if(layer->id > LAST_LAYER_ID) { layer->id = FIRST_LAYER_ID; } } node->last_layer_id = layer->id; /* Try to add new Tag to the hashed linked list of tags */ vbucket = v_hash_array_add_item(&node->layers, (void*)layer, sizeof(struct VSLayer)); if(vbucket==NULL) { free(layer); return 0; } layer->state = ENTITY_CREATING; /* Send layer_create to all node subscribers */ node_subscriber = node->node_subs.first; while(node_subscriber != NULL) { vs_layer_send_create(node_subscriber, node, layer); node_subscriber = node_subscriber->next; } return 0; }