Added support for large field values (up to 4 GB), async and direct I/O on Linux and Solaris, and performed major code cleanup.

git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@213 0109f412-320b-0410-ab79-c3e0c5ffbbe6
This commit is contained in:
ahodgkinson
2006-03-28 19:25:14 +00:00
parent 0023b51ad8
commit 3eaf791406
197 changed files with 53521 additions and 82897 deletions

View File

@@ -1,364 +1,343 @@
//-------------------------------------------------------------------------
// Desc: Free blocks, avail list handling
// Tabs: 3
//
// Copyright (c) 1991-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: fsblk_u.cpp 12282 2006-01-19 14:52:56 -0700 (Thu, 19 Jan 2006) dsanders $
//-------------------------------------------------------------------------
#include "flaimsys.h"
/***************************************************************************
Desc: Need to use the current avail block - free up and point to next
*****************************************************************************/
RCODE FSBlockUseNextAvail(
FDB_p pDb,
LFILE * pLFile,
SCACHE ** ppSCacheRV)
{
RCODE rc = FERR_OK;
FLMUINT uiPbcAddr;
SCACHE * pSCache;
FLMBYTE * pucBlkBuf;
FLMBOOL bGotBlock = FALSE;
FLMBYTE * pucLogHdr;
pucLogHdr = &pDb->pFile->ucUncommittedLogHdr [0];
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE,
pDb->LogHdr.uiFirstAvailBlkAddr,
NULL, &pSCache)))
{
goto Exit;
}
bGotBlock = TRUE;
/*
GWBUG 34514
A corruption we have seen a couple of times is where a free
block points to itself in the free list. This will hang the machine
so this check has been added to verify that the block is a free block.
*/
if( BH_GET_TYPE( pSCache->pucBlk) != BHT_FREE )
{
rc = RC_SET( FERR_DATA_ERROR);
goto Exit;
}
/* Log the block because we are changing it! */
if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
goto Exit;
}
*ppSCacheRV = pSCache;
pucBlkBuf = pSCache->pucBlk;
pDb->LogHdr.uiFirstAvailBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf [BH_NEXT_BLK]);
UD2FBA( pDb->LogHdr.uiFirstAvailBlkAddr, &pucLogHdr [LOG_PF_AVAIL_BLKS]);
UD2FBA( 0, &pucBlkBuf [BH_NEXT_BLK]);
// One less block in the avail list.
flmDecrUint( &pucLogHdr [LOG_PF_NUM_AVAIL_BLKS], 1);
// Decrement so chains are consistent
pucLogHdr [LOG_PF_FIRST_BC_CNT]--;
if (ALGetNBC( pucBlkBuf) == BT_END) /* or first BC count == 1 */
{
/* This is a chain block - so take care of the back chains */
uiPbcAddr = ALGetPBC( pucBlkBuf);
ALResetAvailBlk( pucBlkBuf);
if (uiPbcAddr == BT_END) /* Only block in avail list */
{
UD2FBA( BT_END, &pucLogHdr [LOG_PF_FIRST_BACKCHAIN]);
pucLogHdr [LOG_PF_FIRST_BC_CNT] = 0; // Should be this already!
}
else
{
SCACHE * pPbcSCache;
/*
Hit a backchain block
Setup backchain links and adjust
LOG_PF_FIRST_BC_CNT to BACKCHAIN_CNT
This is not perfect because there may
be less blocks in that chain than expected.
*/
/* Ensure next block is chained. */
pucLogHdr [LOG_PF_FIRST_BC_CNT] = BACKCHAIN_CNT;
UD2FBA( (FLMUINT32)uiPbcAddr, &pucLogHdr [LOG_PF_FIRST_BACKCHAIN]);
/*
Read the previous backchain and modify its
nextBackchain pointer.
*/
/* Read the old first backchain block and change the NBC. */
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiPbcAddr,
NULL, &pPbcSCache)))
{
goto Exit;
}
/* Log the block because we are changing it! */
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pPbcSCache)))
{
ALPutNBC( pPbcSCache->pucBlk, BT_END);
}
ScaReleaseCache( pPbcSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
}
// If this is an index block, check to see if it is encrypted.
if (pLFile && pLFile->pIxd && pLFile->pIxd->uiEncId)
{
pucBlkBuf[ BH_ENCRYPTED] = 1;
}
Exit:
if ((RC_BAD( rc)) && (bGotBlock))
{
ScaReleaseCache( pSCache, FALSE);
}
return( rc);
}
/***************************************************************************
Desc: This routine puts a block back in a physical file's avail list.
Notes: This routine assumes that the block pointed to by pSCache has
been locked into memory. Regardless of whether or not the block
is actually freed on disk, its cache will be released. The
cached block should NOT be accessed after a call to FSBlockFree.
*****************************************************************************/
RCODE FSBlockFree(
FDB_p pDb,
SCACHE * pSCache // Pointer to pointer of cache block
// that is to be freed. NOTE: Regardless of whether
// or not the block is actually freed, it will be
// released.
)
{
RCODE rc = FERR_OK;
FLMUINT uiFirstAvailAddress;
FLMBYTE * pucBlkBuf;
FLMUINT uiBlkAddress;
SCACHE * pPbcSCache;
FLMUINT uiPbcAddr;
FLMBYTE * pucLogHdr;
pucLogHdr = &pDb->pFile->ucUncommittedLogHdr [0];
/* Log the block before modifying it. */
if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
goto Exit;
}
pucBlkBuf = pSCache->pucBlk;
/*
Set all elements except block address and checkpoint info
to zeros. If you add any new block elements please make
sure they are taken care of here.
*/
/* Leave block address alone. */
uiBlkAddress = GET_BH_ADDR( pucBlkBuf);
ALResetAvailBlk( pucBlkBuf);
uiFirstAvailAddress = pDb->LogHdr.uiFirstAvailBlkAddr;
UD2FBA( (FLMUINT32)uiFirstAvailAddress, &pucBlkBuf [BH_NEXT_BLK]);
pucBlkBuf [BH_TYPE] = BHT_FREE;
pucBlkBuf [BH_LEVEL] = 0;
UW2FBA( BH_OVHD, &pucBlkBuf [BH_ELM_END]);
// Wipe the contents of encrypted blocks...
if (pucBlkBuf[ BH_ENCRYPTED])
{
f_memset( &pucBlkBuf[ BH_OVHD], 0, pDb->pFile->FileHdr.uiBlockSize -
BH_OVHD);
pucBlkBuf [BH_ENCRYPTED] = 0;
}
/* Leave CHECKPOINT, PREV_CP and PREV_BLK_ADDR alone. */
/* Update the physical file log information. */
pDb->LogHdr.uiFirstAvailBlkAddr = uiBlkAddress;
UD2FBA( (FLMUINT32)uiBlkAddress, &pucLogHdr [LOG_PF_AVAIL_BLKS]);
/* Is it time to add a new backchain? */
if (pucLogHdr [LOG_PF_FIRST_BC_CNT] >= BACKCHAIN_CNT ||
FB2UD( &pucLogHdr [LOG_PF_NUM_AVAIL_BLKS]) == 0)
{
/* Start over - increments to 1 below. */
pucLogHdr [LOG_PF_FIRST_BC_CNT] = 0;
ALPutNBC( pucBlkBuf, BT_END);
/* Increment & check if no avail blks. */
if (FB2UD( &pucLogHdr [LOG_PF_NUM_AVAIL_BLKS]) == 0)
{
ALPutPBC( pucBlkBuf, BT_END);
}
else
{
uiPbcAddr = (FLMUINT)FB2UD( &pucLogHdr [LOG_PF_FIRST_BACKCHAIN]);
ALPutPBC( pucBlkBuf, uiPbcAddr);
/* Read the old first backchain block and change the NBC. */
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiPbcAddr,
NULL, &pPbcSCache)))
{
goto Exit;
}
/* Log the block because we are changing it! */
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pPbcSCache)))
{
ALPutNBC( pPbcSCache->pucBlk, uiBlkAddress);
}
ScaReleaseCache( pPbcSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
UD2FBA( (FLMUINT32)uiBlkAddress,
&pucLogHdr [LOG_PF_FIRST_BACKCHAIN]);
}
/* Be sure to increment these. */
flmIncrUint( &pucLogHdr [LOG_PF_NUM_AVAIL_BLKS], 1);
pucLogHdr [LOG_PF_FIRST_BC_CNT]++;
Exit:
ScaReleaseCache( pSCache, FALSE);
return( rc);
}
/***************************************************************************
Desc: Fix up the previous/next links removal of the block
Notes: This routine assumes that the block pointed to by pSCache has
been locked into memory. Regardless of whether or not the block
is actually freed on disk, its cache will be released. The
cached block should NOT be accessed after a call to FSBlockFree.
*****************************************************************************/
RCODE FSBlockFixLinks(
FDB_p pDb,
LFILE * pLFile, // Logical file.
SCACHE * pSCache // Pointer to pointer of block that
// is to be unlinked. NOTE: Regardless of whether
// or not the block is actually freed, it will be
// released.
)
{
RCODE rc = FERR_OK;
FLMUINT uiPrevBlkAddr;
FLMUINT uiNextBlkAddr;
FLMBYTE * pucBlkBuf;
pucBlkBuf = pSCache->pucBlk;
uiPrevBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf [BH_PREV_BLK]);
uiNextBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf [BH_NEXT_BLK]);
/* First free block. NOTE: Do NOT access pSCache after this call */
if (RC_BAD( rc = FSBlockFree( pDb, pSCache)))
{
goto Exit;
}
/* Read the previous block if current is not the left end. */
if (uiPrevBlkAddr != BT_END)
{
if (RC_BAD( rc = ScaGetBlock( pDb, pLFile, BHT_LEAF, uiPrevBlkAddr,
NULL, &pSCache)))
{
goto Exit;
}
/* Log the block before modifying it. */
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
UD2FBA( uiNextBlkAddr, &pSCache->pucBlk [BH_NEXT_BLK]);
}
ScaReleaseCache( pSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
/* Read the next block if current is not the left end. */
if (uiNextBlkAddr != BT_END)
{
if (RC_BAD( rc = ScaGetBlock( pDb, pLFile, BHT_LEAF, uiNextBlkAddr,
NULL, &pSCache)))
{
goto Exit;
}
/* Log the block before modifying it. */
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
UD2FBA( uiPrevBlkAddr, &pSCache->pucBlk [BH_PREV_BLK]);
}
ScaReleaseCache( pSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
Exit:
return( rc);
}
//-------------------------------------------------------------------------
// Desc: Free blocks, avail list handling
// Tabs: 3
//
// Copyright (c) 1991-2006 Novell, Inc. All Rights Reserved.
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of version 2 of the GNU General Public
// License as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, contact Novell, Inc.
//
// To contact Novell about this file by physical or electronic mail,
// you may find current contact information at www.novell.com
//
// $Id: fsblk_u.cpp 12282 2006-01-19 14:52:56 -0700 (Thu, 19 Jan 2006) dsanders $
//-------------------------------------------------------------------------
#include "flaimsys.h"
/****************************************************************************
Desc: Need to use the current avail block - free up and point to next
****************************************************************************/
RCODE FSBlockUseNextAvail(
FDB * pDb,
LFILE * pLFile,
SCACHE ** ppSCacheRV)
{
RCODE rc = FERR_OK;
FLMUINT uiPbcAddr;
SCACHE * pSCache;
FLMBYTE * pucBlkBuf;
FLMBOOL bGotBlock = FALSE;
FLMBYTE * pucLogHdr;
pucLogHdr = &pDb->pFile->ucUncommittedLogHdr[0];
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE,
pDb->LogHdr.uiFirstAvailBlkAddr, NULL, &pSCache)))
{
goto Exit;
}
bGotBlock = TRUE;
// A corruption we have seen a couple of times is where a free block
// points to itself in the free list. This will hang the machine so
// this check has been added to verify that the block is a free block.
if (BH_GET_TYPE( pSCache->pucBlk) != BHT_FREE)
{
rc = RC_SET( FERR_DATA_ERROR);
goto Exit;
}
// Log the block because we are changing it!
if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
goto Exit;
}
*ppSCacheRV = pSCache;
pucBlkBuf = pSCache->pucBlk;
pDb->LogHdr.uiFirstAvailBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf[BH_NEXT_BLK]);
UD2FBA( pDb->LogHdr.uiFirstAvailBlkAddr, &pucLogHdr[LOG_PF_AVAIL_BLKS]);
UD2FBA( 0, &pucBlkBuf[BH_NEXT_BLK]);
// One less block in the avail list.
flmDecrUint( &pucLogHdr[LOG_PF_NUM_AVAIL_BLKS], 1);
// Decrement so chains are consistent
pucLogHdr[LOG_PF_FIRST_BC_CNT]--;
if (ALGetNBC( pucBlkBuf) == BT_END)
{
// This is a chain block - so take care of the back chains
uiPbcAddr = ALGetPBC( pucBlkBuf);
ALResetAvailBlk( pucBlkBuf);
if (uiPbcAddr == BT_END)
{
UD2FBA( BT_END, &pucLogHdr[LOG_PF_FIRST_BACKCHAIN]);
pucLogHdr[LOG_PF_FIRST_BC_CNT] = 0;
}
else
{
SCACHE * pPbcSCache;
// Hit a backchain block Setup backchain links and adjust
// LOG_PF_FIRST_BC_CNT to BACKCHAIN_CNT This is not perfect
// because there may be less blocks in that chain than expected.
//
// Ensure next block is chained.
pucLogHdr[LOG_PF_FIRST_BC_CNT] = BACKCHAIN_CNT;
UD2FBA( (FLMUINT32) uiPbcAddr, &pucLogHdr[LOG_PF_FIRST_BACKCHAIN]);
// Read the previous backchain and modify its nextBackchain
// pointer.
//
// Read the old first backchain block and change the NBC.
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiPbcAddr, NULL,
&pPbcSCache)))
{
goto Exit;
}
// Log the block because we are changing it!
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pPbcSCache)))
{
ALPutNBC( pPbcSCache->pucBlk, BT_END);
}
ScaReleaseCache( pPbcSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
}
// If this is an index block, check to see if it is encrypted.
if (pLFile && pLFile->pIxd && pLFile->pIxd->uiEncId)
{
pucBlkBuf[BH_ENCRYPTED] = 1;
}
Exit:
if ((RC_BAD( rc)) && (bGotBlock))
{
ScaReleaseCache( pSCache, FALSE);
}
return (rc);
}
/****************************************************************************
Desc: This routine puts a block back in a physical file's avail list.
****************************************************************************/
RCODE FSBlockFree(
FDB * pDb,
SCACHE * pSCache)
{
RCODE rc = FERR_OK;
FLMUINT uiFirstAvailAddress;
FLMBYTE * pucBlkBuf;
FLMUINT uiBlkAddress;
SCACHE * pPbcSCache;
FLMUINT uiPbcAddr;
FLMBYTE * pucLogHdr;
pucLogHdr = &pDb->pFile->ucUncommittedLogHdr[0];
// Log the block before modifying it.
if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
goto Exit;
}
pucBlkBuf = pSCache->pucBlk;
// Set all elements except block address and checkpoint info to zeros.
// If you add any new block elements please make sure they are taken
// care of here.
//
// Leave block address alone.
uiBlkAddress = GET_BH_ADDR( pucBlkBuf);
ALResetAvailBlk( pucBlkBuf);
uiFirstAvailAddress = pDb->LogHdr.uiFirstAvailBlkAddr;
UD2FBA( (FLMUINT32) uiFirstAvailAddress, &pucBlkBuf[BH_NEXT_BLK]);
pucBlkBuf[BH_TYPE] = BHT_FREE;
pucBlkBuf[BH_LEVEL] = 0;
UW2FBA( BH_OVHD, &pucBlkBuf[BH_ELM_END]);
// Wipe the contents of encrypted blocks...
if (pucBlkBuf[BH_ENCRYPTED])
{
f_memset( &pucBlkBuf[BH_OVHD], 0,
pDb->pFile->FileHdr.uiBlockSize - BH_OVHD);
pucBlkBuf[BH_ENCRYPTED] = 0;
}
// Leave CHECKPOINT, PREV_CP and PREV_BLK_ADDR alone.
// Update the physical file log information.
pDb->LogHdr.uiFirstAvailBlkAddr = uiBlkAddress;
UD2FBA( (FLMUINT32) uiBlkAddress, &pucLogHdr[LOG_PF_AVAIL_BLKS]);
// Is it time to add a new backchain?
if (pucLogHdr[LOG_PF_FIRST_BC_CNT] >= BACKCHAIN_CNT ||
FB2UD( &pucLogHdr[LOG_PF_NUM_AVAIL_BLKS]) == 0)
{
// Start over - increments to 1 below.
pucLogHdr[LOG_PF_FIRST_BC_CNT] = 0;
ALPutNBC( pucBlkBuf, BT_END);
// Increment and check if no avail blocks
if (FB2UD( &pucLogHdr[LOG_PF_NUM_AVAIL_BLKS]) == 0)
{
ALPutPBC( pucBlkBuf, BT_END);
}
else
{
uiPbcAddr = (FLMUINT) FB2UD( &pucLogHdr[LOG_PF_FIRST_BACKCHAIN]);
ALPutPBC( pucBlkBuf, uiPbcAddr);
// Read the old first backchain block and change the NBC.
if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiPbcAddr, NULL,
&pPbcSCache)))
{
goto Exit;
}
// Log the block because we are changing it!
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pPbcSCache)))
{
ALPutNBC( pPbcSCache->pucBlk, uiBlkAddress);
}
ScaReleaseCache( pPbcSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
UD2FBA( (FLMUINT32) uiBlkAddress, &pucLogHdr[LOG_PF_FIRST_BACKCHAIN]);
}
// Be sure to increment these.
flmIncrUint( &pucLogHdr[LOG_PF_NUM_AVAIL_BLKS], 1);
pucLogHdr[LOG_PF_FIRST_BC_CNT]++;
Exit:
ScaReleaseCache( pSCache, FALSE);
return (rc);
}
/****************************************************************************
Desc: Fix up the previous/next links
****************************************************************************/
RCODE FSBlockFixLinks(
FDB * pDb,
LFILE * pLFile,
SCACHE * pSCache)
{
RCODE rc = FERR_OK;
FLMUINT uiPrevBlkAddr;
FLMUINT uiNextBlkAddr;
FLMBYTE * pucBlkBuf;
pucBlkBuf = pSCache->pucBlk;
uiPrevBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf[BH_PREV_BLK]);
uiNextBlkAddr = (FLMUINT) FB2UD( &pucBlkBuf[BH_NEXT_BLK]);
// First free block. NOTE: Do NOT access pSCache after this call
if (RC_BAD( rc = FSBlockFree( pDb, pSCache)))
{
goto Exit;
}
// Read the previous block if current is not the left end.
if (uiPrevBlkAddr != BT_END)
{
if (RC_BAD( rc = ScaGetBlock( pDb, pLFile, BHT_LEAF, uiPrevBlkAddr, NULL,
&pSCache)))
{
goto Exit;
}
// Log the block before modifying it.
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
UD2FBA( uiNextBlkAddr, &pSCache->pucBlk[BH_NEXT_BLK]);
}
ScaReleaseCache( pSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
// Read the next block if current is not the left end.
if (uiNextBlkAddr != BT_END)
{
if (RC_BAD( rc = ScaGetBlock( pDb, pLFile, BHT_LEAF, uiNextBlkAddr,
NULL, &pSCache)))
{
goto Exit;
}
// Log the block before modifying it.
if (RC_OK( rc = ScaLogPhysBlk( pDb, &pSCache)))
{
UD2FBA( uiPrevBlkAddr, &pSCache->pucBlk[BH_PREV_BLK]);
}
ScaReleaseCache( pSCache, FALSE);
if (RC_BAD( rc))
{
goto Exit;
}
}
Exit:
return (rc);
}