From 26e8c51b3c467c883a0d7765bbda591bae4e3236 Mon Sep 17 00:00:00 2001 From: ahodgkinson Date: Thu, 20 Jul 2006 19:20:32 +0000 Subject: [PATCH] FLAIM Change. Added support for running a database sweep within an update transaction. git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@687 0109f412-320b-0410-ab79-c3e0c5ffbbe6 --- flaim/src/flsweep.cpp | 443 ++++++++++++++++++++++---------------- flaim/util/basic_test.cpp | 62 ++++-- 2 files changed, 300 insertions(+), 205 deletions(-) diff --git a/flaim/src/flsweep.cpp b/flaim/src/flsweep.cpp index df6b2ba..54a0fdc 100644 --- a/flaim/src/flsweep.cpp +++ b/flaim/src/flsweep.cpp @@ -34,16 +34,18 @@ public: DbDict() { m_puiStateTbl = NULL; - }; + m_bInternalTrans = FALSE; + } ~DbDict(); - RCODE Init( + RCODE init( FDB * pDb, + FLMBOOL bInternalTrans, FLMUINT uiMode, FLMBOOL * pbFoundPurgeField); - FINLINE FLMUINT GetState( + FINLINE FLMUINT getState( FLMUINT uiFieldID) { if( uiFieldID > m_uiTblSize) @@ -56,17 +58,18 @@ public: } } - RCODE ChangeState( + RCODE changeState( FLMUINT uiFieldID, FLMUINT uiNewState); - RCODE Finish( void); + RCODE finish( void); private: - FDB * m_pDb; - FLMUINT * m_puiStateTbl; - FLMUINT m_uiTblSize; + FDB * m_pDb; + FLMBOOL m_bInternalTrans; + FLMUINT * m_puiStateTbl; + FLMUINT m_uiTblSize; }; /**************************************************************************** @@ -82,6 +85,7 @@ public: { f_memset( &m_SwpInfo, 0, sizeof( SWEEP_INFO)); m_pDb = NULL; + m_bInternalTrans = FALSE; m_uiCallbackFreq = 0; m_fnStatusHook = NULL; m_UserData = 0; @@ -94,31 +98,34 @@ public: { } - FINLINE void Init( + FINLINE void init( FDB * pDb, + FLMBOOL bInternalTrans, FLMUINT uiCallbackFreq, STATUS_HOOK fnStatusHook, void * UserData) { m_pDb = pDb; + m_bInternalTrans = bInternalTrans; m_uiCallbackFreq = uiCallbackFreq; m_fnStatusHook = fnStatusHook; m_UserData = UserData; } - RCODE NextContainer( + RCODE nextContainer( FLMUINT * puiContainer); - RCODE NextRecord( + RCODE nextRecord( FlmRecord ** ppRecord); - RCODE UpdateRecord( + RCODE updateRecord( FLMUINT uiDrn, FlmRecord * pRecord); private: FDB * m_pDb; + FLMBOOL m_bInternalTrans; FLMUINT m_uiCallbackFreq; STATUS_HOOK m_fnStatusHook; void * m_UserData; @@ -181,42 +188,61 @@ FLMEXP RCODE FLMAPI FlmDbSweep( goto ExitCS; } - if( ( pDbWalk = f_new DbWalk) == NULL) + if( (pDbWalk = f_new DbWalk) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } f_memset( &SwpInfo, 0, sizeof( SWEEP_INFO)); - - if( RC_BAD( rc = fdbInit( pDb, FLM_READ_TRANS | FLM_DONT_POISON_CACHE, - 0, 0, &bStartedTrans))) + + if( RC_BAD( rc = fdbInit( pDb, FLM_NO_TRANS, + FDB_TRANS_GOING_OK, 0, NULL))) { goto Exit; } + + if( pDb->uiTransType == FLM_READ_TRANS) + { + rc = RC_SET_AND_ASSERT( FERR_ILLEGAL_TRANS_OP); + goto Exit; + } + else if( pDb->uiTransType == FLM_NO_TRANS) + { + if( RC_BAD( rc = flmBeginDbTrans( pDb, FLM_READ_TRANS, + 0, FLM_DONT_POISON_CACHE))) + { + goto Exit; + } - pDbWalk->Init( pDb, uiCallbackFreq, fnStatusHook, UserData); + bStartedTrans = TRUE; + } + + pDbWalk->init( pDb, bStartedTrans, uiCallbackFreq, fnStatusHook, UserData); SwpInfo.hDb = pDbWalk->m_SwpInfo.hDb = hDb; - /* Only initialize a DbDict if needed */ + // Only initialize a DbDict if needed + if( (uiSweepMode & SWEEP_CHECKING_FLDS) || (uiSweepMode & SWEEP_PURGED_FLDS)) { FLMBOOL bFoundPurgeField; - if( ( pDbDict = f_new DbDict) == NULL) + if( (pDbDict = f_new DbDict) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } - if( RC_BAD( rc = pDbDict->Init( pDb, uiSweepMode, &bFoundPurgeField))) + if( RC_BAD( rc = pDbDict->init( pDb, bStartedTrans, + uiSweepMode, &bFoundPurgeField))) { goto Exit; } // If user is performing purge field sweep and dictionary contains no // purged fields then just return. + if( uiSweepMode == SWEEP_PURGED_FLDS && !bFoundPurgeField) { goto Exit; @@ -227,11 +253,12 @@ FLMEXP RCODE FLMAPI FlmDbSweep( { // Get the next container - if (RC_BAD( rc = pDbWalk->NextContainer( &uiContainer))) + if( RC_BAD( rc = pDbWalk->nextContainer( &uiContainer))) { - if (rc == FERR_EOF_HIT) + if( rc == FERR_EOF_HIT) { // No more containers to process. + rc = FERR_OK; break; } @@ -241,11 +268,12 @@ FLMEXP RCODE FLMAPI FlmDbSweep( } } - if (!pDbDict && + if( !pDbDict && !(uiCallbackFreq & EACH_RECORD || uiCallbackFreq & EACH_FIELD)) { // User is performing a status sweep and they are not visiting // each record or field. Go to next container. + continue; } @@ -253,16 +281,16 @@ FLMEXP RCODE FLMAPI FlmDbSweep( // Visit each record in the container. - for (;;) + for( ;;) { FLMBOOL bRecChanged; void * pvField; void * pvPrevField; FLMUINT uiDrn; - if (RC_BAD( rc = pDbWalk->NextRecord( &pRecord))) + if( RC_BAD( rc = pDbWalk->nextRecord( &pRecord))) { - if (rc == FERR_EOF_HIT) + if( rc == FERR_EOF_HIT) { rc = FERR_OK; break; @@ -283,18 +311,17 @@ FLMEXP RCODE FLMAPI FlmDbSweep( SwpInfo.pRecord = pRecord; SwpInfo.pvField = pvField; - // call the field call-back here.. + // Call the field call-back - if ((uiCallbackFreq & EACH_FIELD) && fnStatusHook) + if( (uiCallbackFreq & EACH_FIELD) && fnStatusHook) { - if (RC_BAD( rc = (fnStatusHook)( FLM_SWEEP_STATUS, - (void *)&SwpInfo, - (void *)EACH_FIELD, - UserData))) + if( RC_BAD( rc = (fnStatusHook)( FLM_SWEEP_STATUS, + (void *)&SwpInfo, (void *)EACH_FIELD, UserData))) { - if (rc == FERR_EOF_HIT) + if( rc == FERR_EOF_HIT) { // User returned FERR_EOF_HIT, means skip to next record. + rc = FERR_OK; break; } @@ -307,72 +334,71 @@ FLMEXP RCODE FLMAPI FlmDbSweep( // Continue to next field if no DbDict object. - if (! pDbDict) + if( !pDbDict) { continue; } - uiState = pDbDict->GetState( pRecord->getFieldID( pvField)); + uiState = pDbDict->getState( pRecord->getFieldID( pvField)); // If the field is encrypted, we need to check the state of the // encryption definition record as well, since it is being // referenced by this field. - if (pRecord->isEncryptedField( pvField)) + + if( pRecord->isEncryptedField( pvField)) { - uiEncState = pDbDict->GetState( pRecord->getEncryptionID( pvField)); + uiEncState = pDbDict->getState( + pRecord->getEncryptionID( pvField)); } else { uiEncState = 0; } - if (!uiState && !uiEncState) + if( !uiState && !uiEncState) { continue; } - if ((uiState == ITT_FLD_STATE_CHECKING || + if( (uiState == ITT_FLD_STATE_CHECKING || uiState == ITT_FLD_STATE_PURGE || uiEncState == ITT_ENC_STATE_CHECKING || uiEncState == ITT_ENC_STATE_PURGE) && - (uiCallbackFreq & EACH_CHANGE) && - fnStatusHook) + (uiCallbackFreq & EACH_CHANGE) && fnStatusHook) { - if (RC_BAD( rc = (fnStatusHook)( FLM_SWEEP_STATUS, - (void *)&SwpInfo, - (void *)EACH_CHANGE, - UserData))) + if( RC_BAD( rc = (fnStatusHook)( FLM_SWEEP_STATUS, + (void *)&SwpInfo, (void *)EACH_CHANGE, UserData))) { goto Exit; } } - if (uiState == ITT_FLD_STATE_CHECKING) + if( uiState == ITT_FLD_STATE_CHECKING) { // Change the field's state to 'active' - if (RC_BAD( rc = pDbDict->ChangeState( - pRecord->getFieldID( pvField), - ITT_FLD_STATE_ACTIVE))) + if( RC_BAD( rc = pDbDict->changeState( + pRecord->getFieldID( pvField), ITT_FLD_STATE_ACTIVE))) { goto Exit; } } - else if (uiState == ITT_FLD_STATE_PURGE) + else if( uiState == ITT_FLD_STATE_PURGE) { // If needed, create writeable version of record and // reposition to field - if (pRecord->isReadOnly()) + if( pRecord->isReadOnly()) { FlmRecord * pTmpRec; FLMUINT uiFieldID = pRecord->getFieldID( pvField); - if ((pTmpRec = pRecord->copy()) == NULL) + if( (pTmpRec = pRecord->copy()) == NULL) { rc = RC_SET( FERR_MEM); goto Exit; } + pRecord->Release(); pRecord = pTmpRec; @@ -386,9 +412,9 @@ FLMEXP RCODE FLMAPI FlmDbSweep( // Remove the purged field from the record. bRecChanged = TRUE; - if (pvField == pRecord->root()) + if( pvField == pRecord->root()) { - // Passing a NULL pRecord to UpdateRecord will delete + // Passing a NULL pRecord to updateRecord will delete // the record. pRecord->Release(); @@ -401,7 +427,6 @@ FLMEXP RCODE FLMAPI FlmDbSweep( } else { - // Must save the previous field before removing the // field so we can set pvField to it after removing // pvField. @@ -412,29 +437,32 @@ FLMEXP RCODE FLMAPI FlmDbSweep( } } - // Check the EncDef state, independant of the field state. If the field - // has been purged, we don't need to update the EncDef record since it - // is no longer being referenced by this field. - if (uiEncState == ITT_ENC_STATE_CHECKING && uiState != ITT_FLD_STATE_PURGE) + // Check the EncDef state, independant of the field state. If the + // field has been purged, we don't need to update the EncDef + // record since it is no longer being referenced by this field. + + if( uiEncState == ITT_ENC_STATE_CHECKING && + uiState != ITT_FLD_STATE_PURGE) { // Change the EncDef record's state to 'active' - if (RC_BAD( rc = pDbDict->ChangeState( - pRecord->getEncryptionID( pvField), - ITT_ENC_STATE_ACTIVE))) + if( RC_BAD( rc = pDbDict->changeState( + pRecord->getEncryptionID( pvField), ITT_ENC_STATE_ACTIVE))) { goto Exit; } } - // If the EncDef record has a state of purge, then we must change - // the field of this record so that it is no longer encrypted. - else if (uiEncState == ITT_ENC_STATE_PURGE && + else if( uiEncState == ITT_ENC_STATE_PURGE && uiState != ITT_FLD_STATE_PURGE) { FLMUINT uiDataLength = pRecord->getDataLength( pvField); const FLMBYTE * pucDataSource = pRecord->getDataPtr( pvField); FLMBYTE * pucDestPtr; + // If the EncDef record has a state of purge, then we must + // change the field of this record so that it is no longer + // encrypted. + if( RC_BAD( rc = pRecord->allocStorageSpace( pvField, pRecord->getDataType( pvField), uiDataLength, 0, 0, 0, &pucDestPtr, NULL))) @@ -449,9 +477,9 @@ FLMEXP RCODE FLMAPI FlmDbSweep( // Record was changed because a purged field was found. - if (bRecChanged) + if( bRecChanged) { - if (RC_BAD( rc = pDbWalk->UpdateRecord( uiDrn, pRecord))) + if( RC_BAD( rc = pDbWalk->updateRecord( uiDrn, pRecord))) { goto Exit; } @@ -461,9 +489,9 @@ FLMEXP RCODE FLMAPI FlmDbSweep( // Now complete any changes needed within the dictionary - if (pDbDict) + if( pDbDict) { - rc = pDbDict->Finish(); + rc = pDbDict->finish(); } Exit: @@ -480,9 +508,12 @@ Exit: pDbWalk = NULL; } - if( bStartedTrans && pDb->uiTransType != FLM_NO_TRANS) + if( bStartedTrans) { - (void)flmAbortDbTrans( pDb); + if( pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( pDb); + } } ExitCS: @@ -493,17 +524,14 @@ ExitCS: { pRecord->Release(); } + return( rc); } -////////////////////////////////////////////////////////////////////////////// -// DbWalk Class Implementation -////////////////////////////////////////////////////////////////////////////// - /**************************************************************************** Desc: Get the next container within this database ****************************************************************************/ -RCODE DbWalk::NextContainer( // Returns next container to visit +RCODE DbWalk::nextContainer( FLMUINT * puiContainer) { LFILE * pLFileTbl = (LFILE *)m_pDb->pDict->pLFileTbl; @@ -511,11 +539,11 @@ RCODE DbWalk::NextContainer( // Returns next container to visit RCODE rc = FERR_OK; FLMUINT uiTblSize; - for (uiTblSize = m_pDb->pDict->uiLFileCnt; + for( uiTblSize = m_pDb->pDict->uiLFileCnt; m_uiNextLFile < uiTblSize; m_uiNextLFile++) { - if (pLFileTbl [m_uiNextLFile].uiLfType == LF_CONTAINER && + if( pLFileTbl [m_uiNextLFile].uiLfType == LF_CONTAINER && (pLFileTbl [m_uiNextLFile].uiLfNum == FLM_DATA_CONTAINER || pLFileTbl [m_uiNextLFile].uiLfNum < FLM_DICT_CONTAINER)) { @@ -529,14 +557,12 @@ RCODE DbWalk::NextContainer( // Returns next container to visit m_SwpInfo.pRecord = NULL; m_SwpInfo.pvField = NULL; - if ((m_uiCallbackFreq & EACH_CONTAINER) && m_fnStatusHook) + if( (m_uiCallbackFreq & EACH_CONTAINER) && m_fnStatusHook) { - if (RC_BAD( rc = (m_fnStatusHook)( FLM_SWEEP_STATUS, - (void *)&m_SwpInfo, - (void *)EACH_CONTAINER, - m_UserData))) + if( RC_BAD( rc = (m_fnStatusHook)( FLM_SWEEP_STATUS, + (void *)&m_SwpInfo, (void *)EACH_CONTAINER, m_UserData))) { - if (rc == FERR_EOF_HIT) + if( rc == FERR_EOF_HIT) { // User wants to skip this container. @@ -560,7 +586,7 @@ RCODE DbWalk::NextContainer( // Returns next container to visit } } - if (!bFoundContainer) + if( !bFoundContainer) { rc = RC_SET( FERR_EOF_HIT); goto Exit; @@ -574,65 +600,77 @@ Exit: /**************************************************************************** Desc: Returns the next record within the current container. ****************************************************************************/ -RCODE DbWalk::NextRecord( - FlmRecord ** ppRecord) // Returned record +RCODE DbWalk::nextRecord( + FlmRecord ** ppRecord) { - RCODE rc = FERR_OK; - FLMUINT uiDrn; + RCODE rc = FERR_OK; + FLMUINT uiDrn; // Loop till we get a record or hit end of container. - for (;;) + for( ;;) { - // Abort and start a new read transaction every 1000 records. - - if ((m_uiRecsRead % 1000) == 0) + if( m_bInternalTrans) { + // Abort and start a new read transaction every 1000 records. + + if( (m_uiRecsRead % 1000) == 0) + { AbortTrans: - if (m_pDb->uiTransType != FLM_NO_TRANS) - { - (void)flmAbortDbTrans( m_pDb); - } - - if (RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, - 0, FLM_DONT_POISON_CACHE))) - { - goto Exit; + + if( m_pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( m_pDb); + } + + if( RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, + 0, FLM_DONT_POISON_CACHE))) + { + goto Exit; + } } } - if (*ppRecord) + if( *ppRecord) { (*ppRecord)->Release(); *ppRecord = NULL; } - if (RC_BAD( rc = FlmRecordRetrieve( (HFDB)m_pDb, - m_SwpInfo.uiContainer, - m_uiLastDrn, FO_EXCL, - ppRecord, &uiDrn))) + if( RC_BAD( rc = FlmRecordRetrieve( (HFDB)m_pDb, m_SwpInfo.uiContainer, + m_uiLastDrn, FO_EXCL, ppRecord, &uiDrn))) { - if (rc == FERR_OLD_VIEW) + if( rc == FERR_OLD_VIEW) { - goto AbortTrans; + if( m_bInternalTrans) + { + goto AbortTrans; + } + + goto Exit; } // It is possible for the container to go away in the // middle of walking through it, because we are stopping // and starting transactions. - if (rc == FERR_BAD_CONTAINER) + if( rc == FERR_BAD_CONTAINER) { - // Must abort the transaction because FERR_BAD_CONTAINER // will not allow the transaction to continue // if we are in an update transaction. - - if (m_pDb->uiTransType != FLM_NO_TRANS) + + if( !m_bInternalTrans) + { + goto Exit; + } + + if( m_pDb->uiTransType != FLM_NO_TRANS) { (void)flmAbortDbTrans( m_pDb); } - if (RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, + + if( RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, 0, FLM_DONT_POISON_CACHE))) { goto Exit; @@ -643,8 +681,10 @@ AbortTrans: rc = RC_SET( FERR_EOF_HIT); } + goto Exit; } + m_uiLastDrn = uiDrn; m_uiRecsRead++; m_SwpInfo.pRecord = *ppRecord; @@ -652,24 +692,26 @@ AbortTrans: // Make STATUS_HOOK callback - if ((m_uiCallbackFreq & EACH_RECORD) && m_fnStatusHook) + if( (m_uiCallbackFreq & EACH_RECORD) && m_fnStatusHook) { - if ((rc = (m_fnStatusHook)( FLM_SWEEP_STATUS, (void *)&m_SwpInfo, - (void *) EACH_RECORD, - m_UserData)) == FERR_EOF_HIT) + if( (rc = (m_fnStatusHook)( FLM_SWEEP_STATUS, (void *)&m_SwpInfo, + (void *) EACH_RECORD, m_UserData)) == FERR_EOF_HIT) { // User wants to skip this record. + continue; } else { // Return this record + break; } } else { // Return the record + break; } } @@ -680,23 +722,25 @@ Exit: } /**************************************************************************** -Desc: The last record returned from DbWalk::NextRecord contained 'purged' fields - which have been removed. This function will now replace the old record - with the new record. This record maybe == NULL, in which case the - record will be deleted. +Desc: The last record returned from DbWalk::nextRecord contained 'purged' + fields which have been removed. This function will now replace the + old record with the new record. This record may be == NULL, in which + case the record will be deleted. ****************************************************************************/ -RCODE DbWalk::UpdateRecord( - FLMUINT uiDrn, // DRN of record to modify or delete - FlmRecord * pRecord // if NULL delete the record - ) +RCODE DbWalk::updateRecord( + FLMUINT uiDrn, + FlmRecord * pRecord) { - RCODE rc = FERR_OK; - FLMBOOL bRestartTrans = FALSE; + RCODE rc = FERR_OK; + FLMBOOL bRestartTrans = FALSE; - if (m_pDb->uiTransType != FLM_NO_TRANS) + if( m_bInternalTrans) { - (void)flmAbortDbTrans( m_pDb); - bRestartTrans = TRUE; + if( m_pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( m_pDb); + bRestartTrans = TRUE; + } } // Either modify or delete the specified record @@ -713,9 +757,11 @@ RCODE DbWalk::UpdateRecord( // Now (if needed) restart the read transaction. - if (bRestartTrans) + if( bRestartTrans) { - if (RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, + flmAssert( m_bInternalTrans); + + if( RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, 0, FLM_DONT_POISON_CACHE))) { goto Exit; @@ -728,10 +774,9 @@ Exit: } -////////////////////////////////////////////////////////////////////////////// -// DbDict Class Implementation -////////////////////////////////////////////////////////////////////////////// - +/**************************************************************************** +Desc: +****************************************************************************/ DbDict::~DbDict() { if( m_pDb) @@ -749,10 +794,11 @@ DbDict::~DbDict() Desc: Read the dictionary and create a internal table that records the state of field templates within the specified dictionary ****************************************************************************/ -RCODE DbDict::Init( +RCODE DbDict::init( FDB * pDb, - FLMUINT uiMode, // are we looking for checking or purged or both - FLMBOOL * pbFoundPurgeField)// [out] dictionary contained field that is marked purged. + FLMBOOL bInternalTrans, + FLMUINT uiMode, + FLMBOOL * pbFoundPurgeField) { RCODE rc = FERR_OK; ITT * pItt = NULL; @@ -762,18 +808,20 @@ RCODE DbDict::Init( *pbFoundPurgeField = FALSE; m_pDb = pDb; + m_bInternalTrans = bInternalTrans; - /* Need to set a flag that which tells lower level FLAIM code - that its okay to: - 1) Set a field state to 'unused' and - 2) Delete a field thats in a 'purged' state. - - */ + // Need to set a flag that which tells lower level FLAIM code + // that its okay to: + // 1) Set a field state to 'unused' and + // 2) Delete a field thats in a 'purged' state. + m_pDb->bFldStateUpdOk = TRUE; - /* Allocate state table */ + // Allocate state table + m_uiTblSize = m_pDb->pDict->uiIttCnt; - if( RC_BAD( rc = f_calloc( + + if( RC_BAD( rc = f_calloc( (m_uiTblSize * sizeof( FLMUINT)), &m_puiStateTbl))) { goto Exit; @@ -792,11 +840,13 @@ RCODE DbDict::Init( uiStateMask |= ITT_FLD_STATE_PURGE; } - /* Now loop through the ITT table and set the correct states within - the DbDict's state table */ + // Now loop through the ITT table and set the correct states within + // the DbDict's state table + for( uiItem = 0; uiItem < uiCount; pItt++, uiItem++) { - /* Make sure the entry is a field or an encryption definition record. */ + // Make sure the entry is a field or an encryption definition record + if( ITT_IS_FIELD( pItt)) { m_puiStateTbl[ uiItem] = (pItt->uiType & uiStateMask); @@ -804,31 +854,31 @@ RCODE DbDict::Init( { *pbFoundPurgeField = TRUE; - /* make sure this field is not references and - can therefore be deleted. */ - if (RC_BAD( rc = flmCheckDictFldRefs( m_pDb->pDict, uiItem))) + // Make sure this field is not references and + // can therefore be deleted + + if( RC_BAD( rc = flmCheckDictFldRefs( m_pDb->pDict, uiItem))) { goto Exit; } } } - else if (ITT_IS_ENCDEF( pItt) && !m_pDb->pFile->bInLimitedMode) + else if( ITT_IS_ENCDEF( pItt) && !m_pDb->pFile->bInLimitedMode) { - if (RC_BAD( rc = fdictGetEncInfo( - m_pDb, - uiItem, - NULL, - &m_puiStateTbl[ uiItem]))) + if( RC_BAD( rc = fdictGetEncInfo( m_pDb, uiItem, NULL, + &m_puiStateTbl[ uiItem]))) { goto Exit; } - if (m_puiStateTbl[ uiItem] == ITT_ENC_STATE_PURGE) + + if( m_puiStateTbl[ uiItem] == ITT_ENC_STATE_PURGE) { *pbFoundPurgeField = TRUE; - /* make sure this field is not references and - can therefore be deleted. */ - if (RC_BAD( rc = flmCheckDictEncDefRefs( m_pDb->pDict, uiItem))) + // Make sure this field is not references and + // can therefore be deleted. + + if( RC_BAD( rc = flmCheckDictEncDefRefs( m_pDb->pDict, uiItem))) { goto Exit; } @@ -845,39 +895,45 @@ Exit: Desc: Change the specified field's state. Currently this is only for "Checking" -> "Active" ****************************************************************************/ -RCODE DbDict::ChangeState( - FLMUINT uiFieldID, // Item to change - FLMUINT uiNewState) // New state +RCODE DbDict::changeState( + FLMUINT uiFieldID, + FLMUINT uiNewState) { - RCODE rc; - FLMBOOL bRestartTrans = FALSE; + RCODE rc = FERR_OK; + FLMBOOL bRestartTrans = FALSE; if( m_puiStateTbl[ uiFieldID] != ITT_FLD_STATE_CHECKING) { return( RC_SET( FERR_FAILURE)); } - if( m_pDb->uiTransType != FLM_NO_TRANS) + if( m_bInternalTrans) { - (void)flmAbortDbTrans( m_pDb); - bRestartTrans = TRUE; + if( m_pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( m_pDb); + bRestartTrans = TRUE; + } } - /* Change the state tables value for this field/record template */ + // Change the state tables value for this field/record template m_puiStateTbl[ uiFieldID] = 0; - /* Change the state of the dictionary item. */ + // Change the state of the dictionary item. if( RC_BAD( rc = flmChangeItemState( m_pDb, uiFieldID, uiNewState))) { goto Exit; } - /* Now restart the read transaction. */ + // Now restart the read transaction. + if( bRestartTrans) { - if (RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, + flmAssert( m_bInternalTrans); + + if( RC_BAD( rc = flmBeginDbTrans( m_pDb, FLM_READ_TRANS, 0, FLM_DONT_POISON_CACHE))) { goto Exit; @@ -893,32 +949,35 @@ Exit: Desc: Following a complete sweep of a database, this function will handle items that are still marked 'checking' or 'purge'. ****************************************************************************/ -RCODE DbDict::Finish() // Finish will make any final changes to the - // database's dictionary +RCODE DbDict::finish( void) { RCODE rc = FERR_OK; FLMUINT uiItem; - /* If we have a read transaction going then end it. */ - if( m_pDb->uiTransType != FLM_NO_TRANS) + // If we have an internal read transaction going then end it. + + if( m_bInternalTrans) { - (void)flmAbortDbTrans( m_pDb); + if( m_pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( m_pDb); + } } - /* Loop through the state table changing: - 'checking' fields to 'unused' and - deleting 'purged' fields */ + // Loop through the state table changing: 'checking' fields to 'unused' and + // deleting 'purged' fields - for( uiItem = 1; uiItem < m_uiTblSize && RC_OK( rc) ; uiItem++) + for( uiItem = 1; uiItem < m_uiTblSize && RC_OK( rc); uiItem++) { if( m_puiStateTbl[ uiItem] == ITT_FLD_STATE_CHECKING) { - /* Change state to "unused" */ + // Change state to "unused" + rc = flmChangeItemState( m_pDb, uiItem, ITT_FLD_STATE_UNUSED); } else if( m_puiStateTbl[ uiItem] == ITT_FLD_STATE_PURGE) { - /* Delete the 'purged' item */ + // Delete the 'purged' item if( RC_BAD( rc = FlmRecordDelete( (HFDB)m_pDb, FLM_DICT_CONTAINER, uiItem, FLM_NO_TIMEOUT | FLM_AUTO_TRANS))) @@ -930,9 +989,12 @@ RCODE DbDict::Finish() // Finish will make any final changes to the Exit: - if( m_pDb->uiTransType != FLM_NO_TRANS) + if( m_bInternalTrans) { - (void)flmAbortDbTrans( m_pDb); + if( m_pDb->uiTransType != FLM_NO_TRANS) + { + (void)flmAbortDbTrans( m_pDb); + } } return( rc); @@ -956,7 +1018,7 @@ RCODE flmChangeItemState( FlmRecord * pOldRecord = NULL; void * pvField; - // If needed start a update transaction ... + // If needed, start a update transaction if( pDb->uiTransType == FLM_NO_TRANS) { @@ -965,6 +1027,7 @@ RCODE flmChangeItemState( { goto Exit; } + bStartedTrans = TRUE; } diff --git a/flaim/util/basic_test.cpp b/flaim/util/basic_test.cpp index dd80fee..976abd8 100644 --- a/flaim/util/basic_test.cpp +++ b/flaim/util/basic_test.cpp @@ -1804,15 +1804,15 @@ Exit: Desc: ****************************************************************************/ RCODE IFlmTestImpl::deleteFieldTest( - FLMUINT uiFieldNum - ) + FLMUINT uiFieldNum) { - RCODE rc = FERR_OK; - FlmRecord * pDictRec = NULL; - FlmRecord * pNewRec = NULL; - void * pvField; - FLMUINT uiDrn; - FLMBOOL bPassed = FALSE; + RCODE rc = FERR_OK; + FlmRecord * pDictRec = NULL; + FlmRecord * pNewRec = NULL; + void * pvField; + FLMUINT uiDrn; + FLMBOOL bPassed = FALSE; + FLMBOOL bTransActive = FALSE; beginTest( "Delete Field Definition Test"); @@ -1927,12 +1927,26 @@ RCODE IFlmTestImpl::deleteFieldTest( goto Exit; } - if (RC_BAD( rc = FlmDbSweep( m_hDb, SWEEP_CHECKING_FLDS, EACH_CHANGE, NULL, NULL))) + if( RC_BAD( rc = FlmDbTransBegin( m_hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) + { + goto Exit; + } + + bTransActive = TRUE; + + if( RC_BAD( rc = FlmDbSweep( m_hDb, SWEEP_CHECKING_FLDS, + EACH_CHANGE, NULL, NULL))) { MAKE_ERROR_STRING( "calling FlmDbSweep", rc, m_szFailInfo); goto Exit; } + bTransActive = FALSE; + if( RC_BAD( rc = FlmDbTransCommit( m_hDb))) + { + goto Exit; + } + if (pNewRec) { pNewRec->Release(); @@ -2023,12 +2037,25 @@ RCODE IFlmTestImpl::deleteFieldTest( goto Exit; } - if (RC_BAD( rc = FlmDbSweep( m_hDb, SWEEP_PURGED_FLDS, EACH_CHANGE, NULL, NULL))) + if( RC_BAD( rc = FlmDbTransBegin( m_hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) + { + goto Exit; + } + + bTransActive = TRUE; + + if( RC_BAD( rc = FlmDbSweep( m_hDb, SWEEP_PURGED_FLDS, EACH_CHANGE, NULL, NULL))) { MAKE_ERROR_STRING( "calling FlmDbSweep", rc, m_szFailInfo); goto Exit; } + bTransActive = FALSE; + if( RC_BAD( rc = FlmDbTransCommit( m_hDb))) + { + goto Exit; + } + // Make sure the dictionary definition is gone now. if (pDictRec) @@ -2062,15 +2089,20 @@ RCODE IFlmTestImpl::deleteFieldTest( Exit: - if (pDictRec) + if( pDictRec) { pDictRec->Release(); } - if (pNewRec) + if( pNewRec) { pNewRec->Release(); } + + if( bTransActive) + { + FlmDbTransAbort( m_hDb); + } endTest( bPassed); return( rc); @@ -2228,7 +2260,7 @@ RCODE IFlmTestImpl::sortedFieldsTest( // Start an update transaction - if( RC_BAD( rc = FlmDbTransBegin( m_hDb, FLM_UPDATE_TRANS, 15))) + if( RC_BAD( rc = FlmDbTransBegin( m_hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) { MAKE_ERROR_STRING( "calling FlmDbTransBegin", rc, m_szFailInfo); goto Exit; @@ -3417,7 +3449,7 @@ RCODE IFlmTestImpl::reduceSizeTest( // Start a transaction and attempt to do the remove - should fail. - if( RC_BAD( rc = FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, 15))) + if( RC_BAD( rc = FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) { MAKE_ERROR_STRING( "calling FlmDbTransBegin", rc, m_szFailInfo); goto Exit; @@ -3466,7 +3498,7 @@ RCODE IFlmTestImpl::reduceSizeTest( goto Exit; } - if( RC_BAD( rc = FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, 15))) + if( RC_BAD( rc = FlmDbTransBegin( hDb, FLM_UPDATE_TRANS, FLM_NO_TIMEOUT))) { MAKE_ERROR_STRING( "calling FlmDbTransBegin", rc, m_szFailInfo); goto Exit;