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