📄 phydb.c
字号:
/*************************************************************************
*
* 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 + -