📄 repll.c
字号:
B_COPYSTRINGN(pbRootBlk+5+(iCount*4),&(pTemp->iContentId),4);
if (!fFound)
{
iNbrCh++;
}
}
else if (pTemp->iAction==CHANNEL_REMOVE)
{
iCount=0;
/* Remove channel id from root block (replace with 0) */
while (iCount<iNbrCh)
{
/* Get id */
B_COPYSTRINGN(&iTempId,pbRootBlk+5+(iCount*4),4);
if (iTempId==pTemp->iContentId)
{
/* Found - remove */
B_COPYSTRINGN(pbRootBlk+5+(iCount*4),&iZero,4);
iNbrCh--;
/* Exit loop */
iCount=iNbrCh;
}
iCount++;
}
}
pTemp=pTemp->pNext;
}
/* Store nbr of channels */
B_COPYSTRINGN(pbRootBlk+1,&iNbrCh,2);
}
/*========================================================================
REP_UpdateRootBlockResources
==========================================================================
The function updates the resources in the root block according to the
tMODIFYROOT-elements in the context. The input data (pbRootBlk)
contains the old root block, but is large enough to include all
changes.
The resources are stored in the root block on the resource location
based on the OLD number of channels.
The iResourceDiff is needed to keep track of where the hash values
are stored in the root block with space added for all changes in the
resources. The function starts by moving the Hash values iResourceDiff*4
BYTES to the end of the root block.
The function is called by REP_UpdateRootBlock
Input: pContext (MUST be pREPCONTEXT), new root block, and ResourceDiff
Output: -
========================================================================*/
void REP_UpdateRootBlockResources (void* pContext, BYTE* pbRootBlk,
UINT32 iResourceDiff)
{
UINT16 iNbrRes=0;
UINT16 iNbrCh=0;
UINT32 iCount=0;
UINT32 iTempId=0;
UINT32 iZero=0;
UINT32 iHashOffset=0;
BOOL fFound=FALSE;
pMODIFYROOT pTemp=NULL;
pTemp=((REPCONTEXT*)pContext)->pModRoot;
B_COPYSTRINGN(&iNbrCh,pbRootBlk+1,2);
B_COPYSTRINGN(&iNbrRes,pbRootBlk+3,2);
/* Hash offset - the hash values start position in the root block
with space added for all resource changes */
iHashOffset=5+(4*iNbrCh)+(4*iNbrRes)+(4*iResourceDiff);
/* Move the hash values to the end of the root block */
memmove(pbRootBlk+iHashOffset,pbRootBlk+5+(4*iNbrCh)+
(4*iNbrRes),(4*iNbrRes)*sizeof(BYTE));
/* Step through the resources in the Modify List */
while (pTemp!=NULL)
{
if (pTemp->iAction==RESOURCE_ADD)
{
/* Add resource id and hash value to root block */
iCount=0;
fFound=FALSE;
/* Find id 0 */
while ((iCount<iNbrRes)&&(!fFound))
{
/* Get id */
B_COPYSTRINGN(&iTempId,pbRootBlk+5+(iNbrCh*4)+(iCount*4),4);
if (iTempId==0)
{
/* Space found - use this index */
fFound=TRUE;
}
else
{
iCount++;
}
}
/* Store id and hash */
B_COPYSTRINGN(pbRootBlk+5+(iNbrCh*4)+(iCount*4),
&(pTemp->iContentId),4);
B_COPYSTRINGN(pbRootBlk+iHashOffset+(iCount*4),
&(pTemp->iHashValue),4);
if (!fFound)
{
iNbrRes++;
}
}
else if (pTemp->iAction==RESOURCE_REMOVE)
{
iCount=0;
/* Remove channel id from root block (replace with 0) */
while (iCount<iNbrRes)
{
/* Get id */
B_COPYSTRINGN(&iTempId,pbRootBlk+5+(iNbrCh*4)+(iCount*4),4);
if (iTempId==pTemp->iContentId)
{
/* Found - remove */
B_COPYSTRINGN(pbRootBlk+iHashOffset+(iCount*4),&iZero,4);
iNbrRes--;
/* Exit loop */
iCount=iNbrRes;
}
iCount++;
}
}
pTemp=pTemp->pNext;
}
/* Store nbr of channels */
B_COPYSTRINGN(pbRootBlk+3,&iNbrRes,2);
}
/*========================================================================
REP_UpdateRootBlock
==========================================================================
The function updates the root block according to the tMODIFYROOT-
elements in the context. If the function fails, the root block is
deleted (or set to *corrupt*), otherwise it is stored with status
*OK*.
Note! The tMODIFYROOT-element list is deleted from memory.
The function is called by REP_RootBlockSafe.
Input: pContext (MUST be pREPCONTEXT).
Output: TRUE/FALSE
========================================================================*/
BOOL REP_UpdateRootBlock (void* pContext)
{
UINT32 iRootId=REP_ROOTBLK_ID;
UINT16 iNbrRes=0;
UINT16 iNbrCh=0;
UINT32 iSize=0;
UINT32 iTempSize=0;
UINT32 iNewSize;
INT32 iResourceDiff=0;
BYTE* pbRoot=NULL;
BYTE* pbChRoot=NULL;
BYTE* pbResRoot=NULL;
/* Get size */
iSize=Storage_GetBlockSize(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID);
if (iSize>0)
{
/* Allocate memory */
pbRoot=NEWARRAY(BYTE,iSize);
#ifdef WTA_DEBUG
xTraceAlg("Root block found");
#endif
/* Get root block data */
if (Storage_Get(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID,0,iSize,pbRoot))
{
#ifdef WTA_DEBUG
xTraceAlg("Root block data successfully retrieved");
#endif
#ifdef WTA_DEBUG
if (pbRoot==NULL)
{
xTraceAlg("Root block NULL");
}
else
{
xTraceAlg("Root block not NULL");
}
#endif
/* Found. Calculate new size. */
B_COPYSTRINGN(&iNbrCh,pbRoot+1,2);
B_COPYSTRINGN(&iNbrRes,pbRoot+3,2);
#ifdef WTA_DEBUG
xTraceAlg("Root block data copied");
#endif
iResourceDiff=REP_CountResourcesDiff(pContext);
#ifdef WTA_DEBUG
xTraceAlg("Root Block resources Diff calculated");
#endif
iNewSize=5+(iNbrCh*4)+(iNbrRes*8)+(8*iResourceDiff)+
(4*REP_CountChannelDiff(pContext));
if (iNewSize>0)
{
/* Create new data strings */
pbChRoot=NEWARRAY(BYTE,iNewSize);
pbResRoot=NEWARRAY(BYTE,iNewSize);
/* Copy old string. Since the iSize is the size of the
root block rounded up to the nearest 8th byte, the
iNewSize is used if iSize is bigger than iNewSize. */
if (iSize>iNewSize)
{
iTempSize=iNewSize;
}
else
{
iTempSize=iSize;
}
B_COPYSTRINGN(pbChRoot,pbRoot,iTempSize);
B_COPYSTRINGN(pbResRoot,pbRoot,iTempSize);
DEALLOC(&pbRoot);
#ifdef WTA_DEBUG
xTraceAlg("Root block: Updating to be started");
#endif
/* Update channels according to Modify List */
REP_UpdateRootBlockChannels (pContext,pbChRoot);
#ifdef WTA_DEBUG
xTraceAlg("Root block: channels added");
#endif
/* Update resources according to Modify List */
REP_UpdateRootBlockResources(pContext,pbResRoot,iResourceDiff);
#ifdef WTA_DEBUG
xTraceAlg("Root block: resources added");
#endif
/* Merge lists AND CHANGE iNewSize */
pbRoot=REP_MergeUpdateRootBlock (pbChRoot,pbResRoot,&iNewSize);
#ifdef WTA_DEBUG
xTraceAlg("Root block: Lists merged");
#endif
/* Remove modify list */
REP_RemoveModifyList (pContext);
#ifdef WTA_DEBUG
xTraceAlg("Root block: Modifylist removed");
#endif
/* Remove temporary headers */
DEALLOC(&pbChRoot);
DEALLOC(&pbResRoot);
if (iNewSize>iSize)
{
#ifdef WTA_DEBUG
xTraceAlg("Root block: Store on new location");
#endif
/* Remove old root block */
Storage_DeleteBlock(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID);
#ifdef WTA_DEBUG
xTraceAlg("Root block: Old block removed");
#endif
/* Store new root block */
if (Storage_AllocateBlock(&((REPCONTEXT*)pContext)
->Storage,iNewSize,&iRootId))
{
if (Storage_Put(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID,0,iNewSize,pbRoot))
{
/* Root block stored successfully */
DEALLOC(&pbRoot);
return TRUE;
}
}
}
else
{
#ifdef WTA_DEBUG
xTraceAlg("Root block: Store on same location");
#endif
/* Store on same location */
if (Storage_Put(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID,0,iNewSize,pbRoot))
{
DEALLOC(&pbRoot);
return TRUE;
}
}
}
}
}
/* Error in updating. Try to remove root block instead. */
Storage_DeleteBlock(&((REPCONTEXT*)pContext)->Storage,REP_ROOTBLK_ID);
/* Remove modify list */
REP_RemoveModifyList (pContext);
/* Remove root block */
DEALLOC(&pbRoot);
return FALSE;
}
/*========================================================================
REP_ChangeRootBlockStatus
==========================================================================
The function changes the status of the root block according to the
inputted value. The status is not changed if the root block is
corrupt (REPROOT_STATUS_CORRUPT). If the status could not be changed
the function tries to remove the root block from the repository.
The function is called by REP_RootBlockSafe and REP_GetAllChannels
Input: pContext (MUST be pREPCONTEXT), new status
Output: -
==========================================================================*/
void REP_ChangeRootBlockStatus (void* pContext, UINT8 iStatus)
{
BYTE abRoot[1];
/* Get root block */
if (Storage_Get(&((REPCONTEXT*)pContext)->
Storage,REP_ROOTBLK_ID,0,1,abRoot))
{
/* Root block found. Change status if necessary. */
if ((abRoot[0]!=iStatus)&&(abRoot[0]!=REPROOT_STATUS_CORRUPT))
{
abRoot[0]=iStatus;
/* Store status */
Storage_Put(&((REPCONTEXT*)pContext)->
Storage,REP_ROOTBLK_ID,0,1,abRoot);
return;
}
}
/* Try to remove root block. */
Storage_DeleteBlock(&((REPCONTEXT*)pContext)->Storage,REP_ROOTBLK_ID);
}
/*========================================================================
REP_StoreRootBlock
==========================================================================
The function creates a root block based on the data in the RepContext
The old root block is thereafter removed and replaced with the new
one. The status is set to *OK*. If anything goes wrong the root block
is deleted (or status set to *corrupt*).
Note! The tMODIFYROOT-element list is NOT included.
The function is called by REP_ScanRepository
Input: pContext (MUST be pREPCONTEXT)
Output: TRUE if OK, FALSE if error
========================================================================*/
BOOL REP_StoreRootBlock (void* pContext)
{
BYTE* pbData=NULL;
UINT16 iNbrCh=0;
UINT16 iNbrRes=0;
UINT32 iSize=0;
UINT32 iRootBlkId=REP_ROOTBLK_ID;
/* Calculate size of root block */
iNbrCh=(((REPCONTEXT*)pContext)->iNumberOfElements);
iNbrRes=(((REPCONTEXT*)pContext)->iNumberOfResources);
iSize=5+(4*iNbrCh)+(8*iNbrRes);
/* Create data */
pbData=NEWARRAY(BYTE,iSize);
/* Status */
pbData[0]=REPROOT_STATUS_OK;
/* Number of channels */
B_COPYSTRINGN(pbData+1,&iNbrCh,2);
/* Number of resources */
B_COPYSTRINGN(pbData+3,&iNbrRes,2);
/* Store channel id:s */
B_COPYSTRINGN(pbData+5,((REPCONTEXT*)pContext)->
piElementList,(iNbrCh*4));
/* Store resource id:s */
B_COPYSTRINGN(pbData+5+(iNbrCh*4),((REPCONTEXT*)pContext)->
piResourceList,(iNbrRes*4));
/* Store resource hash values */
B_COPYSTRINGN(pbData+5+(iNbrCh*4)+(iNbrRes*4),
((REPCONTEXT*)pContext)->piHashList,(iNbrRes*4));
/* Delete old root block */
Storage_DeleteBlock(&((REPCONTEXT*)pContext)->Storage,REP_ROOTBLK_ID);
/* Store new root block */
if (Storage_AllocateBlock(&((REPCONTEXT*)pContext)->Storage,
iSize,&iRootBlkId))
{
/* Store data block */
if (!Storage_Put(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID,0,iSize,pbData))
{
/* Error - remove block */
Storage_DeleteBlock(&((REPCONTEXT*)pContext)->Storage,
REP_ROOTBLK_ID);
}
/* Dealloc data */
DEALLOC(&pbData);
return TRUE;
}
/* Dealloc data */
DEALLOC(&pbData);
return FALSE;
}
/*========================================================================
HELP FUNCTIONS FOR RESOURCES AND CHANNELS
=========================================================================*/
/*========================================================================
REP_GetResourceUrl
==========================================================================
The function returns the url corresponding to the the resource id.
If error NULL is returned. It is the caller's responsibility to
deallocate the memory.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -