Beispiel #1
0
int vs_handle_taggroup_create_ack(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *cmd)
{
	struct VSNode *node;
	struct VSTagGroup *tg;
	struct VSEntityFollower *tg_foll;
	struct TagGroup_Create_Ack_Cmd *cmd_tg_create_ack = (struct TagGroup_Create_Ack_Cmd*)cmd;
	int all_created = 1, ret = 0;

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, cmd_tg_create_ack->node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__FUNCTION__, cmd_tg_create_ack->node_id);
		return 0;
	}

	pthread_mutex_lock(&node->mutex);

	if( (tg = vs_taggroup_find(node, cmd_tg_create_ack->taggroup_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s() tag_group (id: %d) in node (id: %d) not found\n",
				__FUNCTION__,
				cmd_tg_create_ack->taggroup_id,
				cmd_tg_create_ack->node_id);
	} else {

		ret = 1;

		for(tg_foll = tg->tg_folls.first;
				tg_foll != NULL;
				tg_foll = tg_foll->next)
		{
			/* Try to find follower of this tag group */
			if(tg_foll->node_sub->session->session_id == vsession->session_id) {
				/* Switch from state CREATING to state CREATED */
				if(tg_foll->state == ENTITY_CREATING) {
					tg_foll->state = ENTITY_CREATED;
				}

				/* If the tag group is in the state DELETING, then it is possible
				 * now to sent tag_group_destroy command to the client, because
				 * the client knows about this tag group now */
				if(tg->state == ENTITY_DELETING) {
					struct Generic_Cmd *taggroup_destroy_cmd = v_taggroup_destroy_create(node->id, tg->id);

					/* Push this command to the outgoing queue */
					if ( taggroup_destroy_cmd!= NULL &&
							v_out_queue_push_tail(tg_foll->node_sub->session->out_queue,
									tg_foll->node_sub->prio,
									taggroup_destroy_cmd) == 1) {
						tg_foll->state = ENTITY_DELETING;
					} else {
						v_print_log(VRS_PRINT_DEBUG_MSG,
								"taggroup_destroy (node_id: %d, tg_id: %d) wasn't added to the queue\n",
								node->id, tg->id);
						ret = 0;
					}
				}
			} else {
				if(tg_foll->state != ENTITY_CREATED) {
					all_created = 0;
				}
			}
		}

		if(all_created == 1) {
			tg->state = ENTITY_CREATED;
		}
	}

	pthread_mutex_unlock(&node->mutex);

	return ret;
}
Beispiel #2
0
/**
 * \brief This function tries to handle node_create command
 */
int vs_handle_taggroup_create(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *taggroup_create_cmd)
{
	struct VSNode			*node;
	struct VSTagGroup		*tg;
	struct VBucket			*vbucket;
	uint32 					node_id = UINT32(taggroup_create_cmd->data[0]);
	uint16 					taggroup_id = UINT16(taggroup_create_cmd->data[UINT32_SIZE]);
	uint16 					type = UINT16(taggroup_create_cmd->data[UINT32_SIZE+UINT16_SIZE]);
	int						ret = 0;

	/* Client has to send taggroup_create command with taggroup_id equal to
	 * the value 0xFFFF */
	if(taggroup_id != VRS_RESERVED_TAGGROUP_ID) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() taggroup_id: %d is not 0xFFFF\n",
				__FUNCTION__, taggroup_id);
		return 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;
	}

	vbucket = node->tag_groups.lb.first;
	/* Check, if there isn't tag group with the same type */
	while(vbucket != NULL) {
		tg = vbucket->data;
		if(tg->custom_type == type) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s() taggroup type: %d is already used in node: %d\n",
					__FUNCTION__, type, node->id);
			goto end;
		}
		vbucket = vbucket->next;
	}

	/* Is user owner of this node or can user write to this 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 create new tag group */
	tg = vs_taggroup_create(node, VRS_RESERVED_TAGGROUP_ID, type);
	if(tg == NULL) {
		goto end;
	} else {
		struct VSNodeSubscriber *node_subscriber;

		/* Set state for this entity */
		tg->state = ENTITY_CREATING;

		ret = 1;

		/* Send tag group create command to all subscribers to the node
		 * that can read this node */
		for(node_subscriber = node->node_subs.first;
				node_subscriber != NULL;
				node_subscriber = node_subscriber->next)
		{
			if( vs_node_can_read(node_subscriber->session, node) == 1) {
				if(vs_taggroup_send_create(node_subscriber, node, tg) != 1) {
					ret = 0;
				}
			}
		}
	}

end:

	pthread_mutex_unlock(&node->mutex);

	return ret;
}
Beispiel #3
0
/**
 * \brief This function tries to handle Tag_Destroy command
 */
int vs_handle_tag_destroy_ack(struct VS_CTX *vs_ctx,
                              struct VSession *vsession,
                              struct Generic_Cmd *cmd)
{

    struct VSNode				*node;
    struct VSTagGroup			*tg;
    struct VSTag				*tag;
    struct VSEntityFollower		*tag_follower;
    struct Tag_Destroy_Ack_Cmd	*tag_destroy_ack = (struct Tag_Destroy_Ack_Cmd*)cmd;
    uint32						node_id = tag_destroy_ack->node_id;
    uint16						taggroup_id = tag_destroy_ack->taggroup_id;
    uint16						tag_id = tag_destroy_ack->tag_id;
    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);

    /* 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;
    }

    /* Try to find Tag */
    if ( (tag = vs_tag_find(tg, tag_id)) == NULL) {
        v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag (id: %d) in tag_group (id: %d), node (id: %d) not found\n",
                    __FUNCTION__, tag_id, taggroup_id, node_id);
        goto end;
    }

    /* Try to find tag follower that generated this fake command */
    tag_follower = tag->tag_folls.first;
    while(tag_follower != NULL) {
        if(tag_follower->node_sub->session->session_id == vsession->session_id) {
            tag_follower->state = ENTITY_DELETED;
            v_list_free_item(&tag->tag_folls, tag_follower);
            break;
        }
        tag_follower = tag_follower->next;
    }

    /* When tag doesn't have any follower, then it is possible to destroy
     * this tag and remove it from list of tags from the tag group */
    if(tag->tag_folls.first == NULL) {
        tag->state = ENTITY_DELETED;
        vs_tag_destroy(tg, tag);
    }

    ret = 1;

end:
    pthread_mutex_unlock(&node->mutex);

    return ret;
}
Beispiel #4
0
/**
 * \brief This function tries to handle Tag_Set_Int8 command
 */
int vs_handle_tag_set(struct VS_CTX *vs_ctx,
                      struct VSession *vsession,
                      struct Generic_Cmd *tag_set,
                      uint8 data_type,
                      uint8 count)
{
    struct VSNode				*node;
    struct VSTagGroup			*tg;
    struct VSTag				*tag;
    struct VSEntitySubscriber	*tg_subscriber;
    uint32 						node_id;
    uint16 						taggroup_id;
    uint16						tag_id;
    int							ret = 0;

    node_id = UINT32(tag_set->data[0]);
    taggroup_id = UINT16(tag_set->data[UINT32_SIZE]);
    tag_id = UINT16(tag_set->data[UINT32_SIZE + UINT16_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;
    }

    pthread_mutex_lock(&node->mutex);

    /* Node has to be created */
    if(vs_node_is_created(node) != 1) {
        goto end;
    }

    /* Is user owner of this node or can user write to this 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;
    }

    /* Try to find Tag */
    if ( (tag = vs_tag_find(tg, tag_id)) == NULL) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "%s() tag (id: %d) in tag_group (id: %d), node (id: %d) not found\n",
                    __FUNCTION__, tag_id, taggroup_id, node_id);
        goto end;
    }

    /* Data type has to match */
    if(data_type != tag->data_type) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "%s() data type (%d) of tag (id: %d) in tg (id: %d) in node (id: %d) does not match data type of received command (%d)\n",
                    __FUNCTION__, tag->data_type, tag_id,
                    taggroup_id, node_id, data_type);
        goto end;
    }

    /* Count of values has to match */
    if(count != tag->count) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "%s() count of values (%d) of tag (id: %d) in tg (id: %d) in node (id: %d) does not match count of values of received command (%d)\n",
                    __FUNCTION__, tag->count, tag_id, taggroup_id, node_id, count);
        goto end;
    }

    /* Set value in tag */
    switch(tag->data_type) {
    case VRS_VALUE_TYPE_UINT8:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT8_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_UINT16:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT16_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_UINT32:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT32_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_UINT64:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], UINT64_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_REAL16:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL16_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_REAL32:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL32_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_REAL64:
        memcpy(tag->value, &tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE], REAL64_SIZE*tag->count);
        break;
    case VRS_VALUE_TYPE_STRING8:
        if(tag->value == NULL) {
            tag->value = strdup(PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]));
        } else {
            size_t new_str_len = strlen(PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]));
            size_t old_str_len = strlen((char*)tag->value);
            /* Rewrite old string */
            if(new_str_len == old_str_len) {
                strcpy((char*)tag->value, PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]));
            } else {
                tag->value = (char*)realloc(tag->value, new_str_len*sizeof(char));
                strcpy((char*)tag->value, PTR(tag_set->data[UINT32_SIZE + UINT16_SIZE + UINT16_SIZE]));
            }
        }
        break;
    default:
        assert(0);
        break;
    }

    ret = 1;

    /* Set this tag as initialized, because value of this tag was set. */
    tag->flag = TAG_INITIALIZED;

    vs_taggroup_inc_version(tg);

    /* Send this tag to all client subscribed to the TagGroup */
    tg_subscriber = tg->tg_subs.first;
    while(tg_subscriber != NULL) {
        if(vs_tag_send_set(tg_subscriber->node_sub->session, tg_subscriber->node_sub->prio, node, tg, tag) != 1) {
            ret = 0;
        }
        tg_subscriber = tg_subscriber->next;
    }

end:
    pthread_mutex_unlock(&node->mutex);

    return ret;
}
Beispiel #5
0
/**
 * \brief This function tries to handle Tag_Create command.
 *
 * This function change state of follower from CREATING to CREATED
 * and it sends value to this client.
 */
int vs_handle_tag_create_ack(struct VS_CTX *vs_ctx,
                             struct VSession *vsession,
                             struct Generic_Cmd *cmd)
{
    struct VSNode				*node;
    struct VSTagGroup			*tg;
    struct VSTag				*tag;
    struct VSEntityFollower		*tag_follower;
    struct Tag_Create_Ack_Cmd	*tag_create_ack = (struct Tag_Create_Ack_Cmd*)cmd;
    uint32						node_id = tag_create_ack->node_id;
    uint16						taggroup_id = tag_create_ack->taggroup_id;
    uint16						tag_id = tag_create_ack->tag_id;
    int							all_created = 1, tag_found = 0, 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);

    /* 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;
    }

    /* Try to find Tag */
    if ( (tag = vs_tag_find(tg, tag_id)) == NULL) {
        v_print_log(VRS_PRINT_DEBUG_MSG, "%s() tag (id: %d) in tag_group (id: %d), node (id: %d) not found\n",
                    __FUNCTION__, tag_id, taggroup_id, node_id);
        goto end;
    }

    /* Try to find tag follower that generated this fake command */
    tag_follower = tag->tag_folls.first;
    while(tag_follower != NULL) {
        if(tag_follower->node_sub->session->session_id == vsession->session_id) {
            tag_found = 1;
            /* When tag contain value, then send this value to the client */
            if( (tag->flag & TAG_INITIALIZED) && (tag_follower->state != ENTITY_CREATED)) {
                ret = vs_tag_send_set(tag_follower->node_sub->session, tag_follower->node_sub->prio, node, tg, tag);
            }
            tag_follower->state = ENTITY_CREATED;

            /* When this tag has been destroyed during sending tag_create
             * command, then send tag_destroy command now */
            if(tag->state == ENTITY_DELETING) {
                struct Generic_Cmd *tag_destroy_cmd = v_tag_destroy_create(node->id, tg->id, tag->id);

                if( tag_destroy_cmd != NULL &&
                        (v_out_queue_push_tail(tag_follower->node_sub->session->out_queue,
                                               0,
                                               tag_follower->node_sub->prio,
                                               tag_destroy_cmd) == 1))
                {
                    tag_follower->state = ENTITY_DELETING;
                } else {
                    v_print_log(VRS_PRINT_DEBUG_MSG,
                                "Tag_Destroy (node_id: %d, taggroup_id: %d, tag_id: %d) wasn't added to the queue\n",
                                node->id, tg->id, tag->id);
                    ret = 0;
                }
            }
        } else if(tag_follower->state != ENTITY_CREATED) {
            all_created = 0;
        }
        tag_follower = tag_follower->next;
    }

    /* When all clients knows about this tag, then switch tag to state CREATED */
    if(all_created == 1) {
        tag->state = ENTITY_CREATED;
    }

    if(tag_found == 0) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "%s() tag_follower of tag (id: %d) in tag_group (id: %d) in node (id: %d) not found\n",
                    __FUNCTION__, tag_id, tg->id, node->id);
    } else {
        ret = 1;
    }

end:

    pthread_mutex_unlock(&node->mutex);

    return ret;
}
Beispiel #6
0
/**
 * \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;
}
Beispiel #7
0
/**
 * \brief This function is called, when server receive ack command of packet
 * that contained node_create command sent to the client
 *
 * When this function is called, then we can be sure, that client knows about
 * the node. This node can be switched to the NODE_CREATED state for the
 * follower of this node
 */
int vs_handle_node_create_ack(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *cmd)
{
	VSNode *node;
	struct VSEntityFollower *node_follower;
	struct Node_Create_Ack_Cmd *node_create_ack = (struct Node_Create_Ack_Cmd*)cmd;
	int all_created = 1;

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, node_create_ack->node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__FUNCTION__, node_create_ack->node_id);
		return 0;
	}

	node_follower = node->node_folls.first;
	while(node_follower != NULL) {
		if(node_follower->node_sub->session->session_id == vsession->session_id) {

			if(node_follower->state == ENTITY_CREATING) {
				node_follower->state = ENTITY_CREATED;

				/* If the node is in state DELETING, then send to the client command
				 * node_delete. The client knows about this node now and can receive
				 * node_destroy command */
				if(node->state == ENTITY_DELETING) {
					/* Create Destroy_Node command */
					struct Generic_Cmd *node_destroy_cmd = v_node_destroy_create(node->id);

					/* Push this command to the outgoing queue */
					if ( node_destroy_cmd != NULL &&
							v_out_queue_push_tail(node_follower->node_sub->session->out_queue,
									node_follower->node_sub->prio,
									node_destroy_cmd) == 1)
					{
						node_follower->state = ENTITY_DELETING;
					} else {
						v_print_log(VRS_PRINT_DEBUG_MSG,
								"node_destroy (id: %d) wasn't added to the queue\n",
								node->id);
					}
				}
			} else {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"node %d isn't in CREATING state\n");
			}
		} else {
			if(node_follower->state != ENTITY_CREATED) {
				all_created = 0;
			}
		}
		node_follower = node_follower->next;
	}

	/* When all followers know about this node, then change state of this node */
	if(all_created == 1) {
		node->state = ENTITY_CREATED;
	}

	return 0;
}
Beispiel #8
0
/**
 * \brief This function handle changing link between nodes
 */
int vs_handle_link_change(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *node_link)
{
	struct VSUser			*user = (struct VSUser*)vsession->user;
	struct VSNode			*old_parent_node, *parent_node, *child_node;
	struct VSLink			*link;
	struct VSNodeSubscriber	*node_subscriber;
	struct VSEntityFollower *node_follower;
	uint32					parent_node_id = UINT32(node_link->data[0]);
	uint32					child_node_id = UINT32(node_link->data[UINT32_SIZE]);
	int						i;

	/* Try to find child node */
	if((child_node = vs_node_find(vs_ctx, child_node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s():%d node (id: %d) not found\n",
				__func__, __LINE__, child_node_id);
		return 0;
	}

	/* Child node has to be created */
	if(! (child_node->state == ENTITY_CREATED || child_node->state == ENTITY_CREATING)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node id: %d is not in NODE_CREATED state: %d\n",
				__func__, __LINE__, child_node->id, child_node->state);
		return 0;
	}

	/* Is user owner of child node or can user write to child node? */
	if(vs_node_can_write(vsession, child_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to child node: %d (owner: %s)\n",
				__func__, __LINE__, user->username, child_node->id,
				child_node->owner->username);
		return 0;
	}

	/* Old link */
	link = child_node->parent_link;

	/* Old parent node */
	old_parent_node = link->parent;

	/* Is user owner of old parent node or can user write to old parent node? */
	if(vs_node_can_write(vsession, old_parent_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to old parent node: %d (owner: %s)\n",
				__func__, __LINE__, user->username, old_parent_node->id,
				old_parent_node->owner->username);
		return 0;
	}

	/* Try to find new parent node */
	if((parent_node = vs_node_find(vs_ctx, parent_node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s():%d node (id: %d) not found\n",
				__func__, __LINE__, parent_node_id);
		return 0;
	}

	/* Parent node has to be created */
	if(! (parent_node->state == ENTITY_CREATED || parent_node->state == ENTITY_CREATING)) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node (id: %d) is not in NODE_CREATED state: %d\n",
				__func__, __LINE__, parent_node->id, parent_node->state);
		return 0;
	}

	/* Test if client doesn't want to recreate existing link */
	if( parent_node == old_parent_node) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d link between nodes (parent_id: %d) (child_id: %d) already exists\n",
				__func__, __LINE__, parent_node->id, child_node->id);
		return 0;
	}

	/* Is user owner of parent node or can user write to parent node? */
	if(vs_node_can_write(vsession, parent_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d user: %s can't write to parent node: %d (owner: %s)\n",
				__func__, __LINE__, user->username, parent_node->id,
				parent_node->owner->username);
		return 0;
	}

	/* Test, if new link could be created */
	if(vs_link_test_nodes(parent_node, child_node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s():%d node: %d can't be child of node: %d\n",
				__func__, __LINE__, child_node->id, parent_node->id);
		return 0;
	}

	/* Remove link from old parent node */
	v_list_rem_item(&old_parent_node->children_links, link);

	/* Add link to new parent node */
	v_list_add_tail(&parent_node->children_links, link);
	link->parent = parent_node;

	/* Update child node internal properties according new parent node */
	vs_link_update_child(parent_node, child_node);

	/* Update version in child node, parent node and old parent node */
	vs_node_inc_version(parent_node);
	vs_node_inc_version(child_node);
	vs_node_inc_version(old_parent_node);

	/* Subscribers of old and new parent node will receive information about
	 * changing link between nodes. Prevent double sending command Node_Link,
	 * when clients are subscribed to both nodes. */

	/* Set temporary value in all sessions */
	for(i=0; i<vs_ctx->max_sessions; i++) {
		vs_ctx->vsessions[i]->tmp = 0;
	}

	/* Send Node_Link command to subscribers of old parent node and set
	 * session temporary value */
	node_subscriber = old_parent_node->node_subs.first;
	while(node_subscriber != NULL) {
		if(vs_node_can_read(node_subscriber->session, old_parent_node) == 1) {
			node_subscriber->session->tmp = 1;
			vs_link_change_send(node_subscriber, link);
		}
		node_subscriber = node_subscriber->next;
	}

	/* When client is subscribed to the new parent node and aware of child
	 * node, then send to the client only node_link */
	node_follower = child_node->node_folls.first;
	while(node_follower != NULL) {
		if(node_follower->node_sub->session->tmp != 1) {
			vs_link_change_send(node_follower->node_sub, link);
			node_follower->node_sub->session->tmp = 1;
		}
		node_follower = node_follower->next;
	}

	/* Send Node_Create command to subscribers of new parent node, when
	 * subscribers were not subscribed to child node */
	node_subscriber = parent_node->node_subs.first;
	while(node_subscriber != NULL) {
		if(node_subscriber->session->tmp != 1) {
			if(vs_node_can_read(node_subscriber->session, parent_node) == 1) {
				vs_node_send_create(node_subscriber, child_node, NULL);
			}
		}
		node_subscriber = node_subscriber->next;
	}

	return 1;
}
Beispiel #9
0
/**
 * \brief This function handle node_subscribe command
 */
int vs_handle_taggroup_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *taggroup_subscribe)
{
	struct VSNode	*node;
	uint32			node_id = UINT32(taggroup_subscribe->data[0]);
	uint16			taggroup_id = UINT16(taggroup_subscribe->data[UINT32_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",
				__func__, node_id);
		return 0;
	}

	pthread_mutex_lock(&node->mutex);

	/* Node has to be created */
	if( vs_node_is_created(node) != 1 ) {
		goto end;
	}

	/* Is user owner of the node or can user read the node? */
	if(vs_node_can_read(vsession, node) == 1) {
		struct VSNodeSubscriber		*node_subscriber;
		struct VSTagGroup			*tg;
		struct VSTag				*tag;
		struct VSEntitySubscriber	*tg_subscriber;
		struct VBucket				*bucket;

		/* Try to find node subscriber */
		node_subscriber = node->node_subs.first;
		while(node_subscriber != NULL) {
			if(node_subscriber->session == vsession) {
				break;
			}
			node_subscriber = node_subscriber->next;
		}

		/* Client has to be subscribed to the node first */
		if(node_subscriber == NULL) {
			v_print_log(VRS_PRINT_DEBUG_MSG,
					"%s(): client has to be subscribed to the node: %d before subscribing to the tag_group: %d\n",
					__func__, node_id, taggroup_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",
					__func__, taggroup_id, node_id);
			goto end;
		}

		/* Is Client already subscribed to this tag group? */
		tg_subscriber = tg->tg_subs.first;
		while(tg_subscriber != NULL) {
			if(tg_subscriber->node_sub->session->session_id == vsession->session_id) {
				v_print_log(VRS_PRINT_DEBUG_MSG,
						"%s() client already subscribed to the tag_group (id: %d) in node (id: %d)\n",
						__func__, taggroup_id, node_id);
				goto end;
			}
			tg_subscriber = tg_subscriber->next;
		}

		ret = 1;

		/* Add new subscriber to the list of tag group subscribers */
		tg_subscriber = (struct VSEntitySubscriber*)malloc(sizeof(struct VSEntitySubscriber));
		tg_subscriber->node_sub = node_subscriber;
		v_list_add_tail(&tg->tg_subs, tg_subscriber);

		/* Try to send tag_create for all tags in this tag group */
		bucket = tg->tags.lb.first;
		while(bucket != NULL) {
			tag = (struct VSTag*)bucket->data;
			vs_tag_send_create(tg_subscriber, node, tg, tag);
			/* When TCP/WebSocket is used and tag is initialized, then it
			 * is possible (necessary) to send value too. */
			if( ((vsession->flags & VRS_TP_TCP) ||
					(vsession->flags & VRS_TP_WEBSOCKET)) &&
					(tag->flag & TAG_INITIALIZED))
			{
				vs_tag_send_set(vsession, node_subscriber->prio, node, tg, tag);
			}
			bucket = bucket->next;
		}
	} else {
		v_print_log(VRS_PRINT_DEBUG_MSG,
				"%s(): user: %s doesn't have permissions to subscribe to taggroup: %d in node: %d\n",
				__func__,
				((struct VSUser *)vsession->user)->username,
				taggroup_id, node->id);
	}

end:

	pthread_mutex_unlock(&node->mutex);

	return ret;
}
Beispiel #10
0
int vs_handle_layer_set_value(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *layer_set_value_cmd,
		uint8 data_type,
		uint8 count)
{
	struct VSNode *node;
	struct VSLayer *layer;
	struct VSLayerValue *item, _item;
	struct VBucket *vbucket;
	struct VSUser *user;
	struct VSEntitySubscriber *layer_subscriber;

	uint32 node_id = UINT32(layer_set_value_cmd->data[0]);
	uint16 layer_id = UINT16(layer_set_value_cmd->data[UINT32_SIZE]);
	uint32 item_id = UINT32(layer_set_value_cmd->data[UINT32_SIZE + UINT16_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;
	}

	/* 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 the node: %d\n",
				__FUNCTION__, user->username, node->id);
		return 0;
	}

	/* Try to find layer */
	if( (layer = vs_layer_find(node, layer_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %d) in node (id: %d) not found\n",
				__FUNCTION__, layer_id, node_id);
		return 0;
	}

	/* Check type of value */
	if( data_type != layer->data_type ) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() data type (%d) of layer (id: %d) in node (id: %d) does not match data type of received command (%d)\n",
				__FUNCTION__, layer->data_type, layer_id, node_id, data_type);
		return 0;
	}

	/* Check count of value */
	if( count != layer->num_vec_comp ) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() count of values (%d) of layer (id: %d) in node (id: %d) does not match count of values of received command (%d)\n",
				__FUNCTION__, layer->num_vec_comp, layer_id, node_id, count);
		return 0;
	}

	/* Set item value */

	/* Try to find item value first */
	_item.id = item_id;
	vbucket = v_hash_array_find_item(&layer->values, &_item);
	if(vbucket == NULL) {
		/* When this item doesn't exist yet, then allocate memory for this item
		 * and add it to the hashed array */
		item = calloc(1, sizeof(struct VSLayerValue));
		item->id = item_id;
		v_hash_array_add_item(&layer->values, item, sizeof(struct VSLayerValue));

		/* Allocate memory for values and copy data to this memory */
		switch(layer->data_type) {
			case VRS_VALUE_TYPE_UINT8:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(uint8));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT8_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT16:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(uint16));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT16_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT32:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(uint32));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT32_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT64:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(uint64));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT64_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL16:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(real16));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL16_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL32:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(real32));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL32_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL64:
				item->value = (void*)calloc(layer->num_vec_comp, sizeof(real64));
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL64_SIZE);
				break;
			default:
				return 0;
		}
	} else {
		item = (struct VSLayerValue*)vbucket->data;
		switch(layer->data_type) {
			case VRS_VALUE_TYPE_UINT8:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT8_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT16:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT16_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT32:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT32_SIZE);
				break;
			case VRS_VALUE_TYPE_UINT64:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*UINT64_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL16:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL16_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL32:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL32_SIZE);
				break;
			case VRS_VALUE_TYPE_REAL64:
				memcpy(item->value,
						&layer_set_value_cmd->data[UINT32_SIZE+UINT16_SIZE+UINT32_SIZE],
						layer->num_vec_comp*REAL64_SIZE);
				break;
			default:
				return 0;
		}
	}

	/* Send item value set to all layer subscribers */
	layer_subscriber = layer->layer_subs.first;
	while(layer_subscriber != NULL) {
		vs_layer_send_set_value(layer_subscriber, node, layer, item);
		layer_subscriber = layer_subscriber->next;
	}

	return 1;
}
Beispiel #11
0
int vs_handle_layer_subscribe(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *layer_subscribe_cmd)
{
	struct VSNode *node;
	struct VSUser *user;
	struct VSLayer *layer;
	struct VSNodeSubscriber *node_subscriber;
	struct VSEntitySubscriber *layer_subscriber;
	struct VBucket *vbucket;
	struct VSLayerValue *value;

	uint32 node_id = UINT32(layer_subscribe_cmd->data[0]);
	uint16 layer_id = UINT16(layer_subscribe_cmd->data[UINT32_SIZE]);
/*
	uint32 version = UINT32(layer_subscribe_cmd->data[UINT32_SIZE+UINT16_SIZE]);
	uint32 crc32 = UINT32(layer_subscribe_cmd->data[UINT32_SIZE+UINT16_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;
	}

	/* 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 read the node */
	if(vs_node_can_read(vs_ctx, vsession, node) != 1) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): user: %s can't read the node: %d\n",
				__FUNCTION__, user->username, node->id);
		return 0;
	}

	/* Try to find node subscriber */
	node_subscriber = node->node_subs.first;
	while(node_subscriber != NULL) {
		if(node_subscriber->session == vsession) {
			break;
		}
		node_subscriber = node_subscriber->next;
	}

	/* Client has to be subscribed to the node first */
	if(node_subscriber == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s(): client has to be subscribed to the node: %d before subscribing to the layer: %d\n",
				__FUNCTION__, node_id, layer_id);
		return 0;
	}

	/* Try to find layer */
	if( (layer = vs_layer_find(node, layer_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %d) in node (id: %d) not found\n",
				__FUNCTION__, layer_id, node_id);
		return 0;
	}

	/* Layer has to be created */
	if(! (layer->state == ENTITY_CREATING || layer->state == ENTITY_CREATED)) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %u) in node (id: %d) is not in CREATED state: %d\n",
				__FUNCTION__, layer->id, node->id, node->state);
		return 0;
	}

	/* Try to find layer subscriber (client can't be subscribed twice) */
	layer_subscriber = layer->layer_subs.first;
	while(layer_subscriber != NULL) {
		if(layer_subscriber->node_sub->session->session_id == vsession->session_id) {
			v_print_log(VRS_PRINT_DEBUG_MSG, "%s() client already subscribed to the layer (id: %d) in node (id: %d)\n",
									__FUNCTION__, layer_id, node_id);
			return 0;
		}
		layer_subscriber = layer_subscriber->next;
	}

	/* Add new subscriber to the list of layer subscribers */
	layer_subscriber = (struct VSEntitySubscriber*)malloc(sizeof(struct VSEntitySubscriber));
	layer_subscriber->node_sub = node_subscriber;
	v_list_add_tail(&layer->layer_subs, layer_subscriber);

	/* Send value set for all items in this layer
	 * TODO: do not push all values to outgoing queue at once, when there is lot
	 * of values in this layer. Implement this, when queue limits will be
	 * finished. */
	vbucket = layer->values.lb.first;
	while(vbucket != NULL) {
		value = (struct VSLayerValue*)vbucket->data;
		vs_layer_send_set_value(layer_subscriber, node, layer, value);
		vbucket = vbucket->next;
	}

	return 1;
}
Beispiel #12
0
/**
 * \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;
}
Beispiel #13
0
/**
 * \brief This function is called, when client acknowledge receiving of
 * layer_create command
 */
int vs_handle_layer_create_ack(struct VS_CTX *vs_ctx,
		struct VSession *vsession,
		struct Generic_Cmd *cmd)
{
	struct VSNode *node;
	struct VSLayer *layer;
	struct VSEntityFollower *layer_foll;
	struct Layer_Create_Ack_Cmd *layer_create_cmd_ack = (struct Layer_Create_Ack_Cmd*)cmd;
	int all_created = 1;

	/* Try to find node */
	if((node = vs_node_find(vs_ctx, layer_create_cmd_ack->node_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() node (id: %d) not found\n",
				__FUNCTION__, layer_create_cmd_ack->node_id);
		return 0;
	}

	/* Try to find layer */
	if( (layer = vs_layer_find(node, layer_create_cmd_ack->layer_id)) == NULL) {
		v_print_log(VRS_PRINT_DEBUG_MSG, "%s() layer (id: %d) in node (id: %d) not found\n",
				__FUNCTION__, layer_create_cmd_ack->layer_id, layer_create_cmd_ack->node_id);
		return 0;
	}

	for(layer_foll = layer->layer_folls.first;
			layer_foll != NULL;
			layer_foll = layer_foll->next)
	{
		if(layer_foll->node_sub->session->session_id == vsession->session_id) {
			/* Switch from state CREATING to state CREATED */
			if(layer_foll->state == ENTITY_CREATING) {
				layer_foll->state = ENTITY_CREATED;
			}

			/* If the layer is in the state DELETING, then it is possible
			 * now to sent layer_destroy command to the client, because
			 * the client knows about this layer now */
			if(layer->state == ENTITY_DELETING) {
				struct Generic_Cmd *layer_destroy_cmd = v_layer_destroy_create(node->id, layer->id);

				/* Push this command to the outgoing queue */
				if ( layer_destroy_cmd!= NULL &&
						v_out_queue_push_tail(layer_foll->node_sub->session->out_queue,
								layer_foll->node_sub->prio,
								layer_destroy_cmd) == 1) {
					layer_foll->state = ENTITY_DELETING;
				} else {
					v_print_log(VRS_PRINT_DEBUG_MSG, "layer_destroy (node_id: %d, layer_id: %d) wasn't added to the queue\n",
							node->id, layer->id);
				}
			} else {
				if(layer_foll->state != ENTITY_CREATED) {
					all_created = 0;
				}
			}
		}
	}

	if(all_created == 1) {
		layer->state = ENTITY_CREATED;
	}


	return 0;
}