一种简易log记录系统设计

/*************************************************************
* 转载时请保留博客链接地址:https://blog.csdn.net/yunjie167/article/details/84285513
**************************************************************/
#include <stdio.h>
#include <string.h>
#define u8	unsigned char
#define u16	unsigned short
#define u32	unsigned long

#define ERROR_OPREA			-1 
#define ERROR_NOSPACE			-2 
#define ERROR_NO_UPDATE_LOG		-3 
#define ERROR_NO_RECORD			-4 

#define PAGENUMS	4
#define PAGESIZE	512 

u8 VirFlashBuff[PAGENUMS][PAGESIZE];

#define ITEM_HEADER_SIZE	sizeof(SFS_Item_t)

typedef struct {
	u16 remain;		//剩余的字节数
	u16 recycle;	//可回收的字节数 
} SFS_Info_t;

SFS_Info_t sfs_info;

#define LOGMSG_KEY		0xFE

#define	MAGICNUM		0xAABB
#define	UNUSEVALUE		0xFFFFFFFF

#define MARK_USE		0xDF
#define MARK_DIRTY		0xDD 

#define FLASHSIZE		sizeof(VirFlashBuff)

/*
typedef struct {
	const SFS_Item_t *p_header;
	const void * p_data;
} sfs_flash_record_t;*/

typedef struct {
	u16 magic;
	u8 pagenum;
	u8 pagetype; 
	//u16 page_state;
	//u16 resv;
} SFS_Header_t;

SFS_Header_t SFS_Header;

typedef struct {
	u8 recodeKEY;
	u8 mark;	
	u16 length;	
} SFS_Item_t;

/*
typedef struct {
	u16 recodeKEY;
} SFS_Des_t;*/

//flash里建议用字来存储,这里只是模拟flash的操作 
int my_memcpy(u32 *des,const u32 *src,int length)
{
	int flag=0;
	int cpsize=0; 
	if(((u32)src&0x03)!=0)
		 printf("地址不对齐!!!!!!!!!!!!!!!!!!!\n");
	if(length>0)	
	{	
		if(length & 0x03)
			flag=1;
		length>>=2;	
		length+=flag;
		
		cpsize=length<<2;
		
		while(length--)
			*des++=*src++;
	}
	return cpsize;
}

void SFS_Init(void)
{
	u32 *t=(u32 *)VirFlashBuff;
	if(*t != MAGICNUM)
	{
		memset(VirFlashBuff,0xff,sizeof(VirFlashBuff));
		SFS_Header.magic=MAGICNUM;
		memcpy(VirFlashBuff,&SFS_Header,sizeof(SFS_Header)); 
		sfs_info.remain=sizeof(VirFlashBuff)-sizeof(SFS_Header);
		sfs_info.recycle=0;
		printf("整个Flash缓存已经初始化过了! sfs_info.remain=%ld\n",sfs_info.remain);
	}
	//如果已经初始化的了,也得计算下sfs_info.remain 
}

u8 * Find_Record(SFS_Item_t *des)
{
	u32 *pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
	SFS_Item_t tmpdes;
	
	for(;pstart<pstart+FLASHSIZE/4;)
	{
		if(*pstart!=UNUSEVALUE)
		{
			tmpdes=*(SFS_Item_t *)&(*pstart);
			if(tmpdes.recodeKEY==des->recodeKEY && tmpdes.mark!=MARK_DIRTY)
			{
				des->length=tmpdes.length;
				return (u8 *)(pstart+sizeof(SFS_Item_t)/4);	//偏移到数据区域 
			}
			else
			{
				tmpdes=*(SFS_Item_t*)pstart;	//寻找下一个数据项目 
				pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
				if(tmpdes.length%4!=0)
					pstart++;
			}
		}
		else
		{
			return NULL;
		}
	}
}


u8 * Find_Record_Token(SFS_Item_t *des,u32 **ftok)
{
	u32 *pstart;
	SFS_Item_t tmpdes;
	u8 *retaddr=NULL;
	
	if(*ftok!=NULL)
	{
		pstart=*ftok;
	}
	else
	{
		pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
	}
	
	for(;pstart<pstart+FLASHSIZE/4;)
	{
		if(*pstart!=UNUSEVALUE)
		{
			tmpdes=*(SFS_Item_t *)&(*pstart);
			if(tmpdes.recodeKEY==des->recodeKEY && tmpdes.mark!=MARK_DIRTY)
			{
				des->length=tmpdes.length;
				retaddr=(u8 *)(pstart+sizeof(SFS_Item_t)/4);
				
				tmpdes=*(SFS_Item_t*)pstart;	//将下一个项目地址赋值给ftok 
				pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
				if(tmpdes.length%4!=0)
					pstart++;
				*ftok=pstart;
				
				return retaddr;			
			}
			else
			{
				tmpdes=*(SFS_Item_t*)pstart;	//寻找下一个数据项目 
				pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
				if(tmpdes.length%4!=0)
					pstart++;
			}
		}
		else
		{
			*ftok=NULL;
			return NULL;
		}
	}
}

u8 *FindEmptyPostion(void) 
{
	u32 *pstart=(u32 *)(((u8 *)&VirFlashBuff)+(sizeof(SFS_Header_t)));
	
	SFS_Item_t tmpdes;
	
	for(;pstart<pstart+FLASHSIZE/4;)
	{
		if(*pstart==UNUSEVALUE)
		{
			printf("FindEmptyPostion():pstart=0x%X \n",pstart);
			return (u8 *)pstart;
		}
		else
		{
			tmpdes=*(SFS_Item_t*)pstart;	//寻找下一个数据项目 
			pstart+=(tmpdes.length+sizeof(SFS_Item_t))/4;
			if(tmpdes.length%4!=0)
				pstart++;
		}	
	}
	return NULL;
}

int SaveItem2Falsh(SFS_Item_t *des,void *pMsg,int length)
{
	u8 *pstart;
	int cpysize;
	
	if(sfs_info.remain<length+ITEM_HEADER_SIZE)	//存储空间不足,直接返回 
		return -2;
	
	pstart=FindEmptyPostion();
	if(pstart!=NULL)
	{
		printf("找到一个空的位置:0x%X,",pstart);
		des->length=length;
		des->mark=MARK_USE;
		my_memcpy((u32 *)pstart,(u32 *)des,sizeof(SFS_Item_t)); //memcpy(pstart,des,sizeof(SFS_Item_t));	//将记录写上 
		cpysize=my_memcpy((u32 *)(pstart+sizeof(SFS_Item_t)),(u32 *)pMsg,length); //memcpy(pstart+sizeof(SFS_Item_t),pMsg,length);
		sfs_info.remain-=(cpysize+ITEM_HEADER_SIZE);
		printf("剩余%d个字节\n",sfs_info.remain);
		return 0;
	}
	return -1;
}

int delete_record(SFS_Item_t *des)
{
	u8 *p_header;
	SFS_Item_t *tmpdes; 
	int flag=0; 
	int ret=0;
	
	if(des->recodeKEY==LOGMSG_KEY) //如果是日志类的要删除就得全部删除
	{
		flag=1;
		printf("\t您删除的是日志类消息,会全部删除!!!!!!\t");
	} 

	do {
		if((p_header=Find_Record(des)) != NULL)
		{
			p_header-=ITEM_HEADER_SIZE; //指向头域
		 	tmpdes=(SFS_Item_t *)p_header;
		 	tmpdes->mark=MARK_DIRTY;
		 	sfs_info.recycle+=tmpdes->length+ITEM_HEADER_SIZE;
		 	ret++;
		}
		else
			break; 
	} while(flag);
	
	return ret;
}

int update_a_record(SFS_Item_t *des,void *pMsg,int length)
{
	u8 *p_header;
	SFS_Item_t *tmpdes; 
	int ret=-1; 
	
	if(des->recodeKEY==LOGMSG_KEY)
	{
		printf("\t日志类信息不支持更改!!!!!!\t");
		return -3; 
	}
	
	if(sfs_info.remain<length+ITEM_HEADER_SIZE)	//存储空间不足,直接返回 
		return -2;
			
	ret=delete_record(des);	//删除掉之前的旧记录 
	if(ret<0)
		return ret;
	 
	return SaveItem2Falsh(des, pMsg, length);	//再将新的存储进去 
}

#define TEST_KEY 	0x0D


#pragma  pack (push,4) 
typedef struct {
	int a;
	u8 str[16];
	float b;
	u8 c;
	short d; 
} TestVal_t;
#pragma pack(pop) 

TestVal_t TestVal;

int ret;

int main()
{
	int repeat;
	
	SFS_Init();
	SFS_Item_t des;
	
	des.recodeKEY=TEST_KEY;
	strcpy(TestVal.str,"hello!");
	TestVal.a=0x11223344;
	TestVal.b=3.1415926f;	
	ret=SaveItem2Falsh(&des,&TestVal,sizeof(TestVal_t));
	if(ret>=0)
	{
		printf("存储数据成功1!\n");
		
		ret=delete_record(&des);
		if(ret>=0)
		{
			printf("删除记录1成功!!!\n");
		}
	}
	//------------------------------------
	TestVal.a=0x33221199;
	TestVal.c=0x55;
	TestVal.d=0xaa66; 
	ret=SaveItem2Falsh(&des,&TestVal,sizeof(TestVal_t));
	if(ret>=0)
	{
		printf("存储数据成功2!\n");
	//--------------update------------------
		printf("更新存储记录2...\n");
		TestVal.a=0x44444444;
		if(update_a_record(&des,&TestVal,sizeof(TestVal_t))>=0)
		{
			printf("更新存储记录2成功!\n\n");
		}			
	}
	
	//--------------find------------------
	{
		u8 *p_recode;
		TestVal_t readval;
				
		des.recodeKEY=TEST_KEY;
		
		if((p_recode=Find_Record(&des))!=NULL)
		{
			memcpy(&readval,p_recode,des.length);
			printf("找到一个记录! 0x%X length=%d\n",p_recode,des.length);
			printf("readval.str=%s,readval.a=0x%X,readval.b=%f,readval.c=0X%x,readval.d=0X%x\n"
				,readval.str,readval.a,readval.b,readval.c,readval.d);
		}
		else
		{
			printf("未找到KEY=0x%X\n",des.recodeKEY);
		} 
	}
	
	//--------------save a string------------------
	repeat=5;
	while(repeat)
	{
		int stringlen;
		//des.recodeID=LOGMSG_ID;
		des.recodeKEY=LOGMSG_KEY;
		char mytest_str[64];//="你们好啊今天杭州下大雪!!!!.\n";
		sprintf(mytest_str,"你们好啊今天杭州下大雪! %d\n",repeat);
	 	stringlen=strlen(mytest_str);
		ret=SaveItem2Falsh(&des,mytest_str,stringlen+1); //加1是想多存一个字符串结束符 
		if(ret>=0)
		{
			printf("存储字符串 %d\n",repeat);
		}
		else
		{
			printf("存储空间不足!!!\n");
			if(sfs_info.recycle+sfs_info.remain>=stringlen+1+ITEM_HEADER_SIZE) 
			{
				printf("回收后的空间是足够的.remain=%d\n",sfs_info.recycle+sfs_info.remain);
			}
			else
			{
				printf("回收后的空间还是不够 !!!\n");
			} 
			break; 
		} 
		repeat--;
	}
	
	//--------------find all log------------------	
	printf("*********** find all log!!! ***********\n");
	{
		u8 *p_recode;
		u32 *ftok=NULL;
				
		des.recodeKEY=LOGMSG_KEY;	
		do {
			if((p_recode=Find_Record_Token(&des,&ftok))!=NULL)
			{
				printf("找到一个记录!length=%d %.*s\n",des.length,des.length,p_recode);
			}	
			else
			{
				printf("查找结束!\n"); 
			}	
		} while(ftok!=NULL);
	}
	
	des.recodeKEY=LOGMSG_KEY;
	ret=delete_record(&des);
	printf("删除记录%d条\n",ret);
	
	printf("end\n");
}

一个简易文件日志记录系统,适合单片机使用.

猜你喜欢

转载自blog.csdn.net/yunjie167/article/details/84285513
今日推荐