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

📄 phydb.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
📖 第 1 页 / 共 2 页
字号:
	record_size = (WORD)(*(data) | *(data + 1) << 8);
#else
	Bytes2Word( &record_size, data );
#endif

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

	if( info->info.freeBlockNum >= new_block_num )//空闲块足够,不用申请新的记录块
	{
		free_block_ad = info->info.freeBlockHead;
		record_block_num = new_block_num;

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

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

		//修改当前建立记录的next和prev
		fseek( info->fp, info->info.freeBlockHead+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到新建记录的数据区
		fwrite( &free_block_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next
		fwrite( &info->info.usedBlockTail, PREV_BYTE_NUM, 1, info->fp );//建立prev
		fseek( info->fp, 0, SEEK_SET );	

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

		if( info->info.freeBlockHead != 0 )	//有空闲块
		{
			//链接空闲块到记录链表上
			ModifyFirstFreeBlock( info, info->info.freeBlockHead );
		}

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

		if( free_block_num != 0 )
		{
			free_block_ad = info->info.freeBlockHead;
			new_block_num = (WORD)(new_block_num - free_block_num);

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

/*			//修改当前建立记录的next和prev
			data += (SIZE_BYTE_NUM+FLAG_BYTE_NUM);
			next_ad = 0;
			memcpy( data, &next_ad, NEXT_BYTE_NUM);
			data += NEXT_BYTE_NUM;
			memcpy( data, &info->info.usedBlockTail, PREV_BYTE_NUM);
			data += PREV_BYTE_NUM;
			data -= (SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM+PREV_BYTE_NUM);
*/
			temp = (WORD)free_block_num;
//			WriteDataToFile( info, &free_block_ad, &((WORD)free_block_num), &record_size, &(data), &tmp_ad );
			WriteDataToFile( info, &free_block_ad, &temp, &record_size, &(data), &tmp_ad );
			free_block_num = (DWORD)temp;

			//修改当前建立记录的next和prev
			fseek( info->fp, info->info.freeBlockHead+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到新建记录的数据区
			next_ad = 0;
			fwrite( &next_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next
			fwrite( &info->info.usedBlockTail, PREV_BYTE_NUM, 1, info->fp );//建立prev
			fseek( info->fp, 0, SEEK_SET );	

			//更新记录块使用信息
			info->info.usedBlockTail = info->info.freeBlockHead;//更新尾记录首地址
		}

		//空闲记录块数不够,申请新的记录块
		if( info->info.freeBlockNum == 0 )
		{
			if( info->info.usedBlockNum == 0 )  //新建数据库的第一个记录
			{
				info->info.usedBlockTail = info->info.usedBlockHead = 0x00000004;//文件的头4个字节存首地址;第一次创建数据库时,第一条记录的地址
				fseek( info->fp, 0, SEEK_SET );
				fwrite( &info->info.usedBlockHead, HEAD_ADDRESS_BYTE_NUM, 1, info->fp );//写入有效记录块的首地址
				record_block_ad = info->info.usedBlockHead;
			}else{//新建记录
				record_block_ad = HEAD_ADDRESS_BYTE_NUM + info->info.usedBlockNum * RECORD_BLOCK_SIZE;//将要申请的记录块的地址
				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
			}
			new_record_ad = record_block_ad;
/*			
			//修改数据库新建记录的next和prev(所有记录块都是新申请的)
			data += (SIZE_BYTE_NUM+FLAG_BYTE_NUM);
			next_ad = 0;
			memcpy( data, &next_ad, NEXT_BYTE_NUM);
			data += NEXT_BYTE_NUM;
			memcpy( data, &info->info.usedBlockTail, PREV_BYTE_NUM);
			data += PREV_BYTE_NUM;
			data -= (SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM+PREV_BYTE_NUM);

			info->info.usedBlockTail = record_block_ad;
*/

		}else{//链接新申请的记录块到原空闲块上
			record_block_ad = HEAD_ADDRESS_BYTE_NUM + ( info->info.usedBlockNum + info->info.freeBlockNum ) * RECORD_BLOCK_SIZE;//将要申请的记录块地址
			fseek( info->fp, tmp_ad, SEEK_SET );//定位到最后一个空闲块的首部
			fwrite( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入下一个将要申请的记录块的地址
		}

		//填入剩余数据
		while( new_block_num != 0) 
		{
			fseek( info->fp, record_block_ad, SEEK_SET );//定位到新申请的记录块的首部
//			fwrite( &record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入下一个将要申请的记录块的地址
			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 );//写入最后一块不完整的数据块
				data += record_size;
				record_size = 0;
			}
			new_block_num--;
		}
	
		//修改数据库新建记录的next和prev(所有记录块都是新申请的)
		if( info->info.freeBlockNum == 0 ) 
		{
			fseek( info->fp, new_record_ad+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到新建记录的数据区
			next_ad = 0;
			fwrite( &next_ad, NEXT_BYTE_NUM, 1, info->fp );//建立next
			fwrite( &info->info.usedBlockTail, PREV_BYTE_NUM, 1, info->fp );//建立prev
			info->info.usedBlockTail = new_record_ad;
		}
		fseek( info->fp, 0, SEEK_SET );	
		
		//更新记录块使用信息
		info->info.freeBlockHead = 0;//更新空闲块首地址
		info->info.usedBlockNum += record_block_num;//更新有效记录块数目
		info->info.freeBlockNum = 0;//更新空闲块数目

	}

	id = info->info.usedBlockTail;

	return	(id);
//	return	DB_OK;
}

//---------------------------------------------------------------
//    GlobalDelRecord()
//
//		  Delete the specified record from the specified database.
//
//    Parameters:
//        info          - the used information of the record block.
//        id			- the address of the deleted record.
//
//    Returns:
//		  DB_ERROR		:	failure
//        id			:   the address of the deleted record
//---------------------------------------------------------------
DWORD GlobalDelRecord( DBPHYLAYERINFO *info, DWORD id )
{
	WORD	used_block_flag = 0;
	WORD	record_size = 0;
	DWORD	block_num = 0;
	DWORD	del_record_ad;
	DWORD	next_record_ad, prev_record_ad;

	//验证指定数据库的有效性(数据库文件是否已打开)
	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 );

	//删除记录的记录块数目
	block_num = ( record_size + BLOCK_DATA_SIZE - 1 ) / BLOCK_DATA_SIZE;

	//获取要删除记录的下一条(next)记录的地址
	fseek( info->fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );
	fread( &next_record_ad, NEXT_BYTE_NUM, 1, info->fp );

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

	del_record_ad = id;

	//判断指定记录是否是首记录
	if( id == info->info.usedBlockHead )//删除的是首记录,更新首记录地址为下一条记录
	{
//		if( ( next_record_ad != 0 ) && ( info->info.usedBlockNum != 0 ) )//数据库中不止一个记录或有空闲块
		if( info->info.usedBlockHead != info->info.usedBlockTail )//数据库中不止一个记录或有空闲块
		{
			info->info.usedBlockHead = next_record_ad;//更新有效记录块首地址
			fseek( info->fp, 0, SEEK_SET );//定位到文件头
			fwrite( &info->info.usedBlockHead, HEAD_ADDRESS_BYTE_NUM, 1, info->fp );//写入新的效记录块首地址
			fseek( info->fp, info->info.usedBlockHead+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM, SEEK_SET );//定位到首记录的prev
			fwrite( &info->info.usedBlockHead, PREV_BYTE_NUM, 1, info->fp );//首记录的prev填记录的首地址
		}else{//数据库中只有一个记录
			info->info.usedBlockTail = 0;
		}
	}else{
		//获取要删除记录的上一条(prev)记录的地址
		fseek( info->fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM, SEEK_SET );
		fread( &prev_record_ad, PREV_BYTE_NUM, 1, info->fp );

		//写入要删除记录的上一条记录地址(断开next的链表)
		fseek( info->fp, prev_record_ad+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );
		fwrite( &next_record_ad, NEXT_BYTE_NUM, 1, info->fp );

		if( del_record_ad != info->info.usedBlockTail )//删除的不是尾记录
//		if( next_record_ad != 0 )//有空闲块
		{
			//写入要删除记录的下一条记录地址(断开prev的链表)
			fseek( info->fp, next_record_ad+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM, SEEK_SET );//要删除的记录的下一条记录的首部
			fwrite( &prev_record_ad, PREV_BYTE_NUM, 1, info->fp );
		}else{//删除的是尾记录
			info->info.usedBlockTail = prev_record_ad;//删除的是尾记录,更新尾记录信息
		}
	}

	//修改尾记录的next
	fseek( info->fp, info->info.usedBlockTail+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );//定位到尾记录首部
	fwrite( &del_record_ad, NEXT_BYTE_NUM, 1, info->fp );
	fseek( info->fp, 0, SEEK_SET );	

	//修改空闲块的头
	ModifyFirstFreeBlock( info, del_record_ad );
	
	//把释放的记录块接在空闲块的链表上
	while( block_num != 1 )
	{
		fseek( info->fp, del_record_ad, SEEK_SET );//定位到记录块的首部
		fread( &del_record_ad, ADDRESS_BYTE_NUM, 1, info->fp );//读出下一个记录块的地址(NBO)
		block_num--;
	}

	fseek( info->fp, del_record_ad, SEEK_SET );//定位到最后一块释放的记录块首部
	fwrite( &info->info.freeBlockHead, ADDRESS_BYTE_NUM, 1, info->fp );//把释放的记录块接在空闲块的链表上
	fseek( info->fp, 0, SEEK_SET );	

	//更新记录块使用信息
	info->info.freeBlockHead = id;//更新空闲记录块首地址

	//返回被删除记录的地址
	return (id);
//	return	DB_OK;
}

//---------------------------------------------------------------
//    ModifyFirstFreeBlock()
//
//		  Modify the infomation of the first free block.
//
//    Parameters:
//        info					- the used information of the record block.
//        first_free_block_ad	- the address of the first free block.
//
//    Returns:
//		  void
//---------------------------------------------------------------
void ModifyFirstFreeBlock( DBPHYLAYERINFO *info, DWORD first_free_block_ad )
{
	DWORD	free_block_size = 0;
	WORD	free_block_flag = 0;
	DWORD	next_ad;

	fseek( info->fp, first_free_block_ad+ADDRESS_BYTE_NUM, SEEK_SET );//定位到要释放的记录块的数据区
	//填充首块空闲块的头信息
	free_block_size = info->info.freeBlockNum * BLOCK_DATA_SIZE;
	fwrite( &free_block_size, SIZE_BYTE_NUM, 1, info->fp );
	free_block_flag = FREE_BLOCK_FLAG;
	fwrite( &free_block_flag, FLAG_BYTE_NUM, 1, info->fp );
	next_ad = 0;
	fwrite( &next_ad, NEXT_BYTE_NUM, 1, info->fp );
	fwrite( &info->info.usedBlockTail, PREV_BYTE_NUM, 1, info->fp );
	fseek( info->fp, 0, SEEK_SET );	
}

//---------------------------------------------------------------
//    WriteDataToFile()
//
//		  Write new data to the file .
//
//    Parameters:
//        info				- the used information of the record block.
//        record_block_ad	- the address of the first record block.
//		  block_num			- the number of the record block.
//		  record_size		- the size of the record.
//		  data				- the specified contents.
//		  tmp_ad			- the temp address.
//
//    Returns:
//		  void
//---------------------------------------------------------------
//void WriteDataToFile(  DBPHYLAYERINFO *info, DWORD *record_block_ad, WORD *block_num, WORD *record_size, DWORD *data, DWORD *tmp_ad )
void WriteDataToFile(  DBPHYLAYERINFO *info, DWORD *record_block_ad, WORD *block_num, WORD *record_size, BYTE **data, DWORD *tmp_ad )
{
	BYTE	*tmp_data;
	DWORD	last_block_ad;
	
	tmp_data = *data;

	while( (*block_num) != 0 )
	{
		fseek( info->fp, *record_block_ad, SEEK_SET );//定位到空闲块的首部
		*tmp_ad = *record_block_ad;
		fread( record_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//读出下一个空闲块的地址
		if( *record_size > BLOCK_DATA_SIZE )
		{
			fseek( info->fp, *tmp_ad+ADDRESS_BYTE_NUM, SEEK_SET );//定位到记录块的数据区
			fwrite( tmp_data, BLOCK_DATA_SIZE, 1, info->fp );//写入修改后BLOCK_DATA_SIZE长度的数据
			tmp_data += BLOCK_DATA_SIZE;
			*record_size -= BLOCK_DATA_SIZE;
		}else{
			last_block_ad = 0;
			fseek( info->fp, *tmp_ad, SEEK_SET );//定位到记录块的首部
			fwrite( &last_block_ad, ADDRESS_BYTE_NUM, 1, info->fp );//写入最后一块数据区的地址
				
			fwrite( tmp_data, BLOCK_DATA_SIZE, 1, info->fp );//写入最后一块不完整的数据块
//			fwrite( tmp_data, *record_size, 1, info->fp );//写入最后一块不完整的数据块
			tmp_data += *record_size;
			*record_size = 0;
		}
		(*block_num)--;
	}
	*data = tmp_data;
}

⌨️ 快捷键说明

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