Exemple #1
0
/**
 * \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;
}
Exemple #2
0
/**
 * \brief This function creates VQueueCommand to priority queue
 */
static struct VOutQueueCommand * _v_out_queue_command_create(struct VOutQueue *out_queue,
		uint8 flag,
		uint8 prio,
		struct Generic_Cmd *cmd)
{
	/* Create new command in queue */
	struct VOutQueueCommand *queue_cmd = (struct VOutQueueCommand*)calloc(1, sizeof(struct VOutQueueCommand));

	if(queue_cmd != NULL) {
		/* Set up id and priority of command */
		queue_cmd->id = cmd->id;
		queue_cmd->prio = prio;
		queue_cmd->counter = NULL;
		queue_cmd->share = NULL;

		if(out_queue->cmds[cmd->id]->flag & NOT_SHARE_ADDR) {
			_v_out_queue_command_add(out_queue->queues[prio], flag, 0, queue_cmd, cmd);
		} else {
			_v_out_queue_command_add(out_queue->queues[prio], flag, 1, queue_cmd, cmd);
		}

		/* Add new command data */
		queue_cmd->vbucket = v_hash_array_add_item(&out_queue->cmds[cmd->id]->cmds, cmd, out_queue->cmds[cmd->id]->item_size);
		queue_cmd->vbucket->ptr = (void*)queue_cmd;

		assert(queue_cmd->vbucket->data != NULL);

		/* When this priority queue was empty, then update summary of real priorities */
		if(out_queue->queues[prio]->count == 0) {
			if(prio>=VRS_DEFAULT_PRIORITY)
				out_queue->r_prio_sum_high += out_queue->queues[prio]->r_prio;
			else
				out_queue->r_prio_sum_low += out_queue->queues[prio]->r_prio;
		}

		/* Update count and size of commands */
		out_queue->count++;
		out_queue->size += out_queue->cmds[cmd->id]->item_size;

		out_queue->queues[prio]->count++;
		out_queue->queues[prio]->size += out_queue->cmds[cmd->id]->item_size;

		/* If necessary update maximal or minimal priority */
		if(prio > out_queue->max_prio) {
			out_queue->max_prio = prio;
		} else if(prio < out_queue->min_prio) {
			out_queue->min_prio = prio;
		}

	}

	return queue_cmd;
}
Exemple #3
0
/**
 * \brief This function adds command to the head or tail of the queue
 */
static int _v_out_queue_push(struct VOutQueue *out_queue,
		uint8 flag,
		uint8 prio,
		struct Generic_Cmd *cmd)
{
	struct VOutQueueCommand *queue_cmd;
	struct VBucket *vbucket;
	int ret = 1;

	assert(cmd!=NULL);

	/* Try to find command with the same address, when duplicities are not
	 * allowed in command queue */
	if(out_queue->cmds[cmd->id]->flag & REMOVE_HASH_DUPS) {
		vbucket = v_hash_array_find_item(&out_queue->cmds[cmd->id]->cmds, (void*)cmd);
		if(vbucket != NULL) {
			/* Bucket has to include not NULL pointer */
			assert(vbucket->ptr!=NULL);

			queue_cmd = (struct VOutQueueCommand*)vbucket->ptr;

			/* Remove old command from the queue if the priority is different
			 * and add command to the end of new priority queue */
			if(queue_cmd->prio != prio) {

				/* Remove old obsolete data */
				v_hash_array_remove_item(&out_queue->cmds[cmd->id]->cmds, vbucket->data);
				/* Remove old  command */
				v_list_rem_item(&out_queue->queues[queue_cmd->prio]->cmds, queue_cmd);

				/* Update size and count in old priority queue */
				out_queue->queues[queue_cmd->prio]->count--;
				out_queue->queues[queue_cmd->prio]->size -= out_queue->cmds[cmd->id]->item_size;

				/* If needed, then update counter of commands with the same id in the queue */
				if(queue_cmd->counter != NULL) {
					*queue_cmd->counter -= 1;
					if(*queue_cmd->counter == 0) {
						free(queue_cmd->counter);
						queue_cmd->counter = NULL;
						free(queue_cmd->share);
						queue_cmd->share = NULL;
						free(queue_cmd->len);
						queue_cmd->len = NULL;
					}
				}

				/* When this priority queue is empty now, then update summary of real priorities */
				if(out_queue->queues[queue_cmd->prio]->count == 0) {
					if(prio>=VRS_DEFAULT_PRIORITY)
						out_queue->r_prio_sum_high -= out_queue->queues[queue_cmd->prio]->r_prio;
					else
						out_queue->r_prio_sum_low -= out_queue->queues[queue_cmd->prio]->r_prio;
				}

				/* Update new priority command */
				queue_cmd->id = cmd->id;
				queue_cmd->prio = prio;

				if(out_queue->cmds[cmd->id]->flag & NOT_SHARE_ADDR) {
					_v_out_queue_command_add(out_queue->queues[prio], flag, 0, queue_cmd, cmd);
				} else {
					_v_out_queue_command_add(out_queue->queues[prio], flag, 1, queue_cmd, cmd);
				}

				/* Add data of the command to the hashed linked list */
				queue_cmd->vbucket = v_hash_array_add_item(&out_queue->cmds[cmd->id]->cmds, cmd, out_queue->cmds[cmd->id]->item_size);
				queue_cmd->vbucket->ptr = (void*)queue_cmd;

				assert(queue_cmd->vbucket->data != NULL);

				/* When this priority queue was empty, then update summary of real priorities */
				if(out_queue->queues[prio]->count == 0) {
					if(prio>=VRS_DEFAULT_PRIORITY)
						out_queue->r_prio_sum_high += out_queue->queues[prio]->r_prio;
					else
						out_queue->r_prio_sum_low += out_queue->queues[prio]->r_prio;
				}

				/* Update count and size in new priority queue */
				out_queue->queues[prio]->count++;
				out_queue->queues[prio]->size += out_queue->cmds[cmd->id]->item_size;

				/* If necessary update maximal or minimal priority */
				if(prio > out_queue->max_prio) {
					out_queue->max_prio = prio;
				} else if(prio < out_queue->min_prio) {
					out_queue->min_prio = prio;
				}

			} else {
				/* Debug print */
#if 0
				v_print_log(VRS_PRINT_DEBUG_MSG, "Replacing obsolete command with new\n");
				v_cmd_print(VRS_PRINT_DEBUG_MSG, (struct Generic_Cmd*)vbucket->data);
				v_cmd_print(VRS_PRINT_DEBUG_MSG, cmd);
#endif

				/* Destroy original command */
				v_cmd_destroy((struct Generic_Cmd**)&vbucket->data);

				/* Replace data of current queue command with new data */
				vbucket->data = (void*)cmd;
			}
		} else {
			/* Add new command in queue */
			queue_cmd = _v_out_queue_command_create(out_queue, flag, prio, cmd);

			if(queue_cmd == NULL) {
				ret = 0;
			}
		}
	} else {
		/* Add new command in queue */
		queue_cmd = _v_out_queue_command_create(out_queue, flag, prio, cmd);

		if(queue_cmd == NULL) {
			ret = 0;
		}
	}

	return ret;
}
Exemple #4
0
/**
 * \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;
}
Exemple #5
0
/**
 * \brief This function add command to the history of sent command
 *
 * When this new added command updates some recent command with
 * the same address, then this command is set as obsolete. Pointer at this
 * command is set to NULL in previous packet.
 *
 * \param[in]	*history		The structure containing history of sent packets
 * and commands
 * \param[in]	*sent_packet	The current packet
 * \param[in]	*cmd			The data of command
 *
 * \return This function returns 1, when command was added to history.
 * When it wasn't able to add command to history, then zero is returned.
 */
int v_packet_history_add_cmd(struct VPacket_History *history,
		struct VSent_Packet *sent_packet,
		struct Generic_Cmd *cmd,
		uint8 prio)
{
	struct VSent_Command *sent_cmd;
	struct VBucket *vbucket;
	void *_cmd = (void*)cmd;
	uint8 cmd_id = cmd->id;
	uint16 cmd_size = v_cmd_struct_size(cmd);
	int ret = 0;

	/* Are duplications allowed for this type of commands? */
	if(history->cmd_hist[cmd_id]->flag & REMOVE_HASH_DUPS) {
		/* Try to find command with the same address */
		vbucket = v_hash_array_find_item(&history->cmd_hist[cmd_id]->cmds, _cmd);
		if(vbucket != NULL) {
			struct Generic_Cmd *obsolete_cmd = (struct Generic_Cmd*)vbucket->data;

			/* Bucket has to include not NULL pointer */
			assert(vbucket->ptr!=NULL);
			assert(vbucket->data!=NULL);

			/* Debug print */
#if 0
			v_print_log(VRS_PRINT_INFO, "Replacing obsolete command\n");
			v_cmd_print(VRS_PRINT_INFO, obsolete_cmd);
			v_cmd_print(VRS_PRINT_INFO, cmd);
#endif

			/* When old data are obsolete, then set pointer at command in old
			 * command to the NULL (obsolete command would not be re-send) */
			((struct VSent_Command*)(vbucket->ptr))->vbucket = NULL;

			/* Remove data with the same key as cmd_data has from hashed linked
			 * list */
			ret = v_hash_array_remove_item(&history->cmd_hist[cmd_id]->cmds, vbucket->data);

			if(ret == 1) {
				/* Destroy original command */
				v_cmd_destroy(&obsolete_cmd);
			} else {
				v_print_log(VRS_PRINT_DEBUG_MSG, "Could not remove obsolete command (id: %d) from history\n", cmd_id);
				ret = 0;
			}
		}
	}

	/* Add own command data to the hashed linked list */
	vbucket = v_hash_array_add_item(&history->cmd_hist[cmd_id]->cmds, _cmd, cmd_size);

	if(vbucket != NULL) {
		/* Create new command */
		sent_cmd = (struct VSent_Command*)malloc(sizeof(struct VSent_Command));
		/* Check if it was possible to allocate enough memory for sent command */
		if(sent_cmd != NULL) {
			sent_cmd->id = cmd_id;
			/* Add command to the linked list of sent packet */
			v_list_add_tail(&sent_packet->cmds, sent_cmd);
			/* Set up pointer at command data */
			sent_cmd->vbucket = vbucket;
			/* Set up pointer at owner of this command item to be able to obsolete
			 * this command in future */
			vbucket->ptr = (void*)sent_cmd;
			/* Store information about command priority. Lost commands should
			 * be re-send with same priority*/
			sent_cmd->prio = prio;

			ret = 1;
		} else {
			/* When memory wasn't allocated, then free bucket from hashed
			 * linked list */
			v_print_log(VRS_PRINT_ERROR, "Unable allocate enough memory for sent command\n");
			ret = v_hash_array_remove_item(&history->cmd_hist[cmd_id]->cmds, _cmd);
			if(ret == 1) {
				v_cmd_destroy(_cmd);
			}
			ret = 0;
		}
	} else {
		v_print_log(VRS_PRINT_ERROR, "Unable to add command (id: %d) to packet history\n", cmd_id);
		ret = 0;
	}

	return ret;
}
Exemple #6
0
/**
 * \brief This function creates new Verse Tag
 */
struct VSTag *vs_tag_create(struct VSTagGroup *tg,
                            uint16 tag_id,
                            uint8 data_type,
                            uint8 count,
                            uint16 custom_type)
{
    struct VSTag *tag = NULL;
    struct VBucket *tag_bucket;

    tag = (struct VSTag*)calloc(1, sizeof(struct VSTag));
    if(tag == NULL) {
        v_print_log(VRS_PRINT_DEBUG_MSG, "Out of memory.\n");
        return NULL;
    }

    /* Initialize new tag */
    vs_tag_init(tag);

    if(tag_id == RESERVED_TAG_ID) {
        /* Try to find first free id for tag */
        tag->id = tg->last_tag_id;
        while( v_hash_array_find_item(&tg->tags, tag) != NULL ) {
            tag->id++;

            if(tag->id > LAST_TAG_ID) {
                tag->id = FIRST_TAG_ID;
            }
        }
    } else {
        tag->id = tag_id;
    }
    tg->last_tag_id = tag->id;

    /* Try to add new Tag to the hashed linked list of tags */
    tag_bucket = v_hash_array_add_item(&tg->tags, (void*)tag, sizeof(struct VSTag));

    if(tag_bucket==NULL) {
        v_print_log(VRS_PRINT_DEBUG_MSG,
                    "Tag could not be added to tag group: %d.\n",
                    tg->id);
        free(tag);
        return NULL;
    }

    tag->data_type = data_type;
    tag->count = count;
    tag->custom_type = custom_type;

    /* Allocate memory for value (not for type string8) */
    switch(data_type) {
    case VRS_VALUE_TYPE_UINT8:
        tag->value = (void*)calloc(count, sizeof(uint8));
        break;
    case VRS_VALUE_TYPE_UINT16:
        tag->value = (void*)calloc(count, sizeof(uint16));
        break;
    case VRS_VALUE_TYPE_UINT32:
        tag->value = (void*)calloc(count, sizeof(uint32));
        break;
    case VRS_VALUE_TYPE_UINT64:
        tag->value = (void*)calloc(count, sizeof(uint64));
        break;
    case VRS_VALUE_TYPE_REAL16:
        tag->value = (void*)calloc(count, sizeof(real16));
        break;
    case VRS_VALUE_TYPE_REAL32:
        tag->value = (void*)calloc(count, sizeof(real32));
        break;
    case VRS_VALUE_TYPE_REAL64:
        tag->value = (void*)calloc(count, sizeof(real64));
        break;
    case VRS_VALUE_TYPE_STRING8:
        /* Memory for this type of tag is allocated, when value of
         * tag is set. */
        tag->value = NULL;
        break;
    default:
        break;
    }

    vs_taggroup_inc_version(tg);

    return tag;
}
Exemple #7
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;
}
Exemple #8
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;
}