📄 appdb.c
字号:
BYTE* LocalReadRecord( DBLACB *lacb, DWORD id )
{
BYTE *record;
//验证指定数据库连接的有效性
if( lacb == NULL )
return NULL;
if( lacb->gacb->symbol != DB_SYMBOL )
return NULL;
dbdbgprintf( "### Read Record ###" );
record = lacb->gacb->funcs->localReadRecord( lacb, id);
dbdbgprintf( "### Read Record OK ###" );
return record;//返回读取的记录内容
}
/****************************************************************/
// 功能:修改指定数据库指定记录的内容
DWORD LocalModifyRecord( DBLACB *lacb, DWORD id, BYTE *data, WORD dataLen )
{
//验证指定数据库连接的有效性
if( lacb == NULL )
return DB_ERROR;
if( lacb->gacb->symbol != DB_SYMBOL )
return DB_ERROR;
//验证新记录数据的有效性
if( data == NULL )//(数据不为空)
return DB_ERROR;
dbdbgprintf( "### Modify Record ###" );
id = lacb->gacb->funcs->localModifyRecord( lacb, id, data, dataLen );//修改指定记录
dbdbgprintf( "### Modify Record OK ###" );
return id;
}
/****************************************************************/
// 功能:将指定记录添加到指定数据库中
DWORD LocalAddRecord( DBLACB *lacb, BYTE *data, WORD dataLen )
{
DWORD id;
//验证指定数据库连接的有效性
if( lacb == NULL )
return DB_ERROR;
if( lacb->gacb->symbol != DB_SYMBOL )
return DB_ERROR;
//验证新记录数据的有效性
if( data == NULL )//(数据不为空)
return DB_ERROR;
dbdbgprintf( "### Add Record ###" );
id = lacb->gacb->funcs->localAddRecord( lacb, data, dataLen );//修改指定记录
dbdbgprintf( "### Add Record OK ###" );
return id;
}
/****************************************************************/
// 功能:删除指定数据库的指定记录
DWORD LocalDelRecord( DBLACB *lacb, DWORD id )
{
//验证指定数据库连接的有效性
if( lacb == NULL )
return DB_ERROR;
if( lacb->gacb->symbol != DB_SYMBOL )
return DB_ERROR;
dbdbgprintf( "### Delete Record ###" );
id = lacb->gacb->funcs->localDelRecord( lacb, id );//修改指定记录
dbdbgprintf( "### Delete Record OK ###" );
return id;
}
/****************************************************************/
// 功能:在指定数据库中查找与指定字段匹配(完全匹配/部分匹配)的记录(精确查找)
LOCALSEARCHLIST* LocalFindRecord( DBLACB *lacb, BYTE field, BYTE *data, BYTE mode )
{
LOCALSEARCHLIST *recordindex;
//验证指定数据库连接的有效性
if( lacb == NULL )
return NULL;
if( lacb->gacb->symbol != DB_SYMBOL )
return NULL;
dbdbgprintf( "### Find Record ###" );
recordindex = lacb->gacb->funcs->localFindRecord( lacb, field, data, mode );
dbdbgprintf( "### Find Record OK ###" );
return recordindex;
}
/****************************************************************/
// 功能:在指定数据库中查找与指定字段索引匹配(完全匹配/部分匹配)的记录(模糊查找)
//LOCALSEARCHLIST* LocalSearchRecord( DBLACB *lacb, BYTE field, BYTE *data, BYTE mode )
// 功能:对某目录下的目录和文件进行某字段的排序(此函数现只支持“记事本”数据库)
LOCALSEARCHLIST* LocalSortRecord( DBLACB *lacb, BYTE field, BYTE *data, BYTE reserved )
{
LOCALSEARCHLIST *recordindex;
//验证指定数据库连接的有效性
if( lacb == NULL )
return NULL;
if( lacb->gacb->symbol != DB_SYMBOL )
return NULL;
dbdbgprintf( "### Sort Record ###" );
recordindex = lacb->gacb->funcs->localSortRecord( lacb, field, data, reserved );
dbdbgprintf( "### Sort Record OK ###" );
return recordindex;
}
/****************************************************************/
// 功能:对指定列表进行排序
LOCALSEARCHLIST* LocalSortList( DBLACB *lacb, LOCALSEARCHLIST *searchlist, BYTE field, BYTE reserved )
{
LOCALSEARCHLIST *recordindex;
//验证指定数据库连接的有效性
if( lacb == NULL )
return NULL;
if( lacb->gacb->symbol != DB_SYMBOL )
return NULL;
//验证指定数据库连接的有效性
if( searchlist == NULL )
return NULL;
dbdbgprintf( "### Sort Record List ###" );
recordindex = lacb->gacb->funcs->localSortList( lacb, searchlist, field, reserved );
dbdbgprintf( "### Sort Record List OK ###" );
return recordindex;
}
/****************************************************************/
// 功能:立即保存DB到Flash中
DWORD SaveDB( DBLACB *lacb )
{
//验证指定数据库连接的有效性
if( lacb == NULL )
return DB_ERROR;
if( lacb->gacb->symbol != DB_SYMBOL )
return DB_ERROR;
#ifndef SIM_ON_PC
fclosenow( lacb->gacb->PLInfo->fp );
{
BYTE id;
id = (BYTE)( lacb->gacb - GAcb );
lacb->gacb->PLInfo->fp = fopen( DBDescript[id].path, "rb+" );
}
#endif
return DB_OK;
}
/****************************************************************/
// 功能:释放旧的查找表
void DelOldSearchList( LOCALSEARCHLIST *searchlist )
{
RECORDDATA *next_record_data, *prev_record_data;
dbdbgprintf( "### Delete Search Result ###" );
if( searchlist != NULL )
{
next_record_data = searchlist->head;
while( ( next_record_data != NULL ) && ( searchlist->num != 0 ) )
{
prev_record_data = next_record_data;
next_record_data++;
if( prev_record_data->data != NULL )
SysLfree( prev_record_data->data );
searchlist->num--;
}
SysLfree( searchlist->head );
searchlist->head = NULL;
searchlist->num = 0;
SysLfree( searchlist );
}
dbdbgprintf( "### Delete Search Result OK ###" );
}
/****************************************************************/
//检测数据库文件是否正确
DWORD CheckBaseDate( DBGACB *gacb )
{
DWORD id = gacb->PLInfo->info.usedBlockHead, head = 0;
WORD i, count = 0;
CHECKDBINDEX *checkdbindex = NULL, *temp_checkdbindex, *pre_checkdbindex = NULL;
FILE *fp = gacb->PLInfo->fp;
if( gacb->symbol != DB_SYMBOL )
return DB_FILE_ERROR;
//检查头信息的正确性,头信息的地址应为4的整数倍
if( id % 4 != 0 ) //不为4的整数倍,使数据库清空
{
head = 0;
fwrite( &head, 4, 1, fp );// 在数据库文件中只有有效记录块的首地址(UBH)一项,其初始值为0
return DB_FILE_ERROR;
}
gacb->PLInfo->info.usedBlockTail = 0;
if( id != 0 ) // 判断记录是否为空
{
// 记录不为空
DBRECORDHEAD *head_info = NULL;
BYTE *record = NULL, *data;
#ifdef SIM_ON_PC
WORD *field;
#else
WORD field;
#endif
WORD record_size = 0;
DWORD rv = DB_OK;
FIELDINDEXLIST *field_index_list;
DWORD file_len;
file_len = (DWORD)GetFileLength( fp );
// 逐条读取记录,建立字段索引表和记录字段表
do
{
rv = GlobalReadRecord( gacb->PLInfo, id, &record );
if( rv == DB_FREE_RECORD ) //空闲记录
record = NULL;
if( ( rv == DB_NO_MEM ) || ( rv == DB_ERROR ) )
return DB_ERROR;
if( record == NULL )//空闲记录块
{
if( ( head_info = (DBRECORDHEAD *)SysLmalloc(sizeof(DBRECORDHEAD)) ) == NULL )
return DB_ERROR;
//检查空闲记录的size,空闲块长度要小于文件长度
// fseek( fp, id+ADDRESS_BYTE_NUM, SEEK_SET );
// fread( &head_info->size, SIZE_BYTE_NUM, 1, fp );
if( record_size > file_len ) //空闲块长度大于文件长度
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查空闲记录的symbol,空闲标志为FREE_BLOCK_FLAG
fseek( fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM, SEEK_SET );
fread( &head_info->symbol, FLAG_BYTE_NUM, 1, fp );
if( head_info->symbol != FREE_BLOCK_FLAG ) //空闲标志不为FREE_BLOCK_FLAG
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查空闲记录的next,空闲记录的next要小于文件长度和为0
fseek( fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM, SEEK_SET );
fread( &head_info->next, NEXT_BYTE_NUM, 1, fp );
if( head_info->next > file_len || head_info->next != 0 ) //空闲记录的next大于文件长度,和不为0
// if( head_info->next != 0 ) //空闲记录的next不为0
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查空闲记录的prev,空闲记录的prev要小于文件长度
fseek( fp, id+ADDRESS_BYTE_NUM+SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM, SEEK_SET );
fread( &head_info->prev, PREV_BYTE_NUM, 1, fp );
// if( gacb->PLInfo->info.usedBlockTail != head_info->prev ) //前一个记录与空闲记录记录不相符
if( ( gacb->PLInfo->info.usedBlockTail != head_info->prev ) || ( ( head_info->prev) % 4 != 0 ) ) //前一个记录与当前记录不相符
{
SysLfree(head_info);
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
}else{
SysLfree(head_info);
goto endrv;
}
}else{ //有效记录块
if( count == 0 )
{
gacb->PLInfo->info.usedBlockTail = id;
}
head_info = (DBRECORDHEAD *)record;
//检查当前记录的size,记录长度要小于文件长度
if( head_info->size > file_len )//记录长度大于文件长度
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查记录的symbol,空闲标志为USED_BLOCK_FLAG
if( head_info->symbol != USED_BLOCK_FLAG ) //空闲标志不为USED_BLOCK_FLAG
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查当前记录的next,记录的next要小于文件长度和不为0
if( ( head_info->next > file_len ) || ( head_info->next )% 4 != 0 ) //记录的next大于文件长度,和不为0
// if( ( head_info->next == 0 ) && ( gacb->PLInfo->info.freeBlockNum != 0 ) )
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
//检查当前记录的prev,记录的prev要小于文件长度, 前一个记录与当前记录不相符
if( ( head_info->prev > file_len ) || ( gacb->PLInfo->info.usedBlockTail != head_info->prev ) || ( ( head_info->prev) % 4 != 0 )) //前一个记录与当前记录不相符
// if( ( gacb->PLInfo->info.usedBlockTail != head_info->prev ) || ( ( head_info->prev) % 4 != 0 ) ) //前一个记录与当前记录不相符
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
data = (BYTE *)(&head_info->data);
#ifdef SIM_ON_PC
field = (WORD *)data;
#endif
//检查记录中字段值的偏移,偏移必须小于( record_size - (SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM+PREV_BYTE_NUM) ))
field_index_list = gacb->FList;
// for( i = 0; i < gacb->IFNum; i++ )
for( i = 0; i < gacb->fieldNum; i++ )
{
#ifdef SIM_ON_PC
if( field[i] != 0 ) // 字段有字段值
#else
Bytes2Word( &field, data+i*sizeof(WORD) );
if( field != 0 ) // 字段有字段值
#endif
{
#ifdef SIM_ON_PC
WORD next_field_value = field[i], prev_field_value;
#else
WORD next_field_value = field, prev_field_value, temp;
#endif
while( next_field_value != 0 )
{
prev_field_value = next_field_value;
// 根据字段类型取出字段值
switch( field_index_list->type )
{
case MULTI_VALUE_FIELD: // 多值字段,带字段值索引
#ifdef SIM_ON_PC
next_field_value = *(WORD *)( data + next_field_value );
#else
temp = next_field_value;
Bytes2Word( &next_field_value, data + next_field_value );
#endif
break;
case SINGLE_VALUE_FIELD: // 单值字段,不带字段值索引
next_field_value = 0;
break;
}
if( ( next_field_value > ( record_size - (SIZE_BYTE_NUM+FLAG_BYTE_NUM+NEXT_BYTE_NUM+PREV_BYTE_NUM) ) )
|| ( prev_field_value > next_field_value ) )
{
return RewriteDBFile( count, gacb->PLInfo, checkdbindex );
}
}
}
field_index_list++;
}
if( count != 0 )
{
gacb->PLInfo->info.usedBlockTail = id;
}
id = head_info->next;
}
//把记录暂存入缓冲区
if( ( temp_checkdbindex = (CHECKDBINDEX *)SysLmalloc( sizeof(CHECKDBINDEX) ) ) == NULL )
return DB_ERROR;
temp_checkdbindex->record = record;
temp_checkdbindex->next = NULL;
if( count == 0 )
{
checkdbindex = temp_checkdbindex;
pre_checkdbindex = checkdbindex;
}else{
pre_checkdbindex->next = temp_checkdbindex;
pre_checkdbindex = temp_checkdbindex;
}
count++;
}while( id != 0 );
}
endrv:
temp_checkdbindex = checkdbindex;
while( temp_checkdbindex != NULL )
{
pre_checkdbindex = temp_checkdbindex;
temp_checkdbindex = pre_checkdbindex->next;
SysLfree( pre_checkdbindex );
}
SysLfree( gacb->PLInfo );
return DB_OK;
}
/****************************************************************/
//数据库出错,更新数据库数据
DWORD RewriteDBFile( WORD count, DBPHYLAYERINFO *info, CHECKDBINDEX *checkdbindex )
{
CHECKDBINDEX *next_checkdbindex, *pre_checkdbindex;
WORD i;
DWORD head, id = 0;
if( count == 0 )
{
head = 0;
fwrite( &head, 4, 1, info->fp );// 在数据库文件中只有有效记录块的首地址(UBH)一项,其初始值为0
}else{
next_checkdbindex = checkdbindex;
for( i = 0; i < count; i++ )
{
id = GlobalInsertRecord( info, id, next_checkdbindex->record );//添加新记录到数据库
if( ( id == DB_ERROR ) || ( id == DB_FREE_RECORD ) )
return DB_ERROR;
pre_checkdbindex = next_checkdbindex;
next_checkdbindex = next_checkdbindex->next;
SysLfree( pre_checkdbindex );
}
}
SysLfree( info );
return DB_FILE_ERROR;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -