1 Star 0 Fork 17

netdebug/cetus

forked from Jasen/cetus 
加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
network-queue.c 4.76 KB
一键复制 编辑 原始数据 按行查看 历史
王斌 提交于 2018-12-10 10:35 +08:00 . Optimize memory allocations
/* $%BEGINLICENSE%$
Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; version 2 of the
License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
02110-1301 USA
$%ENDLICENSE%$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "glib-ext.h"
#include "network-queue.h"
#include "network-mysqld-proto.h"
network_queue *
network_queue_new()
{
network_queue *queue;
queue = g_new0(network_queue, 1);
queue->chunks = g_queue_new();
return queue;
}
void
network_queue_free(network_queue *queue)
{
if (!queue)
return;
GString *packet;
while ((packet = g_queue_pop_head(queue->chunks))) {
g_string_free(packet, TRUE);
}
g_queue_free(queue->chunks);
g_free(queue);
}
void
network_queue_clear(network_queue *queue)
{
if (!queue)
return;
GString *packet;
while ((packet = g_queue_pop_head(queue->chunks)) != NULL) {
g_string_free(packet, TRUE);
}
queue->len = queue->offset = 0;
}
int
network_queue_append(network_queue *queue, GString *s)
{
if (s->len == 0) {
g_warning("%s: packet len:%d", G_STRLOC, (int)s->len);
}
if (s->len > PACKET_LEN_MAX) {
g_warning("%s: packet len:%d is too long", G_STRLOC, (int)s->len);
}
queue->len += s->len;
g_queue_push_tail(queue->chunks, s);
return 0;
}
/**
* get a string from the head of the queue and leave the queue unchanged
*
* @param queue the queue to read from
* @param peek_len bytes to collect
* @param dest GString to write it. If NULL, we allow a new one and return it
* @return NULL if not enough data
* if dest is not NULL, dest, otherwise a new GString containing the data
*/
GString *
network_queue_peek_str(network_queue *queue, gsize peek_len, GString *dest)
{
gsize we_want = peek_len;
GList *node;
/*
* TODO: convert to DTrace probe
* g_debug("[%s] looking for %d bytes, queue has %d", G_STRLOC, peek_len, queue->len);
*/
if (queue->len < peek_len) {
return NULL;
}
if (!dest) {
/* no define */
dest = g_string_sized_new(calculate_alloc_len(peek_len));
}
g_assert_cmpint(dest->allocated_len, >, peek_len);
for (node = queue->chunks->head; node && we_want; node = node->next) {
GString *chunk = node->data;
if (node == queue->chunks->head) {
gsize we_have = we_want < (chunk->len - queue->offset) ? we_want : (chunk->len - queue->offset);
g_string_append_len(dest, chunk->str + queue->offset, we_have);
we_want -= we_have;
} else {
gsize we_have = we_want < chunk->len ? we_want : chunk->len;
g_string_append_len(dest, chunk->str, we_have);
we_want -= we_have;
}
}
return dest;
}
/**
* get a string from the head of the queue and remove the chunks from the queue
*/
GString *
network_queue_pop_str(network_queue *queue, gsize steal_len, GString *dest)
{
gsize we_want = steal_len;
GString *chunk;
if (queue->len < steal_len) {
return NULL;
}
while ((chunk = g_queue_peek_head(queue->chunks))) {
gsize we_have = we_want < (chunk->len - queue->offset) ? we_want : (chunk->len - queue->offset);
if (!dest && (queue->offset == 0) && (chunk->len == steal_len)) {
/* optimize the common case that we want to have to full chunk
*
* if dest is null, we can remove the GString from the queue and
* return it directly without copying it
*/
dest = g_queue_pop_head(queue->chunks);
queue->len -= we_have;
return dest;
}
if (!dest) {
/* if we don't have a dest-buffer yet, create one */
dest = g_string_sized_new(calculate_alloc_len(steal_len));
}
g_string_append_len(dest, chunk->str + queue->offset, we_have);
queue->offset += we_have;
queue->len -= we_have;
we_want -= we_have;
if (chunk->len == queue->offset) {
/* the chunk is done, remove it */
g_string_free(g_queue_pop_head(queue->chunks), TRUE);
queue->offset = 0;
} else {
break;
}
}
return dest;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C
1
https://gitee.com/netdebug/cetus.git
git@gitee.com:netdebug/cetus.git
netdebug
cetus
cetus
master

搜索帮助