📄 celltable.c
字号:
* dms_CellWrite()
*/
WORD dms_CellTableDeleteCellInProcess(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
CELL_TABLE_ENTRY *pTmpEntry;
if (lpCellInProcess == NULL){
return 0;
}
pTmpEntry = lpCellInProcess;
lpCellInProcess = lpCellInProcess->pNext;
pTmpEntry->pNext = NULL;
*apwSectorIndex = pTmpEntry->wSectorIndex;
*apwSectorBlockIndex = pTmpEntry->wSectorBlockIndex;
dms_BlockFree(pTmpEntry);
return 1;
}
/**
* dms_CellTableDeleteBlockInProcess
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* dms_BlockFree()
* Used By:
* dms_CellInitialize()
*/
WORD dms_CellTableDeleteBlockInProcess(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
if (lpBlockInProcess == NULL){
return 0;
}
*apwSectorIndex = lpBlockInProcess->wSectorIndex;
*apwSectorBlockIndex = lpBlockInProcess->wSectorBlockIndex;
dms_BlockFree(lpBlockInProcess);
lpBlockInProcess = NULL;
return 1;
}
/**
* dms_CellTableResetBlockPointer
* Sets an internal pointer to the first block of the
* given cell in the cell table.
* This function allows dms_CellTableGetNextBlock to be
* called repeatly to get info about each block in the cell.
* One use for this function is to be called by a read operation.
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* Nothing outside this file.
* Used By:
* dms_CellWrite()
* dms_CellRead()
*/
void dms_CellTableResetBlockPointer(WORD awCellIndex){
lpCurrentBlockPointer = lpCellTable[awCellIndex];
}
/**
* dms_CellTableGetNextBlock
* Assigns apwSectorIndex and apwSectorBlockIndex to the values of the current
* block in the list then returns 1.
* Otherwise if the end of the list is reached then returns 0.
*
* Prerequisites:
* dms_CellTableInitialize()
* dms_CellTableCheckValidity()
* Uses:
* Nothing outside this file.
* Used By:
* dms_CellWrite()
* dms_CellRead()
*/
WORD dms_CellTableGetNextBlock(WORD *apwSectorIndex, WORD *apwSectorBlockIndex){
if (lpCurrentBlockPointer == NULL) {
return 0;
}
*apwSectorIndex = lpCurrentBlockPointer->wSectorIndex;
*apwSectorBlockIndex = lpCurrentBlockPointer->wSectorBlockIndex;
lpCurrentBlockPointer = lpCurrentBlockPointer->pNext;
return 1;
}
/**
* dms_lCellTableCheckCellInProcess
* Called after all Blocks are added to table.
* Checks the CellInProcess list and compares it with the cell in the cell table
* and determines which one needs deleted.
* Checks the BlockInProcess and compares it with the block in the cell table and
* determines which one needs deleted.
*/
void dms_lCellTableCheckCellInProcess(void){
DMS_STATUS eStatus1;
DMS_STATUS eStatus2;
CELL_TABLE_ENTRY *pTmpList1;
CELL_TABLE_ENTRY *pTmpList2;
CELL_TABLE_ENTRY *pTmpEntry;
WORD wBlockCount1 = 0;
WORD wBlockCount2 = 0;
if (lpBlockInProcess != NULL){
/*
* There is a block that was in process when a power failure occured.
* As of now the only time a block is in process is during a move
* of that block. In this case the blocks are identical so either
* one can be deleted.
* Leave the block in the BlockInProcess and it will be deleted later when
* dms_CellTableDeleteBlockInProcess() is called.
* the extra one.
*/
}
if (lpCellInProcess == NULL){
/*
* There was no cell in process.
* Then nothing else to check here.
*/
return;
}
/*
* Sort the lpBlockInProcess list and the lpCellTable[lwCellIndexOfCellInProcess]
* list so that one list has all CellValid1 and the other has CellValid2 because
* dms_CellTableAddBlock may mix them up.
*/
/* Move tables to a temp table. */
pTmpList1 = lpCellTable[lwCellIndexOfCellInProcess];
pTmpList2 = lpCellInProcess;
lpCellTable[lwCellIndexOfCellInProcess] = NULL;
lpCellInProcess = NULL;
/*
* Remove blocks from the temp lists and insert them into the apporiate list.
* Put CellValid2 blocks in the CellTable and CellValid1 blocks in the CellInProcess.
* At this point it does not matter which ones go where but the odds are that the
* CellValid1 blocks are incomplete. Later a complete check will be done to
* determine which cell is a keeper.
*/
while (pTmpList1 != NULL){
/* remove first entry from the temp list */
pTmpEntry = pTmpList1;
pTmpList1 = pTmpList1->pNext;
pTmpEntry->pNext = NULL;
if (pTmpEntry->bCellStatus == CellValid1) {
dms_lCellTableInsertBlock(&lpCellInProcess,pTmpEntry);
} else {
/* must be CellValid2 */
dms_lCellTableInsertBlock(&lpCellTable[lwCellIndexOfCellInProcess],pTmpEntry);
}
}
while (pTmpList2 != NULL){
/* remove first entry from the temp list */
pTmpEntry = pTmpList2;
pTmpList2 = pTmpList2->pNext;
pTmpEntry->pNext = NULL;
if (pTmpEntry->bCellStatus == CellValid1) {
dms_lCellTableInsertBlock(&lpCellInProcess,pTmpEntry);
} else {
/* must be CellValid2 */
dms_lCellTableInsertBlock(&lpCellTable[lwCellIndexOfCellInProcess],pTmpEntry);
}
}
/* Count the blocks and check for missing blocks */
eStatus1 = dms_lCellTableCountAndCheckBlocks(lpCellInProcess, &wBlockCount1);
eStatus2 = dms_lCellTableCountAndCheckBlocks(lpCellTable[lwCellIndexOfCellInProcess], &wBlockCount2);
/* Determine which version of the cell to keep */
if ( eStatus1 == No_Error && eStatus2 != No_Error
|| eStatus1 == No_Error && wBlockCount1 > wBlockCount2
|| eStatus1 == No_Error && eStatus2 == No_Error && wBlockCount1 == wBlockCount2
&& lpCellInProcess->bCellStatus == CellValid2){ /* Note lpCellInProcess was already checked to be NULL */
/*
* Keep the cell in process
* Swap lpCellInProcess and lpCellTable[lwCellIndexOfCellInProcess]
* Leave the unwanted cell in the CellInProcess and it will be deleted later when
* dms_CellTableDeleteCellInProcess() is called.
*/
pTmpList1 = lpCellTable[lwCellIndexOfCellInProcess];
lpCellTable[lwCellIndexOfCellInProcess] = lpCellInProcess;
lpCellInProcess = pTmpList1;
} else {
/*
* Delete cell in process.
* Keep the lists the way they are.
* Leave the unwanted cell in the CellInProcess and it will be deleted later when
* dms_CellTableDeleteCellInProcess() is called.
* Note: If CellTable cell is also not valid go ahead and set
* CellInProcess to be erased and let the bad cell
* be caught later by dms_CellTableCheckValidity.
*/
}
return;
}
/**
* dms_lCellTableCreateNewEntry
*/
CELL_TABLE_ENTRY *dms_lCellTableCreateNewEntry(WORD awBlockIndex,
BYTE abCellStatus,
WORD awSectorIndex,
WORD awSectorBlockIndex){
CELL_TABLE_ENTRY *pTmpEntry;
pTmpEntry = (CELL_TABLE_ENTRY*) malloc(sizeof(CELL_TABLE_ENTRY));
if (pTmpEntry != NULL){
pTmpEntry->bCellStatus = abCellStatus;
pTmpEntry->wBlockIndex = awBlockIndex;
pTmpEntry->wSectorIndex = awSectorIndex;
pTmpEntry->wSectorBlockIndex = awSectorBlockIndex;
pTmpEntry->pNext = NULL;
}
return pTmpEntry;
}
/**
* dms_lCellTableRemoveBlock
* Local Function.
* Traverses through the list and removes the entry whose wBlockIndex matches the
* provided awBlockIndex and returns a pointer to the removed entry.
* Returns NULL is entry is not found.
*/
CELL_TABLE_ENTRY *dms_lCellTableRemoveBlock(CELL_TABLE_ENTRY **appCell, WORD awBlockIndex){
CELL_TABLE_ENTRY *pReturnEntry;
while (*appCell != NULL){
if ((*appCell)->wBlockIndex == awBlockIndex){
pReturnEntry = (*appCell);
(*appCell) = (*appCell)->pNext;
pReturnEntry->pNext = NULL;
return pReturnEntry;
}
appCell = &((*appCell)->pNext);
}
return NULL;
}
/**
* dms_lCellTableRemoveExactBlock
* Local Function.
* Traverses through the list and removes the entry whose SectorIndex
* and SectorBlockIndex matches the provided and returns a pointer
* to the removed entry.
* Returns NULL is entry is not found.
*/
CELL_TABLE_ENTRY *dms_lCellTableRemoveExactBlock(CELL_TABLE_ENTRY **appCell,
WORD awSectorIndex,
WORD awSectorBlockIndex){
CELL_TABLE_ENTRY *pReturnEntry;
while (*appCell != NULL){
if ((*appCell)->wSectorIndex == awSectorIndex && (*appCell)->wSectorBlockIndex == awSectorBlockIndex){
pReturnEntry = (*appCell);
(*appCell) = (*appCell)->pNext;
pReturnEntry->pNext = NULL;
return pReturnEntry;
}
appCell = &((*appCell)->pNext);
}
return NULL;
}
/**
* dms_lCellTableInsertBlock
* Local Function.
* Traverses through the list and inserts entry in order of assending block index.
* Does not allow duplicate blocks.
* Returns Duplicate_Block if aNewEntry is a duplicate.
* Note: If function fails then remember to free pNewEntry.
* Note: Used by dms_CellTableAddBlock() and assumes returns Duplicate_Block,
* Exact_Duplicate_Block, or No_Error only.
*/
DMS_STATUS dms_lCellTableInsertBlock(CELL_TABLE_ENTRY **appCell,CELL_TABLE_ENTRY *pNewEntry){
while (*appCell != NULL && (*appCell)->wBlockIndex < pNewEntry->wBlockIndex){
appCell = &((*appCell)->pNext);
}
if (*appCell != NULL && (*appCell)->wBlockIndex == pNewEntry->wBlockIndex){
if ((*appCell)->bCellStatus == pNewEntry->bCellStatus){
return Exact_Duplicate_Block;
} else {
return Duplicate_Block;
}
}
pNewEntry->pNext = (*appCell);
(*appCell) = pNewEntry;
return No_Error;
}
/**
* dms_lCellTableCountAndCheckBlocks
* Local Function.
* Traverses through the list, counts the blocks, and makes sure that none are missing.
* Note: Because the cell size is determined by the blocks found if the last block is
* missing there is no way to detect it.
*/
DMS_STATUS dms_lCellTableCountAndCheckBlocks(CELL_TABLE_ENTRY *apCellTable, WORD *apwBlockCount){
*apwBlockCount = 0;
while (apCellTable != NULL){
if (apCellTable->wBlockIndex != *apwBlockCount) {
return Missing_Block_In_Cell;
}
(*apwBlockCount)++;
apCellTable = apCellTable->pNext;
}
return No_Error;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -