iblock.c
来自「使用标准C开发的同时支持CMPP3.0 和 CMPP2.0 的SP短信网关程序」· C语言 代码 · 共 536 行
C
536 行
/*
* VERSION: iblock.c
*
* PURPOSE: queue and idle block management module.
*
*
*
*/
#ifdef LINUX
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include "vscp_os.h"
#include "iblock.h"
#include "smctimer.h"
#define MAST_RECORD_NUM (2000)
typedef struct IblockQueueSTR
{
void * member;
struct IblockQueueSTR * next;
} IblockQueueType;
typedef struct IblockQueueHeadSTR
{
int count;
CriticalSection cs;
IblockQueueType * next;
IblockQueueType * tail;
} IblockQueueHeadType;
static IblockQueueHeadType IblockQueueHead;
int InitIblockQueue(void)
{
CriticalSectionInit(&IblockQueueHead.cs);
IblockQueueHead.tail = NULL;
IblockQueueHead.count = 0;
IblockQueueHead.next = NULL;
return 0;
}
int AddIblockQueue(void *m)
{
IblockQueueType *tmp;
if (m == NULL)
return 1;
tmp = calloc(sizeof(IblockQueueType),1);
if (tmp == NULL)
return 1;
CriticalSectionEnter(&(IblockQueueHead.cs));
tmp->member = m;
if (IblockQueueHead.count == 0)
{
IblockQueueHead.next = tmp;
}
else
{
IblockQueueHead.tail->next = tmp;
}
IblockQueueHead.tail = tmp;
IblockQueueHead.count++;
CriticalSectionLeave(&IblockQueueHead.cs);
return 0;
}
void * DelIblockQueueMember(IblockQueueHeadType * head)
{
IblockQueueType *tmp;
void * ret;
if ((head == NULL) || (IblockQueueHead.count == 0))
return NULL;
CriticalSectionEnter(&(IblockQueueHead.cs));
tmp = IblockQueueHead.next;
IblockQueueHead.next = IblockQueueHead.next->next;
IblockQueueHead.count--;
ret = tmp->member;
free(tmp);
CriticalSectionLeave(&IblockQueueHead.cs);
return ret;
}
/*
* Initialize a queue.
*/
int InitQueue(QueueType *q)
{
CriticalSectionInit(&q->cs);
q->tail = NULL;
q->count = 0;
return 0;
}
/*
* Get the block members's number in the queue.
*/
unsigned int MemberNumber(QueueType *q)
{
return q->count;
}
/*
* Delete a member from the queue.
*/
void * DelMember(QueueType *q)
{
QueueMemberType * tmp;
CriticalSectionEnter(&(q->cs));
if (q->count <= 0)
{
CriticalSectionLeave(&q->cs);
return NULL;
}
if (q->count == 1)
{
tmp = q->tail;
q->tail = NULL;
}
else
{
tmp = ((QueueMemberType *)(q->tail))->next;
((QueueMemberType *)(q->tail))->next = tmp->next;
}
q->count --;
CriticalSectionLeave(&q->cs);
return tmp -> buf;
}
/*
* Add a member to the queue.
*/
void AddMember(QueueType *q, void *m)
{
QueueMemberType * tmp=(void *) ((char *)m - QHSIZE);
CriticalSectionEnter(&(q->cs));
if (q->count == 0)
{
tmp -> next = tmp;
q->tail = tmp;
}
else
{
tmp->next = ((QueueMemberType *)q->tail)->next;
((QueueMemberType *)(q->tail))->next = tmp;
q->tail = tmp;
}
q->count++;
CriticalSectionLeave(&q->cs);
}
/*
* Peek the first member of the queue.
*/
void * PeekFirstMember(QueueType * q)
{
QueueMemberType * tmp;
CriticalSectionEnter(&(q->cs));
if (q->count <= 0)
{
CriticalSectionLeave(&q->cs);
return NULL;
}
tmp = ((QueueMemberType *)(q->tail))->next;
CriticalSectionLeave(&q->cs);
return tmp->buf;
}
/*
* Detach a member from the queue.
*/
int DetachMember(QueueType * q, void *p)
{
void * p1, * p2;
int i;
p=(void *)((char *)p - QHSIZE);
CriticalSectionEnter(&(q->cs));
if (q->count == 0)
{
CriticalSectionLeave(&q->cs);
printf("DetachMember() failed because of q->count==0!\n");
return 1;
}
if (q->tail == p)
{
q->tail = ((QueueMemberType *)(q->tail))->next;
q->count --;
CriticalSectionLeave(&q->cs);
return 0;
}
p1 = q->tail;
p2 = ((QueueMemberType *)(q->tail))->next;
for( i=1; i<q->count; i++)
{
if (p2 == p)
{
((QueueMemberType *)p1)->next = ((QueueMemberType *)p2)->next;
q->count --;
CriticalSectionLeave(&q->cs);
return 0;
}
p1 = p2;
p2 = ((QueueMemberType *)p2)->next;
}
CriticalSectionLeave(&q->cs);
return 2;
}
#ifdef WIN32
#pragma pack(push, 1)
#endif
#ifdef LINUX
#pragma pack(push, 1)
#endif
typedef struct BlockQueueSTR {
unsigned short crc;
unsigned char classtype;
int tk;
unsigned int no;
QueueMemberType blk;
} BlockQueueType;
#ifdef WIN32
#pragma pack(pop)
#endif
#ifdef LINUX
#pragma pack(pop)
#endif
#ifdef WIN32
#define BHSIZE (int) &(((BlockQueueType *)0)->blk)
#endif
#ifdef LINUX
#define BHSIZE (int) &(((BlockQueueType *)0)->blk)
#endif
#define BQHSIZE ( (QHSIZE) + (BHSIZE) )
#define MAX_IBLOCK_NUM (10000)
#define MIN_IBLOCK_AVALIBLE_COUNT (10)
typedef struct IdleBlockSTR {
unsigned int bsize;
unsigned int total;
QueueType bq;
} IdleBlockType;
static IdleBlockType ibt[IBLOCKNUM];
/*
* Initialize the idle block queues.
*/
int InitIdleBlock(void)
{
int i;
for (i=0; i < IBLOCKNUM; i++)
{
ibt[i].bsize = (i+1)*MINBLOCKSIZE;
ibt[i].total = 0;
InitQueue(&ibt[i].bq);
}
InitIblockQueue();
return 0;
}
void * GetBlockInfo(void)
{
int i;
unsigned char * ptr = GetIdleBlock(((sizeof(ibt)/sizeof(ibt[0]))*16 + 8),M_IBLOCK_C);
unsigned int * val = (unsigned int *)(ptr + 2);
for (i=0; i < IBLOCKNUM; i++)
{
if(ibt[i].bq.count == 0 && ibt[i].total == 0)
continue;
*val++ = i;
*val++ = ibt[i].bsize;
*val++ = ibt[i].bq.count;
*val++ = ibt[i].total;
}
*(unsigned short *)ptr = (unsigned short)(((unsigned char *)val - ptr) -2);
return ptr;
}
/*
* Get the block's size.
*/
int BlockSize(void * ptr)
{
BlockQueueType *bptr;
bptr = (BlockQueueType *)((char *)ptr - BQHSIZE);
return ibt[bptr->classtype].bsize;
}
/*
* Get a idle block whose size is len.
*/
void * GetIdleBlockChk(unsigned int len, unsigned int no)
{
int i;
BlockQueueType *ptr;
char szTrace[128];
void *tmp;
unsigned char amess[32];
/* if the size is larger than maximum value, then return. */
if (len > MAXBLOCKSIZE-BQHSIZE)
return NULL;
/* In the idle block queue, find the suitable one. */
i = (len + BQHSIZE-1) / MINBLOCKSIZE;
if (ibt[i].bq.count > MIN_IBLOCK_AVALIBLE_COUNT)
{
while ((tmp = DelMember(&ibt[i].bq)) != NULL)
{
ptr = (void *)((char *)tmp - BQHSIZE);
if ((ptr->crc != 0xaa55) || (ptr->classtype != i) ||
(ptr->tk != 0))
{
memset(szTrace,0,sizeof(szTrace));
// sprintf(szTrace, "GetIdleBlock() failed: bad block type = %x, crc = %x, tk = %x\n", \
// ptr->classtype,ptr->crc,ptr->tk);
// WriteLog(szTrace);
continue;
}
ptr->no = no;
ptr->tk = GetSysTimeByMilliSecond();
return tmp;
}
}
/* Allocate a new block for the request. */
if ((ptr = malloc(ibt[i].bsize)) == NULL)
{
return NULL;
}
ptr->crc = 0xaa55;
ptr->classtype = (unsigned char)i;
ibt[i].total++;
if ((ibt[i].total > MAX_IBLOCK_NUM) && ((ibt[i].total%MAX_IBLOCK_NUM)==0))
{
memset(szTrace,0,sizeof(szTrace));
memset(amess,0,sizeof(amess));
*(unsigned short *)amess = 17;
*(int *)&amess[2] = i;
*(unsigned int *)&amess[6] = ibt[i].total;
GetTimeToMM((TimePTR)&amess[10]);
}
ptr->no = no;
ptr->tk = GetSysTimeByMilliSecond();
AddIblockQueue(ptr);
return (char *)ptr + BQHSIZE;
}
/*
* Put the block to the idle block queue.
*/
int PutIdleBlock(void * ptr)
{
BlockQueueType *ibptr;
unsigned int i;
if ((ptr == NULL) || (*(char **)ptr == NULL))
return 1;
ibptr = (BlockQueueType *)((*(char **)ptr)-BQHSIZE);
*(char **)ptr = NULL;
i = ibptr->classtype;
if ((ibptr->crc != 0xaa55) || (i >= IBLOCKNUM) ||
(ibptr->tk == 0))
{
return 1;
}
ibptr->tk = 0;
AddMember(&ibt[i].bq, ibptr->blk.buf);
return 0;
}
/*
* clean the iblock table
*/
#define MAXBLOCKFILESIZE (5*1024*1024)
#define MILSECONDOF2DAYS (2*24*60*60*1000)
void CleanIblockTable(void)
{
int i;
int num = 0;
BlockQueueType *ptr;
IblockQueueType * ibtptr;
FILE *fp;
time_t t;
char* st;
#ifdef WIN32
WIN32_FIND_DATA fd;
HANDLE handle;
#endif
#ifdef LINUX
struct stat buf;
#endif
CriticalSectionEnter(&IblockQueueHead.cs);
fp = sysfopen("sysiblock.log","a+");
if(fp == NULL)
{
CriticalSectionLeave(&IblockQueueHead.cs);
return ;
}
#ifdef WIN32
handle = FindFirstFile("sysiblock.log", &fd);
if (fd.nFileSizeLow >= MAXBLOCKFILESIZE )
{
sysfclose(fp);
fp = sysfopen("sysiblock.log","w+");
if(fp == NULL)
{
FindClose( handle );
CriticalSectionLeave(&IblockQueueHead.cs);
return ;
}
}
FindClose( handle );
#endif
#ifdef LINUX
stat("sysiblock.log",&buf);
if (buf.st_size>= MAXBLOCKFILESIZE )
{
sysfclose(fp);
fp = sysfopen("sysiblock.log","w+");
if(fp == NULL)
{
CriticalSectionLeave(&IblockQueueHead.cs);
return ;
}
}
#endif
time(&t);
st = asctime(localtime(&t));
fprintf(fp,"\n*****Iblock Record Begin !***** : %s\n",st);
ibtptr = IblockQueueHead.next;
for (i=0; i<IblockQueueHead.count; i++)
{
if (ibtptr == NULL)
break;
ptr = ibtptr->member;
if (ptr == NULL)
break;
if (ptr->crc == 0xaa55)
{
if (ptr->tk != 0)
{
if (IsTimerExpire(ptr->tk + MILSECONDOF2DAYS))
{
num++;
fprintf(fp,"\tNo=%x \tbuf[0]:%d \tbuf[1]:%d\n",ptr->no,(unsigned char)ptr->blk.buf[0],(unsigned char)ptr->blk.buf[1]);
if (num >= MAST_RECORD_NUM)
{
fprintf(fp,"\tIblock Record Num > %d ! break !\n",MAST_RECORD_NUM);
break;
}
}
}
}
ibtptr = ibtptr->next;
}
fprintf(fp,"\tIblock Record Num is %d ! : %s\n",num,st);
fprintf(fp,"*****Iblock Record End !***** : %s\n",st);
sysfclose(fp);
CriticalSectionLeave(&IblockQueueHead.cs);
}
void CheckIBlockFun(void * para)
{
TimeType ctime;
GetTimeToMM(&ctime);
if(ctime.hour == 2)
{
printf("Check Memory !\n");
CleanIblockTable();
}
// LogSetTimer(&CheckIBlockTV);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?