示例#1
0
文件: v_out_queue.c 项目: donno/verse
/*
 * \brief This function pop command from queue with specific priority.
 *
 * Returned command is allocated on the heap and have to be free from calling
 * function. When *count is not NULL, then this function will write number of
 * commands with same ID that could be compressed on this address. When *len
 * is not NULL, then this function will write length of compressed commands
 * at this address. When *len value is not 0, then this value represents maximal
 * size of commands that could be removed from this priority queue.
 *
 * \param[in]	*out_queue	The pointer at list of priority queues
 * \param[in]	prio		The value of priority
 * \param[out]	*count		The pointer at count of commands with same id that
 * could be compressed.
 * \param[out]	*share		The size of address that could be shared
 * \param[out]	*len		The length of compressed commands.
 *
 * \return This function returns pointer at command. This command is allocated
 * at the heap.
 */
struct Generic_Cmd *v_out_queue_pop(struct VOutQueue *out_queue,
		uint8 prio,
		uint16 *count,
		int8 *share,
		uint16 *len)
{
	struct VPrioOutQueue *prio_queue = out_queue->queues[prio];
	struct VOutQueueCommand *queue_cmd;
	struct Generic_Cmd *cmd=NULL;
	int i, can_pop_cmd = 1;

	/* Lock mutex */
	pthread_mutex_lock(&out_queue->lock);

	/*printf("\tcount: %u, share: %u, len: %u\n", *count, *share, *len);*/

	queue_cmd = prio_queue->cmds.first;

	if(queue_cmd != NULL ) {
		cmd = (struct Generic_Cmd *)queue_cmd->vbucket->data;

		assert(cmd != NULL);

		/* Return value of count and length of compressed commands */
		if(queue_cmd->counter != NULL) {
			if(count != NULL) {
				*count = *queue_cmd->counter;
			}
			if(share != NULL) {
				*share = *queue_cmd->share;
			}
			if(len != NULL) {
				/* When *len value is not 0, then this value represents maximal
				 * size of buffer that could be filled with this priority queue. This
				 * function should return value, that is smaller or equal than this
				 * maximum. */
				if(*len != 0) {
					if(*len < *queue_cmd->len) {
						if (count != NULL) {
							*count = v_cmd_count(cmd, *len, *queue_cmd->share);
							/* FIXME: compute length and count correctly, when command is added to the queue */
							*count = ((*count) > (*queue_cmd->counter)) ? *queue_cmd->counter : *count;
							/* Is enough space in buffer to unpack this command? */
							if(*count == 0) {
								can_pop_cmd = 0;
							}
							*len = v_cmds_len(cmd, *count, *queue_cmd->share, 0);
						} else {
							can_pop_cmd = 0;
						}
					} else {
						*len = *queue_cmd->len;
					}
				} else {
					*len = *queue_cmd->len;
				}
			}
		} else {
			if(count != NULL) {
				*count = 0;
			}
			if(share != NULL) {
				*share = 0;
			}
			if(len != NULL) {
				if(v_cmd_size(cmd) > *len) {
					can_pop_cmd = 0;
				}
				*len = 0;
			}
		}

		/* Is it possible to pop command from the queue */
		if(can_pop_cmd == 1) {
			/* Remove command from hashed linked list */
			v_hash_array_remove_item(&out_queue->cmds[cmd->id]->cmds, (void*)cmd);

			/* Remove command from priority queue */
			v_list_rem_item(&prio_queue->cmds, queue_cmd);

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

			/* Update count and size of commands in subqueue with priority prio */
			out_queue->queues[prio]->count--;
			out_queue->queues[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;
				/* Free values, when it's last command in the queue */
				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 and it is possibly necessary to change maximal
			 * or minimal priority queue*/
			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;
				}

				if(out_queue->max_prio == prio && out_queue->min_prio != prio) {
					for(i=prio; i>=out_queue->min_prio; i--) {
						if(out_queue->queues[i]->count != 0) {
							out_queue->max_prio = i;
							break;
						}
					}
				} else if(out_queue->min_prio == prio && out_queue->max_prio != prio) {
					for(i=prio; i<=out_queue->max_prio; i++) {
						if(out_queue->queues[i]->count != 0) {
							out_queue->min_prio = i;
							break;
						}
					}
				} else if(out_queue->min_prio == prio && out_queue->max_prio == prio) {
					out_queue->min_prio = out_queue->max_prio = VRS_DEFAULT_PRIORITY;
				}
			}

			/* Free queue command */
			free(queue_cmd);
		} else {
			cmd = NULL;
		}
	}

	pthread_mutex_unlock(&out_queue->lock);

	return cmd;
}
示例#2
0
文件: v_out_queue.c 项目: donno/verse
/**
 * \brief This function add VQueueCommand to the priority queue
 */
static void _v_out_queue_command_add(struct VPrioOutQueue *prio_queue,
		uint8 flag,
		uint8 share_addr,
		struct VOutQueueCommand *queue_cmd,
		struct Generic_Cmd *cmd)
{
	struct VOutQueueCommand *border_queue_cmd = NULL;

	/* Will be command added to then head or tail of queue? */
	if(flag & OUT_QUEUE_ADD_TAIL) {
		border_queue_cmd = prio_queue->cmds.last;
	} else if(flag & OUT_QUEUE_ADD_HEAD) {
		border_queue_cmd = prio_queue->cmds.first;
	}

	/* Add command to the end of new priority queue. If needed
	 * update counter of same commands in the queue */
	if(border_queue_cmd != NULL) {

		/* Is ID of this command same as ID of the last command
		 * in this priority queue? */
		if( (share_addr == 1) && (border_queue_cmd->id == queue_cmd->id)) {
			struct Generic_Cmd *border_cmd = (struct Generic_Cmd *)border_queue_cmd->vbucket->data;

			/* Is the last command in this priority queue and the
			 * first command with this ID? */
			if(border_queue_cmd->counter == NULL) {

				/* Set initial number of commands with same ID */
				border_queue_cmd->counter = (uint16*)malloc(sizeof(uint16));
				*border_queue_cmd->counter = 1;

				/* Compute size of address that could be shared */
				border_queue_cmd->share = (int8*)malloc(sizeof(int8));
				*border_queue_cmd->share = v_cmd_cmp_addr(border_cmd, cmd, 0xFF);

				/* Allocate memory for length of compressed commands */
				border_queue_cmd->len = (uint16*)malloc(sizeof(uint16));
				*border_queue_cmd->len = v_cmds_len(border_cmd, *border_queue_cmd->counter, *border_queue_cmd->share, 0);

			} else if(*border_queue_cmd->share > 0) {
				/* Try to update size of address that could be shared */
				*border_queue_cmd->share = v_cmd_cmp_addr(border_cmd, cmd, *border_queue_cmd->share);
			}

			/* Set up pointer */
			queue_cmd->counter = border_queue_cmd->counter;
			queue_cmd->share = border_queue_cmd->share;
			queue_cmd->len = border_queue_cmd->len;

			/* Update values */
			(*queue_cmd->counter)++;
			*queue_cmd->len = v_cmds_len(cmd, *queue_cmd->counter, *queue_cmd->share, *queue_cmd->len);
		} else {
			queue_cmd->counter = NULL;
			queue_cmd->share = NULL;
			queue_cmd->len = NULL;
		}
	}

	/* Will be command added to then head or tail of queue? */
	if(flag & OUT_QUEUE_ADD_TAIL) {
		v_list_add_tail(&prio_queue->cmds, queue_cmd);
	} else if(flag & OUT_QUEUE_ADD_HEAD) {
		v_list_add_head(&prio_queue->cmds, queue_cmd);
	}

}
示例#3
0
/**
 * \brief This function packs and compress command to the packet from one
 * priority queue.
 *
 * \param[in]	*C	The verse context
 * \param[in]	*sent_packet	The pointer at structure with send packet
 * \param[in]	buffer_pos		The curent size of buffer of sent packet
 * \param[in]	prio			The priority of sub queue
 * \param[in]	prio_win		The window size of current prio queue
 * \param[out]	tot_cmd_size	The total size of commands that were poped from prio queue
 */
static int pack_prio_queue(struct vContext *C,
		struct VSent_Packet *sent_packet,
		int buffer_pos,
		uint8 prio,
		uint16 prio_win,
		uint16 *tot_cmd_size)
{
	struct VSession *vsession = CTX_current_session(C);
	struct VDgramConn *vconn = CTX_current_dgram_conn(C);
	struct IO_CTX *io_ctx = CTX_io_ctx(C);
	struct Generic_Cmd *cmd;
	int ret, last_cmd_count = 0;
	uint16 cmd_count, cmd_len, cmd_size, sum_len=0;
	int8 cmd_share;
	uint8  last_cmd_id = CMD_RESERVED_ID;

	while( (v_out_queue_get_count_prio(vsession->out_queue, prio) > 0) &&
			(sum_len < prio_win) &&
			(buffer_pos < vconn->io_ctx.mtu))
	{
		cmd_count = 0;
		cmd_share = 0;

		/* Compute how many commands could be compressed to the packet
		 * and compute right length of compressed commands. */
		cmd_len = ((prio_win - sum_len)<(vconn->io_ctx.mtu - buffer_pos)) ?
				(prio_win - sum_len) :
				(vconn->io_ctx.mtu - buffer_pos);

		/* Remove command from queue */
		cmd = v_out_queue_pop(vsession->out_queue, prio, &cmd_count, &cmd_share, &cmd_len);

		/* When it is not possible to pop more commands from queue, then break
		 * while loop */
		if(cmd == NULL) {
			break;
		}

		/* Is this command fake command? */
		if(cmd->id < MIN_CMD_ID) {
			if(cmd->id == FAKE_CMD_CONNECT_TERMINATE) {
				struct VS_CTX *vs_ctx = CTX_server_ctx(C);
				if(vs_ctx != NULL) {
					vconn->host_state = UDP_SERVER_STATE_CLOSEREQ;
				} else {
					vconn->host_state = UDP_CLIENT_STATE_CLOSING;
				}
			} else if(cmd->id == FAKE_CMD_FPS) {
				struct Fps_Cmd *fps_cmd = (struct Fps_Cmd*)cmd;
				/* Change value of FPS. It will be sent in negotiate command
				 * until it is confirmed be the peer (server) */
				vsession->fps_host = fps_cmd->fps;
			}
			v_cmd_destroy(&cmd);
		} else {

			/* What was size of command in queue */
			cmd_size = v_cmd_size(cmd);

			if(!(buffer_pos < (vconn->io_ctx.mtu - cmd_size))) {
				/* When there is not enough space for other command,
				 * then push command back to the beginning of queue. */
				v_out_queue_push_head(vsession->out_queue, prio, cmd);
				break;
			} else {

				/* Update total size of commands that were poped from queue */
				*tot_cmd_size += cmd_size;

				/* When compression is not allowed, then add this command as is */
				if( vconn->host_cmd_cmpr == CMPR_NONE) {
					cmd_count = 0;
					cmd_len = cmd_size;
					/* Debug print */
					v_print_log(VRS_PRINT_DEBUG_MSG, "Cmd: %d, count: %d, length: %d\n",
							cmd->id, cmd_count, cmd_len);
					/* Add command to the buffer */
					buffer_pos += v_cmd_pack(&io_ctx->buf[buffer_pos], cmd, cmd_len, 0);
				} else {
					/* When command compression is allowed and was ID of command changed? */
					if( (cmd->id != last_cmd_id) || (last_cmd_count <= 0) )	{
						/* When this command is alone, then use default command size */
						if(cmd_count == 0) {
							cmd_len = cmd_size;
						} else {
							/* FIXME: do not recompute command length here, but do it right,
							 * when command is added to the queue */
							cmd_len = v_cmds_len(cmd, cmd_count, cmd_share, cmd_len);
						}
						/* Debug print */
						v_print_log(VRS_PRINT_DEBUG_MSG, "Cmd: %d, count: %d, length: %d\n",
								cmd->id, cmd_count, cmd_len);
						/* Add command to the buffer */
						buffer_pos += v_cmd_pack(&io_ctx->buf[buffer_pos], cmd, cmd_len, cmd_share);
						/* Set up current count of commands in the line */
						last_cmd_count = cmd_count;
						/* Update summary of commands length */
						sum_len += cmd_len;
					} else {
						buffer_pos += v_cmd_pack(&io_ctx->buf[buffer_pos], cmd, 0, cmd_share);
					}
				}

				/* Print command */
				v_cmd_print(VRS_PRINT_DEBUG_MSG, cmd);

				/* TODO: remove command alias here (layer value set/unset) */

				/* Add command to the packet history */
				ret = v_packet_history_add_cmd(&vconn->packet_history, sent_packet, cmd, prio);
				assert(ret==1);

				/* Update last command id */
				last_cmd_id = cmd->id;
				/* Decrement counter of commands in queue */
				last_cmd_count--;
			}
		}
	}

	return buffer_pos;
}