板卡上的日志缓冲区只可以记录1000条日志,当超过1000条记录时,新增的日志将覆盖旧的记录(是最旧的记录)

王晓华前辈在“一个队列引发的惨案”一节中,说到用循环队列处理固定长度缓冲区问题,小僧读到这里,深深一惊,不禁感叹算法与数据结构结合的巧妙!!!也许是因为小僧是菜鸟,也许是因为小僧少见多怪,也许是因为小僧……反正不论如何,小僧始终觉得这个想法很好,值得借鉴。

结合小僧目前的见识,粗略对王前辈提到的内容进行了一点点加工,话休繁絮,且听小僧一一道来。

对于网络设备而言(小僧目前仅仅接触过UAG设备和负载均衡设备,而且主攻负载均衡设备),系统日志肯定是必须的,而且有一定规格,随着设备的运行,系统日志肯定会满规格,并且覆盖旧日志的情况非常普遍,既然如此,单单就系统日志这一类情况来看,使用链表这种随添随加的数据结构,效率未必高。因为在一开始,未满规格时,每来一条日志,都要现场开辟一段空间来作为节点,而开辟空间的过程是要有一定开销的,因为设备已经启动并有了流量;就算满规格了,不用再开辟空间了,那么想一想,日志嘛,暂时就是固定长度的字符串而已,并没有让这些节点携带某些特殊标记,既然如此,在小僧看来,辛辛苦苦开辟的空间,仅仅用来存个字符串,未免太奢侈。

综上所述,对于该问题的解决,小僧打算使用二维数组log_buf[x][y]。x表示系统日志规格,即总共可以有多少条日志,y表示一条日志的长度。这个二维数组是全局的,在设备启动时就分配好了空间,所以不用担心有流量时/跑业务时临时开辟空间来存日志。另外,对头、尾节点的指向,此时因为采用了数组,所以可以直接用下标,而不用一个结构体指针来专门指向,个人认为,对于菜鸟来讲,这样还是更好一些啊 。

好了,背景介绍完毕,请看代码

#include <stdio.h>
#include <string.h>

#define LOG_NORM      10     /* 日志规格:最多可以有多少条日志 */
#define LOG_LEN       20     /* 单条日志长度 */
#define LOG_TEST_NUM  20     /* 测试用日志总条数 */
#define CONSISTENCY_PROC(tmp)   (tmp = (tmp + 1) % LOG_NORM)  /* 一致性处理 */

int head = 0, tail = 0; 

char log_buff[LOG_NORM][LOG_LEN];
char *log_example[LOG_TEST_NUM] = {
"0 log_test",
"1 log_test",
"2 log_test",
"3 log_test",
"4 log_test",
"5 log_test",
"6 log_test",
"7 log_test",
"8 log_test",
"9 log_test",
"10 log_test",
"11 log_test",
"12 log_test",
"13 log_test",
"14 log_test",
"15 log_test",
"16 log_test",
"17 log_test",
"18 log_test",
"19 log_test"
};

void print_current_log_list(int head, int tail)
{
    int tmp = head;
    
    printf("start, head = %d, tail = %d\n", head, tail);
    while (1)
    {
        printf("log_buff[%d]: %s\n", tmp, log_buff[tmp]);
        
        CONSISTENCY_PROC(tmp);
        if (tmp == tail)
        {
            printf("log_buff[%d]: %s\n", tmp, log_buff[tmp]);
            printf("end\n");
            break;
        }
    }

}

int main(int argc, char *argv[])
{
    int i;
    
    memset(log_buff, 0, sizeof(log_buff));

    for (i = 0; i < LOG_TEST_NUM; i++)
    {
        if (0 == i)
        {
            memcpy(log_buff[head], log_example[i], strlen(log_example[i]));
            printf("start, head = %d, tail = %d\n", head, tail);
            printf("log_buff[%d]: %s\n", head, log_buff[head]);
            printf("end\n");
            continue;
        }
        
        CONSISTENCY_PROC(tail);
        if (tail == head)
        {
            CONSISTENCY_PROC(head);
        }        
        memcpy(log_buff[tail], log_example[i], strlen(log_example[i]));
        print_current_log_list(head, tail);
    }

    return;
}

因为这仅仅是一个示例代码而已,所以小僧只是用了一个指针数组来指向20条示例日志,而日志规格是10条;小僧使用一个函数来专门遍历每次有日志“插入”时当前存储的所有日志。如果施主感兴趣,小僧建议还是运行一下该程序较好,可以更直观的感受用下标表示头、尾而不是使用指针指向来表示头尾的那种畅快淋漓!!!

在小僧看来,这么多行代码,真正有价值就是下面这段

        CONSISTENCY_PROC(tail);
        if (tail == head)
        {
            CONSISTENCY_PROC(head);
        }        

当转了一圈,发现蛇咬了尾巴时,那么尾不动,将下一条日志的下标赋值给头即可(这编辑器我也是醉了,排版这么难搞)。



 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值