⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 phydb.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************
*
* Copyright  2000 National ASIC Center, All right Reserved
*
* FILE NAME:			phylayer.c
* PROGRAMMER:			XuanHui
* Date of Creation:		2002/8/13
*
* DESCRIPTION:
*		Based on the document system, offer operations of read, modification, insert and deletion
*	of records to the upper lever (database application mode).
*
* NOTE:
*
* FUNCTIONS LIST:
*	the following define four member function.
*
*		BYTE *GlobalReadRecord( DBPHYLAYERINFO *info, DWORD id );
*		DWORD GlobalModifyRecord( DBPHYLAYERINFO *info, DWORD id, BYTE *data );
*		DWORD GlobalInsertRecord( DBPHYLAYERINFO *info, DWORD id, BYTE *data );
*		DWORD GlobalDelRecord( DBPHYLAYERINFO *info, DWORD id );
*
*	the following two function is two sub_function
*		static void ModifyFirstFreeBlock( DBPHYLAYERINFO *info, DWORD first_free_block_ad );
*		static void WriteDataToFile(  DBPHYLAYERINFO *info, DWORD *record_block_ad, WORD *block_num, WORD *record_size, BYTE *data, DWORD *tmp_ad );
*
*GLOBAL VARS LIST:
*

*************************************************************************/
//#include "phydb.h"
#include <database\phydb.h>

static void ModifyFirstFreeBlock( DBPHYLAYERINFO *info, DWORD first_free_block_ad );
//static void WriteDataToFile(  DBPHYLAYERINFO *info, DWORD *record_block_ad, WORD *block_num, WORD *record_size, DWORD *data, DWORD *tmp_ad );
static void WriteDataToFile(  DBPHYLAYERINFO *info, DWORD *record_block_ad, WORD *block_num, WORD *record_size, BYTE **data, DWORD *tmp_ad );

//---------------------------------------------------------------
//    *GlobalReadRecord()
//
//        Read the contents of the specified record from the specified database.
//
//    Parameters:
//        info          - the used information of the record block.
//        id			- the address of the specified record.
//
//    Returns:
//		  DB_ERROR		:	failure
//        data			:   the address of the buffer area
//---------------------------------------------------------------
DWORD GlobalReadRecord( DBPHYLAYERINFO *info, DWORD id, BYTE **data )
//DWORD GlobalReadRecord( DBPHYLAYERINFO *info, DWORD id, DWORD *data )
{
	WORD	used_block_flag = 0;
	WORD	record_size = 0;
	DWORD	record_block_ad = 0;
	BYTE	*record_data;

	//验证指定数据库的有效性(数据库文件是否已打开)
	if( info == NULL )
		return DB_ERROR;
	//if( info->fp == NULL || info->fp->magic != FILE_MAGIC)
	if( info->fp == NULL )
		return DB_ERROR;

	//验证指定记录的有效性(记录块标识是否为'UB')
	fseek( info->fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM, SEEK_SET );
	fread( &used_block_flag, FLAG_BYTE_NUM, 1, info->fp );
	if( used_block_flag != USED_BLOCK_FLAG )
//		return DB_ERROR;
		return DB_FREE_RECORD;
	
	//确定记录数据内容的大小
	fseek( info->fp, id+ADDRESS_BYTE_NUM, SEEK_SET );
	fread( &record_size, SIZE_BYTE_NUM, 1, info->fp );

	if( data == NULL )
		return DB_ERROR;

	//申请同样大小的数据缓冲区
	record_data = (BYTE *)SysLmalloc( record_size );
	if( record_data == NULL )
//		return DB_ERROR;
		return DB_NO_MEM;
	*data = record_data;

	//读取指定记录的内容
	record_block_ad = id;
	while( record_size != 0 )
	{
		fseek( info->fp, record_block_ad, SEEK_SET );//定位到记录块的首部
		fread( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//读出下一个记录块的地址(NBO)
		if( record_size > BLOCK_DATA_SIZE )
		{
			fread( record_data, BLOCK_DATA_SIZE, 1, info->fp );//数据写入record_data中
			record_data += BLOCK_DATA_SIZE;
			record_size -= BLOCK_DATA_SIZE;
		}else{
			fread( record_data, record_size, 1, info->fp );//读入最后一块不完整的数据块
			record_data += record_size;
			record_size = 0;
		}
	}

//	return	(record_data);
	return	DB_OK;
}

//---------------------------------------------------------------
//    GlobalModifyRecord()
//
//		  Change the specified record for the specified contents in the specified database.
//
//    Parameters:
//        info          - the used information of the record block.
//        id			- the address of the modified record.
//		  data			- the specified contents
//
//    Returns:
//		  DB_ERROR		:	failure
//        id			:   the address of the modified record
//---------------------------------------------------------------
DWORD GlobalModifyRecord( DBPHYLAYERINFO *info, DWORD id, BYTE *data )
{
	WORD	used_block_flag = 0;
	WORD	record_size = 0, old_record_size = 0;
	WORD	old_block_num = 0, new_block_num = 0, record_block_num = 0;
	DWORD	free_block_num = 0;
	DWORD	record_block_ad = 0, free_block_ad, tmp_ad = 0, next_ad;
	WORD	temp;

	//验证指定数据库的有效性(数据库文件是否已打开)
	if( info == NULL )
		return DB_ERROR;
	//if( info->fp == NULL || info->fp->magic != FILE_MAGIC)
	if( info->fp == NULL )
		return DB_ERROR;

	//验证指定记录的有效性(记录块标识是否为'UB')
	fseek( info->fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM, SEEK_SET );
	fread( &used_block_flag, FLAG_BYTE_NUM, 1, info->fp );
	if( used_block_flag != USED_BLOCK_FLAG )
//		return DB_ERROR;
		return DB_FREE_RECORD;

	//验证新记录数据的有效性
	if( data == NULL )//(数据不为空)
		return DB_ERROR;
#ifdef	SIM_ON_PC					
	used_block_flag = (WORD)((*(data+SIZE_BYTE_NUM)) | ( *(data + SIZE_BYTE_NUM + 1) << 8 ));
#else
	Bytes2Word( &used_block_flag, data+SIZE_BYTE_NUM );
#endif
	if( used_block_flag != USED_BLOCK_FLAG )//记录块标识是否为'UB'
		return DB_ERROR;

	//确定新记录数据的大小
#ifdef	SIM_ON_PC					
	record_size = (WORD)( *(data) | *(data + 1) << 8 );
#else
	Bytes2Word( &record_size, data );
#endif

	//原纪录中可容纳数据的大小
	fseek( info->fp, id+ADDRESS_BYTE_NUM, SEEK_SET );
	fread( &old_record_size, SIZE_BYTE_NUM, 1, info->fp );
	old_block_num = (WORD)(( old_record_size + BLOCK_DATA_SIZE - 1 ) / BLOCK_DATA_SIZE);

	//新数据需要的记录块数目
	new_block_num = (WORD)(( record_size + BLOCK_DATA_SIZE - 1 ) / BLOCK_DATA_SIZE);

	//将记录数据写入到指定记录块中
	record_block_ad = id;

	if( new_block_num > old_block_num )
	{
		new_block_num = (WORD)( new_block_num - old_block_num );//新数据所需添加的record block数目

		//把新数据中old_block_num写入数据库
		WriteDataToFile( info, &record_block_ad, &old_block_num, &record_size, &data, &tmp_ad );

		//记录原记录的最后一记录块的首部
		fseek( info->fp, tmp_ad, SEEK_SET );

		//写长于old_block_num的数据
		if( info->info.freeBlockNum >= new_block_num )//空闲块足够,不用申请新的记录块
		{
			fwrite( &info->info.freeBlockHead, ADDRESS_BYTE_NUM, 1, info->fp );//把空闲块接在当前记录的链上
			free_block_ad = info->info.freeBlockHead;

			free_block_num = (DWORD)new_block_num;

			WriteDataToFile( info, &free_block_ad, &new_block_num, &record_size, &data, &tmp_ad );
			
			//修改最后一条记录的next
			fseek( info->fp, info->info.usedBlockTail+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到最后一条记录的next
			fwrite( &free_block_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next的链表
			fseek( info->fp, 0, SEEK_SET );	

			//更新记录块使用信息
			info->info.freeBlockHead = free_block_ad;//更新空闲块空闲记录块首地址
			info->info.freeBlockNum -= free_block_num;//更新空闲块数目
			info->info.usedBlockNum += free_block_num;//更新记录块数目

			//修改空闲块的头
			ModifyFirstFreeBlock( info, info->info.freeBlockHead );

		}else{//空闲块不够,要申请新的记录块
			record_block_num = new_block_num;//新增记录块的数目
			new_block_num = (WORD)(new_block_num - info->info.freeBlockNum);//需要申请的记录块

			if( info->info.freeBlockNum != 0 )//写空闲块
			{
				fwrite( &info->info.freeBlockHead, ADDRESS_BYTE_NUM, 1, info->fp );//把空闲块接在当前记录的链上
				free_block_ad = info->info.freeBlockHead;

				temp = (WORD)info->info.freeBlockNum;
//				WriteDataToFile( info, &free_block_ad, &((WORD)info->info.freeBlockNum), &record_size, &data, &tmp_ad );
				WriteDataToFile( info, &free_block_ad, &temp, &record_size, &data, &tmp_ad );
				info->info.freeBlockNum = (DWORD)temp;

				fseek( info->fp, tmp_ad, SEEK_SET );
			}

		//空闲记录块数不够,申请新的记录块

			//链接新申请的记录块到原记录或原空闲块上
			record_block_ad = HEAD_ADDRESS_BYTE_NUM + ( info->info.usedBlockNum + ( record_block_num - new_block_num ) ) * RECORD_BLOCK_SIZE;//将要申请的记录块的地址
			fwrite( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入下一个将要申请的记录块的地址

			//填入剩余数据
			while( new_block_num != 0) 
			{
				fseek( info->fp, record_block_ad, SEEK_SET );//定位到新申请的记录块的首部
				if( record_size > BLOCK_DATA_SIZE)
				{
					record_block_ad += RECORD_BLOCK_SIZE;
					fwrite( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入下一个将要申请的记录块的地址
					fwrite( data, BLOCK_DATA_SIZE, 1, info->fp );//写入BLOCK_DATA_SIZE长度的数据
					data += BLOCK_DATA_SIZE;
					record_size -= BLOCK_DATA_SIZE;
				}else{
					record_block_ad = 0;
					fwrite( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入下一个将要申请的记录块的地址
//					fwrite( data, record_size, 1, info->fp );//写入最后一块不完整的数据块
					fwrite( data, BLOCK_DATA_SIZE, 1, info->fp );//写入最后一块不完整的数据块
					record_size = 0;
				}
				new_block_num--;
			}
		
			//修改最后一条记录的next
			fseek( info->fp, info->info.usedBlockTail+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到最后一条记录的next
			next_ad = 0;
			fwrite( &next_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next的链表
			fseek( info->fp, 0, SEEK_SET );	

			//更新记录块使用信息
			info->info.freeBlockHead = 0;//更新空闲块空闲记录块首地址
			info->info.freeBlockNum = 0;//更新空闲块数目
			info->info.usedBlockNum += record_block_num;//更新记录块数目
		}
	}else{	//new_block_num <= old_block_num 

		old_block_num = (WORD)(old_block_num - new_block_num);//多余的记录块

		WriteDataToFile( info, &record_block_ad, &new_block_num, &record_size, &data, &tmp_ad );

		//更新记录块使用信息
		info->info.freeBlockNum += old_block_num;//更新空闲块数目
		info->info.usedBlockNum -= old_block_num;//更新记录块数目

		if( old_block_num != 0 )
		{
			//修改尾记录的next
			fseek( info->fp, info->info.usedBlockTail+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到最后一条记录的next
			fwrite( &record_block_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next的链表

			//修改空闲块的头
			ModifyFirstFreeBlock( info, record_block_ad );

			next_ad = record_block_ad;//暂存空闲块首地址
			
			//把释放的记录块接在空闲块的链表上
			while( old_block_num != 1 )
			{
				fseek( info->fp, record_block_ad, SEEK_SET );//定位到记录块的首部
				fread( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//读出下一个记录块的地址(NBO)
				old_block_num--;
			}
			fseek( info->fp, record_block_ad, SEEK_SET );//定位到最后一块释放的记录块首部
			fwrite( &info->info.freeBlockHead, ADDRESS_BYTE_NUM, 1, info->fp );//把释放的记录块接在空闲块的链表上
			fseek( info->fp, 0, SEEK_SET );	

			info->info.freeBlockHead = next_ad;//更新空闲块空闲记录块首地址
		}
	}

	//返回新记录的首地址
	return	(id);
//	return	DB_OK;
}

//---------------------------------------------------------------
//    GlobalInsertRecord()
//
//		  Insert the specified record after the specified position of the specified database.
//
//    Parameters:
//        info          - the used information of the record block.
//        id			- the address of the insert record.
//		  data			- the specified contents.
//
//    Returns:
//		  DB_ERROR		:	failure
//        id			:   the address of the insert record
//---------------------------------------------------------------
DWORD GlobalInsertRecord( DBPHYLAYERINFO *info, DWORD id, BYTE *data )
{
	WORD	used_block_flag = 0;
	WORD	record_size = 0;
	WORD	new_block_num = 0, record_block_num = 0;
	DWORD	free_block_num = 0;
	DWORD	record_block_ad, free_block_ad, next_ad, tmp_ad = 0, new_record_ad = 0;
	WORD	temp;
//	BYTE	*test_data;
//	BYTE	*data_tmp, *tmp_first_data;

	//验证指定数据库的有效性(数据库文件是否已打开)
	if( info == NULL )
		return DB_ERROR;
	//if( info->fp == NULL || info->fp->magic != FILE_MAGIC)
	if( info->fp == NULL )
		return DB_ERROR;

	//验证新记录数据的有效性
	if( data == NULL )//(数据不为空)
		return DB_ERROR;
#ifdef	SIM_ON_PC					
	used_block_flag = (WORD)((*(data+SIZE_BYTE_NUM)) | ( *(data + SIZE_BYTE_NUM + 1) << 8 ));
#else
	Bytes2Word( &used_block_flag, data+SIZE_BYTE_NUM );
#endif
	if( used_block_flag != USED_BLOCK_FLAG )//记录块标识是否为'UB'
//		return DB_ERROR;
		return DB_FREE_RECORD;

	//确定新记录数据的大小
#ifdef	SIM_ON_PC					

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -