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 + -
显示快捷键?