From c44e49e82cd32cd4c699aa2315ea3e819af292dd Mon Sep 17 00:00:00 2001 From: ahodgkinson Date: Mon, 10 Jul 2006 23:38:53 +0000 Subject: [PATCH] Added option in FLAIM to disable direct I/O on Linux and Unix platforms. Re-architected the FTK I/O layer and cleaned up the async interfaces. git-svn-id: https://svn.code.sf.net/p/flaim/code/trunk@643 0109f412-320b-0410-ab79-c3e0c5ffbbe6 --- flaim/src/checksum.cpp | 1 - flaim/src/fdbcnfig.cpp | 13 +- flaim/src/fdbcopy.cpp | 56 +- flaim/src/fdbremov.cpp | 5 +- flaim/src/fdbrenam.cpp | 10 +- flaim/src/fdict.cpp | 2 +- flaim/src/ffilehdr.cpp | 4 +- flaim/src/filesys.h | 4 +- flaim/src/flaim.h | 8 +- flaim/src/flaimsys.h | 10 +- flaim/src/flbackup.cpp | 66 +- flaim/src/flcreate.cpp | 60 +- flaim/src/fldbglog.cpp | 141 +- flaim/src/flindex.cpp | 5 +- flaim/src/flmstat.cpp | 3 - flaim/src/flopen.cpp | 38 +- flaim/src/flreduce.cpp | 291 ++-- flaim/src/fqeval.cpp | 2 +- flaim/src/frebuild.cpp | 84 +- flaim/src/fsconvrt.cpp | 2 +- flaim/src/fslfileu.cpp | 7 +- flaim/src/fssearch.cpp | 2 - flaim/src/fstructs.h | 174 +-- flaim/src/fsysdata.cpp | 714 ++-------- flaim/src/ftrans.cpp | 36 +- flaim/src/imonchk.cpp | 6 +- flaim/src/imonfhsh.cpp | 2 +- flaim/src/imonfsys.cpp | 24 - flaim/src/imonix.cpp | 4 +- flaim/src/imonsel.cpp | 6 +- flaim/src/imonutil.cpp | 2 +- flaim/src/kybuild.cpp | 4 +- flaim/src/recover.cpp | 56 +- flaim/src/rfl.cpp | 177 +-- flaim/src/rfl.h | 6 +- flaim/src/scache.cpp | 397 ++---- flaim/src/translog.cpp | 99 +- flaim/util/basic_test.cpp | 2 +- flaim/util/flmunittest.cpp | 7 +- ftk/src/ftk.h | 998 +++++++------ ftk/src/ftkdir.cpp | 10 +- ftk/src/ftkfsys.cpp | 1523 +++++++++++++++++++- ftk/src/ftkftx.cpp | 14 +- ftk/src/ftkiobuf.cpp | 861 +++++------ ftk/src/ftklock.cpp | 14 +- ftk/src/ftkmem.cpp | 4 +- ftk/src/ftkmfh.cpp | 5 +- ftk/src/ftkmisc.cpp | 756 +++++++++- ftk/src/ftknlm.cpp | 2765 +++++++++++++++--------------------- ftk/src/ftksupr.cpp | 1018 ++++++------- ftk/src/ftksys.h | 1222 ++++++---------- ftk/src/ftkthrd.cpp | 12 - ftk/src/ftkunix.cpp | 1420 +++++------------- ftk/src/ftkwin.cpp | 1607 ++++++--------------- xflaim/src/fdbcopy.cpp | 33 +- xflaim/src/fdbremov.cpp | 7 + xflaim/src/fdbrenam.cpp | 10 + xflaim/src/ffilehdr.cpp | 34 + xflaim/src/filesys.h | 4 - xflaim/src/flaimsys.h | 10 +- xflaim/src/flbackup.cpp | 43 +- xflaim/src/flblddb.cpp | 72 +- xflaim/src/flclose.cpp | 2 +- xflaim/src/flcreate.cpp | 10 +- xflaim/src/flgethdr.cpp | 53 - xflaim/src/flindex.cpp | 7 +- xflaim/src/flopen.cpp | 63 +- xflaim/src/flreduce.cpp | 35 +- xflaim/src/frestore.cpp | 2 +- xflaim/src/fslfileu.cpp | 2 +- xflaim/src/fstructs.h | 183 +-- xflaim/src/fsysdata.cpp | 579 +------- xflaim/src/recover.cpp | 16 +- xflaim/src/rfl.cpp | 85 +- xflaim/src/rfl.h | 6 +- xflaim/src/scache.cpp | 274 ++-- xflaim/src/translog.cpp | 62 +- 77 files changed, 7192 insertions(+), 9159 deletions(-) delete mode 100644 xflaim/src/flgethdr.cpp diff --git a/flaim/src/checksum.cpp b/flaim/src/checksum.cpp index 9faf235..182eb83 100644 --- a/flaim/src/checksum.cpp +++ b/flaim/src/checksum.cpp @@ -138,7 +138,6 @@ RCODE BlkCheckSum( // will be zero), so forgiving it will be OK most of the time. // So that those don't cause us to report block checksum errors, // we just allow it - checksumming isn't a perfect check anyway. - // VISIT: We do eventually want to get rid of this forgiving code. if (uiNewChecksum == uiCurrChecksum || ((!uiNewChecksum) && (uiCurrChecksum == 1))) diff --git a/flaim/src/fdbcnfig.cpp b/flaim/src/fdbcnfig.cpp index 7884358..eff394a 100644 --- a/flaim/src/fdbcnfig.cpp +++ b/flaim/src/fdbcnfig.cpp @@ -934,8 +934,7 @@ FSTATIC RCODE flmDbGetSizes( // Open the file and get its size. if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( szTmpName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pFileHdl))) + gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { if (rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH) { @@ -1022,12 +1021,10 @@ FSTATIC RCODE flmDbGetSizes( // Open the file and get its size. - if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - szTmpName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pFileHdl))) + if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( + szTmpName, gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { - if (rc == FERR_IO_PATH_NOT_FOUND || + if( rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH) { rc = FERR_OK; @@ -1040,7 +1037,7 @@ FSTATIC RCODE flmDbGetSizes( } else { - if (RC_BAD( rc = pFileHdl->size( &ui64LastFileSize))) + if( RC_BAD( rc = pFileHdl->size( &ui64LastFileSize))) { goto Exit; } diff --git a/flaim/src/fdbcopy.cpp b/flaim/src/fdbcopy.cpp index e36370b..10dd9bb 100644 --- a/flaim/src/fdbcopy.cpp +++ b/flaim/src/fdbcopy.cpp @@ -79,6 +79,8 @@ FLMEXP RCODE FLMAPI FlmDbCopy( { goto Exit; } + + gv_FlmSysData.pFileHdlCache->closeUnusedFiles(); // Open the database so we can force a checkpoint. @@ -236,7 +238,9 @@ FSTATIC RCODE flmCopyDb( goto Exit; } - if( RC_BAD( rc = pSrcSFileHdl->setup( pSrcSFileClient))) + if( RC_BAD( rc = pSrcSFileHdl->setup( pSrcSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -350,7 +354,9 @@ FSTATIC RCODE flmCopyDb( goto Exit; } - if( RC_BAD( rc = pDestSFileHdl->setup( pDestSFileClient))) + if( RC_BAD( rc = pDestSFileHdl->setup( pDestSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -437,10 +443,9 @@ FSTATIC RCODE flmCopyDb( goto Exit; } - if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - pszActualSrcRflPath, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pTmpFileHdl))) + if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( + pszActualSrcRflPath, gv_FlmSysData.uiFileOpenFlags, + &pTmpFileHdl))) { if (rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH) @@ -509,8 +514,8 @@ FSTATIC RCODE flmCopyDb( // Close all file handles in the source and destination - pSrcSFileHdl->releaseFiles( TRUE); - pDestSFileHdl->releaseFiles( TRUE); + pSrcSFileHdl->releaseFiles(); + pDestSFileHdl->releaseFiles(); // Copy the database files. @@ -900,8 +905,7 @@ FSTATIC RCODE flmCopyFile( // Open the source file. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - pDbCopyInfo->szSrcFileName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, + pDbCopyInfo->szSrcFileName, gv_FlmSysData.uiFileOpenFlags, &pSrcFileHdl))) { goto Exit; @@ -911,8 +915,7 @@ FSTATIC RCODE flmCopyFile( // not exist, attempt to create it. if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - pDbCopyInfo->szDestFileName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, + pDbCopyInfo->szDestFileName, gv_FlmSysData.uiFileOpenFlags, &pDestFileHdl))) { if (rc != FERR_IO_PATH_NOT_FOUND && @@ -922,9 +925,7 @@ FSTATIC RCODE flmCopyFile( } if( RC_BAD( rc = gv_FlmSysData.pFileSystem->createFile( - pDbCopyInfo->szDestFileName, - FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_SH_DENYNONE | - FLM_IO_CREATE_DIR | FLM_IO_DIRECT, + pDbCopyInfo->szDestFileName, gv_FlmSysData.uiFileCreateFlags, &pDestFileHdl))) { goto Exit; @@ -949,8 +950,7 @@ FSTATIC RCODE flmCopyFile( { // Read the first 2K of the source file. - if (RC_BAD( rc = pSrcFileHdl->sectorRead( 0L, 2048, - pucBuffer, &uiBytesRead))) + if (RC_BAD( rc = pSrcFileHdl->read( 0L, 2048, pucBuffer, &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) { @@ -980,20 +980,16 @@ FSTATIC RCODE flmCopyFile( f_memset( ucLogHdr, 0, sizeof(ucLogHdr)); } - /* - Set the transaction ID to zero. MUST ALSO SET THE TRANS ACTIVE FLAG - TO FALSE - OTHERWISE READERS WILL ATTEMPT TO DECREMENT THE - TRANSACTION ID AND WILL END UP WITH 0xFFFFFFFF - very bad! - We must use zero, because it is the only transaction ID that will not - appear on ANY block. - */ + // Set the transaction ID to zero. MUST ALSO SET THE TRANS ACTIVE FLAG + // TO FALSE - OTHERWISE READERS WILL ATTEMPT TO DECREMENT THE + // TRANSACTION ID AND WILL END UP WITH 0xFFFFFFFF - very bad! + // We must use zero, because it is the only transaction ID that will not + // appear on ANY block. UD2FBA( 0, &ucLogHdr [LOG_CURR_TRANS_ID]); - /* - Recalculate the log header checksum so that readers will not get a - checksum error. - */ + // Recalculate the log header checksum so that readers will not get a + // checksum error. uiNewChecksum = lgHdrCheckSum( ucLogHdr, FALSE); UW2FBA( (FLMUINT16)uiNewChecksum, &ucLogHdr [LOG_HDR_CHECKSUM]); @@ -1032,7 +1028,7 @@ FSTATIC RCODE flmCopyFile( // Read data from source file. - if (RC_BAD( rc = pSrcFileHdl->sectorRead( uiOffset, uiBytesToRead, + if (RC_BAD( rc = pSrcFileHdl->read( uiOffset, uiBytesToRead, pucBuffer, &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) @@ -1089,7 +1085,9 @@ FSTATIC RCODE flmCopyFile( // than we asked for. if (uiOffset >= uiEndOffset || uiBytesRead < uiBytesToRead) + { break; + } } // If we overwrote the destination file, as opposed to creating diff --git a/flaim/src/fdbremov.cpp b/flaim/src/fdbremov.cpp index eda44bb..08e532c 100644 --- a/flaim/src/fdbremov.cpp +++ b/flaim/src/fdbremov.cpp @@ -77,11 +77,12 @@ FLMEXP RCODE FLMAPI FlmDbRemove( goto Exit; } + gv_FlmSysData.pFileHdlCache->closeUnusedFiles(); + // Open the file so we can get the log header. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - pszDbName, FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pFileHdl))) + pszDbName, gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { goto Exit; } diff --git a/flaim/src/fdbrenam.cpp b/flaim/src/fdbrenam.cpp index 7310ca7..b885883 100644 --- a/flaim/src/fdbrenam.cpp +++ b/flaim/src/fdbrenam.cpp @@ -277,23 +277,24 @@ FLMEXP RCODE FLMAPI FlmDbRename( // First make sure we have closed the databases and gotten rid of // them from our internal memory tables - in case they had been open. - if (RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, + if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, (void *)pszDbName, (void *)pszDataDir))) { goto Exit; } - if (RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, + if( RC_BAD( rc = FlmConfig( FLM_CLOSE_FILE, (void *)pszFullNewName, (void *)pszDataDir))) { goto Exit; } + + gv_FlmSysData.pFileHdlCache->closeUnusedFiles(); // Open the file so we can get the log header. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszDbName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pFileHdl))) + gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { goto Exit; } @@ -336,6 +337,7 @@ FLMEXP RCODE FLMAPI FlmDbRename( pszDataExtOld--; } + if (*pszExtOld != '.') { pszExtOld = pszOldName + f_strlen( pszOldName); diff --git a/flaim/src/fdict.cpp b/flaim/src/fdict.cpp index 9338b72..c58217a 100644 --- a/flaim/src/fdict.cpp +++ b/flaim/src/fdict.cpp @@ -3803,9 +3803,9 @@ FSTATIC RCODE fdictFixupIfdPointers( } // Move the field type to the pIfd->uiFlags + IFD_SET_FIELD_TYPE( pIfd, ITT_FLD_GET_TYPE( pItt)); - // Visit: We could verify all of the fields in the field path. // Need to include 'any', 'use', 'parent' tags as valid tags. if( !pItt->pvItem) diff --git a/flaim/src/ffilehdr.cpp b/flaim/src/ffilehdr.cpp index c21d54d..a595d48 100644 --- a/flaim/src/ffilehdr.cpp +++ b/flaim/src/ffilehdr.cpp @@ -349,8 +349,8 @@ RCODE flmWriteVersionNum( szVersionStr[ 3] = (FLMBYTE)(uiVersionNum % 10) + '0'; szVersionStr[ 4] = 0; - if (RC_OK( rc = pSFileHdl->writeHeader( - FLAIM_HEADER_START + FLM_FILE_FORMAT_VER_POS, + if (RC_OK( rc = pSFileHdl->writeBlock( + FSBlkAddress( 0, FLAIM_HEADER_START + FLM_FILE_FORMAT_VER_POS), FLM_FILE_FORMAT_VER_LEN, szVersionStr, &uiWriteBytes))) { diff --git a/flaim/src/filesys.h b/flaim/src/filesys.h index e3bb754..d61c776 100644 --- a/flaim/src/filesys.h +++ b/flaim/src/filesys.h @@ -1169,8 +1169,7 @@ struct UCUR; RCODE lgFlushLogBuffer( DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, - FFILE * pFile, - FLMBOOL bDoAsync); + FFILE * pFile); RCODE lgOutputBlock( DB_STATS * pDbStats, @@ -1178,7 +1177,6 @@ struct UCUR; FFILE * pFile, SCACHE * pLogBlock, FLMBYTE * pucBlk, - FLMBOOL bDoAsync, FLMUINT * puiLogEofRV); void lgSetSyncCheckpoint( diff --git a/flaim/src/flaim.h b/flaim/src/flaim.h index b5d595b..6510143 100644 --- a/flaim/src/flaim.h +++ b/flaim/src/flaim.h @@ -1757,8 +1757,14 @@ /// Input: pvValue2 is (FLMUINT), query stratify time limit (seconds).\ \n /// FlmGetConfig().\ Get maximum query stratify iterations.\ \n /// Output: pvValue is (FLMUINT *), maximum query stratify iterations. - FLM_QUERY_STRATIFY_LIMITS + FLM_QUERY_STRATIFY_LIMITS, + /// FlmConfig().\ Enable or disable direct I/O.\ \n + /// Input: pvValue1 is (FLMBOOL), TRUE = enable, FALSE = disable.\ \n + /// FlmGetConfig().\ Get direct I/O state.\ \n + /// Output: pvValue is (FLMBOOL *), TRUE = enabled, FALSE = disabled. + FLM_DIRECT_IO_STATE + } eFlmConfigTypes; // Defaults for certain settable items diff --git a/flaim/src/flaimsys.h b/flaim/src/flaimsys.h index 4e56413..7cec685 100644 --- a/flaim/src/flaimsys.h +++ b/flaim/src/flaimsys.h @@ -1076,10 +1076,6 @@ RCODE flmGetCSConnection( void flmCloseCSConnection( CS_CONTEXT ** ppCSContext); -RCODE flmAllocHashTbl( - FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV); - RCODE flmGetTmpDir( char * pszOutputTmpDir); @@ -1543,7 +1539,7 @@ RCODE impFileIsExpImp( void flmDbgLogExit( void); -#endif // #ifdef FLM_DBG_LOG +#endif // FLM_DBG_LOG void flmDeleteCCSRefs( FDICT * pDict); @@ -2603,6 +2599,10 @@ public: FLMUINT FLMAPI getFileOffset( FLMUINT uiBlockAddr); + FLMUINT FLMAPI getBlockAddress( + FLMUINT uiFileNumber, + FLMUINT uiFileOffset); + RCODE FLMAPI getFilePath( FLMUINT uiFileNumber, char * pszPath); diff --git a/flaim/src/flbackup.cpp b/flaim/src/flbackup.cpp index 677a66e..86646ac 100644 --- a/flaim/src/flbackup.cpp +++ b/flaim/src/flbackup.cpp @@ -134,16 +134,14 @@ public: private: - // Methods - RCODE signalThread( void); RCODE _setup( void); - static RCODE readThread( + static RCODE FLMAPI readThread( IF_Thread * pThread); - static RCODE writeThread( + static RCODE FLMAPI writeThread( IF_Thread * pThread); FLMBOOL m_bSetup; @@ -1224,6 +1222,8 @@ FLMEXP RCODE FLMAPI FlmDbRestore( (void)FlmConfig( FLM_CLOSE_FILE, (void *)pszDbPath, (void *)pszDataDir); + gv_FlmSysData.pFileHdlCache->closeUnusedFiles(); + // Lock the global mutex f_mutexLock( gv_FlmSysData.hShareMutex); @@ -1800,7 +1800,9 @@ FSTATIC RCODE flmRestoreFile( goto Exit; } - if( RC_BAD( rc = pSFile->setup( pSFileClient))) + if( RC_BAD( rc = pSFile->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1808,12 +1810,9 @@ FSTATIC RCODE flmRestoreFile( pSFile->setBlockSize( uiBlockSize); // Don't want to do extra file extensions or flush when file - // is extended. Setting the extend size to ~0 has the effect - // of not updating the directory entry (a time-consuming operation) - // on Windows platforms. On all other platforms, we will just - // go with the default behavior. + // is extended. - pSFile->setExtendSize( (FLMUINT)(~0)); + pSFile->setExtendSize( 0); *ppSFile = pSFile; (*ppSFile)->AddRef(); } @@ -1933,8 +1932,8 @@ FSTATIC RCODE flmRestoreFile( // Compare the incremental backup sequence number to the value in the // database's log header. - if( RC_BAD( rc = pSFile->readHeader( - DB_LOG_HEADER_START + LOG_INC_BACKUP_SEQ_NUM, + if( RC_BAD( rc = pSFile->readBlock( + FSBlkAddress( 0, DB_LOG_HEADER_START + LOG_INC_BACKUP_SEQ_NUM), 4, ucTmpSeqNum, &uiTmp))) { goto Exit; @@ -1949,8 +1948,8 @@ FSTATIC RCODE flmRestoreFile( // Compare the incremental backup serial number to the value in the // database's log header. - if( RC_BAD( rc = pSFile->readHeader( - DB_LOG_HEADER_START + LOG_INC_BACKUP_SERIAL_NUM, + if( RC_BAD( rc = pSFile->readBlock( + FSBlkAddress( 0, DB_LOG_HEADER_START + LOG_INC_BACKUP_SERIAL_NUM), F_SERIAL_NUM_SIZE, ucTmpSerialNum, &uiTmp))) { goto Exit; @@ -2004,7 +2003,7 @@ FSTATIC RCODE flmRestoreFile( // Write the database header - if( RC_BAD( rc = pSFile->writeHeader( 0, + if( RC_BAD( rc = pSFile->writeBlock( FSBlkAddress( 0, 0), uiBlockSize, pucBlkBuf, &uiBytesWritten))) { goto Exit; @@ -2090,17 +2089,9 @@ FSTATIC RCODE flmRestoreFile( pucBlkBuf[ BH_CHECKSUM_LOW] = ucLowChecksumByte; // Write the block to the database - // - // Unix systems can have sector sizes that are larger than our - // typical 4K database blocks. The Unix implementation of SectorWrite - // (called by writeBlock) will write the passed-in block and clobber any - // additional data beyond the end of the block to the end of the sector if - // it has enough room in the block buffer to write a full sector. If the - // block buffer is less than a full sector, the Unix SectorWrite will only - // write out the amount requested, not a full sector. if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) + uiBlockSize, pucBlkBuf, &uiBytesWritten))) { if( rc == FERR_IO_PATH_NOT_FOUND || rc == FERR_IO_INVALID_PATH) @@ -2120,7 +2111,7 @@ FSTATIC RCODE flmRestoreFile( } if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) + uiBlockSize, pucBlkBuf, &uiBytesWritten))) { goto Exit; } @@ -2793,11 +2784,11 @@ Exit: /**************************************************************************** Desc: This thread reads data in the background ****************************************************************************/ -RCODE F_BackerStream::readThread( +RCODE FLMAPI F_BackerStream::readThread( IF_Thread * pThread) { - F_BackerStream * pBackerStream = (F_BackerStream *)pThread->getParm1(); RCODE rc = FERR_OK; + F_BackerStream * pBackerStream = (F_BackerStream *)pThread->getParm1(); for( ;;) { @@ -2837,7 +2828,7 @@ Exit: /**************************************************************************** Desc: This thread writes data in the background ****************************************************************************/ -RCODE F_BackerStream::writeThread( +RCODE FLMAPI F_BackerStream::writeThread( IF_Thread * pThread) { RCODE rc = FERR_OK; @@ -3030,8 +3021,7 @@ RCODE F_FSRestore::openRflFile( // Open the file. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( - szRflPath, FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &m_pFileHdl))) + szRflPath, gv_FlmSysData.uiFileOpenFlags, &m_pFileHdl))) { goto Exit; } @@ -3067,13 +3057,11 @@ RCODE F_FSRestore::openIncFile( flmAssert( m_bSetupCalled); flmAssert( !m_pMultiFileHdl); - /* - Since this is a non-interactive restore, we will "guess" - that incremental backups are located in the same parent - directory as the main backup set. We will further assume - that the incremental backup sets have been named XXXXXXXX.INC, - where X is a hex digit. - */ + // Since this is a non-interactive restore, we will "guess" + // that incremental backups are located in the same parent + // directory as the main backup set. We will further assume + // that the incremental backup sets have been named XXXXXXXX.INC, + // where X is a hex digit. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->pathReduce( m_szBackupSetPath, szIncPath, NULL))) @@ -3112,8 +3100,8 @@ RCODE F_FSRestore::read( void * pvBuffer, FLMUINT * puiBytesRead) { - FLMUINT uiBytesRead = 0; RCODE rc = FERR_OK; + FLMUINT uiBytesRead = 0; flmAssert( m_bSetupCalled); flmAssert( m_pFileHdl || m_pMultiFileHdl); @@ -3134,6 +3122,8 @@ RCODE F_FSRestore::read( goto Exit; } } + + f_assert( uiBytesRead <= uiLength); Exit: diff --git a/flaim/src/flcreate.cpp b/flaim/src/flcreate.cpp index 1929a09..5ff99b7 100644 --- a/flaim/src/flcreate.cpp +++ b/flaim/src/flcreate.cpp @@ -278,7 +278,9 @@ RCODE flmCreateNewFile( goto Exit; } - if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -474,34 +476,33 @@ FSTATIC RCODE flmInitFileHdrs( CREATE_OPTS * pCreateOpts, FLMUINT uiBlkSize, FLMUINT uiTransID, - FLMBYTE * pInitBuf) + FLMBYTE * pucInitBuf) { RCODE rc = FERR_OK; FFILE * pFile = pDb->pFile; FLMBYTE * pucLastCommittedLogHdr; FLMUINT uiLogicalEOF; - FLMUINT uiWriteBytes; FLMUINT uiMinRflFileSize; FLMUINT uiMaxRflFileSize; FLMBYTE * pucBuf = NULL; // Initialize the FFILE structure and first 2048 bytes/blk of the file. - f_memset( pInitBuf, 0, uiBlkSize); + f_memset( pucInitBuf, 0, uiBlkSize); flmInitFileHdrInfo( pCreateOpts, &pFile->FileHdr, - &pInitBuf [FLAIM_HEADER_START]); + &pucInitBuf [FLAIM_HEADER_START]); if (pCreateOpts) { - flmSetFilePrefix( pInitBuf, pCreateOpts->uiAppMajorVer, + flmSetFilePrefix( pucInitBuf, pCreateOpts->uiAppMajorVer, pCreateOpts->uiAppMinorVer); } else { - flmSetFilePrefix( pInitBuf, 0, 0); + flmSetFilePrefix( pucInitBuf, 0, 0); } - if (RC_BAD( rc = pDb->pSFileHdl->writeHeader( 0L, uiBlkSize, - pInitBuf, &uiWriteBytes))) + if (RC_BAD( rc = pDb->pSFileHdl->writeBlock( 0L, uiBlkSize, + pucInitBuf, NULL))) { goto Exit; } @@ -697,22 +698,21 @@ FSTATIC RCODE flmInitFileHdrs( // Initialize and output the first LFH block - f_memset( pInitBuf, 0, uiBlkSize); - SET_BH_ADDR( pInitBuf, (FLMUINT32)pFile->FileHdr.uiFirstLFHBlkAddr); - pInitBuf [BH_TYPE] = BHT_LFH_BLK; - UD2FBA( (FLMUINT32)BT_END, &pInitBuf [BH_PREV_BLK]); - UD2FBA( (FLMUINT32)BT_END, &pInitBuf [BH_NEXT_BLK]); - UW2FBA( (FLMUINT16)BH_OVHD, &pInitBuf [BH_ELM_END]); - UD2FBA( (FLMUINT32)uiTransID, &pInitBuf [BH_TRANS_ID]); + f_memset( pucInitBuf, 0, uiBlkSize); + SET_BH_ADDR( pucInitBuf, (FLMUINT32)pFile->FileHdr.uiFirstLFHBlkAddr); + pucInitBuf [BH_TYPE] = BHT_LFH_BLK; + UD2FBA( (FLMUINT32)BT_END, &pucInitBuf [BH_PREV_BLK]); + UD2FBA( (FLMUINT32)BT_END, &pucInitBuf [BH_NEXT_BLK]); + UW2FBA( (FLMUINT16)BH_OVHD, &pucInitBuf [BH_ELM_END]); + UD2FBA( (FLMUINT32)uiTransID, &pucInitBuf [BH_TRANS_ID]); - BlkCheckSum( pInitBuf, CHECKSUM_SET, + BlkCheckSum( pucInitBuf, CHECKSUM_SET, pFile->FileHdr.uiFirstLFHBlkAddr, uiBlkSize); pDb->pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); pDb->pSFileHdl->setExtendSize( pFile->uiFileExtendSize); - if (RC_BAD( rc = pDb->pSFileHdl->writeBlock( - pFile->FileHdr.uiFirstLFHBlkAddr, - uiBlkSize, pInitBuf, NULL, &uiWriteBytes))) + if( RC_BAD( rc = pDb->pSFileHdl->writeBlock( + pFile->FileHdr.uiFirstLFHBlkAddr, uiBlkSize, pucInitBuf, NULL))) { goto Exit; } @@ -723,20 +723,20 @@ FSTATIC RCODE flmInitFileHdrs( { FLMUINT uiPcodeAddr; - f_memset( pInitBuf, 0, uiBlkSize); + f_memset( pucInitBuf, 0, uiBlkSize); uiPcodeAddr = pFile->FileHdr.uiFirstLFHBlkAddr + uiBlkSize; - SET_BH_ADDR( pInitBuf, (FLMUINT32)uiPcodeAddr); - pInitBuf [BH_TYPE] = BHT_PCODE_BLK; - UD2FBA( (FLMUINT32)BT_END, &pInitBuf [BH_PREV_BLK]); - UD2FBA( (FLMUINT32)BT_END, &pInitBuf [BH_NEXT_BLK]); - UW2FBA( (FLMUINT16)BH_OVHD, &pInitBuf [BH_ELM_END]); - UD2FBA( (FLMUINT32)uiTransID, &pInitBuf [BH_TRANS_ID]); + SET_BH_ADDR( pucInitBuf, (FLMUINT32)uiPcodeAddr); + pucInitBuf [BH_TYPE] = BHT_PCODE_BLK; + UD2FBA( (FLMUINT32)BT_END, &pucInitBuf [BH_PREV_BLK]); + UD2FBA( (FLMUINT32)BT_END, &pucInitBuf [BH_NEXT_BLK]); + UW2FBA( (FLMUINT16)BH_OVHD, &pucInitBuf [BH_ELM_END]); + UD2FBA( (FLMUINT32)uiTransID, &pucInitBuf [BH_TRANS_ID]); - BlkCheckSum( pInitBuf, CHECKSUM_SET, uiPcodeAddr, uiBlkSize); + BlkCheckSum( pucInitBuf, CHECKSUM_SET, uiPcodeAddr, uiBlkSize); pDb->pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); pDb->pSFileHdl->setExtendSize( pFile->uiFileExtendSize); - if (RC_BAD( rc = pDb->pSFileHdl->writeBlock( uiPcodeAddr, - uiBlkSize, pInitBuf, NULL, &uiWriteBytes))) + if (RC_BAD( rc = pDb->pSFileHdl->writeBlock( + uiPcodeAddr, uiBlkSize, pucInitBuf, NULL))) { goto Exit; } diff --git a/flaim/src/fldbglog.cpp b/flaim/src/fldbglog.cpp index 9332fe2..76e57bd 100644 --- a/flaim/src/fldbglog.cpp +++ b/flaim/src/fldbglog.cpp @@ -31,51 +31,47 @@ FSTATIC void _flmDbgLogFlush( void); FSTATIC void _flmDbgOutputMsg( char * pszMsg); -// Global data - -F_MUTEX g_hDbgLogMutex = F_MUTEX_NULL; -F_FileSystem * g_pFileSystem = NULL; -F_FileHdl * g_pLogFile = NULL; -char * g_pszLogBuf = NULL; -FLMUINT g_uiLogBufOffset = 0; -FLMUINT g_uiLogFileOffset = 0; -FLMBOOL g_bDbgLogEnabled = TRUE; +F_MUTEX gv_hDbgLogMutex = F_MUTEX_NULL; +IF_FileSystem * gv_pFileSystem = NULL; +IF_FileHdl * gv_pLogFile = NULL; +char * gv_pszLogBuf = NULL; +FLMUINT gv_uiLogBufOffset = 0; +FLMUINT gv_uiLogFileOffset = 0; +FLMBOOL gv_bDbgLogEnabled = TRUE; #define DBG_LOG_BUFFER_SIZE ((FLMUINT)512000) - /**************************************************************************** Desc: ****************************************************************************/ void flmDbgLogInit( void) { - FLMBYTE szLogPath[ 256]; RCODE rc = FERR_OK; + char szLogPath[ 256]; - flmAssert( g_hDbgLogMutex == F_MUTEX_NULL); - flmAssert( g_pFileSystem == NULL); + flmAssert( gv_hDbgLogMutex == F_MUTEX_NULL); + flmAssert( gv_pFileSystem == NULL); // Allocate a buffer for the log if( RC_BAD( rc = f_alloc( - DBG_LOG_BUFFER_SIZE + 1024, &g_pszLogBuf))) + DBG_LOG_BUFFER_SIZE + 1024, &gv_pszLogBuf))) { goto Exit; } // Create the mutex - if( RC_BAD( f_mutexCreate( &g_hDbgLogMutex))) + if( RC_BAD( f_mutexCreate( &gv_hDbgLogMutex))) { rc = RC_SET( FERR_MEM); goto Exit; } // Create a new file system object - - if( (g_pFileSystem = f_new F_FileSystem) == NULL) + + if( RC_BAD( rc = FlmGetFileSystem( &gv_pFileSystem))) { - rc = RC_SET( FERR_MEM); goto Exit; } @@ -89,16 +85,17 @@ void flmDbgLogInit( void) // Create the file. - if( RC_BAD( rc = g_pFileSystem->Create( szLogPath, - F_IO_RDWR | F_IO_EXCL | F_IO_SH_DENYNONE | F_IO_DIRECT, &g_pLogFile))) + if( RC_BAD( rc = gv_pFileSystem->createFile( szLogPath, + FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, + &gv_pLogFile))) { // See if we can open the file and then truncate it. - if( RC_OK( g_pFileSystem->Open( szLogPath, - F_IO_RDWR | F_IO_SH_DENYNONE | F_IO_DIRECT, &g_pLogFile))) + if( RC_OK( gv_pFileSystem->openFile( szLogPath, + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &gv_pLogFile))) { - if( RC_BAD( rc = g_pLogFile->Truncate( 0))) + if( RC_BAD( rc = gv_pLogFile->truncate())) { goto Exit; } @@ -119,12 +116,12 @@ Desc: ****************************************************************************/ void flmDbgLogExit( void) { - if( g_bDbgLogEnabled) + if( gv_bDbgLogEnabled) { // Output "Log End" message - f_mutexLock( g_hDbgLogMutex); + f_mutexLock( gv_hDbgLogMutex); _flmDbgOutputMsg( "--- LOG END ---"); - f_mutexUnlock( g_hDbgLogMutex); + f_mutexUnlock( gv_hDbgLogMutex); // Flush the log flmDbgLogFlush(); @@ -132,33 +129,33 @@ void flmDbgLogExit( void) // Free all resources - if( g_hDbgLogMutex != F_MUTEX_NULL) + if( gv_hDbgLogMutex != F_MUTEX_NULL) { - f_mutexDestroy( &g_hDbgLogMutex); + f_mutexDestroy( &gv_hDbgLogMutex); } - if( g_pszLogBuf) + if( gv_pszLogBuf) { - f_free( &g_pszLogBuf); + f_free( &gv_pszLogBuf); } - if( g_pLogFile) + if( gv_pLogFile) { - g_pLogFile->Truncate( g_uiLogFileOffset + g_uiLogBufOffset); - g_pLogFile->Close(); - g_pLogFile->Release(); - g_pLogFile = NULL; + gv_pLogFile->truncate( gv_uiLogFileOffset + gv_uiLogBufOffset); + gv_pLogFile->close(); + gv_pLogFile->Release(); + gv_pLogFile = NULL; } - if( g_pFileSystem) + if( gv_pFileSystem) { - g_pFileSystem->Release(); - g_pFileSystem = NULL; + gv_pFileSystem->Release(); + gv_pFileSystem = NULL; } - g_bDbgLogEnabled = FALSE; + + gv_bDbgLogEnabled = FALSE; } - /**************************************************************************** Desc: ****************************************************************************/ @@ -171,8 +168,10 @@ void flmDbgLogWrite( { char pszTmpBuf[ 256]; - if( !g_bDbgLogEnabled) + if( !gv_bDbgLogEnabled) + { return; + } if( !uiWriteAddress) { @@ -187,12 +186,11 @@ void flmDbgLogWrite( (unsigned)uiBlkAddress, (unsigned)uiWriteAddress, (unsigned)uiTransId, pszEvent); } - f_mutexLock( g_hDbgLogMutex); + f_mutexLock( gv_hDbgLogMutex); _flmDbgOutputMsg( pszTmpBuf); - f_mutexUnlock( g_hDbgLogMutex); + f_mutexUnlock( gv_hDbgLogMutex); } - /**************************************************************************** Desc: ****************************************************************************/ @@ -207,7 +205,7 @@ void flmDbgLogUpdate( char pszTmpBuf[ 256]; char szErr [12]; - if (!g_bDbgLogEnabled) + if (!gv_bDbgLogEnabled) { return; } @@ -235,37 +233,37 @@ void flmDbgLogUpdate( szErr); } - f_mutexLock( g_hDbgLogMutex); + f_mutexLock( gv_hDbgLogMutex); _flmDbgOutputMsg( pszTmpBuf); - f_mutexUnlock( g_hDbgLogMutex); + f_mutexUnlock( gv_hDbgLogMutex); } - /**************************************************************************** Desc: ****************************************************************************/ void flmDbgLogMsg( char * pszMsg) { - if (!g_bDbgLogEnabled) + if (!gv_bDbgLogEnabled) + { return; - f_mutexLock( g_hDbgLogMutex); + } + + f_mutexLock( gv_hDbgLogMutex); _flmDbgOutputMsg( pszMsg); - f_mutexUnlock( g_hDbgLogMutex); + f_mutexUnlock( gv_hDbgLogMutex); } - /**************************************************************************** Desc: ****************************************************************************/ void flmDbgLogFlush( void) { - f_mutexLock( g_hDbgLogMutex); + f_mutexLock( gv_hDbgLogMutex); _flmDbgLogFlush(); - f_mutexUnlock( g_hDbgLogMutex); + f_mutexUnlock( gv_hDbgLogMutex); } - /**************************************************************************** Desc: ****************************************************************************/ @@ -273,8 +271,8 @@ FSTATIC void _flmDbgLogFlush( void) { FLMUINT uiBytesToWrite; FLMUINT uiBytesWritten; - char * pszBufPtr = g_pszLogBuf; - FLMUINT uiTotalToWrite = g_uiLogBufOffset; + char * pszBufPtr = gv_pszLogBuf; + FLMUINT uiTotalToWrite = gv_uiLogBufOffset; RCODE rc = FERR_OK; FLMUINT uiBufferSize = DBG_LOG_BUFFER_SIZE + 1024; @@ -289,34 +287,32 @@ FSTATIC void _flmDbgLogFlush( void) uiBytesToWrite = uiTotalToWrite; } - if( RC_BAD( rc = g_pLogFile->sectorWrite( - g_uiLogFileOffset, uiBytesToWrite, - pszBufPtr, uiBufferSize, NULL, &uiBytesWritten, FALSE))) + if( RC_BAD( rc = gv_pLogFile->write( gv_uiLogFileOffset, uiBytesToWrite, + pszBufPtr, &uiBytesWritten))) { goto Exit; } flmAssert( uiBytesToWrite == uiBytesWritten); - g_uiLogFileOffset += uiBytesWritten; + gv_uiLogFileOffset += uiBytesWritten; pszBufPtr += uiBytesWritten; uiBufferSize -= uiBytesWritten; uiTotalToWrite -= uiBytesWritten; } - if (g_uiLogBufOffset & 0x1FF) + if (gv_uiLogBufOffset & 0x1FF) { - if (g_uiLogBufOffset > 512) + if (gv_uiLogBufOffset > 512) { - f_memcpy( g_pszLogBuf, - &g_pszLogBuf [g_uiLogBufOffset & 0xFFFFFE00], - 512); - g_uiLogBufOffset &= 0x1FF; + f_memcpy( gv_pszLogBuf, + &gv_pszLogBuf [gv_uiLogBufOffset & 0xFFFFFE00], 512); + gv_uiLogBufOffset &= 0x1FF; } - g_uiLogFileOffset -= g_uiLogBufOffset; + gv_uiLogFileOffset -= gv_uiLogBufOffset; } else { - g_uiLogBufOffset = 0; + gv_uiLogBufOffset = 0; } Exit: @@ -324,19 +320,18 @@ Exit: flmAssert( RC_OK( rc)); } - /**************************************************************************** Desc: ****************************************************************************/ void _flmDbgOutputMsg( char * pszMsg) { - char * pszBufPtr = &(g_pszLogBuf[ g_uiLogBufOffset]); + char * pszBufPtr = &(gv_pszLogBuf[ gv_uiLogBufOffset]); f_sprintf( pszBufPtr, "%s\n", pszMsg); - g_uiLogBufOffset += f_strlen( pszBufPtr); + gv_uiLogBufOffset += f_strlen( pszBufPtr); - if( g_uiLogBufOffset >= DBG_LOG_BUFFER_SIZE) + if( gv_uiLogBufOffset >= DBG_LOG_BUFFER_SIZE) { _flmDbgLogFlush(); } diff --git a/flaim/src/flindex.cpp b/flaim/src/flindex.cpp index 25c238f..f7a1789 100644 --- a/flaim/src/flindex.cpp +++ b/flaim/src/flindex.cpp @@ -24,7 +24,7 @@ #include "flaimsys.h" -FSTATIC RCODE flmBackgroundIndexBuildThrd( +FSTATIC RCODE FLMAPI flmBackgroundIndexBuildThrd( IF_Thread * pThread); FSTATIC void stopBackgroundIndexThread( @@ -1089,7 +1089,7 @@ Desc: Thread that will build an index in the background. Caller will create a pDb to use. This pDb must be freed at the conclusion of the routine. ****************************************************************************/ -FSTATIC RCODE flmBackgroundIndexBuildThrd( +FSTATIC RCODE FLMAPI flmBackgroundIndexBuildThrd( IF_Thread * pThread) { RCODE rc = FERR_OK; @@ -1370,7 +1370,6 @@ Loop_Again: goto Exit; } - pThread->setThreadStatus( FLM_THREAD_STATUS_COMMITTING_TRANS); if( pBackgroundIx->indexStatus.uiRecordsProcessed - savedIxStatus.uiRecordsProcessed) { diff --git a/flaim/src/flmstat.cpp b/flaim/src/flmstat.cpp index 91a2f0f..30e642a 100644 --- a/flaim/src/flmstat.cpp +++ b/flaim/src/flmstat.cpp @@ -1317,9 +1317,6 @@ BLOCKIO_STATS * flmGetBlockIOStatPtr( pLFileStats->bHaveStats = pDbStats->bHaveStats = TRUE; - // VISIT: Consider a one level tree. - // Is it more important to count root stats over leaf stats? - // Consider invalid type. if ((BH_GET_TYPE( pBlk) != BHT_LEAF) && diff --git a/flaim/src/flopen.cpp b/flaim/src/flopen.cpp index 17d4eef..a2e271f 100644 --- a/flaim/src/flopen.cpp +++ b/flaim/src/flopen.cpp @@ -42,14 +42,14 @@ FSTATIC RCODE flmReadFileHdr( FSTATIC void flmFreeCPInfo( CP_INFO ** ppCPInfoRV); -FSTATIC RCODE flmCPThread( +FSTATIC RCODE FLMAPI flmCPThread( IF_Thread * pThread); FSTATIC RCODE flmDoRecover( FDB * pDb, F_Restore * pRestoreObj); -FSTATIC RCODE flmDbMonitor( +FSTATIC RCODE FLMAPI flmDbMonitor( IF_Thread * pThread); /**************************************************************************** @@ -365,7 +365,7 @@ Desc: This routine performs all of the necessary steps to complete waiting for the open or create to complete. ****************************************************************************/ RCODE flmCompleteOpenOrCreate( - FDB * * ppDb, + FDB ** ppDb, RCODE rc, FLMBOOL bNewFile, FLMBOOL bAllocatedFdb) @@ -632,7 +632,9 @@ RCODE flmOpenFile( goto Exit; } - if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1014,7 +1016,9 @@ FSTATIC RCODE flmPhysFileOpen( goto Exit; } - if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pDb->pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1103,7 +1107,7 @@ RCODE flmFindFile( FFILE ** ppFileRV) { RCODE rc = FERR_OK; - FBUCKET * pBucket; + F_BUCKET * pBucket; FLMUINT uiBucket; FLMBOOL bMutexLocked = TRUE; FFILE * pFile; @@ -1272,26 +1276,25 @@ RCODE flmAllocFile( // If a password was passed in, allocate a buffer for it. - if (pszDbPassword && pszDbPassword[0]) + if( pszDbPassword && pszDbPassword[0]) { if (RC_BAD( rc = f_calloc( f_strlen( pszDbPassword) + 1, &pFile->pszDbPassword))) { goto Exit; } - f_memcpy( pFile->pszDbPassword, pszDbPassword, f_strlen(pszDbPassword)); + + f_memcpy( pFile->pszDbPassword, pszDbPassword, f_strlen( pszDbPassword)); } // Setup the write buffer managers. - if( RC_BAD( rc = FlmAllocIOBufferMgr( &pFile->pBufferMgr))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( MAX_PENDING_WRITES, + MAX_WRITE_BUFFER_BYTES, FALSE, &pFile->pBufferMgr))) { goto Exit; } - pFile->pBufferMgr->setMaxBuffers( MAX_PENDING_WRITES); - pFile->pBufferMgr->setMaxBytes( MAX_WRITE_BUFFER_BYTES); - // Initialize members of FFILE. pFile->uiBucket = 0xFFFF; @@ -1316,6 +1319,7 @@ RCODE flmAllocFile( { goto Exit; } + flmLinkFileToNUList( pFile); // Allocate a lock object for write locking. @@ -1371,7 +1375,7 @@ FSTATIC RCODE flmReadFileHdr( // Read and verify the file and log headers. if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszDbPath, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &pFileHdl))) + gv_FlmSysData.uiFileOpenFlags, &pFileHdl))) { goto Exit; } @@ -1552,7 +1556,9 @@ RCODE flmStartCPThread( goto Exit; } - if( RC_BAD( rc = pCPInfo->pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pCPInfo->pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1629,7 +1635,7 @@ Desc: This routine functions as a thread. It monitors open files and frees up files which have been closed longer than the maximum close time. ****************************************************************************/ -FSTATIC RCODE flmCPThread( +FSTATIC RCODE FLMAPI flmCPThread( IF_Thread * pThread) { RCODE rc = FERR_OK; @@ -2208,7 +2214,7 @@ Clear_Session_ID: /**************************************************************************** Desc: ****************************************************************************/ -RCODE flmDbMonitor( +RCODE FLMAPI flmDbMonitor( IF_Thread * pThread) { RCODE rc = FERR_OK; diff --git a/flaim/src/flreduce.cpp b/flaim/src/flreduce.cpp index 67ff27a..ec27243 100644 --- a/flaim/src/flreduce.cpp +++ b/flaim/src/flreduce.cpp @@ -62,23 +62,22 @@ Notes: The size of the database file is reduced by freeing a specified FLMEXP RCODE FLMAPI FlmDbReduceSize( HFDB hDb, FLMUINT uiCount, - FLMUINT * puiCountRV - ) + FLMUINT * puiCountRV) { - RCODE rc; - FDB * pDb = (FDB *) hDb; - F_Rfl * pRfl = NULL; - FLMUINT uiLogicalEOF; /* Local variable- change dbd->logEof last*/ - FLMUINT uiBlkAddr; - FLMUINT uiNumBlksMoved = 0; /* Initialize before again: goto loop */ - FLMUINT uiBlkSize; - FLMBYTE BlkHeader [BH_OVHD + BH_OVHD ]; /* Enough for future log extent */ - FLMINT iType; - FLMBOOL bIgnore; - FLMBOOL bLoggingWasOff = FALSE; - FLMBOOL bRestoreLoggingOffFlag = FALSE; - FLMBOOL bLockedDatabase = FALSE; - FLMBOOL bDone = FALSE; + RCODE rc = FERR_OK; + FDB * pDb = (FDB *) hDb; + F_Rfl * pRfl = NULL; + FLMUINT uiLogicalEOF; + FLMUINT uiBlkAddr; + FLMUINT uiNumBlksMoved = 0; + FLMUINT uiBlkSize; + FLMBYTE BlkHeader [BH_OVHD + BH_OVHD ]; + FLMINT iType; + FLMBOOL bIgnore; + FLMBOOL bLoggingWasOff = FALSE; + FLMBOOL bRestoreLoggingOffFlag = FALSE; + FLMBOOL bLockedDatabase = FALSE; + FLMBOOL bDone = FALSE; // Lock the database if not already locked. // Cannot lose exclusive access between the checkpoint and @@ -183,30 +182,24 @@ Transmission_Error: uiLogicalEOF = pDb->LogHdr.uiLogicalEOF; - while( (pDb->LogHdr.uiFirstAvailBlkAddr != BT_END ) - && ((!uiCount) || (uiNumBlksMoved < uiCount))) + while( (pDb->LogHdr.uiFirstAvailBlkAddr != BT_END) && + ((!uiCount) || (uiNumBlksMoved < uiCount))) { // Read the last block and determine block type if( FSGetFileOffset( uiLogicalEOF) == 0) { - IF_FileHdl * pFileHdl = NULL; FLMUINT uiFileNumber = FSGetFileNumber( uiLogicalEOF) - 1; FLMUINT64 ui64FileSize; FLMUINT uiTemp; - - if( RC_BAD( rc = pDb->pSFileHdl->getFileHdl( - uiFileNumber, TRUE, &pFileHdl))) + + if( RC_BAD( rc = pDb->pSFileHdl->getFileSize( uiFileNumber, + &ui64FileSize))) { goto Reduce_Size_Error; } - if( RC_BAD( rc = pFileHdl->size( &ui64FileSize))) - { - goto Reduce_Size_Error; - } - // Adjust to a block bounds uiTemp = (FLMUINT)((ui64FileSize / uiBlkSize) * uiBlkSize); @@ -274,7 +267,6 @@ Transmission_Error: { FLMUINT uiFileNumber = FSGetFileNumber( uiLogicalEOF); FLMUINT64 ui64FileOffset; - IF_FileHdl * pFileHdl = NULL; if( uiFileNumber <= 1) { @@ -288,13 +280,8 @@ Transmission_Error: // Compute the end of the previous block file. - if( RC_BAD( rc = pDb->pSFileHdl->getFileHdl( - uiFileNumber, TRUE, &pFileHdl))) - { - goto Exit; - } - - if( RC_BAD( rc = pFileHdl->size( &ui64FileOffset))) + if( RC_BAD( rc = pDb->pSFileHdl->getFileSize( uiFileNumber, + &ui64FileOffset))) { goto Exit; } @@ -366,16 +353,16 @@ Exit: *puiCountRV = uiNumBlksMoved; } - if (bRestoreLoggingOffFlag) + if( bRestoreLoggingOffFlag) { pRfl->setLoggingOffState( bLoggingWasOff); } - if (bLockedDatabase) + if( bLockedDatabase) { - (void) FlmDbUnlock( hDb); + FlmDbUnlock( hDb); } - + flmExit( FLM_DB_REDUCE_SIZE, pDb, rc); return( rc); @@ -398,18 +385,14 @@ FSTATIC RCODE FLRReadBlkHdr( RCODE rc = FERR_OK; FLMUINT uiBytesRead; FLMUINT uiNumLooks; - IF_FileHdl * pTmpFileHdl = NULL; SCACHE * pBlkSCache; DB_STATS * pDbStats = pDb->pDbStats; LFILE_STATS * pLFileStats; F_TMSTAMP StartTime; FLMUINT64 ui64ElapTime; - /**----------------------------------------------- - *** See if first the block is in cache. - *** Previous writes may not have been forced out - *** to cache. - ***----------------------------------------------*/ + // See if first the block is in cache. Previous writes may not have been + // forced out to cache. if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_LEAF, uiBlkAddress, &uiNumLooks, @@ -418,7 +401,7 @@ FSTATIC RCODE FLRReadBlkHdr( goto Exit; } - if (pBlkSCache) // If found in cache ... + if (pBlkSCache) { f_memcpy( pucBlockHeader, pBlkSCache->pucBlk, BH_OVHD); ScaReleaseCache( pBlkSCache, FALSE); @@ -430,13 +413,9 @@ FSTATIC RCODE FLRReadBlkHdr( ui64ElapTime = 0; f_timeGetTimeStamp( &StartTime); } - - if( RC_OK( rc = pDb->pSFileHdl->getFileHdl( - FSGetFileNumber( uiBlkAddress), TRUE, &pTmpFileHdl))) - { - rc = pTmpFileHdl->read( FSGetFileOffset( uiBlkAddress), - BH_OVHD, pucBlockHeader, &uiBytesRead); - } + + rc = pDb->pSFileHdl->readBlock( uiBlkAddress, BH_OVHD, + pucBlockHeader, &uiBytesRead); if (pDbStats) { @@ -502,23 +481,16 @@ FSTATIC RCODE FLRReadBlkHdr( } } - if (RC_BAD( rc)) + if( RC_BAD( rc)) { - if (rc != FERR_IO_END_OF_FILE && rc != FERR_MEM) - { - pDb->pSFileHdl->releaseFile( FSGetFileNumber( uiBlkAddress), - TRUE); - } goto Exit; } + pucBlockHeader [BH_CHECKSUM_LOW] = (FLMBYTE) uiBlkAddress; } - /**--------------------------------------------------- - *** If the block address does not agree with what - *** is expected then the block is a log extent. - *** Otherwise the block contains the type it is. - ***--------------------------------------------------*/ + // If the block address does not agree with what is expected then the + // block is a log extent. Otherwise the block contains the type it is. if (piTypeRV) { @@ -526,7 +498,8 @@ FSTATIC RCODE FLRReadBlkHdr( } Exit: - return( rc ); + + return( rc); } /**************************************************************************** @@ -537,7 +510,7 @@ Notes: Some of this code could be called in movePcodeLFHBlk but we have ****************************************************************************/ FSTATIC RCODE FLRMoveBtreeBlk( FDB * pDb, - FLMUINT uiBlkAddr, // Block Address + FLMUINT uiBlkAddr, FLMUINT uiLfNumber, FLMBOOL * pbDone) { @@ -553,14 +526,14 @@ FSTATIC RCODE FLRMoveBtreeBlk( FLMUINT uiRightBlkAddr; SCACHE * pFreeSCache; FLMBOOL bReleaseCache2 = FALSE; - BTSK StackArea; /* Single stack allocation */ - BTSK * pStack = &StackArea; /* Points to stack - easier to use */ - FLMUINT uiElmOvhd; /* Number of bytes in block overhead */ - FLMUINT uiSearchKeyLen; /* Length of block's 1st key */ + BTSK StackArea; + BTSK * pStack = &StackArea; + FLMUINT uiElmOvhd; + FLMUINT uiSearchKeyLen; FLMBYTE ucKeyBuf [MAX_KEY_SIZ]; - FLMBYTE ucSearchKey [MAX_KEY_SIZ];/* Holds block's 1st key */ + FLMBYTE ucSearchKey [MAX_KEY_SIZ]; FLMUINT uiTargetLevel; - FLMUINT uiLevel; /* Level numbers in the btree */ + FLMUINT uiLevel; FLMUINT uiRootBlkFlag; FLMUINT uiSavePrevTransID; FLMUINT uiSavePrevBlkAddr; @@ -599,24 +572,14 @@ FSTATIC RCODE FLRMoveBtreeBlk( } pucBlk = pSCache->pucBlk; - /**-------------------------------------------------- - *** Added 05/04/93 - *** Need to make sure that LFILE is up to date. - *** Force reading it in. This does a block read - *** so the cache will get hit without a great - *** performance loss. This is the safest place - *** to do this because only pSCache is pinned. - ***------------------------------------------------*/ + // Need to make sure that LFILE is up to date. if (RC_BAD( rc = flmLFileRead( pDb, pLFile))) { goto Exit; } - /**---------------------------------------- - *** Get all of the information from the - *** block like linkages and a search key. - ***---------------------------------------*/ + // Get all of the information from the block like linkages and a search key. uiLeftBlkAddr = FB2UD( &pucBlk [BH_PREV_BLK ]); uiRightBlkAddr = FB2UD( &pucBlk [BH_NEXT_BLK ]); @@ -632,7 +595,7 @@ FSTATIC RCODE FLRMoveBtreeBlk( uiElmOvhd = BNE_KEY_START; break; case BHT_NON_LEAF_DATA: - uiElmOvhd = 0; // First key starts at BH_OVHD + uiElmOvhd = 0; break; case BHT_NON_LEAF_COUNTS: uiElmOvhd = BNE_KEY_COUNTS_START; @@ -643,15 +606,12 @@ FSTATIC RCODE FLRMoveBtreeBlk( } uiSearchKeyLen = (uiBlockType == BHT_NON_LEAF_DATA - ? 4 - : BBE_GET_KL( &pucBlk [BH_OVHD ])); + ? 4 + : BBE_GET_KL( &pucBlk [BH_OVHD ])); f_memcpy( ucSearchKey, &pucBlk [BH_OVHD + uiElmOvhd ], uiSearchKeyLen ); - /**------------------------------- - *** Get the next free block. - *** Copy block to free block. - ***------------------------------*/ + // Get the next free block. Copy block to free block. if (RC_BAD( rc = FSBlockUseNextAvail( pDb, pLFile, &pFreeSCache))) { @@ -661,13 +621,11 @@ FSTATIC RCODE FLRMoveBtreeBlk( pucFreeBlk = pFreeSCache->pucBlk; uiFreeBlkAddr = GET_BH_ADDR( pucFreeBlk); - /* - The free block has been logged and set to dirty - in FSBlockUseNextAvail(). - BUT, need to preserve previous transaction ID and previous - block address - those should NOT be copied over from the block - we are switching with. - */ + // The free block has been logged and set to dirty + // in FSBlockUseNextAvail(). + // BUT, need to preserve previous transaction ID and previous + // block address - those should NOT be copied over from the block + // we are switching with. uiSavePrevTransID = (FLMUINT)FB2UD( &pFreeSCache->pucBlk [BH_PREV_TRANS_ID]); @@ -688,16 +646,13 @@ FSTATIC RCODE FLRMoveBtreeBlk( bReleaseCache2 = FALSE; uiRootBlkFlag = (FLMUINT)(BH_IS_ROOT_BLK( pucBlk )); - /* Done with block. */ + // Done with block. ScaReleaseCache( pSCache, FALSE); bReleaseCache = FALSE; - /**---------------------------------------------- - *** If this is a root block this is easy! - *** Otherwise you must find the blocks parent - *** and next/prev blocks and change linkages. - ***---------------------------------------------*/ + // If this is a root block this is easy! Otherwise you must find the + // blocks parent and next/prev blocks and change linkages. if( uiRootBlkFlag) { @@ -725,12 +680,9 @@ FSTATIC RCODE FLRMoveBtreeBlk( goto Exit; } - /**-------------------------------------------------- - *** Read left and right blocks and adjust their - *** pointers to point to the new block. - *** This doesn't matter what level of the b-tree - *** you are on. - ***--------------------------------------------------*/ + // Read left and right blocks and adjust their pointers to point to + // the new block. This doesn't matter what level of the b-tree + // you are on. if( uiLeftBlkAddr != BT_END) { @@ -739,11 +691,14 @@ FSTATIC RCODE FLRMoveBtreeBlk( { goto Exit; } + bReleaseCache = TRUE; + if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache))) { goto Exit; } + pucBlk = pSCache->pucBlk; UD2FBA( (FLMUINT32)uiFreeBlkAddr, &pucBlk [BH_NEXT_BLK ]); ScaReleaseCache( pSCache, FALSE); @@ -757,7 +712,9 @@ FSTATIC RCODE FLRMoveBtreeBlk( { goto Exit; } + bReleaseCache = TRUE; + if (RC_BAD( rc = ScaLogPhysBlk( pDb, &pSCache))) { goto Exit; @@ -769,12 +726,10 @@ FSTATIC RCODE FLRMoveBtreeBlk( bReleaseCache = FALSE; } - /**-------------------------------------------------- - *** Now for the hard part! Build a search key. - *** Scan down the tree one level above blk. - *** Scan right until find element that has child blk - *** that matches uiBlkAddr and adjust child blk addr. - ***--------------------------------------------------*/ + // Now for the hard part! Build a search key. + // Scan down the tree one level above blk. + // Scan right until find element that has child blk + // that matches uiBlkAddr and adjust child blk addr. if (RC_BAD(rc = FSGetBlock( pDb, pLFile, pLFile->uiRootBlk, pStack))) @@ -788,7 +743,7 @@ FSTATIC RCODE FLRMoveBtreeBlk( uiLevel = (FLMUINT)CABLK_ELM( pStack, BH_LEVEL ); pStack->uiLevel = uiLevel; - /* Scan the block for the matching key */ + // Scan the block for the matching key if( pStack->uiBlkType != BHT_NON_LEAF_DATA) { @@ -813,12 +768,10 @@ FSTATIC RCODE FLRMoveBtreeBlk( } } - /**---------------------------------------------------------- - *** The block MUST be a non-leaf block so our job is easier. - *** Scan the elements going right to find the element that - *** has the matching block address. - *** Set NO_STACK flag so get next element doesn't pop stack! - ***-----------------------------------------------------------*/ + // The block MUST be a non-leaf block so our job is easier. + // Scan the elements going right to find the element that + // has the matching block address. + // Set NO_STACK flag so get next element doesn't pop stack! pStack->uiFlags = NO_STACK; @@ -827,7 +780,7 @@ FSTATIC RCODE FLRMoveBtreeBlk( if (FSChildBlkAddr( pStack) == uiBlkAddr ) { - /* FOUND THE BLOCK ! ! ! */ + // Found the block if (RC_BAD( rc = FSLogPhysBlk( pDb, pStack))) { @@ -847,14 +800,17 @@ FSTATIC RCODE FLRMoveBtreeBlk( } goto Exit; } - } - /* WOW - WE ARE DONE ! ! ! */ + } + Exit: + FSReleaseBlock( &StackArea, FALSE); + if (bReleaseCache) { ScaReleaseCache( pSCache, FALSE); } + if (bReleaseCache2) { ScaReleaseCache( pFreeSCache, FALSE); @@ -1067,7 +1023,7 @@ FSTATIC RCODE FLRFreeAvailBlk( FLMBOOL bFirstChainFlag; FLMBYTE * pucLogHdr = &pFile->ucUncommittedLogHdr [0]; - /* Check for first avail block condition. */ + // Check for first avail block condition. if (uiBlkAddr == pDb->LogHdr.uiFirstAvailBlkAddr) { @@ -1078,16 +1034,16 @@ FSTATIC RCODE FLRFreeAvailBlk( goto Exit; } - /* Not first block -- resolve pointers */ - - /* Read the block header and get pointers */ + // Read the block header and get pointers if (RC_BAD( rc = FLRReadBlkHdr( pDb, uiBlkAddr, ucBlkHeader, (FLMINT *)0 ))) { goto Exit; } - uiPrevBlkAddr = uiBlkAddr; /* Call uses uiPrevBlkAddr */ + + uiPrevBlkAddr = uiBlkAddr; + if (RC_BAD( rc = FLRFindPrevAvailBlk( pDb, &uiPrevBlkAddr, &bFirstChainFlag))) { @@ -1097,8 +1053,6 @@ FSTATIC RCODE FLRFreeAvailBlk( uiNextBlkAddr = FB2UD( &ucBlkHeader [BH_NEXT_BLK]); if (pFile->FileHdr.uiVersionNum >= 111) { - /* Only valid for versions 1.11 and higher */ - uiPbcAddr = ALGetPBC( ucBlkHeader); uiNbcAddr = ALGetNBC( ucBlkHeader); flmDecrUint( &pucLogHdr [LOG_PF_NUM_AVAIL_BLKS], 1); @@ -1108,9 +1062,9 @@ FSTATIC RCODE FLRFreeAvailBlk( uiPbcAddr = uiNbcAddr = 0; } - /* Check for unexpected error conditions. */ + // Check for unexpected error conditions - if (( uiPrevBlkAddr == uiBlkAddr) || + if( (uiPrevBlkAddr == uiBlkAddr) || ((!uiNbcAddr) && ( uiPbcAddr)) || (( uiNbcAddr) && (!uiPbcAddr))) { @@ -1118,12 +1072,10 @@ FSTATIC RCODE FLRFreeAvailBlk( goto Exit; } - /**-------------------------------- - *** NON-CHAIN BLOCK - *** This is also minor verion 0 - ***-------------------------------*/ + // NON-CHAIN BLOCK + // This is also minor verion 0 - if (!uiNbcAddr) /* either both are zero or both non-zero*/ + if (!uiNbcAddr) { if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, uiPrevBlkAddr, NULL, &pSCache))) @@ -1149,16 +1101,6 @@ FSTATIC RCODE FLRFreeAvailBlk( goto Exit; } - /**-------------------------------- - *** CHAIN BLOCK - *** Only in minor verion > 0 - ***-------------------------------*/ - - /**-------------------------------- - *** CHAIN BLOCK - previous block - *** is nbc (next backchain) - ***-------------------------------*/ - if (uiPrevBlkAddr == uiNbcAddr) { if ( RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, @@ -1199,18 +1141,6 @@ FSTATIC RCODE FLRFreeAvailBlk( bReleaseCache = FALSE; } } - - /**-------------------------------- - *** CHAIN BLOCK - next block - *** is pbc (previous backchain) - *** - *** |----------->>-PBC->>---------| - *** | | - *** header ----> FREE -->>-nextBlk->>--------> FREE - *** | | - *** |---------<<-NBC-<<-----------| - ***-------------------------------*/ - else if ((uiNextBlkAddr == uiPbcAddr) && (uiNextBlkAddr != BT_END)) { if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, @@ -1274,13 +1204,6 @@ FSTATIC RCODE FLRFreeAvailBlk( bReleaseCache = FALSE; } } - - /**----------------------------------- - *** CHAIN BLOCK - normal chain block - *** No adjacent chain blocks - *** May be the last block in the chain - ***----------------------------------*/ - else { if (RC_BAD( rc = ScaGetBlock( pDb, NULL, BHT_FREE, @@ -1353,6 +1276,7 @@ FSTATIC RCODE FLRFreeAvailBlk( } Exit: + if (bReleaseCache) { ScaReleaseCache( pSCache, FALSE); @@ -1381,61 +1305,70 @@ FSTATIC RCODE FLRFindPrevAvailBlk( if( RC_BAD( rc = FLRReadBlkHdr( pDb, uiTargetBlkAddr, ucBlkHeader, (FLMINT *)0 ))) + { goto Exit; + } uiNextBlkAddr = FB2UD( &ucBlkHeader [BH_NEXT_BLK]); if ( uiNextBlkAddr == pDb->LogHdr.uiFirstAvailBlkAddr) { - /* Done */ goto Exit; } - /* Find next chain block */ + // Find next chain block uiNbcAddr = ALGetNBC( ucBlkHeader); - while( ( !uiNbcAddr) && ( uiNextBlkAddr != BT_END)) + while( (!uiNbcAddr) && ( uiNextBlkAddr != BT_END)) { if( RC_BAD( rc = FLRReadBlkHdr( pDb, uiNextBlkAddr, ucBlkHeader, (FLMINT *)0))) + { goto Exit; + } - if( ( uiTempBlkAddr = GET_BH_ADDR( ucBlkHeader)) != uiNextBlkAddr) + if( (uiTempBlkAddr = GET_BH_ADDR( ucBlkHeader)) != uiNextBlkAddr) { rc = RC_SET( FERR_DATA_ERROR); goto Exit; } + uiNbcAddr = ALGetNBC( ucBlkHeader); uiNextBlkAddr = FB2UD( &ucBlkHeader [BH_NEXT_BLK]); } - /* Now find the previous avail block */ + // Now find the previous avail block if( uiNbcAddr == BT_END) { uiNextBlkAddr = pDb->LogHdr.uiFirstAvailBlkAddr; - *pbFirstChainFlagRV = TRUE; /* Within first chain */ + *pbFirstChainFlagRV = TRUE; } else + { uiNextBlkAddr = uiNbcAddr; + } - while( ( uiNextBlkAddr != uiTargetBlkAddr) && ( uiNextBlkAddr != BT_END)) + while( (uiNextBlkAddr != uiTargetBlkAddr) && (uiNextBlkAddr != BT_END)) { if (RC_BAD( rc = FLRReadBlkHdr( pDb, uiNextBlkAddr, ucBlkHeader, (FLMINT *)0 ))) + { goto Exit; + } - if( ( uiTempBlkAddr = GET_BH_ADDR( ucBlkHeader)) != uiNextBlkAddr) + if( (uiTempBlkAddr = GET_BH_ADDR( ucBlkHeader)) != uiNextBlkAddr) { rc = RC_SET( FERR_DATA_ERROR); goto Exit; } + uiNextBlkAddr = FB2UD( &ucBlkHeader [BH_NEXT_BLK]); } *puiBlkAddrRV = uiTempBlkAddr; Exit: - return( rc ); -} + return( rc); +} diff --git a/flaim/src/fqeval.cpp b/flaim/src/fqeval.cpp index 04f2fd3..04df549 100644 --- a/flaim/src/fqeval.cpp +++ b/flaim/src/fqeval.cpp @@ -1884,7 +1884,7 @@ Get_Operand: pLhs->eType != FLM_UNKNOWN) { - // VISIT: We should optimized to flunk or pass text compares. + // VISIT: We should be optimized to flunk or pass text compares. // The problems come with comparing only up to the first // wildcard. diff --git a/flaim/src/frebuild.cpp b/flaim/src/frebuild.cpp index 4782175..78edf6f 100644 --- a/flaim/src/frebuild.cpp +++ b/flaim/src/frebuild.cpp @@ -473,15 +473,9 @@ Desc: This routine recovers all records in the database for all *****************************************************************************/ FSTATIC RCODE bldRecovData( FDB * pDb, - REBUILD_STATE * pRebuildState, // Pointer to rebuild state information. - // This structure has the container - // number being recovered. - CONTAINER_INFO * pContainerInfo, // Information being remembered for - // ALL containers. - FLMBOOL bRecovDictRecs, // Flag indicating whether we are to - // doing a pass to recover dictionary - // data or regular data. - + REBUILD_STATE * pRebuildState, + CONTAINER_INFO * pContainerInfo, + FLMBOOL bRecovDictRecs, FLMBOOL * pbStartedTransRV) { RCODE rc = FERR_OK; @@ -504,10 +498,8 @@ FSTATIC RCODE bldRecovData( RECOV_DICT_INFO * pRecovDictInfo = NULL; FLMUINT uiFileNumber = 0; FLMUINT uiOffset = 0; - IF_FileHdl * pFileHdl = NULL; FLMUINT uiMaxFileSize = pRebuildState->uiMaxFileSize; - FLMUINT uiDbVersion = - pRebuildState->pHdrInfo->FileHdr.uiVersionNum; + FLMUINT uiDbVersion = pRebuildState->pHdrInfo->FileHdr.uiVersionNum; // Read through all blocks in the file -- looking for leaf blocks // of containers. Read until we get an error or run out of file. @@ -519,38 +511,35 @@ FSTATIC RCODE bldRecovData( : (FLMINT)REBUILD_RECOVER_DATA); pCallbackData->bStartFlag = TRUE; pCallbackData->ui64BytesExamined = 0; + for (;;) { if (uiOffset >= uiMaxFileSize || !uiFileNumber) { uiOffset = 0; uiFileNumber++; - if (uiFileNumber > MAX_DATA_BLOCK_FILE_NUMBER( uiDbVersion)) + + if( uiFileNumber > MAX_DATA_BLOCK_FILE_NUMBER( uiDbVersion)) { break; } - - if (RC_BAD( rc = pSFileHdl->getFileHdl( - uiFileNumber, FALSE, &pFileHdl))) - { - if (rc == FERR_IO_PATH_NOT_FOUND || - rc == FERR_IO_INVALID_PATH) - { - rc = FERR_OK; - break; - } - goto Exit; - } } // Read the block into memory. - - if (RC_BAD( rc = pFileHdl->sectorRead( uiOffset, uiBlockSize, - pucBlk, &uiBytesRead))) + + if( RC_BAD( rc = pSFileHdl->readBlock( + FSBlkAddress( uiFileNumber, uiOffset), uiBlockSize, + pucBlk, &uiBytesRead))) { - if (rc == FERR_IO_END_OF_FILE) + if( rc == FERR_IO_PATH_NOT_FOUND) { - if (!uiBytesRead) + rc = FERR_OK; + break; + } + + if( rc == FERR_IO_END_OF_FILE) + { + if( !uiBytesRead) { // Set uiOffset so we will go to the next file. @@ -569,7 +558,7 @@ FSTATIC RCODE bldRecovData( } } - if (fnStatusFunc) + if( fnStatusFunc) { pCallbackData->ui64BytesExamined += (FLMUINT64)uiBlockSize; if (RC_BAD( rc = (*fnStatusFunc)( FLM_REBUILD_STATUS, @@ -2318,7 +2307,7 @@ FLMEXP RCODE FLMAPI FlmDbRebuild( // Open the database file for reading header information if( RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( pszSourceDbPath, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &pCFileHdl))) + gv_FlmSysData.uiFileOpenFlags, &pCFileHdl))) { goto Exit; } @@ -2474,7 +2463,9 @@ FLMEXP RCODE FLMAPI FlmDbRebuild( goto Exit; } - if( RC_BAD( rc = pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -2720,7 +2711,6 @@ FSTATIC RCODE bldDetermineBlkSize( FLMUINT uiCount4K = 0; FLMUINT uiCount8K = 0; FLMUINT64 ui64BytesDone = 0; - IF_FileHdl * pFileHdl = NULL; F_SuperFileHdl * pSFileHdl = NULL; F_SuperFileClient * pSFileClient = NULL; @@ -2744,7 +2734,9 @@ FSTATIC RCODE bldDetermineBlkSize( goto Exit; } - if( RC_BAD( rc = pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pSFileHdl->setup( pSFileClient, + gv_FlmSysData.pFileHdlCache, + (gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -2760,21 +2752,11 @@ FSTATIC RCODE bldDetermineBlkSize( { uiOffset = 0; uiFileNumber++; - if (RC_BAD( rc = pSFileHdl->getFileHdl( - uiFileNumber, FALSE, &pFileHdl))) - { - if (rc == FERR_IO_PATH_NOT_FOUND) - { - rc = RC_SET( FERR_IO_END_OF_FILE); - break; - } - goto Exit; - } } - if ((RC_OK(rc = pFileHdl->read( uiOffset, BH_OVHD, ucBlkHeader, - &uiBytesRead))) || - (rc == FERR_IO_END_OF_FILE)) + if( (RC_OK( rc = pSFileHdl->readBlock( + FSBlkAddress( uiFileNumber, uiOffset), BH_OVHD, + ucBlkHeader, &uiBytesRead))) || rc == FERR_IO_END_OF_FILE) { if (RC_OK( rc)) { @@ -2834,6 +2816,12 @@ FSTATIC RCODE bldDetermineBlkSize( } else { + if( rc == FERR_IO_PATH_NOT_FOUND) + { + rc = RC_SET( FERR_IO_END_OF_FILE); + break; + } + goto Exit; } } diff --git a/flaim/src/fsconvrt.cpp b/flaim/src/fsconvrt.cpp index 43af9cc..07e57b2 100644 --- a/flaim/src/fsconvrt.cpp +++ b/flaim/src/fsconvrt.cpp @@ -100,7 +100,7 @@ RCODE FSVersionConversion40( // VISIT: the change may not be necessary - may be new version. // Look at the root block type. - if( pStack != stackBuf) // && ? Need to look at real block type? + if( pStack != stackBuf) { DbConvertInfo.uiContainer = pLFile->uiLfNum; diff --git a/flaim/src/fslfileu.cpp b/flaim/src/fslfileu.cpp index 2dc4ba7..fe31552 100644 --- a/flaim/src/fslfileu.cpp +++ b/flaim/src/fslfileu.cpp @@ -65,7 +65,7 @@ FSTATIC RCODE flmModifyTrackerRec( FLMUINT uiDrn, FlmRecord * pRecord); -FSTATIC RCODE flmMaintThread( +FSTATIC RCODE FLMAPI flmMaintThread( IF_Thread * pThread); FSTATIC RCODE fdictRemoveIndexes( @@ -2875,7 +2875,7 @@ Exit: /*************************************************************************** Desc: *****************************************************************************/ -FSTATIC RCODE flmMaintThread( +FSTATIC RCODE FLMAPI flmMaintThread( IF_Thread * pThread) { RCODE rc = FERR_OK; @@ -3021,7 +3021,6 @@ FSTATIC RCODE flmMaintThread( } rc = FERR_OK; - pThread->setThreadStatus( FLM_THREAD_STATUS_ABORTING_TRANS); (void)flmAbortDbTrans( pDb); bStartedTrans = FALSE; break; @@ -3055,8 +3054,6 @@ FSTATIC RCODE flmMaintThread( } } - pThread->setThreadStatus( FLM_THREAD_STATUS_COMMITTING_TRANS); - // Commit the transaction pStatus->eDoing = FLM_MAINT_ENDING_TRANS; diff --git a/flaim/src/fssearch.cpp b/flaim/src/fssearch.cpp index 87143d1..ce4bf85 100644 --- a/flaim/src/fssearch.cpp +++ b/flaim/src/fssearch.cpp @@ -88,8 +88,6 @@ RCODE FSBtSearch( goto Exit; } - // VISIT: Verify byLevel for cyclic loops. - if (!pStack->uiLevel) { // Leaf level - we are done. diff --git a/flaim/src/fstructs.h b/flaim/src/fstructs.h index a2ddccd..a9840ae 100644 --- a/flaim/src/fstructs.h +++ b/flaim/src/fstructs.h @@ -787,31 +787,21 @@ Desc: This is the FLAIM Shared System Data Structure. It is the anchor ***************************************************************************/ typedef struct FLMSYSDATA { + FLMUINT uiOpenFFiles; // Number of open FFILEs FFILE * pMrnuFile; // Pointer to the most recently non-used // FFILE structure. FFILE * pLrnuFile; // Pointer to the least recently non-used // FFILE structure. - FBUCKET * pFileHashTbl; // File name hash table (array of FBUCKET). + F_BUCKET * pFileHashTbl; // File name hash table (array of F_BUCKET). #define FILE_HASH_ENTRIES 256 FLMUINT uiNextFFileId; // ID that will be assigned to the next // FFILE created by flmAllocFile. - F_MUTEX hShareMutex; // Mutex for controlling access to // FFILE structures, and shared cache. - F_MUTEX hFileHdlMutex; // Mutex for controlling - // access to shared file handles. - F_MUTEX hServerLockMgrMutex; - // Mutex for controlling access to - // the server lock manager. - - IF_FileSystem * pFileSystem;// File system used to configure options + IF_FileSystem * pFileSystem; // File system used to configure options // for interacting with OS file system. - FLMBOOL bTempDirSet; // TRUE if temporary directory has been set - - FLMBOOL bOkToDoAsyncWrites; - // OK To do async writes, if available. FLMBOOL bCheckCache; // Do extra checking of cache? FLMUINT uiMaxCPInterval; // Maximum number of seconds to allow between @@ -851,7 +841,6 @@ typedef struct FLMSYSDATA RCACHE_MGR RCacheMgr; // Record cache manager IF_Thread * pMonitorThrd; // Monitor thread FLM_STATS Stats; // Statistics structure - F_MUTEX hQueryMutex; // Mutex for managing query list QUERY_HDR * pNewestQuery; // Head of query list (newest) QUERY_HDR * pOldestQuery; // Tail of query list (oldest) @@ -864,14 +853,12 @@ typedef struct FLMSYSDATA FLMBOOL bStatsInitialized; // Has statistics structure been // initialized? - char szTempDir[ F_PATH_MAX_SIZE]; // Temporary working directory for // ResultSets, RecordCache // and other sub-systems that need // temporary files. This is aligned // on a 4-byte boundary - FLMUINT uiMaxUnusedTime; // Maximum number of timer units to keep // unused structures in memory before @@ -882,19 +869,18 @@ typedef struct FLMSYSDATA FEVENT_HDR SizeEvents; // Size threshold events F_Pool KRefPool; // Memory Pool that is only used by // record updaters for key building - HTTPCONFIGPARAMS HttpConfigParms; - FLMUINT uiMaxFileSize; IF_LoggerClient * pLogger; IF_SlabManager * pSlabManager; - IF_ThreadMgr * pThreadMgr; + IF_FileHdlCache * pFileHdlCache; F_SessionMgr * pSessionMgr; F_MUTEX hHttpSessionMutex; - FLMUINT uiMaxStratifyIterations; FLMUINT uiMaxStratifyTime; + FLMUINT uiFileOpenFlags; + FLMUINT uiFileCreateFlags; } FLMSYSDATA; @@ -1789,81 +1775,6 @@ typedef enum HASH_DB_OBJ } eHashObjType; -/**************************************************************************** -Desc: FLAIM object base class -****************************************************************************/ -class F_HashObject : public F_Object -{ -public: - -#define F_INVALID_HASH_BUCKET (~((FLMUINT)0)) - - F_HashObject() - { - m_pNextInBucket = NULL; - m_pPrevInBucket = NULL; - m_pNextInGlobal = NULL; - m_pPrevInGlobal = NULL; - m_uiHashBucket = F_INVALID_HASH_BUCKET; - m_ui32CRC = 0xFFFFFFFF; - } - - virtual ~F_HashObject() - { - flmAssert( !m_pNextInBucket); - flmAssert( !m_pPrevInBucket); - flmAssert( !m_pNextInGlobal); - flmAssert( !m_pPrevInGlobal); - } - - virtual void * getKey( - FLMUINT * puiKeyLen) = 0; - - FLMUINT getHashBucket( void) - { - return( m_uiHashBucket); - } - - FLMUINT32 getKeyCRC( void) - { - return( m_ui32CRC); - } - - FINLINE F_HashObject * getNextInGlobal( void) - { - return( m_pNextInGlobal); - } - - virtual eHashObjType objectType( void) = 0; - -protected: - - // Methods - - void setHashBucket( - FLMUINT uiHashBucket) - { - m_uiHashBucket = uiHashBucket; - } - - void setKeyCRC( - FLMUINT32 ui32CRC) - { - m_ui32CRC = ui32CRC; - } - - // Data - - F_HashObject * m_pNextInBucket; - F_HashObject * m_pPrevInBucket; - F_HashObject * m_pNextInGlobal; - F_HashObject * m_pPrevInGlobal; - FLMUINT m_uiHashBucket; - FLMUINT32 m_ui32CRC; - -friend class F_HashTable; -}; - /**************************************************************************** Desc: FLAIM session database object ****************************************************************************/ @@ -1879,15 +1790,16 @@ public: F_Session * pSession, HFDB hDb); - void * getKey( - FLMUINT * puiKeyLen = NULL); + const void * FLMAPI getKey( void); + + FLMUINT FLMAPI getKeyLength( void); FINLINE HFDB getDbHandle( void) { return( m_hDb); } - FINLINE eHashObjType objectType( void) + FINLINE FLMUINT FLMAPI getObjectType( void) { return( HASH_DB_OBJ); } @@ -1947,14 +1859,15 @@ public: FLMUINT getNextToken( void); - void * getKey( - FLMUINT * puiKeyLen = NULL); + const void * FLMAPI getKey( void); + + FLMUINT FLMAPI getKeyLength( void); FLMINT FLMAPI AddRef(); FLMINT FLMAPI Release(); - FINLINE eHashObjType objectType( void) + FINLINE FLMUINT FLMAPI getObjectType( void) { return( HASH_SESSION_OBJ); } @@ -2047,65 +1960,6 @@ private: FLMUINT m_uiNextToken; }; -/**************************************************************************** -Desc: FLAIM hash table -****************************************************************************/ -class F_HashTable : public F_Object -{ -public: - - F_HashTable(); - - virtual ~F_HashTable(); - - RCODE setupHashTable( - FLMBOOL bMultithreaded, - FLMUINT uiNumBuckets); - - RCODE addObject( - F_HashObject * pObject); - - RCODE getNextObjectInGlobal( - F_HashObject ** ppObject); - - RCODE getObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject, - FLMBOOL bRemove = FALSE); - - RCODE removeObject( - void * pvKey, - FLMUINT uiKeyLen); - - RCODE removeObject( - F_HashObject * pObject); - -private: - - FLMUINT getHashBucket( - void * pvKey, - FLMUINT uiLen, - FLMUINT32 * pui32KeyCRC = NULL); - - void linkObject( - F_HashObject * pObject, - FLMUINT uiBucket); - - void unlinkObject( - F_HashObject * pObject); - - RCODE findObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject); - - F_MUTEX m_hMutex; - F_HashObject * m_pGlobalList; - F_HashObject ** m_ppHashTable; - FLMUINT m_uiBuckets; -}; - #include "fpackoff.h" #endif diff --git a/flaim/src/fsysdata.cpp b/flaim/src/fsysdata.cpp index cfad9b7..5782a74 100644 --- a/flaim/src/fsysdata.cpp +++ b/flaim/src/fsysdata.cpp @@ -42,13 +42,12 @@ #define FLM_MAX_CACHE_SIZE (~((FLMUINT)0)) #endif +#define DEFAULT_OPEN_THRESHOLD 100 // 100 file handles to cache +#define DEFAULT_MAX_AVAIL_TIME 900 // 15 minutes + FLMATOMIC gv_flmSysSpinLock = 0; FLMUINT gv_uiFlmSysStartupCount = 0; -FSTATIC void flmInitHashTbl( - FBUCKET * pHashTable, - FLMUINT uiHashEntries); - FSTATIC RCODE flmGetCacheBytes( FLMUINT uiPercent, FLMUINT uiMin, @@ -84,7 +83,7 @@ FSTATIC void flmCleanup( void); FSTATIC void flmUnlinkFileFromBucket( FFILE * pFile); -RCODE flmSystemMonitor( +RCODE FLMAPI flmSystemMonitor( IF_Thread * pThread); FSTATIC RCODE flmRegisterHttpCallback( @@ -156,67 +155,6 @@ FINLINE void flmFreeDictList( *ppDictRV = NULL; } -/**************************************************************************** -Desc: This routine initializes a hash table. -****************************************************************************/ -FSTATIC void flmInitHashTbl( - FBUCKET * pHashTable, - FLMUINT uiHashEntries) -{ - FLMUINT uiCnt; - FLMUINT uiRandVal; - FLMUINT uiTempVal; - - for( uiCnt = 0; uiCnt < uiHashEntries; uiCnt++) - { - pHashTable [uiCnt].uiHashValue = (FLMBYTE)uiCnt; - pHashTable [uiCnt].pFirstInBucket = NULL; - } - - if (uiHashEntries <= 256) - { - for (uiCnt = 0; uiCnt < uiHashEntries - 1; uiCnt++) - { - uiRandVal = f_getRandomUINT32( (FLMUINT32)uiCnt, (FLMUINT32)(uiHashEntries - 1)); - - if (uiRandVal != uiCnt) - { - uiTempVal = (FLMBYTE)pHashTable [uiCnt].uiHashValue; - pHashTable [uiCnt].uiHashValue = pHashTable [uiRandVal].uiHashValue; - pHashTable [uiRandVal].uiHashValue = uiTempVal; - } - } - } -} - -/**************************************************************************** -Desc: This routine allocates and initializes a hash table. -****************************************************************************/ -RCODE flmAllocHashTbl( - FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV) -{ - RCODE rc = FERR_OK; - FBUCKET * pHashTbl = NULL; - - // Allocate memory for the hash table - - if( RC_BAD( rc = f_calloc( - (FLMUINT)(sizeof( FBUCKET)) * uiHashTblSize, &pHashTbl))) - { - goto Exit; - } - - // Initialize the hash table - - flmInitHashTbl( pHashTbl, uiHashTblSize); - -Exit: - - *ppHashTblRV = pHashTbl; - return( rc); -} - /**************************************************************************** Desc: This routine determines the number of cache bytes to use for caching based on a percentage of available physical memory or a percentage @@ -382,7 +320,6 @@ FLMEXP RCODE FLMAPI FlmStartup( void) // call to f_memoryInit(). gv_FlmSysData.hShareMutex = F_MUTEX_NULL; - gv_FlmSysData.hFileHdlMutex = F_MUTEX_NULL; gv_FlmSysData.uiMaxStratifyIterations = DEFAULT_MAX_STRATIFY_ITERATIONS; gv_FlmSysData.uiMaxStratifyTime = DEFAULT_MAX_STRATIFY_TIME; @@ -391,7 +328,15 @@ FLMEXP RCODE FLMAPI FlmStartup( void) gv_FlmSysData.UpdateEvents.hMutex = F_MUTEX_NULL; gv_FlmSysData.LockEvents.hMutex = F_MUTEX_NULL; gv_FlmSysData.SizeEvents.hMutex = F_MUTEX_NULL; + + // Set the default file open flags + + gv_FlmSysData.uiFileOpenFlags = + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT; + gv_FlmSysData.uiFileCreateFlags = + gv_FlmSysData.uiFileOpenFlags | FLM_IO_EXCL | FLM_IO_CREATE_DIR; + #ifdef FLM_DBG_LOG flmDbgLogInit(); #endif @@ -484,6 +429,7 @@ FLMEXP RCODE FLMAPI FlmStartup( void) gv_FlmSysData.uiMaxCache = uiCacheBytes; uiCacheBytes >>= 1; + if (RC_BAD( rc = ScaInit( uiCacheBytes))) { goto Exit; @@ -506,16 +452,6 @@ FLMEXP RCODE FLMAPI FlmStartup( void) goto Exit; } - if (RC_BAD(rc = f_mutexCreate( &gv_FlmSysData.hFileHdlMutex))) - { - goto Exit; - } - - if (RC_BAD(rc = f_mutexCreate( &gv_FlmSysData.hServerLockMgrMutex))) - { - goto Exit; - } - if (RC_BAD( rc = f_mutexCreate( &gv_FlmSysData.HttpConfigParms.hMutex))) { goto Exit; @@ -536,7 +472,7 @@ FLMEXP RCODE FLMAPI FlmStartup( void) // Allocate memory for the file name hash table - if (RC_BAD(rc = flmAllocHashTbl( FILE_HASH_ENTRIES, + if (RC_BAD(rc = f_allocHashTable( FILE_HASH_ENTRIES, &gv_FlmSysData.pFileHashTbl))) { goto Exit; @@ -551,8 +487,15 @@ FLMEXP RCODE FLMAPI FlmStartup( void) goto Exit; } - gv_FlmSysData.bOkToDoAsyncWrites = gv_FlmSysData.pFileSystem->canDoAsync(); - + // Allocate a file handle cache + + if( RC_BAD( rc = gv_FlmSysData.pFileSystem->allocFileHandleCache( + DEFAULT_OPEN_THRESHOLD, DEFAULT_MAX_UNUSED_TIME, + &gv_FlmSysData.pFileHdlCache))) + { + goto Exit; + } + // Set up the session manager if( (gv_FlmSysData.pSessionMgr = f_new F_SessionMgr) == NULL) @@ -599,6 +542,7 @@ FLMEXP RCODE FLMAPI FlmStartup( void) iHandle = (int)f_getpid(); // Initialize NICI + if (CCS_Init(&iHandle)) { // Failure. @@ -1139,8 +1083,39 @@ FLMEXP RCODE FLMAPI FlmConfig( { case FLM_OPEN_THRESHOLD: { + rc = gv_FlmSysData.pFileHdlCache->setOpenThreshold( (FLMUINT)Value1); break; } + + case FLM_DIRECT_IO_STATE: + { + // Direct I/O state can only be changed when there are no open + // databases. We also only allow DIO to be disabled on Unix + // platforms. + +#ifdef FLM_UNIX + f_mutexLock( gv_FlmSysData.hShareMutex); + + if( !gv_FlmSysData.uiOpenFFiles) + { + if( (FLMBOOL)Value1) + { + gv_FlmSysData.uiFileOpenFlags = + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT; + } + else + { + gv_FlmSysData.uiFileOpenFlags = + FLM_IO_RDWR | FLM_IO_SH_DENYNONE; + } + + gv_FlmSysData.uiFileCreateFlags = + gv_FlmSysData.uiFileOpenFlags | FLM_IO_EXCL | FLM_IO_CREATE_DIR; + } + + f_mutexUnlock( gv_FlmSysData.hShareMutex); +#endif + } case FLM_CACHE_LIMIT: { @@ -1621,8 +1596,7 @@ Desc : Gets configured shared attributes. ****************************************************************************/ FLMEXP RCODE FLMAPI FlmGetConfig( eFlmConfigTypes eConfigType, - void * Value1 - ) + void * Value1) { RCODE rc = FERR_OK; @@ -1652,11 +1626,31 @@ FLMEXP RCODE FLMAPI FlmGetConfig( break; case FLM_OPEN_FILES: + { + *((FLMUINT *)Value1) = f_getOpenFileCount(); break; + } case FLM_OPEN_THRESHOLD: + *((FLMUINT *)Value1) = gv_FlmSysData.pFileHdlCache->getOpenThreshold(); break; + case FLM_DIRECT_IO_STATE: + { + f_mutexLock( gv_FlmSysData.hShareMutex); + + if( gv_FlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) + { + *((FLMBOOL *)Value1) = TRUE; + } + else + { + *((FLMBOOL *)Value1) = FALSE; + } + + f_mutexUnlock( gv_FlmSysData.hShareMutex); + } + case FLM_TMPDIR: f_mutexLock( gv_FlmSysData.hShareMutex); @@ -2229,8 +2223,7 @@ Desc: This routine frees a registered event. FSTATIC void flmFreeEvent( FEVENT * pEvent, F_MUTEX hMutex, - FEVENT ** ppEventListRV - ) + FEVENT ** ppEventListRV) { f_mutexLock( hMutex); if (pEvent->pPrev) @@ -2335,7 +2328,7 @@ FSTATIC void flmCleanup( void) if (gv_FlmSysData.pFileHashTbl) { - FBUCKET * pFileHashTbl; + F_BUCKET * pFileHashTbl; // flmFreeFile expects the global mutex to be locked // IMPORTANT NOTE: pFileHashTbl is ALWAYS allocated @@ -2391,16 +2384,6 @@ FSTATIC void flmCleanup( void) f_mutexDestroy( &gv_FlmSysData.hShareMutex); } - if (gv_FlmSysData.hFileHdlMutex != F_MUTEX_NULL) - { - f_mutexDestroy( &gv_FlmSysData.hFileHdlMutex); - } - - if (gv_FlmSysData.hServerLockMgrMutex != F_MUTEX_NULL) - { - f_mutexDestroy( &gv_FlmSysData.hServerLockMgrMutex); - } - if (gv_FlmSysData.HttpConfigParms.hMutex != F_MUTEX_NULL) { f_mutexDestroy( &gv_FlmSysData.HttpConfigParms.hMutex); @@ -2446,12 +2429,12 @@ FSTATIC void flmCleanup( void) // Free (release) FLAIM's File Shared File System Object. - if (gv_FlmSysData.pFileSystem) + if( gv_FlmSysData.pFileSystem) { gv_FlmSysData.pFileSystem->Release(); gv_FlmSysData.pFileSystem = NULL; } - + #ifdef FLM_DBG_LOG flmDbgLogExit(); #endif @@ -2472,6 +2455,14 @@ FSTATIC void flmCleanup( void) gv_FlmSysData.pThreadMgr = NULL; } + // Release the file handle cache + + if( gv_FlmSysData.pFileHdlCache) + { + gv_FlmSysData.pFileHdlCache->Release(); + gv_FlmSysData.pFileHdlCache = NULL; + } + // Release the slab manager if( gv_FlmSysData.pSlabManager) @@ -2584,7 +2575,7 @@ RCODE flmLinkFileToBucket( { RCODE rc = FERR_OK; FFILE * pTmpFile; - FBUCKET * pBucket; + F_BUCKET * pBucket; FLMUINT uiBucket; char szDbPathStr[ F_PATH_MAX_SIZE]; @@ -2600,16 +2591,19 @@ RCODE flmLinkFileToBucket( uiBucket = f_strHashBucket( szDbPathStr, pBucket, FILE_HASH_ENTRIES); pBucket = &pBucket [uiBucket]; + if (pBucket->pFirstInBucket) { pTmpFile = (FFILE *)pBucket->pFirstInBucket; pTmpFile->pPrev = pFile; } + pFile->uiBucket = uiBucket; pFile->pPrev = (FFILE *)NULL; pFile->pNext = (FFILE *)pBucket->pFirstInBucket; pBucket->pFirstInBucket = pFile; - + gv_FlmSysData.uiOpenFFiles++; + Exit: return( rc); @@ -2622,9 +2616,7 @@ Desc: This routine unlinks an FFILE structure from its name hash bucket. locked. ****************************************************************************/ FSTATIC void flmUnlinkFileFromBucket( - FFILE * pFile /* Pointer to file that is to be unlinked from - its name hash bucket. */ - ) + FFILE * pFile) { if (pFile->uiBucket != 0xFFFF) { @@ -2642,6 +2634,9 @@ FSTATIC void flmUnlinkFileFromBucket( } pFile->uiBucket = 0xFFFF; } + + flmAssert( gv_FlmSysData.uiOpenFFiles); + gv_FlmSysData.uiOpenFFiles--; } /**************************************************************************** @@ -2777,6 +2772,9 @@ void flmCheckNUStructs( break; } } + + gv_FlmSysData.pFileHdlCache->closeUnusedFiles( + FLM_TIMER_UNITS_TO_SECS( gv_FlmSysData.uiMaxUnusedTime)); } /**************************************************************************** @@ -2785,14 +2783,10 @@ Desc: This routine unlinks an FDICT structure from its FFILE structure and NOTE: This routine assumes that the global mutex is locked. ****************************************************************************/ void flmUnlinkDict( - FDICT * pDict /* FDICT that is to be unlinked from its FFFILE - structure. */ - ) + FDICT * pDict) { - /* - Now unlink the local dictionary from its file - if it is connected - to one. - */ + // Now unlink the local dictionary from its file - if it is connected + // to one. if (pDict->pFile) { @@ -2912,7 +2906,7 @@ Desc: This routine functions as a thread. It monitors open files and frees up files which have been closed longer than the maximum close time. ****************************************************************************/ -RCODE flmSystemMonitor( +RCODE FLMAPI flmSystemMonitor( IF_Thread * pThread) { FLMUINT uiLastUnusedCleanupTime = 0; @@ -3381,7 +3375,7 @@ RCODE F_Session::setupSession( goto Exit; } - if( RC_BAD( rc = m_pDbTable->setupHashTable( FALSE, 16))) + if( RC_BAD( rc = m_pDbTable->setupHashTable( FALSE, 16, 0))) { goto Exit; } @@ -3403,7 +3397,7 @@ RCODE F_Session::addDbHandle( { RCODE rc = FERR_OK; F_SessionDb * pSessionDb = NULL; - void * pvKey; + const void * pvKey; FLMUINT uiKeyLen; if( (pSessionDb = f_new F_SessionDb) == NULL) @@ -3424,7 +3418,9 @@ RCODE F_Session::addDbHandle( if( pucKey) { - pvKey = pSessionDb->getKey( &uiKeyLen); + pvKey = pSessionDb->getKey(); + uiKeyLen = pSessionDb->getKeyLength(); + flmAssert( uiKeyLen == F_SESSION_DB_KEY_LEN); f_memcpy( pucKey, (FLMBYTE *)pvKey, uiKeyLen); } @@ -3538,7 +3534,7 @@ void F_Session::releaseFileResources( pNextObject->AddRef(); } - if( pObject->objectType() == HASH_DB_OBJ) + if( pObject->getObjectType() == HASH_DB_OBJ) { pSessionDb = (F_SessionDb *)pObject; @@ -3733,16 +3729,19 @@ void F_Session::unlockSession( void) /**************************************************************************** Desc: Gets the session object's hash key ****************************************************************************/ -void * F_Session::getKey( - FLMUINT * puiKeyLen) +const void * FLMAPI F_Session::getKey( void) { - if( puiKeyLen) - { - *puiKeyLen = (FLMUINT)sizeof( m_ucKey); - } - return( (void *)(&m_ucKey[ 0])); + return( m_ucKey); } +/**************************************************************************** +Desc: +****************************************************************************/ +FLMUINT FLMAPI F_Session::getKeyLength( void) +{ + return( sizeof( m_ucKey)); +} + /**************************************************************************** Desc: Adds a reference to the session object. The mutex is locked prior to incrementing the count since multiple threads are allowed to @@ -3826,7 +3825,7 @@ void F_SessionMgr::releaseFileResources( while( pObject) { - flmAssert( pObject->objectType() == HASH_SESSION_OBJ); + flmAssert( pObject->getObjectType() == HASH_SESSION_OBJ); pSession = (F_Session *)pObject; if( (pObject = pObject->getNextInGlobal()) != NULL) @@ -3876,7 +3875,7 @@ void F_SessionMgr::shutdownSessions() while( pObject) { - flmAssert( pObject->objectType() == HASH_SESSION_OBJ); + flmAssert( pObject->getObjectType() == HASH_SESSION_OBJ); pSession = (F_Session *)pObject; if( (pObject = pObject->getNextInGlobal()) != NULL) @@ -3926,7 +3925,7 @@ RCODE F_SessionMgr::setupSessionMgr( void) goto Exit; } - if( RC_BAD( rc = m_pSessionTable->setupHashTable( FALSE, 128))) + if( RC_BAD( rc = m_pSessionTable->setupHashTable( FALSE, 128, 0))) { goto Exit; } @@ -4094,7 +4093,7 @@ void F_SessionMgr::timeoutInactiveSessions( while( pObject) { - flmAssert( pObject->objectType() == HASH_SESSION_OBJ); + flmAssert( pObject->getObjectType() == HASH_SESSION_OBJ); pSession = (F_Session *)pObject; if( (pObject = pObject->getNextInGlobal()) != NULL) @@ -4125,444 +4124,6 @@ Exit: f_mutexUnlock( m_hMutex); } } - -/**************************************************************************** -Desc: Constructor -****************************************************************************/ -F_HashTable::F_HashTable() -{ - m_hMutex = F_MUTEX_NULL; - m_pGlobalList = NULL; - m_ppHashTable = NULL; - m_uiBuckets = 0; -} - -/**************************************************************************** -Desc: Destructor -****************************************************************************/ -F_HashTable::~F_HashTable() -{ - F_HashObject * pCur; - F_HashObject * pNext; - - pCur = m_pGlobalList; - while( pCur) - { - pNext = pCur->m_pNextInGlobal; - unlinkObject( pCur); - pCur->Release(); - pCur = pNext; - } - - if( m_ppHashTable) - { - f_free( &m_ppHashTable); - } - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexDestroy( &m_hMutex); - } -} - -/**************************************************************************** -Desc: Configures the hash table prior to first use -****************************************************************************/ -RCODE F_HashTable::setupHashTable( - FLMBOOL bMultithreaded, - FLMUINT uiNumBuckets) -{ - RCODE rc = FERR_OK; - - flmAssert( uiNumBuckets); - - // Create the hash table - - if( RC_BAD( rc = f_alloc( - sizeof( F_HashObject *) * uiNumBuckets, &m_ppHashTable))) - { - goto Exit; - } - - m_uiBuckets = uiNumBuckets; - f_memset( m_ppHashTable, 0, sizeof( F_HashObject *) * uiNumBuckets); - - if( bMultithreaded) - { - // Initialize the mutex - - if( RC_BAD( rc = f_mutexCreate( &m_hMutex))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Retrieves an object from the hash table with the specified key. - This routine assumes the table's mutex has already been locked. - A reference IS NOT added to the object for the caller. -****************************************************************************/ -RCODE F_HashTable::findObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject) -{ - F_HashObject * pObject = NULL; - FLMUINT uiBucket; - FLMUINT32 ui32CRC = 0; - RCODE rc = FERR_OK; - - *ppObject = NULL; - - // Calculate the hash bucket and mutex offset - - uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); - - // Search the bucket for an object with a matching - // key. - - pObject = m_ppHashTable[ uiBucket]; - while( pObject) - { - if( pObject->getKeyCRC() == ui32CRC) - { - void * pvTmpKey; - FLMUINT uiTmpKeyLen; - - pvTmpKey = pObject->getKey( &uiTmpKeyLen); - if( uiTmpKeyLen == uiKeyLen && - f_memcmp( pvTmpKey, pvKey, uiKeyLen) == 0) - { - break; - } - } - pObject = pObject->m_pNextInBucket; - } - - if( !pObject) - { - rc = RC_SET( FERR_NOT_FOUND); - goto Exit; - } - - *ppObject = pObject; - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Adds an object to the hash table -****************************************************************************/ -RCODE F_HashTable::addObject( - F_HashObject * pObject) -{ - FLMUINT uiBucket; - F_HashObject * pTmp; - void * pvKey; - FLMUINT uiKeyLen; - FLMUINT32 ui32CRC; - FLMBOOL bMutexLocked = FALSE; - RCODE rc = FERR_OK; - - // Calculate and set the objects hash bucket - - flmAssert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); - - pvKey = pObject->getKey( &uiKeyLen); - flmAssert( uiKeyLen); - - uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); - pObject->setKeyCRC( ui32CRC); - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - // Make sure the object doesn't already exist - - if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pTmp))) - { - if( rc != FERR_NOT_FOUND) - { - goto Exit; - } - rc = FERR_OK; - } - else - { - flmAssert( 0); - rc = RC_SET( FERR_EXISTS); - goto Exit; - } - - // Add a reference to the object - - pObject->AddRef(); - - // Link the object into the appropriate lists - - linkObject( pObject, uiBucket); - -Exit: - - // Unlock the mutex - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Returns the next object in the linked list of objects in the hash - table. If *ppObject == NULL, the first object will be returned. -****************************************************************************/ -RCODE F_HashTable::getNextObjectInGlobal( - F_HashObject ** ppObject) -{ - FLMBOOL bMutexLocked = FALSE; - F_HashObject * pOldObj; - RCODE rc = FERR_OK; - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - if( !(*ppObject)) - { - *ppObject = m_pGlobalList; - } - else - { - pOldObj = *ppObject; - *ppObject = (*ppObject)->m_pNextInGlobal; - pOldObj->Release(); - } - - if( *ppObject == NULL) - { - rc = RC_SET( FERR_EOF_HIT); - goto Exit; - } - - (*ppObject)->AddRef(); - -Exit: - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Retrieves an object from the hash table with the specified key -****************************************************************************/ -RCODE F_HashTable::getObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject, - FLMBOOL bRemove) -{ - F_HashObject * pObject; - FLMBOOL bMutexLocked = FALSE; - RCODE rc = FERR_OK; - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - // Search for an object with a matching key. - - if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pObject))) - { - goto Exit; - } - - if( pObject && bRemove) - { - unlinkObject( pObject); - if( !ppObject) - { - pObject->Release(); - pObject = NULL; - } - } - - if( ppObject) - { - if( !bRemove) - { - pObject->AddRef(); - } - *ppObject = pObject; - pObject = NULL; - } - -Exit: - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Removes an object from the hash table by key -****************************************************************************/ -RCODE F_HashTable::removeObject( - void * pvKey, - FLMUINT uiKeyLen) -{ - return( getObject( pvKey, uiKeyLen, NULL, TRUE)); -} - -/**************************************************************************** -Desc: Removes an object from the hash table by object pointer -****************************************************************************/ -RCODE F_HashTable::removeObject( - F_HashObject * pObject) -{ - FLMUINT uiKeyLen; - void * pvKey; - - pvKey = pObject->getKey( &uiKeyLen); - return( getObject( pvKey, uiKeyLen, NULL, TRUE)); -} - -/**************************************************************************** -Desc: Calculates the hash bucket of a key and optionally returns the key's - CRC. -****************************************************************************/ -FLMUINT F_HashTable::getHashBucket( - void * pvKey, - FLMUINT uiLen, - FLMUINT32 * pui32KeyCRC) -{ - FLMUINT32 ui32CRC = 0; - - f_updateCRC( (FLMBYTE *)pvKey, uiLen, &ui32CRC); - if( pui32KeyCRC) - { - *pui32KeyCRC = ui32CRC; - } - return( ui32CRC % m_uiBuckets); -} - -/**************************************************************************** -Desc: Links an object to the global list and also to its bucket -Notes: This routine assumes that the bucket's mutex is already locked - if the hash table is multi-threaded. -****************************************************************************/ -void F_HashTable::linkObject( - F_HashObject * pObject, - FLMUINT uiBucket) -{ - flmAssert( uiBucket < m_uiBuckets); - flmAssert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); - - // Set the object's bucket - - pObject->setHashBucket( uiBucket); - - // Link the object to its hash bucket - - pObject->m_pNextInBucket = m_ppHashTable[ uiBucket]; - if( m_ppHashTable[ uiBucket]) - { - m_ppHashTable[ uiBucket]->m_pPrevInBucket = pObject; - } - m_ppHashTable[ uiBucket] = pObject; - - // Link to the global list - - pObject->m_pNextInGlobal = m_pGlobalList; - if( m_pGlobalList) - { - m_pGlobalList->m_pPrevInGlobal = pObject; - } - m_pGlobalList = pObject; -} - -/**************************************************************************** -Desc: Unlinks an object from its bucket and the global list. -Notes: This routine assumes that the bucket's mutex is already locked - if the hash table is multi-threaded. -****************************************************************************/ -void F_HashTable::unlinkObject( - F_HashObject * pObject) -{ - FLMUINT uiBucket = pObject->getHashBucket(); - - // Is the bucket valid? - - flmAssert( uiBucket < m_uiBuckets); - - // Unlink from the hash bucket - - if( pObject->m_pNextInBucket) - { - pObject->m_pNextInBucket->m_pPrevInBucket = pObject->m_pPrevInBucket; - } - - if( pObject->m_pPrevInBucket) - { - pObject->m_pPrevInBucket->m_pNextInBucket = pObject->m_pNextInBucket; - } - else - { - m_ppHashTable[ uiBucket] = pObject->m_pNextInBucket; - } - - pObject->m_pPrevInBucket = NULL; - pObject->m_pNextInBucket = NULL; - pObject->setHashBucket( F_INVALID_HASH_BUCKET); - - // Unlink from the global list - - if( pObject->m_pNextInGlobal) - { - pObject->m_pNextInGlobal->m_pPrevInGlobal = pObject->m_pPrevInGlobal; - } - - if( pObject->m_pPrevInGlobal) - { - pObject->m_pPrevInGlobal->m_pNextInGlobal = pObject->m_pNextInGlobal; - } - else - { - m_pGlobalList = pObject->m_pNextInGlobal; - } - - pObject->m_pPrevInGlobal = NULL; - pObject->m_pNextInGlobal = NULL; -} - /**************************************************************************** Desc: Constructor ****************************************************************************/ @@ -4615,14 +4176,17 @@ RCODE F_SessionDb::setupSessionDb( /**************************************************************************** Desc: Returns the key and key length of a database object ****************************************************************************/ -void * F_SessionDb::getKey( - FLMUINT * puiKeyLen) +const void * FLMAPI F_SessionDb::getKey( void) { - if( puiKeyLen) - { - *puiKeyLen = (FLMUINT)sizeof( m_ucKey); - } - return( (void *)(&m_ucKey[ 0])); + return( m_ucKey); +} + +/**************************************************************************** +Desc: Returns the key and key length of a database object +****************************************************************************/ +FLMUINT FLMAPI F_SessionDb::getKeyLength( void) +{ + return( sizeof( m_ucKey)); } /**************************************************************************** @@ -4763,6 +4327,16 @@ FLMUINT FLMAPI F_SuperFileClient::getFileOffset( return( FSGetFileOffset( uiBlockAddr)); } +/**************************************************************************** +Desc: +****************************************************************************/ +FLMUINT FLMAPI F_SuperFileClient::getBlockAddress( + FLMUINT uiFileNumber, + FLMUINT uiFileOffset) +{ + return( FSBlkAddress( uiFileNumber, uiFileOffset)); +} + /**************************************************************************** Desc: ****************************************************************************/ diff --git a/flaim/src/ftrans.cpp b/flaim/src/ftrans.cpp index 7f65db1..45e7adb 100644 --- a/flaim/src/ftrans.cpp +++ b/flaim/src/ftrans.cpp @@ -119,7 +119,7 @@ FLMEXP RCODE FLMAPI FlmDbTransBegin( if( pucHeader) { - if( RC_BAD( rc = pDb->pSFileHdl->readHeader( + if( RC_BAD( rc = pDb->pSFileHdl->readBlock( 0, 2048, pucHeader, &uiBytesRead))) { goto Exit; @@ -1265,12 +1265,10 @@ Desc: This routine commits an active transaction for a particular transaction is committed locally. ****************************************************************************/ RCODE flmCommitDbTrans( - FDB * pDb, - FLMUINT uiNewLogicalEOF, // New logical end-of-file. This is only - // set by the FlmDbReduceSize function when - // it is truncating the file. - FLMBOOL bForceCheckpoint, // Force a checkpoint? - FLMBOOL * pbEmpty) // May be NULL + FDB * pDb, + FLMUINT uiNewLogicalEOF, + FLMBOOL bForceCheckpoint, + FLMBOOL * pbEmpty) { RCODE rc = FERR_OK; FLMBYTE * pucUncommittedLogHdr; @@ -1425,21 +1423,16 @@ RCODE flmCommitDbTrans( // Test for buildup of dirty cache blocks. - if (((pTmpSCache) && - (!pTmpSCache->uiUseCount) && - (pTmpSCache->ui16Flags & - (CA_DIRTY | CA_LOG_FOR_CP | CA_WRITE_TO_LOG))) - - || // Test for end of roll-forward log. - - pRfl->atEndOfLog() - || - bForceCheckpoint) + if( (pTmpSCache && !pTmpSCache->uiUseCount && + (pTmpSCache->ui16Flags & + (CA_DIRTY | CA_LOG_FOR_CP | CA_WRITE_TO_LOG))) || + pRfl->atEndOfLog() || bForceCheckpoint) { bForceCheckpoint = TRUE; uiCPFileNum = pRfl->getCurrFileNum(); uiCPOffset = pRfl->getCurrReadOffset(); } + f_mutexUnlock( gv_FlmSysData.hShareMutex); } } @@ -1457,10 +1450,11 @@ RCODE flmCommitDbTrans( // Set the new logical EOF if passed in. - if (uiNewLogicalEOF) + if( uiNewLogicalEOF) { pDb->LogHdr.uiLogicalEOF = uiNewLogicalEOF; } + UD2FBA( (FLMUINT32)pDb->LogHdr.uiLogicalEOF, &pucUncommittedLogHdr [LOG_LOGICAL_EOF]); @@ -1644,9 +1638,9 @@ Exit1: flmAssert( 0); (void)pFile->pRfl->completeTransWrites( pDb, FALSE, TRUE); } - else if (!bForceCheckpoint) + else if( !bForceCheckpoint) { - if (bIndexAfterCommit) + if( bIndexAfterCommit) { rc = pFile->pRfl->completeTransWrites( pDb, TRUE, FALSE); flmIndexingAfterCommit( pDb); @@ -1674,10 +1668,12 @@ Exit1: TRUE, CP_TIME_INTERVAL_REASON, uiCPFileNum, uiCPOffset); } + if (bIndexAfterCommit) { flmIndexingAfterCommit( pDb); } + flmUnlinkDbFromTrans( pDb, TRUE); } diff --git a/flaim/src/imonchk.cpp b/flaim/src/imonchk.cpp index 1c19679..9e57796 100644 --- a/flaim/src/imonchk.cpp +++ b/flaim/src/imonchk.cpp @@ -74,7 +74,7 @@ FSTATIC RCODE CheckStatusCB( void * pvParm2, void * pvAppData); -FSTATIC RCODE imonDoCheck( +FSTATIC RCODE FLMAPI imonDoCheck( IF_Thread * pThread); FSTATIC void imonLogStr( @@ -1108,7 +1108,7 @@ RCODE F_CheckDbPage::runCheck( // Start a thread to do the check. if (RC_BAD( rc = f_threadCreate( &pThread, imonDoCheck, - "WEB DB CHECK", gv_uiDbThrdGrp, 1, + "IMON DB CHECK", gv_uiDbThrdGrp, 1, (void *)pCheckStatus, (void *)hDb))) { goto Exit; @@ -1792,7 +1792,7 @@ Exit: /**************************************************************************** Desc: Thread to perform a database check for a web page. ****************************************************************************/ -FSTATIC RCODE imonDoCheck( +FSTATIC RCODE FLMAPI imonDoCheck( IF_Thread * pThread) { RCODE rc; diff --git a/flaim/src/imonfhsh.cpp b/flaim/src/imonfhsh.cpp index 85883b6..41e43e2 100644 --- a/flaim/src/imonfhsh.cpp +++ b/flaim/src/imonfhsh.cpp @@ -37,7 +37,7 @@ RCODE F_FileHashTblPage::display( FLMINT iSindex; FLMINT iNindex; FLMBOOL found = FALSE; - FBUCKET * pFileHashTbl; + F_BUCKET * pFileHashTbl; FLMBOOL buckets[FILE_HASH_ENTRIES]; FLMINT next[FILE_HASH_ENTRIES]; FLMBOOL bRefresh; diff --git a/flaim/src/imonfsys.cpp b/flaim/src/imonfsys.cpp index 5b4fd51..ebf469a 100644 --- a/flaim/src/imonfsys.cpp +++ b/flaim/src/imonfsys.cpp @@ -204,19 +204,6 @@ void F_FlmSysDataPage::write_data( - - // hFileHdlMutex - File handle mutex - printAddress( (void *)&gv_FlmSysData.hFileHdlMutex, szAddress); - printHTMLString( - "hFileHdlMutex", - "F_MUTEX", - (void *)&gv_FlmSysData, - (void *)&gv_FlmSysData.hFileHdlMutex, - (char *)szAddress, - (bHighlight = !bHighlight)); - - - // pFileSystem - File system printAddress( (void *)gv_FlmSysData.pFileSystem, szAddress); printHTMLString( @@ -242,17 +229,6 @@ void F_FlmSysDataPage::write_data( - // bOkToDoAsyncWrites - Asynchronous writes - printHTMLString( - "bOkToDoAsyncWrites", - "FLMBOOL", - (void *)&gv_FlmSysData, - (void *)&gv_FlmSysData.bOkToDoAsyncWrites, - (char *)(gv_FlmSysData.bOkToDoAsyncWrites ? "Yes" : "No"), - (bHighlight = !bHighlight)); - - - // bCheckCache - Check cache printHTMLString( "bCheckCache", diff --git a/flaim/src/imonix.cpp b/flaim/src/imonix.cpp index db6b1d9..2d381ad 100644 --- a/flaim/src/imonix.cpp +++ b/flaim/src/imonix.cpp @@ -49,7 +49,7 @@ FSTATIC void copyIndexListStatus( IXLIST_STATUS * pSrcIxListStatus, FLMBOOL bTransferKeyList); -FSTATIC RCODE imonDoIndexList( +FSTATIC RCODE FLMAPI imonDoIndexList( IF_Thread * pThread); /**************************************************************************** @@ -1401,7 +1401,7 @@ Exit: /**************************************************************************** Desc: Thread to perform a query for a web page. ****************************************************************************/ -FSTATIC RCODE imonDoIndexList( +FSTATIC RCODE FLMAPI imonDoIndexList( IF_Thread * pThread) { RCODE rc; diff --git a/flaim/src/imonsel.cpp b/flaim/src/imonsel.cpp index dd34d48..b421dce 100644 --- a/flaim/src/imonsel.cpp +++ b/flaim/src/imonsel.cpp @@ -38,7 +38,7 @@ FSTATIC RCODE queryStatusCB( void * pvParm2, void * pvUserData); -FSTATIC RCODE imonDoQuery( +FSTATIC RCODE FLMAPI imonDoQuery( IF_Thread * pThread); /**************************************************************************** @@ -820,7 +820,7 @@ RCODE F_SelectPage::runQuery( // Start a thread to do the query. if( RC_BAD( rc = f_threadCreate( &pThread, imonDoQuery, - "WEB QUERY", + "IMON QUERY", gv_uiDbThrdGrp, 1, (void *)pQueryStatus, (void *)hDb))) { @@ -1047,7 +1047,7 @@ Exit: /**************************************************************************** Desc: Thread to perform a query for a web page. ****************************************************************************/ -FSTATIC RCODE imonDoQuery( +FSTATIC RCODE FLMAPI imonDoQuery( IF_Thread * pThread) { RCODE rc; diff --git a/flaim/src/imonutil.cpp b/flaim/src/imonutil.cpp index 3bf3c43..ff8bf9a 100644 --- a/flaim/src/imonutil.cpp +++ b/flaim/src/imonutil.cpp @@ -3928,7 +3928,7 @@ void F_DatabasePage::printGlobalDatabaseList( void) { FLMBOOL bHighlight; FLMUINT uiLoop; - FBUCKET * pBucket; + F_BUCKET * pBucket; FFILE * pFile; // Table diff --git a/flaim/src/kybuild.cpp b/flaim/src/kybuild.cpp index 01603c0..05240ae 100644 --- a/flaim/src/kybuild.cpp +++ b/flaim/src/kybuild.cpp @@ -1621,9 +1621,9 @@ FSTATIC FLMINT _KrefCompare( // Compare (SORT1) #2, (SORT2) #3: KEY - including NULL character at // end. - // + // Comparing the NULL character advoids checking the key length. - // + // VISIT: There could be a BUG where key length should be checked, but // it has to do with not storing all compound key pieces in the key. diff --git a/flaim/src/recover.cpp b/flaim/src/recover.cpp index ca67fdd..5fbd131 100644 --- a/flaim/src/recover.cpp +++ b/flaim/src/recover.cpp @@ -41,12 +41,6 @@ FSTATIC RCODE flmProcessBeforeImage( /**************************************************************************** Desc: This routine reads the next before-image block from the file. -Ret: FERR_OK - Indicates that the desired data was successfully read. - FERR_INCOMPLETE_LOG - Indicates that we would have read beyond the log end-of-file. - other - other FLAIM error codes ****************************************************************************/ FSTATIC RCODE flmReadLog( FDB * pDb, @@ -174,14 +168,6 @@ Exit: Desc: This routine reads and processes a before-image block record in the log file. The reapply flag indicates whether the block should be written back to the database file. -Ret: FERR_OK - Indicates that the before-image record was successfully read - and processed. - FERR_INVALID_BLOCK_LENGTH - This error is returned if the block length read from the log - file is invalid. - other - other FLAIM error codes ****************************************************************************/ FSTATIC RCODE flmProcessBeforeImage( FDB * pDb, @@ -273,7 +259,7 @@ FSTATIC RCODE flmProcessBeforeImage( pDb->pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); pDb->pSFileHdl->setExtendSize( pFile->uiFileExtendSize); rc = pDb->pSFileHdl->writeBlock( uiBlkAddress, uiBlkLength, pBlk, - NULL, &uiBytesWritten); + &uiBytesWritten); #ifdef FLM_DBG_LOG flmDbgLogWrite( pFile->uiFFileId, uiBlkAddress, 0, @@ -303,21 +289,13 @@ RCODE flmWriteLogHdr( DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, FFILE * pFile, - FLMBYTE * pucLogHdr, // Log header buffer. - FLMBYTE * pucCPLogHdr, // Log header as it was at the time - // of the checkpoint. - FLMBOOL bIsCheckpoint) // Are we writing a checkpoint? If we - // we are, we may write the log header - // as is. Otherwise, we need to make - // sure we don't write out certain - // parts of the log header - they must - // not be updated on disk until a - // checkpoint actually occurs. + FLMBYTE * pucLogHdr, + FLMBYTE * pucCPLogHdr, + FLMBOOL bIsCheckpoint) { RCODE rc = FERR_OK; - FLMUINT uiBytesWritten; + FLMUINT uiBytesToWrite; FLMUINT uiNewCheckSum; - IF_FileHdl * pCFileHdl = NULL; FLMBYTE * pucTmpLogHdr; F_TMSTAMP StartTime; @@ -334,7 +312,7 @@ RCODE flmWriteLogHdr( } pucTmpLogHdr = &pFile->pucLogHdrWriteBuf[ 16]; - uiBytesWritten = LOG_HEADER_SIZE + 16; + uiBytesToWrite = LOG_HEADER_SIZE + 16; // Very Important Note: FlmDbConfig relies on the fact that we will // write out the prefix area of the database header. Do not remove @@ -418,22 +396,17 @@ RCODE flmWriteLogHdr( // Now update the log header record on disk - if (pDbStats) + if( pDbStats) { pDbStats->bHaveStats = TRUE; pDbStats->LogHdrWrites.ui64Count++; - pDbStats->LogHdrWrites.ui64TotalBytes += uiBytesWritten; + pDbStats->LogHdrWrites.ui64TotalBytes += uiBytesToWrite; f_timeGetTimeStamp( &StartTime); } - if( RC_BAD( rc = pSFileHdl->getFileHdl( 0, TRUE, &pCFileHdl))) - { - goto Exit; - } - - if( RC_BAD( rc = pCFileHdl->sectorWrite( - 0, f_roundUp( uiBytesWritten, 512), - pFile->pucLogHdrWriteBuf, NULL, &uiBytesWritten))) + if( RC_BAD( rc = pSFileHdl->writeBlock( 0, + (FLMUINT)f_roundUp( uiBytesToWrite, 512), + pFile->pucLogHdrWriteBuf, NULL))) { if (pDbStats) { @@ -443,12 +416,12 @@ RCODE flmWriteLogHdr( goto Exit; } - if (pDbStats) + if( pDbStats) { flmAddElapTime( &StartTime, &pDbStats->LogHdrWrites.ui64ElapMilli); } - if (RC_BAD( rc = pCFileHdl->flush())) + if( RC_BAD( rc = pSFileHdl->flush())) { goto Exit; } @@ -509,7 +482,6 @@ RCODE flmPhysRollback( // blocks along the way. uiCurrAddr = uiFirstLogBlkAddr; - pDb->pSFileHdl->enableFlushMinimize(); while (FSAddrIsBelow( uiCurrAddr, uiLogEOF)) { if (RC_BAD( rc = flmProcessBeforeImage( pDb, @@ -529,8 +501,6 @@ RCODE flmPhysRollback( Exit: - pDb->pSFileHdl->disableFlushMinimize(); - // Free the memory handle, if one was allocated. if (pucBlk) diff --git a/flaim/src/rfl.cpp b/flaim/src/rfl.cpp index 3352b9d..ac90fe7 100644 --- a/flaim/src/rfl.cpp +++ b/flaim/src/rfl.cpp @@ -54,14 +54,14 @@ F_Rfl::F_Rfl() m_pCurrentBuf = NULL; m_uiRflWriteBufs = DEFAULT_RFL_WRITE_BUFFERS; m_uiBufferSize = DEFAULT_RFL_BUFFER_SIZE; - f_memset( &m_Buf1, 0, sizeof(m_Buf1)); - f_memset( &m_Buf2, 0, sizeof(m_Buf2)); + f_memset( &m_Buf1, 0, sizeof( m_Buf1)); + f_memset( &m_Buf2, 0, sizeof( m_Buf2)); m_bKeepRflFiles = FALSE; m_uiRflMinFileSize = DEFAULT_MIN_RFL_FILE_SIZE; m_uiRflMaxFileSize = DEFAULT_MAX_RFL_FILE_SIZE; m_pFileHdl = NULL; m_uiLastRecoverFileNum = 0; - f_memset( m_ucCurrSerialNum, 0, sizeof(m_ucCurrSerialNum)); + f_memset( m_ucCurrSerialNum, 0, sizeof( m_ucCurrSerialNum)); m_bLoggingOff = FALSE; m_bLoggingUnknown = FALSE; m_uiUnknownPacketLen = 0; @@ -93,48 +93,42 @@ Desc: *********************************************************************/ F_Rfl::~F_Rfl() { - - // Better not be in the middle of logging unknown packets for the - // application. - flmAssert( !m_bLoggingUnknown); - if (m_Buf1.pIOBuffer) + if( m_Buf1.pIOBuffer) { m_Buf1.pIOBuffer->Release(); m_Buf1.pIOBuffer = NULL; } - if (m_Buf2.pIOBuffer) + if( m_Buf2.pIOBuffer) { m_Buf2.pIOBuffer->Release(); m_Buf2.pIOBuffer = NULL; } - if (m_Buf1.pBufferMgr) + if( m_Buf1.pBufferMgr) { - flmAssert( !m_Buf1.pBufferMgr->havePendingIO() && - !m_Buf1.pBufferMgr->haveUsed()); + flmAssert( !m_Buf1.pBufferMgr->isIOPending()); m_Buf1.pBufferMgr->Release(); m_Buf1.pBufferMgr = NULL; } - if (m_Buf2.pBufferMgr) + if( m_Buf2.pBufferMgr) { - flmAssert( !m_Buf2.pBufferMgr->havePendingIO() && - !m_Buf2.pBufferMgr->haveUsed()); + flmAssert( !m_Buf2.pBufferMgr->isIOPending()); m_Buf2.pBufferMgr->Release(); m_Buf2.pBufferMgr = NULL; } - if (m_hBufMutex != F_MUTEX_NULL) + if( m_hBufMutex != F_MUTEX_NULL) { f_mutexDestroy( &m_hBufMutex); } - if (m_pFileHdl) + if( m_pFileHdl) { m_pFileHdl->Release(); m_pFileHdl = NULL; @@ -326,11 +320,12 @@ RCODE F_Rfl::positionTo( uiBytesToRead = MOD_512( uiFileOffset); m_pCurrentBuf->uiRflFileOffset = ROUND_DOWN_TO_NEAREST_512( uiFileOffset); m_pCurrentBuf->uiRflBufBytes = MOD_512( uiFileOffset); + if (m_pCurrentBuf->uiRflBufBytes) { - if (RC_BAD( rc = m_pFileHdl->sectorRead( + if (RC_BAD( rc = m_pFileHdl->read( m_pCurrentBuf->uiRflFileOffset, m_pCurrentBuf->uiRflBufBytes, - m_pCurrentBuf->pIOBuffer->getBuffer(), &uiBytesRead))) + m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) { @@ -641,43 +636,37 @@ RCODE F_Rfl::setup( // Allocate memory for the RFL buffers - if (!gv_FlmSysData.bOkToDoAsyncWrites) + if( !gv_FlmSysData.pFileSystem->canDoAsync()) { m_uiRflWriteBufs = 1; m_uiBufferSize = DEFAULT_RFL_WRITE_BUFFERS * DEFAULT_RFL_BUFFER_SIZE; } - if (RC_BAD( rc = f_mutexCreate( &m_hBufMutex))) + if( RC_BAD( rc = f_mutexCreate( &m_hBufMutex))) { goto Exit; } - if( RC_BAD( rc = FlmAllocIOBufferMgr( &m_Buf1.pBufferMgr))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( m_uiRflWriteBufs, + m_uiRflWriteBufs * m_uiBufferSize, TRUE, &m_Buf1.pBufferMgr))) { goto Exit; } - if( RC_BAD( rc = FlmAllocIOBufferMgr( &m_Buf2.pBufferMgr))) + if( RC_BAD( rc = m_Buf1.pBufferMgr->getBuffer( + m_uiBufferSize, &m_Buf1.pIOBuffer))) { goto Exit; } - m_Buf1.pBufferMgr->enableKeepBuffer(); - m_Buf1.pBufferMgr->setMaxBuffers( m_uiRflWriteBufs); - m_Buf1.pBufferMgr->setMaxBytes( m_uiRflWriteBufs * m_uiBufferSize); - - if (RC_BAD( rc = m_Buf1.pBufferMgr->getBuffer( &m_Buf1.pIOBuffer, - m_uiBufferSize, m_uiBufferSize))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( m_uiRflWriteBufs, + m_uiRflWriteBufs * m_uiBufferSize, TRUE, &m_Buf2.pBufferMgr))) { goto Exit; } - m_Buf2.pBufferMgr->enableKeepBuffer(); - m_Buf2.pBufferMgr->setMaxBuffers( m_uiRflWriteBufs); - m_Buf2.pBufferMgr->setMaxBytes( m_uiRflWriteBufs * m_uiBufferSize); - - if (RC_BAD( rc = m_Buf2.pBufferMgr->getBuffer( &m_Buf2.pIOBuffer, - m_uiBufferSize, m_uiBufferSize))) + if( RC_BAD( rc = m_Buf2.pBufferMgr->getBuffer( + m_uiBufferSize, &m_Buf2.pIOBuffer))) { goto Exit; } @@ -707,17 +696,18 @@ RCODE F_Rfl::waitForWrites( RFL_BUFFER * pBuffer, FLMBOOL bIsWriter) { - RCODE rc = FERR_OK; - RCODE TempRc; - RFL_WAITER Waiter; - FLMBOOL bMutexLocked = TRUE; + RCODE rc = FERR_OK; + RCODE TempRc; + RFL_WAITER Waiter; + FLMBOOL bMutexLocked = TRUE; // Put self on the wait queue for the buffer. Waiter.uiThreadId = f_threadId(); Waiter.bIsWriter = bIsWriter; Waiter.hESem = F_SEM_NULL; - if (RC_BAD( rc = f_semCreate( &Waiter.hESem))) + + if( RC_BAD( rc = f_semCreate( &Waiter.hESem))) { goto Exit; } @@ -728,6 +718,7 @@ RCODE F_Rfl::waitForWrites( rc = RC_SET( FERR_FAILURE); Waiter.pRc = &rc; Waiter.pNext = NULL; + if (pBuffer->pLastWaiter) { pBuffer->pLastWaiter->pNext = &Waiter; @@ -743,31 +734,27 @@ RCODE F_Rfl::waitForWrites( // Now just wait to be signaled. - if (RC_BAD( TempRc = f_semWait( Waiter.hESem, F_SEM_WAITFOREVER))) + if( RC_BAD( TempRc = f_semWait( Waiter.hESem, F_SEM_WAITFOREVER))) { flmAssert( 0); rc = TempRc; } else { - // Process that signaled us better set the rc to something besides // FERR_FAILURE. - - if (rc == FERR_FAILURE) - { - flmAssert( 0); - } + + flmAssert( rc != FERR_FAILURE); } Exit: - if (Waiter.hESem != F_SEM_NULL) + if( Waiter.hESem != F_SEM_NULL) { f_semDestroy( &Waiter.hESem); } - if (bMutexLocked) + if( bMutexLocked) { f_mutexUnlock( m_hBufMutex); } @@ -778,7 +765,7 @@ Exit: /******************************************************************** Desc: If a commit is in progress, wait for it to finish. *********************************************************************/ -RCODE F_Rfl::waitForCommit(void) +RCODE F_Rfl::waitForCommit( void) { RCODE rc = FERR_OK; FLMBOOL bMutexLocked = FALSE; @@ -850,8 +837,7 @@ RCODE F_Rfl::writeHeader( // Write out the header - if (RC_BAD( rc = m_pFileHdl->sectorWrite( 0L, 512, ucBuf, - NULL, &uiBytesWritten))) + if (RC_BAD( rc = m_pFileHdl->write( 0L, 512, ucBuf, &uiBytesWritten))) { // Remap disk full error @@ -1016,9 +1002,11 @@ RCODE F_Rfl::openFile( } // Open the file. + + f_assert( !m_pFileHdl); if (RC_BAD( rc = gv_FlmSysData.pFileSystem->openFile( szRflFileName, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &m_pFileHdl))) + gv_FlmSysData.uiFileOpenFlags, &m_pFileHdl))) { goto Exit; } @@ -1028,7 +1016,7 @@ RCODE F_Rfl::openFile( // Read the header. - if (RC_BAD( rc = m_pFileHdl->sectorRead( 0, 512, ucBuf, &uiBytesRead))) + if (RC_BAD( rc = m_pFileHdl->read( 0, 512, ucBuf, &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) { @@ -1142,10 +1130,11 @@ RCODE F_Rfl::createFile( } // Create the file + + f_assert( !m_pFileHdl); if (RC_BAD( rc = gv_FlmSysData.pFileSystem->createFile( szRflFileName, - FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &m_pFileHdl))) + gv_FlmSysData.uiFileCreateFlags, &m_pFileHdl))) { goto Exit; } @@ -1286,7 +1275,7 @@ RCODE F_Rfl::flush( RCODE rc = FERR_OK; FLMUINT uiBytesWritten; IF_IOBuffer * pNewBuffer = NULL; - IF_IOBuffer * pAsyncBuf = NULL; + IF_IOBuffer * pIOBuffer = NULL; FLMBYTE * pucOldBuffer; FLMUINT uiFileOffset; FLMUINT uiBufBytes; @@ -1297,7 +1286,7 @@ RCODE F_Rfl::flush( // Must wait for stuff in committing buffer, if any, before going // ahead here. - if (pBuffer != m_pCommitBuf) + if( pBuffer != m_pCommitBuf) { if (RC_BAD( rc = waitForCommit())) { @@ -1305,9 +1294,9 @@ RCODE F_Rfl::flush( } } - if (m_uiRflWriteBufs > 1 && m_pFileHdl->canDoAsync()) + if( m_uiRflWriteBufs > 1 && m_pFileHdl->canDoAsync()) { - pAsyncBuf = pBuffer->pIOBuffer; + pIOBuffer = pBuffer->pIOBuffer; } if ((FLMUINT) (-1) - pBuffer->uiRflFileOffset <= pBuffer->uiRflBufBytes) @@ -1316,13 +1305,14 @@ RCODE F_Rfl::flush( goto Exit; } - pucOldBuffer = pBuffer->pIOBuffer->getBuffer(); + pucOldBuffer = pBuffer->pIOBuffer->getBufferPtr(); uiFileOffset = pBuffer->uiRflFileOffset; uiBufBytes = pBuffer->uiRflBufBytes; + if (m_uiRflWriteBufs > 1) { - if (RC_BAD( rc = pBuffer->pBufferMgr->getBuffer( &pNewBuffer, - m_uiBufferSize, m_uiBufferSize))) + if (RC_BAD( rc = pBuffer->pBufferMgr->getBuffer( + m_uiBufferSize, &pNewBuffer))) { goto Exit; } @@ -1333,13 +1323,27 @@ RCODE F_Rfl::flush( if (!bFinalWrite) { - copyLastBlock( pBuffer, pucOldBuffer, pNewBuffer->getBuffer(), + copyLastBlock( pBuffer, pucOldBuffer, pNewBuffer->getBufferPtr(), uiCurrPacketLen, bStartingNewFile); } } + + if( pIOBuffer) + { + FLMUINT uiBytesToWrite = (FLMUINT)f_roundUp( uiBufBytes, + m_pFileHdl->getSectorSize()); - if( RC_OK( rc = m_pFileHdl->sectorWrite( uiFileOffset, uiBufBytes, - pucOldBuffer, pAsyncBuf, &uiBytesWritten))) + rc = m_pFileHdl->write( uiFileOffset, uiBytesToWrite, pIOBuffer); + } + else + { + pBuffer->pIOBuffer->setPending(); + + rc = m_pFileHdl->write( uiFileOffset, uiBufBytes, + pucOldBuffer, &uiBytesWritten); + } + + if( RC_OK( rc)) { if( m_bKeepRflFiles) { @@ -1369,12 +1373,12 @@ RCODE F_Rfl::flush( if (m_uiRflWriteBufs == 1) { - // We are counting on the fact that the write completed. When we // only have one buffer, we cannot do async writes. - flmAssert( !pAsyncBuf); - if (RC_OK( rc) && !bFinalWrite) + flmAssert( !pIOBuffer); + + if( RC_OK( rc) && !bFinalWrite) { copyLastBlock( pBuffer, pucOldBuffer, pucOldBuffer, uiCurrPacketLen, bStartingNewFile); @@ -1383,29 +1387,25 @@ RCODE F_Rfl::flush( // DO NOT call notifyComplete - that would put // pBuffer->pIOBuffer into the avail list, and we don't want // that. We simply want to keep reusing it. - } else { - // No need to call copyLastBlock, because it was called above - // before calling sectorWrite. The part of the old buffer that + // before calling write. The part of the old buffer that // needs to be transferred to the new buffer has already been // transferred. - if (!pAsyncBuf) + if( !pIOBuffer) { pBuffer->pIOBuffer->notifyComplete( rc); } + pBuffer->pIOBuffer->Release(); pBuffer->pIOBuffer = pNewBuffer; } - if (RC_BAD( rc)) + if( RC_BAD( rc)) { - - // Remap disk full error - if (rc == FERR_IO_DISK_FULL) { rc = RC_SET( FERR_RFL_DEVICE_FULL); @@ -1444,8 +1444,8 @@ void F_Rfl::switchBuffers(void) m_pCurrentBuf->uiRflFileOffset = pOldBuffer->uiRflFileOffset; if (pOldBuffer->uiRflBufBytes) { - copyLastBlock( m_pCurrentBuf, pOldBuffer->pIOBuffer->getBuffer(), - m_pCurrentBuf->pIOBuffer->getBuffer(), 0, FALSE); + copyLastBlock( m_pCurrentBuf, pOldBuffer->pIOBuffer->getBufferPtr(), + m_pCurrentBuf->pIOBuffer->getBufferPtr(), 0, FALSE); } } @@ -2447,7 +2447,7 @@ RCODE F_Rfl::finishPacket( // Get a pointer to packet header. - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes]); // Set the packet address in the packet header. @@ -4949,8 +4949,8 @@ RCODE F_Rfl::readPacket( // Move the bytes left in the buffer down to the beginning of // the buffer. - f_memmove( m_pCurrentBuf->pIOBuffer->getBuffer(), - &(m_pCurrentBuf->pIOBuffer->getBuffer()[m_uiRflReadOffset]), + f_memmove( m_pCurrentBuf->pIOBuffer->getBufferPtr(), + &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[m_uiRflReadOffset]), m_pCurrentBuf->uiRflBufBytes - m_uiRflReadOffset); m_pCurrentBuf->uiRflBufBytes -= m_uiRflReadOffset; m_pCurrentBuf->uiRflFileOffset += m_uiRflReadOffset; @@ -4989,7 +4989,7 @@ RCODE F_Rfl::readPacket( // Read enough to get the entire packet. if (RC_BAD( rc = m_pRestore->read( uiReadLen, &( - m_pCurrentBuf->pIOBuffer->getBuffer()[ + m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes]), &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) @@ -5060,8 +5060,8 @@ RCODE F_Rfl::readPacket( // Read to get the entire packet. - if (RC_BAD( rc = m_pFileHdl->sectorRead( m_pCurrentBuf->uiRflFileOffset, - uiReadLen, m_pCurrentBuf->pIOBuffer->getBuffer(), + if (RC_BAD( rc = m_pFileHdl->read( m_pCurrentBuf->uiRflFileOffset, + uiReadLen, m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { if (rc == FERR_IO_END_OF_FILE) @@ -5283,7 +5283,7 @@ Get_Next_File: // Verify the packet address. m_uiPacketAddress = m_pCurrentBuf->uiRflFileOffset + m_uiRflReadOffset; - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[m_uiRflReadOffset]); + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[m_uiRflReadOffset]); if ((FLMUINT) FB2UD( &pucPacket[RFL_PACKET_ADDRESS_OFFSET]) != m_uiPacketAddress) { rc = RC_SET( FERR_BAD_RFL_PACKET); @@ -5319,7 +5319,7 @@ Get_Next_File: goto Exit; } - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[m_uiRflReadOffset]); + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[m_uiRflReadOffset]); // At this point, we are guaranteed to have the entire packet in the // buffer. @@ -7227,7 +7227,7 @@ Retry_Open: } if (RC_BAD( rc = m_pRestore->read( uiReadLen, - m_pCurrentBuf->pIOBuffer->getBuffer(), &uiBytesRead))) + m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { goto Exit; } @@ -8413,6 +8413,7 @@ Exit: pUnkStream->Release(); pUnkStream = NULL; } + *ppUnknownStream = (F_UnknownStream *)pUnkStream; return( rc); } diff --git a/flaim/src/rfl.h b/flaim/src/rfl.h index 5546036..197bfa4 100644 --- a/flaim/src/rfl.h +++ b/flaim/src/rfl.h @@ -433,7 +433,7 @@ public: FINLINE FLMBYTE * getPacketPtr( void) { - return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + return( &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes])); } @@ -452,7 +452,7 @@ public: { if( m_pCurrentBuf->pBufferMgr) { - flmAssert( !m_pCurrentBuf->pBufferMgr->havePendingIO()); + flmAssert( !m_pCurrentBuf->pBufferMgr->isIOPending()); } if (m_pFileHdl) @@ -562,7 +562,7 @@ private: FINLINE FLMBYTE * getPacketBodyPtr( void) { - return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + return( &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes + RFL_PACKET_OVERHEAD])); } diff --git a/flaim/src/scache.cpp b/flaim/src/scache.cpp index f569593..b879dff 100644 --- a/flaim/src/scache.cpp +++ b/flaim/src/scache.cpp @@ -29,6 +29,7 @@ #endif #define MAX_BLOCKS_TO_SORT 500 +#define FLM_MAX_IO_BUFFER_BLOCKS 16 typedef struct TMP_READ_STATS { @@ -127,8 +128,9 @@ FSTATIC RCODE ScaFlushLogBlocks( FLMBOOL * pbForceCheckpoint, FLMBOOL * pbWroteAll); -FSTATIC void scaWriteComplete( - IF_IOBuffer * pIOBuffer); +FSTATIC void FLMAPI scaWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData); FSTATIC RCODE ScaReduceCache( FDB * pDb); @@ -188,22 +190,13 @@ FSTATIC RCODE ScaReadIntoCache( SCACHE * pPrevInVerList, SCACHE * pNextInVerList, SCACHE ** ppSCacheRV, - FLMBOOL * pbGotFromDisk - ); + FLMBOOL * pbGotFromDisk); FSTATIC void scaSort( SCACHE ** ppSCacheTbl, FLMUINT uiLowerBounds, FLMUINT uiUpperBounds); -FSTATIC RCODE ScaWriteContiguousBlocks( - DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - FFILE * pFile, - IF_IOBuffer * pIOBuffer, - FLMUINT uiBlkAddress, - FLMBOOL bDoAsync); - FSTATIC RCODE scaWriteSortedBlocks( DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, @@ -212,7 +205,6 @@ FSTATIC RCODE scaWriteSortedBlocks( FLMUINT * puiDirtyCacheLeft, FLMBOOL * pbForceCheckpoint, FLMBOOL bIsCPThread, - FLMBOOL bDoAsync, FLMUINT uiNumSortedBlocks, FLMBOOL * pbWroteAll); @@ -1985,16 +1977,12 @@ FSTATIC RCODE ScaFlushLogBlocks( : (SCACHE **)NULL); FLMUINT uiTotalLoggedBlocks = 0; FLMBOOL bForceCheckpoint = *pbForceCheckpoint; - FLMBOOL bDoAsync; IF_LockObject * pWriteLockObj = pFile->pWriteLockObj; #ifdef FLM_DBG_LOG FLMUINT16 ui16OldFlags; #endif pFile->uiCurrLogWriteOffset = 0; - bDoAsync = (gv_FlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; // Get the correct log header. If we are in an update transaction, // need to use the uncommitted log header. Otherwise, use the last @@ -2235,7 +2223,7 @@ FSTATIC RCODE ScaFlushLogBlocks( if (RC_BAD( rc = lgOutputBlock( pDbStats, pSFileHdl, pFile, pLastBlockToLog, pLastBlockToLog->pPrevInVersionList->pucBlk, - bDoAsync, &uiLogEof))) + &uiLogEof))) { goto Exit; } @@ -2305,8 +2293,7 @@ Write_Log_Blocks: if (pFile->uiCurrLogWriteOffset) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - pFile, bDoAsync))) + if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, pFile))) { goto Exit; } @@ -2315,12 +2302,9 @@ Write_Log_Blocks: // If doing async, wait for pending writes to complete before writing // the log header. - if (bDoAsync) + if (RC_BAD( rc = pFile->pBufferMgr->waitForAllPendingIO())) { - if (RC_BAD( rc = pFile->pBufferMgr->waitForAllPendingIO())) - { - goto Exit; - } + goto Exit; } // Must wait for all RFL writes before writing out log header. @@ -2525,24 +2509,22 @@ Exit: // Don't care what rc is at this point. Just calling // lgFlushLogBuffer to clear the buffer. - (void)lgFlushLogBuffer( pDbStats, pSFileHdl, pFile, bDoAsync); + (void)lgFlushLogBuffer( pDbStats, pSFileHdl, pFile); } // Need to wait for any async writes to complete. - if (bDoAsync) + if (bMutexLocked) { - if (bMutexLocked) - { - f_mutexUnlock( gv_FlmSysData.hShareMutex); - bMutexLocked = FALSE; - } - - // Don't care about rc here, but we don't want to leave - // this routine until all pending IO is taken care of. - - (void)pFile->pBufferMgr->waitForAllPendingIO(); + f_mutexUnlock( gv_FlmSysData.hShareMutex); + bMutexLocked = FALSE; } + + // Don't care about rc here, but we don't want to leave + // this routine until all pending IO is taken care of. + + (void)pFile->pBufferMgr->waitForAllPendingIO(); + if (!bMutexLocked) { f_mutexLock( gv_FlmSysData.hShareMutex); @@ -2623,7 +2605,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !pFile->pBufferMgr->havePendingIO()); + flmAssert( !pFile->pBufferMgr->isIOPending()); flmAssert( pFile->pCurrLogBuffer == NULL); *pbForceCheckpoint = bForceCheckpoint; @@ -2633,38 +2615,42 @@ Exit: /**************************************************************************** Desc: This routine is called whenever a write of a dirty block completes. ****************************************************************************/ -FSTATIC void scaWriteComplete( - IF_IOBuffer * pIOBuffer) +FSTATIC void FLMAPI scaWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData) { - RCODE rc = pIOBuffer->getCompletionCode(); - FLMUINT uiNumBlocks = pIOBuffer->getBufferSize() / - pIOBuffer->getBlockSize(); - SCACHE * pSCache; - FFILE * pFile; - DB_STATS * pDbStats = (DB_STATS *)pIOBuffer->getStats(); - FLMUINT uiMilliPerBlock = 0; - FLMUINT uiExtraMilli = 0; - + RCODE rc; + FLMUINT uiNumBlocks = 0; + SCACHE * pSCache = NULL; + FFILE * pFile; + DB_STATS * pDbStats = (DB_STATS *)pvData; + FLMUINT uiMilliPerBlock = 0; + FLMUINT uiExtraMilli = 0; #ifdef FLM_DBG_LOG - FLMUINT16 ui16OldFlags; + FLMUINT16 ui16OldFlags; #endif - if (pDbStats) + f_assert( pIOBuffer->isComplete()); + + rc = pIOBuffer->getCompletionCode(); + uiNumBlocks = pIOBuffer->getCallbackDataCount(); + + if( pDbStats) { - FLMUINT64 ui64ElapMilli = pIOBuffer->getElapTime(); + FLMUINT64 ui64ElapMilli = pIOBuffer->getElapsedTime(); uiMilliPerBlock = (FLMUINT)(ui64ElapMilli / (FLMUINT64)uiNumBlocks); uiExtraMilli = (FLMUINT)(ui64ElapMilli % (FLMUINT64)uiNumBlocks); } f_mutexLock( gv_FlmSysData.hShareMutex); - while (uiNumBlocks) + while( uiNumBlocks) { uiNumBlocks--; - pSCache = (SCACHE *)pIOBuffer->getCompletionCallbackData( uiNumBlocks); + pSCache = (SCACHE *)pIOBuffer->getCallbackData( uiNumBlocks); pFile = pSCache->pFile; - if (pDbStats) + if( pDbStats) { FLMBYTE * pucBlk = pSCache->pucBlk; FLMUINT uiLFileNum; @@ -2673,8 +2659,7 @@ FSTATIC void scaWriteComplete( FLMUINT uiBlkType; FLMUINT uiLfType; - if ((uiLFileNum = - (FLMUINT)FB2UW( &pucBlk [BH_LOG_FILE_NUM])) == 0) + if( (uiLFileNum = (FLMUINT)FB2UW( &pucBlk [BH_LOG_FILE_NUM])) == 0) { pLFileStats = NULL; } @@ -2682,25 +2667,25 @@ FSTATIC void scaWriteComplete( { uiLfType = 0xFF; - if (uiLFileNum == FLM_DICT_INDEX) + if( uiLFileNum == FLM_DICT_INDEX) { uiLfType = LF_INDEX; } - else if (uiLFileNum == FLM_DATA_CONTAINER || + else if( uiLFileNum == FLM_DATA_CONTAINER || uiLFileNum == FLM_DICT_CONTAINER || uiLFileNum == FLM_TRACKER_CONTAINER) { uiLfType = LF_CONTAINER; } - if (RC_BAD( flmStatGetLFile( pDbStats, uiLFileNum, + if( RC_BAD( flmStatGetLFile( pDbStats, uiLFileNum, uiLfType, 0, &pLFileStats, NULL, NULL))) { pLFileStats = NULL; } } - if (pLFileStats) + if( pLFileStats) { uiBlkType = BHT_LEAF; } @@ -2709,15 +2694,14 @@ FSTATIC void scaWriteComplete( uiBlkType = (FLMUINT)(BH_GET_TYPE( pucBlk)); } - if ((pBlockIOStats = flmGetBlockIOStatPtr( pDbStats, - pLFileStats, pucBlk, - uiBlkType)) != NULL) + if( (pBlockIOStats = flmGetBlockIOStatPtr( pDbStats, + pLFileStats, pucBlk, uiBlkType)) != NULL) { pBlockIOStats->BlockWrites.ui64Count++; pBlockIOStats->BlockWrites.ui64TotalBytes += pFile->FileHdr.uiBlockSize; - if (uiExtraMilli) + if( uiExtraMilli) { pBlockIOStats->BlockWrites.ui64ElapMilli += (uiMilliPerBlock + 1); @@ -2732,14 +2716,14 @@ FSTATIC void scaWriteComplete( } ScaReleaseForThread( pSCache); - if (pSCache->ui16Flags & CA_DIRTY) + if( pSCache->ui16Flags & CA_DIRTY) { flmAssert( pSCache->ui16Flags & CA_WRITE_PENDING); #ifdef FLM_DBG_LOG ui16OldFlags = pSCache->ui16Flags; #endif scaClearFlags( pSCache, CA_WRITE_PENDING); - if (RC_OK( rc)) + if( RC_OK( rc)) { scaUnsetDirtyFlag( pSCache, pFile); } @@ -2760,6 +2744,7 @@ FSTATIC void scaWriteComplete( flmAssert( !(pSCache->ui16Flags & CA_WRITE_PENDING)); } } + f_mutexUnlock( gv_FlmSysData.hShareMutex); } @@ -2768,7 +2753,7 @@ Desc: Cleanup old blocks in cache that are no longer needed by any transaction. ****************************************************************************/ void ScaCleanupCache( - FLMUINT uiMaxLockTime) + FLMUINT uiMaxLockTime) { SCACHE * pTmpSCache; SCACHE * pPrevSCache; @@ -2784,8 +2769,8 @@ void ScaCleanupCache( // Stop when we reach end of list or all old blocks have // been freed. - if ((!pTmpSCache) || - (!gv_FlmSysData.SCacheMgr.Usage.uiOldVerBytes)) + if( !pTmpSCache || + !gv_FlmSysData.SCacheMgr.Usage.uiOldVerBytes) { break; } @@ -2802,8 +2787,7 @@ void ScaCleanupCache( uiBlocksExamined = 0; uiCurrTime = FLM_GET_TIMER(); - if (FLM_ELAPSED_TIME( uiCurrTime, uiLastTimePaused) >= - uiMaxLockTime) + if( FLM_ELAPSED_TIME( uiCurrTime, uiLastTimePaused) >= uiMaxLockTime) { // Increment the use count so that this block will not // go away while we are paused. @@ -2877,7 +2861,7 @@ FINLINE FLMBOOL scaCanBeFreed( SCACHE * pSCache, FLMBOOL bCheckIfNeededByReader = TRUE) { - if (!pSCache->uiUseCount && !pSCache->ui16Flags) + if( !pSCache->uiUseCount && !pSCache->ui16Flags) { SCACHE * pNewerSCache = pSCache->pPrevInVersionList; @@ -2952,16 +2936,15 @@ Desc: Reduce cache to below the cache limit. NOTE: This routine assumes still locked. ****************************************************************************/ FSTATIC RCODE ScaReduceCache( - FDB * pDb - ) + FDB * pDb) { - RCODE rc = FERR_OK; - SCACHE * pTmpSCache; - SCACHE * pPrevSCache = NULL; - FFILE * pFile = pDb ? pDb->pFile : NULL; - FLMBOOL bForceCheckpoint; - FLMBOOL bDummy; - FLMUINT uiBlocksFlushed; + RCODE rc = FERR_OK; + SCACHE * pTmpSCache; + SCACHE * pPrevSCache = NULL; + FFILE * pFile = pDb ? pDb->pFile : NULL; + FLMBOOL bForceCheckpoint; + FLMBOOL bDummy; + FLMUINT uiBlocksFlushed; // If cache is not full, we are done. @@ -4992,78 +4975,6 @@ Iterate_Larger_Half: } } -/**************************************************************************** -Desc: Write an IO buffer to disk. -****************************************************************************/ -FSTATIC RCODE ScaWriteContiguousBlocks( - DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - FFILE * pFile, - IF_IOBuffer * pIOBuffer, - FLMUINT uiBlkAddress, - FLMBOOL bDoAsync) -{ - RCODE rc = FERR_OK; - FLMBYTE * pucWriteBuffer; - IF_IOBuffer * pAsyncBuffer = NULL; - FLMUINT uiBytesWritten; - FLMUINT uiWriteLen; - - pucWriteBuffer = pIOBuffer->getBuffer(); - - if (!bDoAsync) - { - pAsyncBuffer = NULL; - } - else - { - pAsyncBuffer = pIOBuffer; - } - - // Determine how many bytes to write - - uiWriteLen = pIOBuffer->getBufferSize(); - pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); - pSFileHdl->setExtendSize( pFile->uiFileExtendSize); - - pIOBuffer->startTimer( pDbStats); - - // NOTE: No guarantee that pIOBuffer will still be around - // after the call to WriteBlock, unless we are doing - // non-asynchronous write. - - rc = pSFileHdl->writeBlock( uiBlkAddress, uiWriteLen, - pucWriteBuffer, pAsyncBuffer, &uiBytesWritten); - if (!pAsyncBuffer) - { - pIOBuffer->notifyComplete( rc); - } - pIOBuffer = NULL; - - if (RC_BAD( rc)) - { - if (pDbStats) - { - pDbStats->bHaveStats = TRUE; - pDbStats->uiWriteErrors++; - } - goto Exit; - } - -Exit: - - // If we allocated a write buffer, but did not do a write with it - // still need to do the notify to clean up cache blocks. - - if (pIOBuffer) - { - flmAssert( RC_BAD( rc)); - pIOBuffer->notifyComplete( rc); - } - - return( rc); -} - /**************************************************************************** Desc: This routine writes all blocks in the sorted list, or releases them. It attempts to write as many as it can that are currently @@ -5078,30 +4989,29 @@ FSTATIC RCODE scaWriteSortedBlocks( FLMUINT * puiDirtyCacheLeft, FLMBOOL * pbForceCheckpoint, FLMBOOL bIsCPThread, - FLMBOOL bDoAsync, FLMUINT uiNumSortedBlocks, FLMBOOL * pbWroteAll) { - RCODE rc = FERR_OK; - FLMBOOL bMutexLocked = FALSE; - FLMUINT uiStartBlkAddr = 0; - FLMUINT uiLastBlkAddr = 0; - FLMUINT uiContiguousBlocks = 0; - FLMUINT uiNumSortedBlocksProcessed; - FLMUINT uiBlockCount; - FLMUINT uiBlockSize = pFile->FileHdr.uiBlockSize; - CP_INFO * pCPInfo = pFile->pCPInfo; - SCACHE * ppContiguousBlocks[ FLM_MAX_IO_BUFFER_BLOCKS]; - FLMBOOL bBlockDirty[ FLM_MAX_IO_BUFFER_BLOCKS]; - FLMUINT uiOffset; - FLMUINT uiTmpOffset; - FLMUINT uiLoop; - FLMUINT uiStartOffset; - FLMUINT uiCopyLen; - FLMBOOL bForceCheckpoint = *pbForceCheckpoint; - SCACHE * pSCache; - IF_IOBuffer * pIOBuffer = NULL; - FLMBYTE * pucBuffer; + RCODE rc = FERR_OK; + FLMBOOL bMutexLocked = FALSE; + FLMUINT uiStartBlkAddr = 0; + FLMUINT uiLastBlkAddr = 0; + FLMUINT uiContiguousBlocks = 0; + FLMUINT uiNumSortedBlocksProcessed; + FLMUINT uiBlockCount; + FLMUINT uiBlockSize = pFile->FileHdr.uiBlockSize; + CP_INFO * pCPInfo = pFile->pCPInfo; + SCACHE * ppContiguousBlocks[ FLM_MAX_IO_BUFFER_BLOCKS]; + FLMBOOL bBlockDirty[ FLM_MAX_IO_BUFFER_BLOCKS]; + FLMUINT uiOffset; + FLMUINT uiTmpOffset; + FLMUINT uiLoop; + FLMUINT uiStartOffset; + FLMUINT uiCopyLen; + FLMBOOL bForceCheckpoint = *pbForceCheckpoint; + SCACHE * pSCache; + IF_IOBuffer * pIOBuffer = NULL; + FLMBYTE * pucBuffer; uiOffset = 0; for (;;) @@ -5275,14 +5185,16 @@ Add_Contiguous_Block: // Ask for a buffer of the size needed. - flmAssert( pIOBuffer == NULL); - if (RC_BAD( rc = pFile->pBufferMgr->getBuffer( - &pIOBuffer, uiContiguousBlocks * uiBlockSize, - uiBlockSize))) + flmAssert( !pIOBuffer); + + if( RC_BAD( rc = pFile->pBufferMgr->getBuffer( + uiContiguousBlocks * uiBlockSize, &pIOBuffer))) { goto Exit; } - pIOBuffer->setCompletionCallback( scaWriteComplete); + + f_assert( pIOBuffer->getRefCount() == 2); + pIOBuffer->setCompletionCallback( scaWriteComplete, pDbStats); // Callback will now take care of everything between // uiStartOffset and uiStartOffset + uiNumSortedBlocksProcessed - 1 @@ -5331,20 +5243,21 @@ Add_Contiguous_Block: // Set callback data so we will release these and clear // the pending flag if we don't do the I/O. - pIOBuffer->setCompletionCallbackData( uiLoop, pSCache); + pIOBuffer->addCallbackData( pSCache); } f_mutexUnlock( gv_FlmSysData.hShareMutex); bMutexLocked = FALSE; - // Copy blocks into the IO buffer. + // Copy blocks into the buffer. - pucBuffer = pIOBuffer->getBuffer(); - for (uiLoop = 0; + pucBuffer = pIOBuffer->getBufferPtr(); + + for( uiLoop = 0; uiLoop < uiBlockCount; uiLoop++, pucBuffer += uiBlockSize) { - pSCache = ppContiguousBlocks [uiLoop]; + pSCache = ppContiguousBlocks[ uiLoop]; // Copy data from block to the write buffer @@ -5360,9 +5273,7 @@ Add_Contiguous_Block: // Encrypt the block? Will check the IXD if (RC_BAD( rc = ScaEncryptBlock( pSCache->pFile, - pucBuffer, - uiCopyLen, - uiBlockSize))) + pucBuffer, uiCopyLen, uiBlockSize))) { goto Exit; } @@ -5382,11 +5293,27 @@ Add_Contiguous_Block: goto Exit; } } + + pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); + pSFileHdl->setExtendSize( pFile->uiFileExtendSize); - rc = ScaWriteContiguousBlocks( pDbStats, pSFileHdl, pFile, - pIOBuffer, uiStartBlkAddr, bDoAsync); + rc = pSFileHdl->writeBlock( uiStartBlkAddr, + pIOBuffer->getBufferSize(), pIOBuffer); + + pIOBuffer->Release(); pIOBuffer = NULL; - + + if( RC_BAD( rc)) + { + if( pDbStats) + { + pDbStats->bHaveStats = TRUE; + pDbStats->uiWriteErrors++; + } + + goto Exit; + } + // See if we should give up our write lock. Will do so if we // are not forcing a checkpoint and we have not exceeded the // maximum time since the last checkpoint AND we have gotten @@ -5485,7 +5412,6 @@ FSTATIC RCODE ScaFlushDirtyBlocks( RCODE rc = FERR_OK; RCODE rc2; SCACHE * pSCache; - FLMBOOL bDoAsync; FLMBOOL bMutexLocked = FALSE; FLMUINT uiSortedBlocks = 0; FLMUINT uiBlockCount = 0; @@ -5504,12 +5430,6 @@ FSTATIC RCODE ScaFlushDirtyBlocks( pFile->pCPInfo->bWritingDataBlocks = TRUE; } - // See if we can do async IO. - - bDoAsync = (gv_FlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; - flmAssert( !pFile->pPendingWriteList); uiDirtyCacheLeft = pFile->uiDirtyCacheCount * pFile->FileHdr.uiBlockSize; @@ -5664,7 +5584,7 @@ Force_Checkpoint: rc = scaWriteSortedBlocks( pDbStats, pSFileHdl, pFile, uiMaxDirtyCache, &uiDirtyCacheLeft, &bForceCheckpoint, bIsCPThread, - bDoAsync, uiSortedBlocks, pbWroteAll); + uiSortedBlocks, pbWroteAll); } else { @@ -5732,17 +5652,13 @@ Exit: bMutexLocked = FALSE; } - if (bDoAsync) + // Wait for writes to complete. + + if (RC_BAD( rc2 = pFile->pBufferMgr->waitForAllPendingIO())) { - - // Wait for writes to complete. - - if (RC_BAD( rc2 = pFile->pBufferMgr->waitForAllPendingIO())) + if (RC_OK( rc)) { - if (RC_OK( rc)) - { - rc = rc2; - } + rc = rc2; } } @@ -5750,7 +5666,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !pFile->pBufferMgr->havePendingIO()); + flmAssert( !pFile->pBufferMgr->isIOPending()); // Don't keep around a large block array if we happened to // allocate one that is bigger than our normal size. It may @@ -5790,7 +5706,6 @@ FSTATIC RCODE ScaReduceNewBlocks( RCODE rc = FERR_OK; RCODE rc2; SCACHE * pSCache; - FLMBOOL bDoAsync = FALSE; FLMBOOL bMutexLocked = FALSE; FLMUINT uiSortedBlocks = 0; FLMUINT uiDirtyCacheLeft; @@ -5811,12 +5726,6 @@ FSTATIC RCODE ScaReduceNewBlocks( pFile->pCPInfo->bWritingDataBlocks = TRUE; } - // See if we can do async IO. - - bDoAsync = (gv_FlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; - flmAssert( !pFile->pPendingWriteList); uiDirtyCacheLeft = pFile->uiDirtyCacheCount * pFile->FileHdr.uiBlockSize; @@ -5885,8 +5794,7 @@ FSTATIC RCODE ScaReduceNewBlocks( rc = scaWriteSortedBlocks( pDbStats, pSFileHdl, pFile, ~((FLMUINT)0), &uiDirtyCacheLeft, - &bForceCheckpoint, FALSE, - bDoAsync, uiSortedBlocks, &bDummy); + &bForceCheckpoint, FALSE, uiSortedBlocks, &bDummy); if( RC_OK( rc)) { @@ -5940,17 +5848,13 @@ Exit: bMutexLocked = FALSE; } - if (bDoAsync) + // Wait for writes to complete. + + if (RC_BAD( rc2 = pFile->pBufferMgr->waitForAllPendingIO())) { - - // Wait for writes to complete. - - if (RC_BAD( rc2 = pFile->pBufferMgr->waitForAllPendingIO())) + if (RC_OK( rc)) { - if (RC_OK( rc)) - { - rc = rc2; - } + rc = rc2; } } @@ -5958,7 +5862,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !pFile->pBufferMgr->havePendingIO()); + flmAssert( !pFile->pBufferMgr->isIOPending()); // Don't keep around a large block array if we happened to // allocate one that is bigger than our normal size. It may @@ -8059,8 +7963,6 @@ FSTATIC RCODE scaFinishCheckpoint( } else if (bTruncateLog) { - IF_FileHdl * pCFileHdl; - if (uiHighLogFileNumber) { (void)pSFileHdl->truncateFiles( @@ -8068,11 +7970,8 @@ FSTATIC RCODE scaFinishCheckpoint( pFile->FileHdr.uiVersionNum), uiHighLogFileNumber); } - - if( RC_OK( pSFileHdl->getFileHdl( 0, TRUE, &pCFileHdl))) - { - (void)pCFileHdl->truncate( LOG_THRESHOLD_SIZE); - } + + (void)pSFileHdl->truncateFile( 0, LOG_THRESHOLD_SIZE); } #ifdef FLM_DBG_LOG @@ -8185,6 +8084,13 @@ FSTATIC RCODE scaFinishCheckpoint( goto Exit; } } + + // Flush everything to disk + + if( RC_BAD( rc = pSFileHdl->flush())) + { + goto Exit; + } // Re-enable the RFL volume OK flag - in case it was turned off somewhere. @@ -8276,18 +8182,17 @@ RCODE ScaDoCheckpoint( FLMUINT uiCPFileNum, FLMUINT uiCPOffset) { - RCODE rc = FERR_OK; - CP_INFO * pCPInfo = pFile->pCPInfo; - FLMBOOL bWroteAll; - FLMUINT uiCPStartTime = 0; - FLMUINT uiTotalToWrite; - FLMUINT uiMaxDirtyCache; - SCACHE * pSCache; - FLMUINT uiTimestamp; - - pSFileHdl->enableFlushMinimize(); + RCODE rc = FERR_OK; + CP_INFO * pCPInfo = pFile->pCPInfo; + FLMBOOL bWroteAll; + FLMUINT uiCPStartTime = 0; + FLMUINT uiTotalToWrite; + FLMUINT uiMaxDirtyCache; + SCACHE * pSCache; + FLMUINT uiTimestamp; f_mutexLock( gv_FlmSysData.hShareMutex); + if (pCPInfo) { pCPInfo->bDoingCheckpoint = TRUE; @@ -8410,8 +8315,6 @@ Exit: } f_mutexUnlock( gv_FlmSysData.hShareMutex); - pSFileHdl->disableFlushMinimize(); - return( rc); } diff --git a/flaim/src/translog.cpp b/flaim/src/translog.cpp index acc0cf9..f236c18 100644 --- a/flaim/src/translog.cpp +++ b/flaim/src/translog.cpp @@ -24,8 +24,9 @@ #include "flaimsys.h" -FSTATIC void lgWriteComplete( - IF_IOBuffer * pIOBuffer); +FSTATIC void FLMAPI lgWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData); /**************************************************************************** Desc: @@ -64,16 +65,17 @@ void scaLogWrite( Desc: This is the callback routine that is called when a disk write is completed. ****************************************************************************/ -FSTATIC void lgWriteComplete( - IF_IOBuffer * pIOBuffer) +FSTATIC void FLMAPI lgWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData) { #ifdef FLM_DBG_LOG - FFILE * pFile = (FFILE *)pIOBuffer->getCompletionCallbackData( 0); + FFILE * pFile = (FFILE *)pIOBuffer->getCallbackData( 0); FLMUINT uiBlockSize = pFile->FileHdr.uiBlockSize; FLMUINT uiLength = pIOBuffer->getBufferSize(); char * pszEvent; #endif - DB_STATS * pDbStats = (DB_STATS *)pIOBuffer->getStats(); + DB_STATS * pDbStats = (DB_STATS *)pvData; #ifdef FLM_DBG_LOG pszEvent = (char *)(RC_OK( pIOBuffer->getCompletionCode()) @@ -85,12 +87,11 @@ FSTATIC void lgWriteComplete( if (pDbStats) { - // Must lock mutex, because this may be called from async write // completion at any time. f_mutexLock( gv_FlmSysData.hShareMutex); - pDbStats->LogBlockWrites.ui64ElapMilli += pIOBuffer->getElapTime(); + pDbStats->LogBlockWrites.ui64ElapMilli += pIOBuffer->getElapsedTime(); f_mutexUnlock( gv_FlmSysData.hShareMutex); } } @@ -101,65 +102,40 @@ Desc: This routine flushes a log buffer to the log file. RCODE lgFlushLogBuffer( DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, - FFILE * pFile, - FLMBOOL bDoAsync) + FFILE * pFile) { - RCODE rc = FERR_OK; - FLMUINT uiBytesWritten; - IF_IOBuffer * pAsyncBuffer; + RCODE rc = FERR_OK; - if (!bDoAsync) - { - pAsyncBuffer = NULL; - } - else - { - pAsyncBuffer = pFile->pCurrLogBuffer; - } - - if (pDbStats) + if( pDbStats) { pDbStats->bHaveStats = TRUE; pDbStats->LogBlockWrites.ui64Count++; pDbStats->LogBlockWrites.ui64TotalBytes += pFile->uiCurrLogWriteOffset; } - pFile->pCurrLogBuffer->setCompletionCallback( lgWriteComplete); - pFile->pCurrLogBuffer->setCompletionCallbackData( 0, - (void *)pFile); + pFile->pCurrLogBuffer->setCompletionCallback( lgWriteComplete, pDbStats); + pFile->pCurrLogBuffer->addCallbackData( (void *)pFile); + pSFileHdl->setMaxAutoExtendSize( pFile->uiMaxFileSize); pSFileHdl->setExtendSize( pFile->uiFileExtendSize); - pFile->pCurrLogBuffer->startTimer( pDbStats); - // NOTE: No guarantee that pFile->pCurrLogBuffer will still be around - // after the call to WriteBlock, unless we are doing - // non-asynchronous write. - - rc = pSFileHdl->writeBlock( pFile->uiCurrLogBlkAddr, - pFile->uiCurrLogWriteOffset, - pFile->pCurrLogBuffer->getBuffer(), - pAsyncBuffer, &uiBytesWritten); - - if (!pAsyncBuffer) - { - pFile->pCurrLogBuffer->notifyComplete( rc); - } - - pFile->pCurrLogBuffer = NULL; - - if (RC_BAD( rc)) + if( RC_BAD( rc = pSFileHdl->writeBlock( pFile->uiCurrLogBlkAddr, + pFile->uiCurrLogWriteOffset, pFile->pCurrLogBuffer))) { if (pDbStats) { pDbStats->uiWriteErrors++; } + goto Exit; } Exit: pFile->uiCurrLogWriteOffset = 0; + pFile->pCurrLogBuffer->Release(); pFile->pCurrLogBuffer = NULL; + return( rc); } @@ -170,20 +146,16 @@ RCODE lgOutputBlock( DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, FFILE * pFile, - SCACHE * pLogBlock, // Cached log block. - FLMBYTE * pucBlk, // Pointer to the corresponding modified - // block in cache. This block will be - // modified to the logged version of - // the block - FLMBOOL bDoAsync, // Do asynchronous writes? - FLMUINT * puiLogEofRV) // Returns log EOF + SCACHE * pLogBlock, + FLMBYTE * pucBlk, + FLMUINT * puiLogEofRV) { - RCODE rc = FERR_OK; - FLMUINT uiFilePos = *puiLogEofRV; - FLMUINT uiBlkSize = pFile->FileHdr.uiBlockSize; - FLMBYTE * pucLogBlk; - FLMUINT uiBlkAddress; - FLMUINT uiLogBufferSize; + RCODE rc = FERR_OK; + FLMUINT uiFilePos = *puiLogEofRV; + FLMUINT uiBlkSize = pFile->FileHdr.uiBlockSize; + FLMBYTE * pucLogBlk; + FLMUINT uiBlkAddress; + FLMUINT uiLogBufferSize; // Time for a new block file? @@ -195,8 +167,7 @@ RCODE lgOutputBlock( if (pFile->uiCurrLogWriteOffset) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - pFile, bDoAsync))) + if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, pFile))) { goto Exit; } @@ -244,7 +215,7 @@ RCODE lgOutputBlock( for( ;;) { if (RC_BAD( rc = pFile->pBufferMgr->getBuffer( - &pFile->pCurrLogBuffer, uiLogBufferSize, uiLogBufferSize))) + uiLogBufferSize, &pFile->pCurrLogBuffer))) { // If we failed to get a buffer of the requested size, // reduce the buffer size by half and try again @@ -256,6 +227,7 @@ RCODE lgOutputBlock( { goto Exit; } + rc = FERR_OK; continue; } @@ -267,7 +239,7 @@ RCODE lgOutputBlock( // Copy data from log block to the log buffer - pucLogBlk = pFile->pCurrLogBuffer->getBuffer() + + pucLogBlk = pFile->pCurrLogBuffer->getBufferPtr() + pFile->uiCurrLogWriteOffset; f_memcpy( pucLogBlk, pLogBlock->pucBlk, uiBlkSize); @@ -311,11 +283,10 @@ RCODE lgOutputBlock( // If this log buffer is full, write it out - if (pFile->uiCurrLogWriteOffset == + if( pFile->uiCurrLogWriteOffset == pFile->pCurrLogBuffer->getBufferSize()) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - pFile, bDoAsync))) + if( RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, pFile))) { goto Exit; } diff --git a/flaim/util/basic_test.cpp b/flaim/util/basic_test.cpp index 3281b74..cd41341 100644 --- a/flaim/util/basic_test.cpp +++ b/flaim/util/basic_test.cpp @@ -2718,7 +2718,7 @@ RCODE IFlmTestImpl::backupRestoreDbTest( void) if (RC_BAD( rc = FlmDbRestore( DB_RESTORE_NAME_STR, NULL, BACKUP_PATH, NULL, NULL, NULL))) { - MAKE_ERROR_STRING( "calling FlmDbBackupEnd", rc, m_szFailInfo); + MAKE_ERROR_STRING( "calling FlmDbRestore", rc, m_szFailInfo); goto Exit; } bPassed = TRUE; diff --git a/flaim/util/flmunittest.cpp b/flaim/util/flmunittest.cpp index b9ccecd..a236a4a 100644 --- a/flaim/util/flmunittest.cpp +++ b/flaim/util/flmunittest.cpp @@ -297,7 +297,7 @@ int main( { goto Exit; } - + Exit: if( pTest) @@ -310,6 +310,11 @@ Exit: pArgs->Release(); } +#ifdef FLM_NLM + f_conPrintf( "\nPress any key to exit ... "); + f_conGetKey(); +#endif + #ifdef FLM_NLM f_conExit(); #endif diff --git a/ftk/src/ftk.h b/ftk/src/ftk.h index 5c67bb0..1b1fbbc 100644 --- a/ftk/src/ftk.h +++ b/ftk/src/ftk.h @@ -467,6 +467,8 @@ #define NE_FLM_CHECKING_FILE_EXISTENCE 0xC22A ///< 0xC22A - Unexpected error occurred while checking to see if a file exists. #define NE_FLM_RENAMING_FILE 0xC22B ///< 0xC22B - Unexpected error occurred while renaming a file. #define NE_FLM_SETTING_FILE_INFO 0xC22C ///< 0xC22C - Unexpected error occurred while setting a file's information. + #define NE_FLM_IO_PENDING 0xC22D ///< 0xC22D - I/O has not yet completed + #define NE_FLM_ASYNC_FAILED 0xC22E ///< 0xC22E - An async I/O operation failed // Stream Errors - These are new @@ -532,6 +534,7 @@ flminterface IF_DirHdl; flminterface IF_FileHdl; flminterface IF_FileSystem; + flminterface IF_FileHdlCache; flminterface IF_IStream; flminterface IF_PosIStream; flminterface IF_ResultSet; @@ -541,6 +544,7 @@ flminterface IF_LogMessageClient; flminterface IF_Thread; flminterface IF_IOBuffer; + flminterface IF_AsyncClient; flminterface IF_Block; class F_Pool; @@ -788,10 +792,7 @@ FLM_THREAD_STATUS_INITIALIZING, FLM_THREAD_STATUS_RUNNING, FLM_THREAD_STATUS_SLEEPING, - FLM_THREAD_STATUS_TERMINATING, - FLM_THREAD_STATUS_STARTING_TRANS, - FLM_THREAD_STATUS_COMMITTING_TRANS, - FLM_THREAD_STATUS_ABORTING_TRANS + FLM_THREAD_STATUS_TERMINATING } eThreadStatus; #define F_THREAD_MIN_STACK_SIZE (16 * 1024) @@ -800,7 +801,7 @@ #define F_DEFAULT_THREAD_GROUP 0 #define F_INVALID_THREAD_GROUP 0xFFFFFFFF - typedef RCODE (* F_THREAD_FUNC)(IF_Thread *); + typedef RCODE (FLMAPI * F_THREAD_FUNC)(IF_Thread *); /**************************************************************************** Desc: Startup and shutdown @@ -1112,13 +1113,19 @@ FLMUINT f_msize( void * pvPtr); - RCODE FLMAPI f_allocAlignedBuffer( + RCODE FLMAPI f_allocAlignedBufferImp( FLMUINT uiMinSize, void ** ppvAlloc); - void FLMAPI f_freeAlignedBuffer( + #define f_allocAlignedBuffer(s,p) \ + f_allocAlignedBufferImp( (s), (void **)(p)) + + void FLMAPI f_freeAlignedBufferImp( void ** ppvAlloc); + #define f_freeAlignedBuffer(p) \ + f_freeAlignedBufferImp( (void **)(p)) + RCODE FLMAPI f_getMemoryInfo( FLMUINT64 * pui64TotalPhysMem, FLMUINT64 * pui64AvailPhysMem); @@ -1195,7 +1202,7 @@ virtual FLMUINT64 FLMAPI getCurrPosition( void) = 0; virtual void FLMAPI truncate( - FLMUINT64 ui64Offset) = 0; + FLMUINT64 ui64Offset = 0) = 0; virtual RCODE FLMAPI read( void * pvBuffer, @@ -1472,6 +1479,10 @@ const char * pszFileName, FLMUINT * puiTimeStamp) = 0; + virtual RCODE FLMAPI getFileSize( + const char * pszFileName, + FLMUINT64 * pui64FileSize) = 0; + virtual RCODE FLMAPI deleteFile( const char * pszFileName) = 0; @@ -1537,6 +1548,15 @@ const char * pszTemplate) = 0; virtual FLMBOOL FLMAPI canDoAsync( void) = 0; + + virtual RCODE FLMAPI allocIOBuffer( + FLMUINT uiMinSize, + IF_IOBuffer ** ppIOBuffer) = 0; + + virtual RCODE FLMAPI allocFileHandleCache( + FLMUINT uiMaxCachedFiles, + FLMUINT uiIdleTimeoutSecs, + IF_FileHdlCache ** ppFileHdlCache) = 0; }; RCODE FLMAPI FlmGetFileSystem( @@ -1544,6 +1564,8 @@ IF_FileSystem * FLMAPI f_getFileSysPtr( void); + FLMUINT FLMAPI f_getOpenFileCount( void); + RCODE FLMAPI f_chdir( const char * pszDir); @@ -1562,7 +1584,7 @@ /**************************************************************************** Desc: ****************************************************************************/ - flminterface FLMEXP IF_FileHdl : public F_Object + flminterface FLMEXP IF_FileHdl : virtual public F_Object { virtual RCODE FLMAPI flush( void) = 0; @@ -1572,6 +1594,22 @@ void * pvBuffer, FLMUINT * puiBytesRead = NULL) = 0; + virtual RCODE FLMAPI read( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + IF_IOBuffer * pIOBuffer) = 0; + + virtual RCODE FLMAPI write( + FLMUINT64 ui64Offset, + FLMUINT uiLength, + const void * pvBuffer, + FLMUINT * puiBytesWritten = NULL) = 0; + + virtual RCODE FLMAPI write( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + IF_IOBuffer * pIOBuffer) = 0; + virtual RCODE FLMAPI seek( FLMUINT64 ui64Offset, FLMINT iWhence, @@ -1584,26 +1622,7 @@ FLMUINT64 * pui64Offset) = 0; virtual RCODE FLMAPI truncate( - FLMUINT64 ui64Size) = 0; - - virtual RCODE FLMAPI write( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - const void * pvBuffer, - FLMUINT * puiBytesWritten = NULL) = 0; - - virtual RCODE FLMAPI sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV = NULL) = 0; - - virtual RCODE FLMAPI sectorWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWritten = NULL) = 0; + FLMUINT64 ui64Offset = 0) = 0; virtual RCODE FLMAPI close( void) = 0; @@ -1619,11 +1638,37 @@ virtual FLMBOOL FLMAPI isReadOnly( void) = 0; + virtual FLMBOOL FLMAPI isOpen( void) = 0; + virtual RCODE FLMAPI lock( void) = 0; virtual RCODE FLMAPI unlock( void) = 0; }; + /**************************************************************************** + Desc: + ****************************************************************************/ + flminterface FLMEXP IF_FileHdlCache : public F_Object + { + virtual RCODE FLMAPI openFile( + const char * pszFileName, + FLMUINT uiIoFlags, + IF_FileHdl ** ppFile) = 0; + + virtual RCODE FLMAPI createFile( + const char * pszFileName, + FLMUINT uiIoFlags, + IF_FileHdl ** ppFile) = 0; + + virtual void FLMAPI closeUnusedFiles( + FLMUINT uiUnusedTime = 0) = 0; + + virtual FLMUINT FLMAPI getOpenThreshold( void) = 0; + + virtual RCODE FLMAPI setOpenThreshold( + FLMUINT uiMaxOpenFiles) = 0; + }; + /**************************************************************************** Desc: ****************************************************************************/ @@ -1663,7 +1708,7 @@ FLMUINT64 * pui64FileSize) = 0; virtual RCODE FLMAPI truncate( - FLMUINT64 ui64NewSize) = 0; + FLMUINT64 ui64Offset = 0) = 0; virtual void FLMAPI close( FLMBOOL bDelete = FALSE) = 0; @@ -1672,16 +1717,6 @@ RCODE FLMAPI FlmAllocMultiFileHdl( IF_MultiFileHdl ** ppFileHdl); - /**************************************************************************** - Desc: - ****************************************************************************/ - typedef struct - { - IF_FileHdl * pFileHdl; - FLMUINT uiFileNumber; - FLMBOOL bDirty; - } CHECKED_OUT_FILE_HDL; - /**************************************************************************** Desc: ****************************************************************************/ @@ -1693,6 +1728,10 @@ virtual FLMUINT FLMAPI getFileOffset( FLMUINT uiBlockAddr) = 0; + virtual FLMUINT FLMAPI getBlockAddress( + FLMUINT uiFileNumber, + FLMUINT uiFileOffset) = 0; + virtual RCODE FLMAPI getFilePath( FLMUINT uiFileNumber, char * pszPath) = 0; @@ -1709,250 +1748,175 @@ virtual ~F_SuperFileHdl(); - RCODE setup( - IF_SuperFileClient * pSuperFileClient); + RCODE FLMAPI setup( + IF_SuperFileClient * pSuperFileClient, + IF_FileHdlCache * pFileHdlCache, + FLMBOOL bUseDirectIO); - RCODE createFile( - FLMUINT uiFileNumber); - - RCODE readBlock( - FLMUINT uiBlkAddress, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE writeBlock( - FLMUINT uiBlkAddress, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pIOBuffer, - FLMUINT * puiBytesWritten); - - RCODE readHeader( - FLMUINT uiOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE writeHeader( - FLMUINT uiOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWritten); - - RCODE getFilePath( + RCODE FLMAPI createFile( FLMUINT uiFileNumber, - char * pszPath); - - RCODE getFileHdl( + IF_FileHdl ** ppFileHdl = NULL); + + RCODE FLMAPI getFileHdl( FLMUINT uiFileNumber, FLMBOOL bGetForUpdate, IF_FileHdl ** ppFileHdlRV); - RCODE getFileSize( + RCODE FLMAPI readBlock( + FLMUINT uiBlkAddress, + FLMUINT uiBytesToRead, + void * pvBuffer, + FLMUINT * puiBytesRead); + + RCODE FLMAPI writeBlock( + FLMUINT uiBlkAddress, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + FLMUINT * puiBytesWritten); + + RCODE FLMAPI writeBlock( + FLMUINT uiBlkAddress, + FLMUINT uiBytesToWrite, + IF_IOBuffer * pIOBuffer); + + RCODE FLMAPI getFilePath( + FLMUINT uiFileNumber, + char * pszPath); + + RCODE FLMAPI getFileSize( FLMUINT uiFileNumber, FLMUINT64 * pui64FileSize); - RCODE releaseFile( - FLMUINT uiFileNum, - FLMBOOL bCloseFile); + RCODE FLMAPI releaseFiles( void); - RCODE releaseFiles( - FLMBOOL bCloseFiles); - - RCODE truncateFile( + RCODE FLMAPI truncateFile( FLMUINT uiEOFBlkAddress); - void truncateFiles( + RCODE FLMAPI truncateFile( + FLMUINT uiFileNumber, + FLMUINT uiOffset); + + void FLMAPI truncateFiles( FLMUINT uiStartFileNum, FLMUINT uiEndFileNum); - RCODE releaseFile( - CHECKED_OUT_FILE_HDL * pChkFileHdl, - FLMBOOL bCloseFile); + RCODE FLMAPI flush( void); - FINLINE void enableFlushMinimize( void) - { - m_bMinimizeFlushes = TRUE; - } - - void disableFlushMinimize( void); - - RCODE flush( void); - - FINLINE void setBlockSize( + FINLINE void FLMAPI setBlockSize( FLMUINT uiBlockSize) { m_uiBlockSize = uiBlockSize; } - FINLINE void setExtendSize( + FINLINE void FLMAPI setExtendSize( FLMUINT uiExtendSize) { m_uiExtendSize = uiExtendSize; } - FINLINE void setMaxAutoExtendSize( + FINLINE void FLMAPI setMaxAutoExtendSize( FLMUINT uiMaxAutoExtendSize) { m_uiMaxAutoExtendSize = uiMaxAutoExtendSize; } - FINLINE FLMBOOL canDoAsync( void) - { - if( m_pCheckedOutFileHdls[ 0].pFileHdl) - { - return( m_pCheckedOutFileHdls[ 0].pFileHdl->canDoAsync()); - } - else - { - IF_FileHdl * pFileHdl; - - if( RC_OK( getFileHdl( 0, FALSE, &pFileHdl))) - { - return( pFileHdl->canDoAsync()); - } - } - - return( FALSE); - } + FLMBOOL FLMAPI canDoAsync( void); private: - FINLINE CHECKED_OUT_FILE_HDL * getCkoFileHdlPtr( - FLMUINT uiFileNum, - FLMUINT * puiSlot) - { - *puiSlot = (uiFileNum - ? (uiFileNum % (m_uiCkoArraySize - 1)) + 1 - : 0); - - return( &m_pCheckedOutFileHdls[ *puiSlot]); - } - - FINLINE void clearCkoFileHdl( - CHECKED_OUT_FILE_HDL * pCkoFileHdl) - { - pCkoFileHdl->pFileHdl = NULL; - pCkoFileHdl->uiFileNumber = 0; - pCkoFileHdl->bDirty = FALSE; - } - - void copyCkoFileHdls( - CHECKED_OUT_FILE_HDL * pSrcCkoArray, - FLMUINT uiSrcHighestUsedSlot); - - RCODE reallocCkoArray( - FLMUINT uiFileNum); - - #define MAX_CHECKED_OUT_FILE_HDLS 8 - IF_SuperFileClient * m_pSuperFileClient; - CHECKED_OUT_FILE_HDL m_CheckedOutFileHdls[ MAX_CHECKED_OUT_FILE_HDLS + 1]; - CHECKED_OUT_FILE_HDL * m_pCheckedOutFileHdls; - FLMUINT m_uiCkoArraySize; + IF_FileHdlCache * m_pFileHdlCache; + IF_FileHdl * m_pCFileHdl; + IF_FileHdl * m_pBlockFileHdl; + FLMBOOL m_bCFileDirty; + FLMBOOL m_bBlockFileDirty; + FLMUINT m_uiBlockFileNum; FLMUINT m_uiBlockSize; FLMUINT m_uiExtendSize; FLMUINT m_uiMaxAutoExtendSize; - FLMUINT m_uiLowestDirtySlot; - FLMUINT m_uiHighestDirtySlot; - FLMUINT m_uiHighestUsedSlot; - FLMUINT m_uiHighestFileNumber; - FLMBOOL m_bMinimizeFlushes; - FLMBOOL m_bSetupCalled; + FLMUINT m_uiDirectIOFlag; }; + /**************************************************************************** + Desc: + ****************************************************************************/ + flminterface FLMEXP IF_AsyncClient : virtual public F_Object + { + virtual RCODE FLMAPI waitToComplete( + FLMBOOL bRelease) = 0; + + virtual RCODE FLMAPI getCompletionCode( void) = 0; + + virtual FLMUINT FLMAPI getElapsedTime( void) = 0; + }; + + /**************************************************************************** + Desc: + ****************************************************************************/ + typedef void (FLMAPI * F_BUFFER_COMPLETION_FUNC)(IF_IOBuffer *, void *); + + /**************************************************************************** + Desc: + ****************************************************************************/ + flminterface FLMEXP IF_IOBuffer : virtual public F_Object + { + virtual FLMBYTE * FLMAPI getBufferPtr( void) = 0; + + virtual FLMUINT FLMAPI getBufferSize( void) = 0; + + virtual void FLMAPI setCompletionCallback( + F_BUFFER_COMPLETION_FUNC fnCompletion, + void * pvData) = 0; + + virtual RCODE FLMAPI addCallbackData( + void * pvData) = 0; + + virtual void * FLMAPI getCallbackData( + FLMUINT uiSlot) = 0; + + virtual FLMUINT FLMAPI getCallbackDataCount( void) = 0; + + virtual void FLMAPI setAsyncClient( + IF_AsyncClient * pAsyncClient) = 0; + + virtual void FLMAPI notifyComplete( + RCODE completionRc) = 0; + + virtual void FLMAPI setPending( void) = 0; + + virtual void FLMAPI clearPending( void) = 0; + + virtual FLMBOOL FLMAPI isPending( void) = 0; + + virtual FLMBOOL FLMAPI isComplete( void) = 0; + + virtual RCODE FLMAPI waitToComplete( void) = 0; + + virtual RCODE FLMAPI getCompletionCode( void) = 0; + + virtual FLMUINT FLMAPI getElapsedTime( void) = 0; + }; + /**************************************************************************** Desc: ****************************************************************************/ flminterface FLMEXP IF_IOBufferMgr : public F_Object { - virtual RCODE FLMAPI waitForAllPendingIO( void) = 0; - - virtual void FLMAPI setMaxBuffers( - FLMUINT uiMaxBuffers) = 0; - - virtual void FLMAPI setMaxBytes( - FLMUINT uiMaxBytes) = 0; - - virtual void FLMAPI enableKeepBuffer( void) = 0; - virtual RCODE FLMAPI getBuffer( - IF_IOBuffer ** ppIOBuffer, FLMUINT uiBufferSize, - FLMUINT uiBlockSize) = 0; + IF_IOBuffer ** ppIOBuffer) = 0; - virtual FLMBOOL FLMAPI havePendingIO( void) = 0; - - virtual FLMBOOL FLMAPI haveUsed( void) = 0; + virtual FLMBOOL FLMAPI isIOPending( void) = 0; + + virtual RCODE FLMAPI waitForAllPendingIO( void) = 0; }; RCODE FLMAPI FlmAllocIOBufferMgr( - IF_IOBufferMgr ** ppBufferMgr); - - #define FLM_MAX_IO_BUFFER_BLOCKS 16 - - /**************************************************************************** - Desc: - ****************************************************************************/ - typedef void (* WRITE_COMPLETION_CB)( - IF_IOBuffer * pWriteBuffer); + FLMUINT uiMaxBuffers, + FLMUINT uiMaxBytes, + FLMBOOL bReuseBuffers, + IF_IOBufferMgr ** ppIOBufferMgr); - /**************************************************************************** - Desc: - ****************************************************************************/ - flminterface FLMEXP IF_IOBuffer : public F_Object - { - typedef enum - { - MGR_LIST_NONE, - MGR_LIST_AVAIL, - MGR_LIST_PENDING, - MGR_LIST_USED - } eBufferMgrList; - - virtual RCODE FLMAPI setupBuffer( - FLMUINT uiBufferSize, - FLMUINT uiBlockSize) = 0; - - virtual FLMBYTE * FLMAPI getBuffer( void) = 0; - - virtual FLMUINT FLMAPI getBufferSize( void) = 0; - - virtual FLMUINT FLMAPI getBlockSize( void) = 0; - - virtual void FLMAPI notifyComplete( - RCODE rc) = 0; - - virtual void FLMAPI signalComplete( - RCODE rc) = 0; - - virtual void FLMAPI setCompletionCallback( - WRITE_COMPLETION_CB fnCompletion) = 0; - - virtual void FLMAPI setCompletionCallbackData( - FLMUINT uiBlockNumber, - void * pvData) = 0; - - virtual void * FLMAPI getCompletionCallbackData( - FLMUINT uiBlockNumber) = 0; - - virtual RCODE FLMAPI getCompletionCode( void) = 0; - - virtual eBufferMgrList FLMAPI getList( void) = 0; - - virtual void FLMAPI makePending( void) = 0; - - virtual FLMBOOL FLMAPI isPending( void) = 0; - - virtual void FLMAPI startTimer( - void * pvStats) = 0; - - virtual void * FLMAPI getStats( void) = 0; - - virtual FLMUINT64 FLMAPI getElapTime( void) = 0; - }; - /**************************************************************************** Desc: ****************************************************************************/ @@ -3602,6 +3566,191 @@ f_memmove((FLMBYTE *)(data) + (FLMINT)(distance), \ (FLMBYTE *)(data), (unsigned)(size)) + /*************************************************************************** + Desc: + ***************************************************************************/ + class FLMEXP F_Printf : public F_Object + { + public: + + #define MAX_LOG_BUF_CHARS 255 + + F_Printf() + { + } + + virtual ~F_Printf() + { + } + + FLMINT FLMAPI strvPrintf( + char * pszDestStr, + const char * pszFormat, + f_va_list * args); + + FLMINT FLMAPI strPrintf( + char * pszDestStr, + const char * pszFormat, + ...); + + FLMINT FLMAPI logvPrintf( + IF_LogMessageClient * pLogMsg, + const char * pszFormat, + f_va_list * args); + + FLMINT FLMAPI logPrintf( + IF_LogMessageClient * pLogMsg, + const char * pszFormat, + ...); + + private: + + void processFieldInfo( + const char ** ppszFormat, + FLMUINT * puiWidth, + FLMUINT * puiPrecision, + FLMUINT * puiFlags, + f_va_list * args); + + void stringFormatter( + char cFormatChar, + FLMUINT uiWidth, + FLMUINT uiPrecision, + FLMUINT uiFlags, + f_va_list * args); + + void colorFormatter( + char cFormatChar, + eColorType eColor, + FLMUINT uiFlags); + + void charFormatter( + char cFormatChar, + f_va_list * args); + + void errorFormatter( + f_va_list * args); + + void notHandledFormatter( void); + + void numberFormatter( + char cFormatChar, + FLMUINT uiWidth, + FLMUINT uiPrecision, + FLMUINT uiFlags, + f_va_list * args); + + void parseArgs( + const char * pszFormat, + f_va_list * args); + + void processFormatString( + FLMUINT uiLen, + ...); + + FLMUINT printNumber( + FLMUINT64 ui64Val, + FLMUINT uiBase, + FLMBOOL bUpperCase, + FLMBOOL bCommas, + char * pszBuf); + + void outputLogBuffer( void); + + FINLINE void outputChar( + char cChar) + { + if (!m_pLogMsg) + { + *m_pszDestStr++ = cChar; + } + else + { + m_szLogBuf [m_uiCharOffset++] = cChar; + m_uiNumLogChars++; + if (m_uiCharOffset == MAX_LOG_BUF_CHARS) + { + outputLogBuffer(); + } + } + } + + FINLINE void memsetChar( + char cChar, + FLMUINT uiCount) + { + if (!m_pLogMsg) + { + f_memset( m_pszDestStr, cChar, uiCount); + m_pszDestStr += uiCount; + } + else + { + FLMUINT uiTmpCount; + + while (uiCount) + { + uiTmpCount = uiCount; + if (m_uiCharOffset + uiTmpCount > MAX_LOG_BUF_CHARS) + { + uiTmpCount = MAX_LOG_BUF_CHARS - m_uiCharOffset; + } + f_memset( &m_szLogBuf [m_uiCharOffset], cChar, uiTmpCount); + m_uiCharOffset += uiTmpCount; + m_uiNumLogChars += uiTmpCount; + uiCount -= uiTmpCount; + if (m_uiCharOffset == MAX_LOG_BUF_CHARS) + { + outputLogBuffer(); + } + } + } + } + + FINLINE void outputStr( + const char * pszStr, + FLMUINT uiLen) + { + if (!m_pLogMsg) + { + f_memcpy( m_pszDestStr, pszStr, uiLen); + m_pszDestStr += uiLen; + } + else + { + FLMUINT uiTmpLen; + + while (uiLen) + { + uiTmpLen = uiLen; + if (m_uiCharOffset + uiTmpLen > MAX_LOG_BUF_CHARS) + { + uiTmpLen = MAX_LOG_BUF_CHARS - m_uiCharOffset; + } + f_memcpy( &m_szLogBuf [m_uiCharOffset], pszStr, uiTmpLen); + m_uiCharOffset += uiTmpLen; + m_uiNumLogChars += uiTmpLen; + uiLen -= uiTmpLen; + pszStr += uiTmpLen; + if (m_uiCharOffset == MAX_LOG_BUF_CHARS) + { + outputLogBuffer(); + } + } + } + } + + // Variables used to do the printf stuff + + char m_szLogBuf [MAX_LOG_BUF_CHARS + 1]; + FLMUINT m_uiNumLogChars; + FLMUINT m_uiCharOffset; + char * m_pszDestStr; + IF_LogMessageClient * m_pLogMsg; + eColorType m_eCurrentForeColor; + eColorType m_eCurrentBackColor; + }; + /**************************************************************************** Desc: XML ****************************************************************************/ @@ -5449,7 +5598,7 @@ } FINLINE void FLMAPI truncate( - FLMUINT64 ui64Offset) + FLMUINT64 ui64Offset = 0) { f_assert( m_bIsOpen); f_assert( ui64Offset >= m_uiOffset); @@ -6220,12 +6369,11 @@ public: F_FixedBlk(); - ~F_FixedBlk() + + virtual ~F_FixedBlk() { } - /* virtual methods that must be implemented */ - eDynRSetBlkTypes blkType() { return m_eBlkType; @@ -6267,11 +6415,9 @@ protected: - // Variables - F_DYNSET_COMPARE_FUNC m_fnCompare; void * m_pvUserData; - eDynRSetBlkTypes m_eBlkType; + eDynRSetBlkTypes m_eBlkType; FLMUINT m_uiEntrySize; FLMUINT m_uiNumSlots; FLMUINT m_uiPosition; @@ -6292,22 +6438,21 @@ m_pAccess = NULL; } - ~F_DynSearchSet() + virtual ~F_DynSearchSet() { - if (m_pAccess) + if( m_pAccess) { m_pAccess->Release(); } } RCODE FLMAPI setup( - char * pszTmpDir, - FLMUINT uiEntrySize); + char * pszTmpDir, + FLMUINT uiEntrySize); FINLINE void FLMAPI setCompareFunc( F_DYNSET_COMPARE_FUNC fnCompare, - void * pvUserData - ) + void * pvUserData) { m_fnCompare = fnCompare; m_pvUserData = pvUserData; @@ -6315,12 +6460,11 @@ } RCODE FLMAPI addEntry( - void * pvEntry); + void * pvEntry); FINLINE RCODE FLMAPI findMatch( - void * pvMatchEntry, - void * pvFoundEntry - ) + void * pvMatchEntry, + void * pvFoundEntry) { return m_pAccess->search( pvMatchEntry, pvFoundEntry); } @@ -6332,18 +6476,16 @@ FINLINE FLMUINT FLMAPI getTotalEntries( void) { - return m_pAccess->getTotalEntries(); + return( m_pAccess->getTotalEntries()); } private: - // Variables - F_DYNSET_COMPARE_FUNC m_fnCompare; - void * m_pvUserData; - FLMUINT m_uiEntrySize; - F_FixedBlk * m_pAccess; - char m_szFileName [F_PATH_MAX_SIZE]; + void * m_pvUserData; + FLMUINT m_uiEntrySize; + F_FixedBlk * m_pAccess; + char m_szFileName[ F_PATH_MAX_SIZE]; }; /*************************************************************************** @@ -6354,212 +6496,178 @@ { void * pFirstInBucket; FLMUINT uiHashValue; - } FBUCKET; + } F_BUCKET; RCODE FLMAPI f_allocHashTable( FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV); + F_BUCKET ** ppHashTblRV); FLMUINT FLMAPI f_strHashBucket( char * pszStr, - FBUCKET * pHashTbl, + F_BUCKET * pHashTbl, FLMUINT uiNumBuckets); FLMUINT FLMAPI f_binHashBucket( void * pBuf, FLMUINT uiBufLen, - FBUCKET * pHashTbl, + F_BUCKET * pHashTbl, FLMUINT uiNumBuckets); + /*************************************************************************** + Desc: + ***************************************************************************/ + class F_HashObject : virtual public F_Object + { + public: + + #define F_INVALID_HASH_BUCKET (~((FLMUINT)0)) + + F_HashObject() + { + m_pNextInBucket = NULL; + m_pPrevInBucket = NULL; + m_pNextInGlobal = NULL; + m_pPrevInGlobal = NULL; + m_uiHashBucket = F_INVALID_HASH_BUCKET; + m_ui32KeyCRC = 0; + m_uiTimeAdded = 0; + } + + virtual ~F_HashObject() + { + flmAssert( !m_pNextInBucket); + flmAssert( !m_pPrevInBucket); + flmAssert( !m_pNextInGlobal); + flmAssert( !m_pPrevInGlobal); + flmAssert( !getRefCount()); + } + + virtual const void * FLMAPI getKey( void) = 0; + + virtual FLMUINT FLMAPI getKeyLength( void) = 0; + + FINLINE FLMUINT FLMAPI getKeyCRC( void) + { + return( m_ui32KeyCRC); + } + + FINLINE FLMUINT FLMAPI getHashBucket( void) + { + return( m_uiHashBucket); + } + + FINLINE F_HashObject * FLMAPI getNextInGlobal( void) + { + return( m_pNextInGlobal); + } + + FINLINE F_HashObject * FLMAPI getNextInBucket( void) + { + return( m_pNextInBucket); + } + + virtual FLMUINT FLMAPI getObjectType( void) = 0; + + protected: + + void setHashBucket( + FLMUINT uiHashBucket) + { + m_uiHashBucket = uiHashBucket; + } + + F_HashObject * m_pNextInBucket; + F_HashObject * m_pPrevInBucket; + F_HashObject * m_pNextInGlobal; + F_HashObject * m_pPrevInGlobal; + FLMUINT m_uiHashBucket; + FLMUINT m_uiTimeAdded; + FLMUINT32 m_ui32KeyCRC; + + friend class F_HashTable; + }; + + /*************************************************************************** + Desc: Hash tables + ***************************************************************************/ + class F_HashTable : public F_Object + { + public: + + F_HashTable(); + + virtual ~F_HashTable(); + + RCODE FLMAPI setupHashTable( + FLMBOOL bMultithreaded, + FLMUINT uiNumBuckets, + FLMUINT uiMaxObjects); + + RCODE FLMAPI addObject( + F_HashObject * pObject, + FLMBOOL bAllowDuplicates = FALSE); + + RCODE FLMAPI getNextObjectInGlobal( + F_HashObject ** ppObject); + + RCODE FLMAPI getNextObjectInBucket( + F_HashObject ** ppObject); + + RCODE FLMAPI getObject( + const void * pvKey, + FLMUINT uiKeyLen, + F_HashObject ** ppObject, + FLMBOOL bRemove = FALSE); + + RCODE FLMAPI removeObject( + void * pvKey, + FLMUINT uiKeyLen); + + RCODE FLMAPI removeObject( + F_HashObject * pObject); + + void FLMAPI removeAllObjects( void); + + void FLMAPI removeAgedObjects( + FLMUINT uiMaxAge); + + FLMUINT FLMAPI getMaxObjects( void); + + RCODE FLMAPI setMaxObjects( + FLMUINT uiMaxObjects); + + private: + + FLMUINT getHashBucket( + const void * pvKey, + FLMUINT uiLen, + FLMUINT32 * pui32KeyCRC = NULL); + + void linkObject( + F_HashObject * pObject, + FLMUINT uiBucket); + + void unlinkObject( + F_HashObject * pObject); + + RCODE findObject( + const void * pvKey, + FLMUINT uiKeyLen, + F_HashObject ** ppObject); + + F_MUTEX m_hMutex; + F_HashObject * m_pMRUObject; + F_HashObject * m_pLRUObject; + F_HashObject ** m_ppHashTable; + FLMUINT m_uiBuckets; + FLMUINT m_uiObjects; + FLMUINT m_uiMaxObjects; + }; + /**************************************************************************** Process ID Functions ****************************************************************************/ FLMUINT f_getpid( void); - /*============================================================================ - Desc: - ============================================================================*/ - class FLMEXP F_Printf : public F_Object - { - public: - - #define MAX_LOG_BUF_CHARS 255 - - F_Printf() - { - } - - virtual ~F_Printf() - { - } - - FLMINT FLMAPI strvPrintf( - char * pszDestStr, - const char * pszFormat, - f_va_list * args); - - FLMINT FLMAPI strPrintf( - char * pszDestStr, - const char * pszFormat, - ...); - - FLMINT FLMAPI logvPrintf( - IF_LogMessageClient * pLogMsg, - const char * pszFormat, - f_va_list * args); - - FLMINT FLMAPI logPrintf( - IF_LogMessageClient * pLogMsg, - const char * pszFormat, - ...); - - private: - - void processFieldInfo( - const char ** ppszFormat, - FLMUINT * puiWidth, - FLMUINT * puiPrecision, - FLMUINT * puiFlags, - f_va_list * args); - - void stringFormatter( - char cFormatChar, - FLMUINT uiWidth, - FLMUINT uiPrecision, - FLMUINT uiFlags, - f_va_list * args); - - void colorFormatter( - char cFormatChar, - eColorType eColor, - FLMUINT uiFlags); - - void charFormatter( - char cFormatChar, - f_va_list * args); - - void errorFormatter( - f_va_list * args); - - void notHandledFormatter( void); - - void numberFormatter( - char cFormatChar, - FLMUINT uiWidth, - FLMUINT uiPrecision, - FLMUINT uiFlags, - f_va_list * args); - - void parseArgs( - const char * pszFormat, - f_va_list * args); - - void processFormatString( - FLMUINT uiLen, - ...); - - FLMUINT printNumber( - FLMUINT64 ui64Val, - FLMUINT uiBase, - FLMBOOL bUpperCase, - FLMBOOL bCommas, - char * pszBuf); - - void outputLogBuffer( void); - - FINLINE void outputChar( - char cChar) - { - if (!m_pLogMsg) - { - *m_pszDestStr++ = cChar; - } - else - { - m_szLogBuf [m_uiCharOffset++] = cChar; - m_uiNumLogChars++; - if (m_uiCharOffset == MAX_LOG_BUF_CHARS) - { - outputLogBuffer(); - } - } - } - - FINLINE void memsetChar( - char cChar, - FLMUINT uiCount) - { - if (!m_pLogMsg) - { - f_memset( m_pszDestStr, cChar, uiCount); - m_pszDestStr += uiCount; - } - else - { - FLMUINT uiTmpCount; - - while (uiCount) - { - uiTmpCount = uiCount; - if (m_uiCharOffset + uiTmpCount > MAX_LOG_BUF_CHARS) - { - uiTmpCount = MAX_LOG_BUF_CHARS - m_uiCharOffset; - } - f_memset( &m_szLogBuf [m_uiCharOffset], cChar, uiTmpCount); - m_uiCharOffset += uiTmpCount; - m_uiNumLogChars += uiTmpCount; - uiCount -= uiTmpCount; - if (m_uiCharOffset == MAX_LOG_BUF_CHARS) - { - outputLogBuffer(); - } - } - } - } - - FINLINE void outputStr( - const char * pszStr, - FLMUINT uiLen) - { - if (!m_pLogMsg) - { - f_memcpy( m_pszDestStr, pszStr, uiLen); - m_pszDestStr += uiLen; - } - else - { - FLMUINT uiTmpLen; - - while (uiLen) - { - uiTmpLen = uiLen; - if (m_uiCharOffset + uiTmpLen > MAX_LOG_BUF_CHARS) - { - uiTmpLen = MAX_LOG_BUF_CHARS - m_uiCharOffset; - } - f_memcpy( &m_szLogBuf [m_uiCharOffset], pszStr, uiTmpLen); - m_uiCharOffset += uiTmpLen; - m_uiNumLogChars += uiTmpLen; - uiLen -= uiTmpLen; - pszStr += uiTmpLen; - if (m_uiCharOffset == MAX_LOG_BUF_CHARS) - { - outputLogBuffer(); - } - } - } - } - - // Variables used to do the printf stuff - - char m_szLogBuf [MAX_LOG_BUF_CHARS + 1]; - FLMUINT m_uiNumLogChars; - FLMUINT m_uiCharOffset; - char * m_pszDestStr; - IF_LogMessageClient * m_pLogMsg; - eColorType m_eCurrentForeColor; - eColorType m_eCurrentBackColor; - }; - #endif // FTK_H diff --git a/ftk/src/ftkdir.cpp b/ftk/src/ftkdir.cpp index 3f93d1e..e836c04 100644 --- a/ftk/src/ftkdir.cpp +++ b/ftk/src/ftkdir.cpp @@ -229,10 +229,10 @@ FLMUINT64 FLMAPI F_DirHdl::currentItemSize( void) #elif defined( FLM_UNIX) || defined ( FLM_LIBC_NLM) ui64Size = m_FindData.FileStat.st_size; #elif defined( FLM_RING_ZERO_NLM) - if( m_FindData.pCurrentItem != NULL ) - { - ui64Size = m_FindData.pCurrentItem->DFileSize; - } + char szTmpPath[ F_PATH_MAX_SIZE]; + + currentItemPath( szTmpPath); + (void)f_getFileSysPtr()->getFileSize( szTmpPath, &ui64Size); #endif } return( ui64Size); @@ -330,7 +330,7 @@ RCODE FLMAPI F_DirHdl::next( void) } else { - m_rc = f_mapPlatformError(lError, NE_FLM_READING_FILE); + m_rc = f_mapPlatformError( lError, NE_FLM_READING_FILE); } break; diff --git a/ftk/src/ftkfsys.cpp b/ftk/src/ftkfsys.cpp index 96a7450..f98f740 100644 --- a/ftk/src/ftkfsys.cpp +++ b/ftk/src/ftkfsys.cpp @@ -25,9 +25,132 @@ #include "ftksys.h" -#define FHM_AVAIL_LIST 0 -#define FHM_USED_LIST 1 -#define FHM_LNODE_COUNT 2 +class F_FileHdlCache; + +FSTATIC FLMBOOL f_canReducePath( + const char * pszSource); + +FSTATIC const char * f_findFileNameStart( + const char * pszPath); + +FSTATIC char * f_getPathComponent( + char ** ppszPath, + FLMUINT * puiEndChar); + +/**************************************************************************** +Desc: +****************************************************************************/ +class F_CachedFileHdl : public F_FileHdl, public F_HashObject +{ +public: + + F_CachedFileHdl() + { + m_pucKey = NULL; + m_uiKeyLen = 0; + m_bInAvailList = FALSE; + m_pFileHdlCache = NULL; + } + + virtual ~F_CachedFileHdl() + { + if( m_pucKey) + { + f_free( &m_pucKey); + } + } + + FLMINT FLMAPI AddRef( void) + { + return( ++m_refCnt); + } + + FLMINT FLMAPI Release( void); + + FINLINE const void * FLMAPI getKey( void) + { + return( m_pucKey); + } + + FINLINE FLMUINT FLMAPI getKeyLength( void) + { + return( m_uiKeyLen); + } + + FINLINE FLMUINT FLMAPI getObjectType( void) + { + return( 0); + } + +private: + + FLMBYTE * m_pucKey; + FLMUINT m_uiKeyLen; + FLMBOOL m_bInAvailList; + F_FileHdlCache * m_pFileHdlCache; + + friend class F_FileHdlCache; +}; + +/**************************************************************************** +Desc: +****************************************************************************/ +class F_FileHdlCache : public IF_FileHdlCache +{ +public: + + F_FileHdlCache(); + + virtual ~F_FileHdlCache(); + + RCODE setup( + FLMUINT uiMaxCachedFiles, + FLMUINT uiIdleTimeoutSecs); + + FINLINE RCODE FLMAPI openFile( + const char * pszFileName, + FLMUINT uiIoFlags, + IF_FileHdl ** ppFile) + { + return( openOrCreate( pszFileName, uiIoFlags, FALSE, ppFile)); + } + + FINLINE RCODE FLMAPI createFile( + const char * pszFileName, + FLMUINT uiIoFlags, + IF_FileHdl ** ppFile) + { + return( openOrCreate( pszFileName, uiIoFlags, TRUE, ppFile)); + } + + void FLMAPI closeUnusedFiles( + FLMUINT uiUnusedTime); + + FLMUINT FLMAPI getOpenThreshold( void) + { + return( m_pAvailList->getMaxObjects()); + } + + RCODE FLMAPI setOpenThreshold( + FLMUINT uiMaxOpenFiles); + +private: + + RCODE openOrCreate( + const char * pszFileName, + FLMUINT uiIoFlags, + FLMBOOL bCreate, + IF_FileHdl ** ppFile); + + static RCODE FLMAPI timeoutThread( + IF_Thread * pThread); + + IF_Thread * m_pTimeoutThread; + F_HashTable * m_pAvailList; + FLMUINT m_uiMaxIdleTime; + + friend class F_CachedFileHdl; +}; /**************************************************************************** Desc: @@ -49,23 +172,17 @@ FINLINE void f_setupTime( FLMBYTE * pbyHighByte) { FLMUINT uiSdTime = 0; + f_timeGetSeconds( &uiSdTime); *pbyHighByte = (FLMBYTE)(uiSdTime >> 24); uiSdTime = uiSdTime << 5; + if( *puiBaseTime < uiSdTime) + { *puiBaseTime = uiSdTime; + } } -FSTATIC FLMBOOL f_canReducePath( - const char * pszSource); - -FSTATIC const char * f_findFileNameStart( - const char * pszPath); - -FSTATIC char * f_getPathComponent( - char ** ppszPath, - FLMUINT * puiEndChar); - /**************************************************************************** Desc: Returns TRUE if character is a "slash" separator ****************************************************************************/ @@ -803,6 +920,37 @@ Exit: #endif } +/**************************************************************************** +Desc: Determine if a path is a directory. +****************************************************************************/ +RCODE FLMAPI F_FileSystem::getFileSize( + const char * pszFileName, + FLMUINT64 * pui64FileSize) +{ + RCODE rc = NE_FLM_OK; + IF_FileHdl * pFileHdl = NULL; + + if( RC_BAD( rc = openFile( pszFileName, + FLM_IO_RDONLY | FLM_IO_SH_DENYNONE, &pFileHdl))) + { + goto Exit; + } + + if( RC_BAD( rc = pFileHdl->size( pui64FileSize))) + { + goto Exit; + } + +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); +} + /**************************************************************************** Desc: Determine if a path is a directory. ****************************************************************************/ @@ -910,10 +1058,10 @@ RCODE FLMAPI F_FileSystem::deleteFile( Desc: Copy a file. ****************************************************************************/ RCODE FLMAPI F_FileSystem::copyFile( - const char * pszSrcFileName, // Name of source file to be copied. - const char * pszDestFileName, // Name of destination file. - FLMBOOL bOverwrite, // Overwrite destination file? - FLMUINT64 * pui64BytesCopied) // Returns number of bytes copied. + const char * pszSrcFileName, + const char * pszDestFileName, + FLMBOOL bOverwrite, + FLMUINT64 * pui64BytesCopied) { RCODE rc = NE_FLM_OK; IF_FileHdl * pSrcFileHdl = NULL; @@ -998,12 +1146,12 @@ Exit: Desc: Do a partial copy from one file into another file. ****************************************************************************/ RCODE FLMAPI F_FileSystem::copyPartialFile( - IF_FileHdl * pSrcFileHdl, // Source file handle. - FLMUINT64 ui64SrcOffset, // Offset to start copying from. - FLMUINT64 ui64SrcSize, // Bytes to copy - IF_FileHdl * pDestFileHdl, // Destination file handle - FLMUINT64 ui64DestOffset, // Destination start offset. - FLMUINT64 * pui64BytesCopiedRV) // Returns number of bytes copied + IF_FileHdl * pSrcFileHdl, + FLMUINT64 ui64SrcOffset, + FLMUINT64 ui64SrcSize, + IF_FileHdl * pDestFileHdl, + FLMUINT64 ui64DestOffset, + FLMUINT64 * pui64BytesCopiedRV) { RCODE rc = NE_FLM_OK; FLMBYTE * pucBuffer = NULL; @@ -1254,14 +1402,16 @@ RCODE FLMAPI F_FileSystem::getSectorSize( } } - if (!GetDiskFreeSpace( (LPCTSTR)pszVolume, &udSectorsPerCluster, + if( !GetDiskFreeSpace( (LPCTSTR)pszVolume, &udSectorsPerCluster, &udBytesPerSector, &udNumberOfFreeClusters, &udTotalNumberOfClusters)) { + f_assert( 0); rc = f_mapPlatformError( GetLastError(), NE_FLM_INITIALIZING_IO_SYSTEM); *puiSectorSize = 0; goto Exit; } + *puiSectorSize = (FLMUINT)udBytesPerSector; Exit: @@ -2275,3 +2425,1328 @@ RCODE FLMAPI f_pathAppend( { return( f_getFileSysPtr()->pathAppend( pszPath, pszPathComponent)); } + +/**************************************************************************** +Desc: +****************************************************************************/ +F_FileHdlCache::F_FileHdlCache() +{ + m_pTimeoutThread = NULL; + m_pAvailList = NULL; + m_uiMaxIdleTime = 0; +} + +/**************************************************************************** +Desc: +****************************************************************************/ +F_FileHdlCache::~F_FileHdlCache() +{ + if( m_pTimeoutThread) + { + m_pTimeoutThread->stopThread(); + m_pTimeoutThread->Release(); + m_pTimeoutThread = NULL; + } + + if( m_pAvailList) + { + m_pAvailList->Release(); + m_pAvailList = NULL; + } + + m_uiMaxIdleTime = 0; +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdlCache::setup( + FLMUINT uiMaxCachedFiles, + FLMUINT uiIdleTimeoutSecs) +{ + RCODE rc = NE_FLM_OK; + + if( (m_pAvailList = f_new F_HashTable) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + + if( RC_BAD( rc = m_pAvailList->setupHashTable( TRUE, + uiMaxCachedFiles, uiMaxCachedFiles))) + { + goto Exit; + } + + m_uiMaxIdleTime = uiIdleTimeoutSecs; + + if( RC_BAD( rc = f_threadCreate( &m_pTimeoutThread, + timeoutThread, "F_FileHdlCache Timeout", F_DEFAULT_THREAD_GROUP, 0, + this, NULL, F_THREAD_DEFAULT_STACK_SIZE))) + { + goto Exit; + } + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdlCache::setOpenThreshold( + FLMUINT uiMaxOpenFiles) +{ + return( m_pAvailList->setMaxObjects( uiMaxOpenFiles)); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdlCache::openOrCreate( + const char * pszFileName, + FLMUINT uiIoFlags, + FLMBOOL bCreate, + IF_FileHdl ** ppFile) +{ + RCODE rc = NE_FLM_OK; + F_CachedFileHdl * pFileHdl = NULL; + F_HashObject * pHashObject; + FLMUINT uiNameLen = f_strlen( pszFileName); + FLMUINT uiKeyLen = uiNameLen + 4; + FLMBYTE ucKeyBuf[ F_PATH_MAX_SIZE + 4]; + + UD2FBA( uiIoFlags, ucKeyBuf); + f_memcpy( &ucKeyBuf[ 4], pszFileName, uiNameLen); + + if( RC_BAD( rc = m_pAvailList->getObject( ucKeyBuf, uiKeyLen, + &pHashObject, TRUE))) + { + if( rc != NE_FLM_NOT_FOUND) + { + goto Exit; + } + + if( (pFileHdl = f_new F_CachedFileHdl) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + + if( RC_BAD( rc = pFileHdl->openOrCreate( pszFileName, + uiIoFlags, bCreate))) + { + goto Exit; + } + + if( RC_BAD( rc = f_alloc( uiKeyLen, &pFileHdl->m_pucKey))) + { + goto Exit; + } + + f_memcpy( pFileHdl->m_pucKey, ucKeyBuf, uiKeyLen); + pFileHdl->m_uiKeyLen = uiKeyLen; + pFileHdl->m_pFileHdlCache = this; + } + else + { + pFileHdl = (F_CachedFileHdl *)pHashObject; + pFileHdl->m_bInAvailList = FALSE; + + if( bCreate) + { + if( RC_BAD( rc = pFileHdl->truncate())) + { + goto Exit; + } + } + } + + *ppFile = pFileHdl; + pFileHdl = NULL; + +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void FLMAPI F_FileHdlCache::closeUnusedFiles( + FLMUINT uiUnusedTime) +{ + if( !uiUnusedTime) + { + m_pAvailList->removeAllObjects(); + } + else + { + m_pAvailList->removeAgedObjects( uiUnusedTime); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdlCache::timeoutThread( + IF_Thread * pThread) +{ + FLMUINT uiCurrentTime; + FLMUINT uiLastPurgeTime = FLM_GET_TIMER(); + F_FileHdlCache * pThis = (F_FileHdlCache *)pThread->getParm1(); + + for( ;;) + { + if( pThread->getShutdownFlag()) + { + break; + } + + uiCurrentTime = FLM_GET_TIMER(); + + if( FLM_TIMER_UNITS_TO_SECS( + FLM_ELAPSED_TIME( uiCurrentTime, uiLastPurgeTime)) >= + pThis->m_uiMaxIdleTime) + { + pThis->m_pAvailList->removeAgedObjects( pThis->m_uiMaxIdleTime); + uiLastPurgeTime = uiCurrentTime; + } + + f_sleep( 100); + } + + return( NE_FLM_OK); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +FLMINT FLMAPI F_CachedFileHdl::Release( void) +{ + FLMINT iRefCnt = --m_refCnt; + F_FileHdlCache * pFileHdlCache = m_pFileHdlCache; + + if( !iRefCnt) + { + if( pFileHdlCache) + { + f_assert( getHashBucket() == F_INVALID_HASH_BUCKET); + + if( m_bInAvailList) + { + // This should only happen if the object is being released + // by the avail list hash table + + m_bInAvailList = FALSE; + } + else if( isOpen()) + { + if( RC_OK( pFileHdlCache->m_pAvailList->addObject( this, TRUE))) + { + m_bInAvailList = TRUE; + } + } + } + + if( !m_refCnt) + { + delete this; + } + } + + return( iRefCnt); +} + +/***************************************************************************** +Desc: +******************************************************************************/ +RCODE FLMAPI F_FileSystem::allocFileHandleCache( + FLMUINT uiMaxCachedFiles, + FLMUINT uiIdleTimeoutSecs, + IF_FileHdlCache ** ppFileHdlCache) +{ + RCODE rc = NE_FLM_OK; + F_FileHdlCache * pFileHdlCache = NULL; + + if( (pFileHdlCache = f_new F_FileHdlCache) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + + if( RC_BAD( rc = pFileHdlCache->setup( + uiMaxCachedFiles, uiIdleTimeoutSecs))) + { + goto Exit; + } + + *ppFileHdlCache = pFileHdlCache; + pFileHdlCache = NULL; + +Exit: + + if( pFileHdlCache) + { + pFileHdlCache->Release(); + } + + return( rc); +} + +/***************************************************************************** +Desc: +******************************************************************************/ +RCODE FLMAPI F_FileSystem::allocIOBuffer( + FLMUINT uiMinSize, + IF_IOBuffer ** ppIOBuffer) +{ + RCODE rc = NE_FLM_OK; + F_IOBuffer * pIOBuffer = NULL; + + if( (pIOBuffer = f_new F_IOBuffer) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + + if( RC_BAD( rc = pIOBuffer->setupBuffer( uiMinSize, NULL))) + { + goto Exit; + } + + *ppIOBuffer = pIOBuffer; + pIOBuffer = NULL; + +Exit: + + if( pIOBuffer) + { + pIOBuffer->Release(); + } + + return( rc); +} + +/***************************************************************************** +Desc: +******************************************************************************/ +void F_FileHdl::initCommonData( void) +{ + m_pszFileName = NULL; + m_uiBytesPerSector = 0; + m_ui64NotOnSectorBoundMask = 0; + m_ui64GetSectorBoundMask = 0; + m_uiExtendSize = 0; + m_uiMaxAutoExtendSize = 0; + m_pucAlignedBuff = NULL; + m_uiAlignedBuffSize = 0; + m_ui64CurrentPos = 0; + m_bFileOpened = FALSE; + m_bDeleteOnRelease = FALSE; + m_bOpenedReadOnly = FALSE; + m_bOpenedExclusive = FALSE; + m_bOpenedInAsyncMode = FALSE; + m_bDoDirectIO = FALSE; +} + +/***************************************************************************** +Desc: +******************************************************************************/ +void F_FileHdl::freeCommonData( void) +{ + if( m_pucAlignedBuff) + { + f_freeAlignedBuffer( (void **)&m_pucAlignedBuff); + m_uiAlignedBuffSize = 0; + } + + if( m_pszFileName) + { + f_free( &m_pszFileName); + } +} + +/**************************************************************************** +Desc: Open a file +****************************************************************************/ +RCODE F_FileHdl::open( + const char * pszFileName, + FLMUINT uiIoFlags) +{ + return( openOrCreate( pszFileName, uiIoFlags, FALSE)); +} + +/**************************************************************************** +Desc: Create a file +****************************************************************************/ +RCODE F_FileHdl::create( + const char * pszFileName, + FLMUINT uiIoFlags) +{ + return( openOrCreate( pszFileName, uiIoFlags, TRUE)); +} + +/**************************************************************************** +Desc: Create a unique file name in the specified directory +****************************************************************************/ +RCODE F_FileHdl::createUnique( + char * pszDirName, + const char * pszFileExtension, + FLMUINT uiIoFlags) +{ + RCODE rc = NE_FLM_OK; + char * pszTmp; + FLMBOOL bModext = TRUE; + FLMUINT uiBaseTime = 0; + FLMBYTE ucHighByte = 0; + char szFileName[ F_FILENAME_SIZE]; + char szDirPath[ F_PATH_MAX_SIZE]; + char szTmpPath[ F_PATH_MAX_SIZE]; + FLMUINT uiCount; + IF_FileSystem * pFileSystem = f_getFileSysPtr(); + + f_assert( !m_bFileOpened); + f_assert( !m_pszFileName); + + szFileName[0] = '\0'; + szTmpPath[0] = '\0'; + +#if defined( FLM_UNIX) + if( !pszDirName || pszDirName[ 0] == '\0') + { + f_strcpy( szDirPath, "./"); + } + else +#endif + { + f_strcpy( szDirPath, pszDirName); + } + + // Truncate any trailing spaces + + pszTmp = (char *)szDirPath; + pszTmp += (f_strlen( pszTmp) - 1); + + while( pszTmp >= (char *)szDirPath && (*pszTmp == 0x20)) + { + *pszTmp = 0; + pszTmp--; + } + + // Append a slash if one isn't already there + +#if defined( FLM_UNIX) + if( pszTmp >= (char *)szDirPath && *pszTmp != '/') + { + pszTmp++; + *pszTmp++ = '/'; + } +#else + if( pszTmp >= (char *)szDirPath && *pszTmp != '\\') + { + pszTmp++; + *pszTmp++ = '\\'; + } +#endif + else + { + pszTmp++; + } + + *pszTmp = 0; + + if( pszFileExtension && f_strlen( pszFileExtension) >= 3) + { + bModext = FALSE; + } + + uiCount = 0; + do + { + pFileSystem->pathCreateUniqueName( &uiBaseTime, szFileName, + pszFileExtension, &ucHighByte, bModext); + + f_strcpy( szTmpPath, szDirPath); + pFileSystem->pathAppend( szTmpPath, szFileName); + + rc = create( szTmpPath, uiIoFlags | FLM_IO_EXCL); + + } while( rc != NE_FLM_OK && (uiCount++ < 10)); + + // Check if the path was created + + if( uiCount >= 10 && rc != NE_FLM_OK) + { + rc = RC_SET( NE_FLM_IO_PATH_CREATE_FAILURE); + goto Exit; + } + + // Created file name needs to be returned + + f_strcpy( pszDirName, szTmpPath); + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +FLMINT FLMAPI F_FileAsyncClient::Release() +{ + FLMINT iRefCnt; + + if( m_refCnt == 1) + { + f_assert( !m_pFileHdl); + f_assert( !m_pIOBuffer); + + f_mutexLock( F_FileHdl::m_hAsyncListMutex); + + if( F_FileHdl::m_uiAvailAsyncCount < 32) + { + f_assert( !m_pNext); + m_pNext = F_FileHdl::m_pFirstAvailAsync; + F_FileHdl::m_pFirstAvailAsync = this; + F_FileHdl::m_uiAvailAsyncCount++; + + m_completionRc = NE_FLM_OK; + m_uiBytesToDo = 0; + m_uiBytesDone = 0; + iRefCnt = m_refCnt; + } + else + { + iRefCnt = --m_refCnt; + } + + f_mutexUnlock( F_FileHdl::m_hAsyncListMutex); + } + else + { + iRefCnt = --m_refCnt; + } + + if( !m_refCnt) + { + delete this; + } + + return( iRefCnt); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +F_FileAsyncClient::~F_FileAsyncClient() +{ + f_assert( !m_pNext); + +#ifdef FLM_WIN + if( m_Overlapped.hEvent) + { + CloseHandle( m_Overlapped.hEvent); + } +#endif + +#ifdef FLM_RING_ZERO_NLM + if( m_hSem) + { + (void)kSemaphoreFree( m_hSem); + m_hSem = NULL; + } +#endif + + if( m_pFileHdl) + { + m_pFileHdl->Release(); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileAsyncClient::prepareForAsync( + IF_IOBuffer * pIOBuffer) +{ + RCODE rc = NE_FLM_OK; + + if( m_pIOBuffer || !m_pFileHdl) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + +#ifdef FLM_WIN + if( !m_Overlapped.hEvent) + { + if( (m_Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL)) == NULL) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); + goto Exit; + } + } + else + { + if( !ResetEvent( m_Overlapped.hEvent)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); + goto Exit; + } + } +#endif + +#if defined( FLM_LINUX) || defined( FLM_SOLARIS) + f_memset( &m_aio, 0, sizeof( m_aio)); +#endif + +#ifdef FLM_RING_ZERO_NLM + if( !m_hSem) + { + if( (m_hSem = kSemaphoreAlloc( (BYTE *)"FTK_SEM", 0)) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + } +#endif + + m_completionRc = NE_FLM_IO_PENDING; + m_uiBytesToDo = 0; + m_uiBytesDone = 0; + m_uiStartTime = FLM_GET_TIMER(); + m_uiEndTime = m_uiStartTime; + + if( pIOBuffer) + { + pIOBuffer->setAsyncClient( this); + m_pIOBuffer = pIOBuffer; + m_pIOBuffer->AddRef(); + m_pIOBuffer->setPending(); + } + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileAsyncClient::waitToComplete( + FLMBOOL bRelease) +{ + RCODE completionRc = NE_FLM_OK; + FLMUINT uiBytesDone = 0; + +#if defined( FLM_WIN) + DWORD udBytesDone; + + if( !GetOverlappedResult( m_pFileHdl->m_hFile, &m_Overlapped, + &udBytesDone, TRUE)) + { + completionRc = f_mapPlatformError( GetLastError(), NE_FLM_ASYNC_FAILED); + } + + uiBytesDone = (FLMUINT)udBytesDone; +#endif + +#if defined( FLM_LINUX) || defined( FLM_SOLARIS) + FLMINT iAsyncResult; + const struct aiocb * ppAio[ 1]; + + ppAio[ 0] = &m_aio; + + for( ;;) + { + aio_suspend( ppAio, 1, NULL); + iAsyncResult = aio_error( &m_aio); + + if( !iAsyncResult) + { + if( (iAsyncResult = aio_return( &m_aio)) < 0) + { + f_assert( 0); + completionRc = f_mapPlatformError( errno, NE_FLM_ASYNC_FAILED); + } + else + { + uiBytesDone = (FLMUINT)iAsyncResult; + } + + break; + } + + if( iAsyncResult == EINTR || iAsyncResult == EINPROGRESS) + { + continue; + } + + f_assert( 0); + completionRc = f_mapPlatformError( iAsyncResult, NE_FLM_ASYNC_FAILED); + } +#endif + +#ifdef FLM_RING_ZERO_NLM + if( kSemaphoreWait( m_hSem) != 0) + { + f_assert( 0); + } + + f_assert( kSemaphoreExamineCount( m_hSem) == 0); + + if( RC_BAD( completionRc)) + { + m_uiBytesDone = 0; + } + else + { + m_uiBytesDone = m_uiBytesToDo; + uiBytesDone = m_uiBytesDone; + } + +#endif + + notifyComplete( completionRc, uiBytesDone, bRelease); + return( completionRc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void FLMAPI F_FileAsyncClient::notifyComplete( + RCODE completionRc, + FLMUINT uiBytesDone, + FLMBOOL bRelease) +{ + m_uiEndTime = FLM_GET_TIMER(); + + m_completionRc = completionRc; + m_uiBytesDone = uiBytesDone; + + if( m_pIOBuffer) + { + m_pIOBuffer->notifyComplete( m_completionRc); + m_pIOBuffer->Release(); + m_pIOBuffer = NULL; + } + + if( m_pFileHdl) + { + m_pFileHdl->Release(); + m_pFileHdl = NULL; + } + + if( bRelease) + { + Release(); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +FLMUINT FLMAPI F_FileAsyncClient::getElapsedTime( void) +{ + return( FLM_TIMER_UNITS_TO_MILLI( + FLM_ELAPSED_TIME( m_uiEndTime, m_uiStartTime))); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileAsyncClient::getCompletionCode( void) +{ + return( m_completionRc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void F_FileAsyncClient::signalComplete( + RCODE rc, + FLMUINT uiBytesDone) +{ + F_UNREFERENCED_PARM( uiBytesDone); + +#ifdef FLM_RING_ZERO_NLM + m_completionRc = rc; + + f_assert( kSemaphoreExamineCount( m_hSem) == 0); + kSemaphoreSignal( m_hSem); +#else + F_UNREFERENCED_PARM( rc); +#endif +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdl::allocFileAsyncClient( + F_FileAsyncClient ** ppAsyncClient) +{ + RCODE rc = NE_FLM_OK; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bMutexLocked = FALSE; + + f_mutexLock( m_hAsyncListMutex); + bMutexLocked = TRUE; + + if( m_pFirstAvailAsync) + { + pAsyncClient = m_pFirstAvailAsync; + m_pFirstAvailAsync = m_pFirstAvailAsync->m_pNext; + pAsyncClient->m_pNext = NULL; + m_uiAvailAsyncCount--; + } + else + { + f_mutexUnlock( m_hAsyncListMutex); + bMutexLocked = FALSE; + + if( (pAsyncClient = f_new F_FileAsyncClient) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + } + + pAsyncClient->m_pFileHdl = this; + pAsyncClient->m_pFileHdl->AddRef(); + + *ppAsyncClient = pAsyncClient; + pAsyncClient = NULL; + +Exit: + + if( bMutexLocked) + { + f_mutexUnlock( m_hAsyncListMutex); + } + + if( pAsyncClient) + { + pAsyncClient->Release(); + } + + return( rc); +} + +/**************************************************************************** +Desc: Read from a file +****************************************************************************/ +RCODE F_FileHdl::directRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesRead = 0; + FLMUINT uiCurrentBytesRead; + FLMBYTE * pucReadBuffer; + FLMBYTE * pucDestBuffer; + FLMUINT uiMaxBytesToRead; + FLMBOOL bHitEOF; + + if( !m_bFileOpened || !m_bDoDirectIO || !uiBytesToRead) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64ReadOffset == FLM_IO_CURRENT_POS) + { + ui64ReadOffset = m_ui64CurrentPos; + } + + // This loop does multiple reads (if necessary) to get all of the + // data. It uses aligned buffers and reads at sector offsets. + + pucDestBuffer = (FLMBYTE *)pvBuffer; + for (;;) + { + + // See if we are using an aligned buffer. If not, allocate + // one (if not already allocated), and use it. + + if ((ui64ReadOffset & m_ui64NotOnSectorBoundMask) || + (((FLMUINT64)pucDestBuffer) & m_ui64NotOnSectorBoundMask) || + (((FLMUINT64)uiBytesToRead & m_ui64NotOnSectorBoundMask))) + { + pucReadBuffer = m_pucAlignedBuff; + + // Must read enough bytes to cover all of the sectors that + // contain the data we are trying to read. The value of + // (ui64ReadOffset & m_ui64NotOnSectorBoundMask) will give us the + // number of additional bytes that are in the sector prior to + // the read offset. We then round that up to the next sector + // to get the total number of bytes we are going to read. + + uiMaxBytesToRead = (FLMUINT)roundToNextSector( uiBytesToRead + + (ui64ReadOffset & m_ui64NotOnSectorBoundMask)); + + // Can't read more than the aligned buffer will hold. + + if (uiMaxBytesToRead > m_uiAlignedBuffSize) + { + uiMaxBytesToRead = m_uiAlignedBuffSize; + } + } + else + { + uiMaxBytesToRead = (FLMUINT)roundToNextSector( uiBytesToRead); + f_assert( uiMaxBytesToRead >= uiBytesToRead); + pucReadBuffer = pucDestBuffer; + } + + bHitEOF = FALSE; + + if( RC_BAD( rc = lowLevelRead( truncateToPrevSector( ui64ReadOffset), + uiMaxBytesToRead, pucReadBuffer, pIOBuffer, &uiCurrentBytesRead))) + { + if( rc != NE_FLM_IO_END_OF_FILE) + { + goto Exit; + } + + bHitEOF = TRUE; + rc = NE_FLM_OK; + } + + // If the offset we want to read from is not on a sector + // boundary, increment the read buffer pointer to the + // offset where the data we need starts and decrement the + // bytes read by the difference between the start of the + // sector and the actual read offset. + + if( uiCurrentBytesRead && ui64ReadOffset & m_ui64NotOnSectorBoundMask) + { + pucReadBuffer += (ui64ReadOffset & m_ui64NotOnSectorBoundMask); + f_assert( uiCurrentBytesRead >= m_uiBytesPerSector); + uiCurrentBytesRead -= (FLMUINT)(ui64ReadOffset & m_ui64NotOnSectorBoundMask); + } + + // If bytes read is more than we actually need, truncate it back + // so that we only copy what we actually need. + + if( uiCurrentBytesRead > uiBytesToRead) + { + uiCurrentBytesRead = uiBytesToRead; + } + + uiBytesToRead -= uiCurrentBytesRead; + uiBytesRead += uiCurrentBytesRead; + + // If using a different buffer for reading, copy the + // data read into the destination buffer. + + if( pucDestBuffer != pucReadBuffer) + { + f_memcpy( pucDestBuffer, pucReadBuffer, uiCurrentBytesRead); + } + + if( !uiBytesToRead) + { + break; + } + + // Still more to read - did we hit EOF above? + + if( bHitEOF) + { + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + break; + } + + pucDestBuffer += uiCurrentBytesRead; + ui64ReadOffset += uiCurrentBytesRead; + } + +Exit: + + if( puiBytesRead) + { + *puiBytesRead = uiBytesRead; + } + + return( rc); +} + +/**************************************************************************** +Desc: Write to a file using direct I/O +****************************************************************************/ +RCODE F_FileHdl::directWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten) +{ + RCODE rc = NE_FLM_OK; + FLMBYTE * pucWriteBuffer; + FLMBYTE * pucSrcBuffer; + FLMUINT uiBytesWritten = 0; + FLMUINT uiMaxBytesToWrite; + FLMUINT uiBytesBeingOutput; + FLMBOOL bWaitForWrite = (pIOBuffer == NULL) + ? TRUE + : FALSE; + FLMUINT64 ui64LastWriteOffset; + FLMUINT uiLastWriteSize; + FLMBOOL bOffsetOnSectorBound; + FLMBOOL bBufferOnSectorBound; + FLMBOOL bSizeIsSectorMultiple; + + if( !m_bFileOpened || !m_bDoDirectIO || !uiBytesToWrite) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64WriteOffset == FLM_IO_CURRENT_POS) + { + ui64WriteOffset = m_ui64CurrentPos; + } + + if( pIOBuffer) + { + pucSrcBuffer = pIOBuffer->getBufferPtr(); + } + else + { + pucSrcBuffer = (FLMBYTE *)pvBuffer; + } + + for (;;) + { + bOffsetOnSectorBound = (ui64WriteOffset & m_ui64NotOnSectorBoundMask) + ? FALSE + : TRUE; + bBufferOnSectorBound = (((FLMUINT)pucSrcBuffer) & m_ui64NotOnSectorBoundMask) + ? FALSE + : TRUE; + bSizeIsSectorMultiple = (uiBytesToWrite & m_ui64NotOnSectorBoundMask) + ? FALSE + : TRUE; + + if( !bOffsetOnSectorBound || + !bBufferOnSectorBound || + !bSizeIsSectorMultiple) + { + bWaitForWrite = TRUE; + pucWriteBuffer = m_pucAlignedBuff; + + // Must write enough bytes to cover all of the sectors that + // contain the data we are trying to write out. The value of + // (ui64WriteOffset & m_ui64NotOnSectorBoundMask) will give us the + // number of additional bytes that are in the sector prior to + // the read offset. We then round to the next sector to get the + // total number of bytes we are going to write. + + uiMaxBytesToWrite = (FLMUINT)roundToNextSector( uiBytesToWrite + + (ui64WriteOffset & m_ui64NotOnSectorBoundMask)); + + // Can't write more than the aligned buffer will hold. + + if( uiMaxBytesToWrite > m_uiAlignedBuffSize) + { + uiMaxBytesToWrite = m_uiAlignedBuffSize; + uiBytesBeingOutput = (FLMUINT)(uiMaxBytesToWrite - + (ui64WriteOffset & m_ui64NotOnSectorBoundMask)); + } + else + { + uiBytesBeingOutput = uiBytesToWrite; + } + + // If the write offset is not on a sector boundary, we must + // read at least the first sector into the buffer. + + if( ui64WriteOffset & m_ui64NotOnSectorBoundMask) + { + + // Read the first sector that is to be written out. + // Read one sector's worth of data - so that we will + // preserve what is already in the sector before + // writing it back out again. + + if( RC_BAD( rc = lowLevelRead( + truncateToPrevSector( ui64WriteOffset), + m_uiBytesPerSector, pucWriteBuffer, NULL, NULL))) + { + goto Exit; + } + } + + // If we are writing more than one sector, and the last sector's + // worth of data we are writing out is only a partial sector, + // we must read in this sector as well. + + if( (uiMaxBytesToWrite > m_uiBytesPerSector) && + (uiMaxBytesToWrite > uiBytesToWrite)) + { + + // Read the last sector that is to be written out. + // Read one sector's worth of data - so that we will + // preserve what is already in the sector before + // writing it back out again. + + if( RC_BAD( rc = lowLevelRead( + (truncateToPrevSector( ui64WriteOffset)) + + (uiMaxBytesToWrite - m_uiBytesPerSector), + m_uiBytesPerSector, + (&pucWriteBuffer[ uiMaxBytesToWrite - m_uiBytesPerSector]), + NULL, NULL))) + { + if (rc == NE_FLM_IO_END_OF_FILE) + { + rc = NE_FLM_OK; + f_memset( &pucWriteBuffer [uiMaxBytesToWrite - m_uiBytesPerSector], + 0, m_uiBytesPerSector); + } + else + { + goto Exit; + } + } + } + + // Finally, copy the data from the source buffer into the + // write buffer. + + f_memcpy( &pucWriteBuffer[ ui64WriteOffset & m_ui64NotOnSectorBoundMask], + pucSrcBuffer, uiBytesBeingOutput); + } + else + { + pucWriteBuffer = pucSrcBuffer; + uiMaxBytesToWrite = uiBytesToWrite; + uiBytesBeingOutput = uiBytesToWrite; + } + + // Position the file to the nearest sector below the write offset. + + ui64LastWriteOffset = truncateToPrevSector( ui64WriteOffset); + uiLastWriteSize = uiMaxBytesToWrite; + + if( !bWaitForWrite) + { + f_assert( pucWriteBuffer == pIOBuffer->getBufferPtr()); + + if( RC_BAD( rc = lowLevelWrite( ui64LastWriteOffset, + uiMaxBytesToWrite, NULL, pIOBuffer, NULL))) + { + goto Exit; + } + } + else + { + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + rc = lowLevelWrite( ui64LastWriteOffset, uiMaxBytesToWrite, + pucWriteBuffer, NULL, NULL); + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) + { + goto Exit; + } + } + + uiBytesToWrite -= uiBytesBeingOutput; + uiBytesWritten += uiBytesBeingOutput; + + if( !uiBytesToWrite) + { + break; + } + + pucSrcBuffer += uiBytesBeingOutput; + ui64WriteOffset += uiBytesBeingOutput; + } + +Exit: + + if( puiBytesWritten) + { + *puiBytesWritten = uiBytesWritten; + } + + return( rc); +} + +/**************************************************************************** +Desc: Sets current position of file. +****************************************************************************/ +RCODE FLMAPI F_FileHdl::seek( + FLMUINT64 ui64Offset, + FLMINT iWhence, + FLMUINT64 * pui64NewOffset) +{ + RCODE rc = NE_FLM_OK; + + switch (iWhence) + { + case FLM_IO_SEEK_CUR: + { + m_ui64CurrentPos += ui64Offset; + break; + } + + case FLM_IO_SEEK_SET: + { + m_ui64CurrentPos = ui64Offset; + break; + } + + case FLM_IO_SEEK_END: + { + if( RC_BAD( rc = size( &m_ui64CurrentPos ))) + { + goto Exit; + } + break; + } + + default: + { + rc = RC_SET_AND_ASSERT( NE_FLM_NOT_IMPLEMENTED); + goto Exit; + } + } + + if( pui64NewOffset) + { + *pui64NewOffset = m_ui64CurrentPos; + } + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdl::tell( + FLMUINT64 * pui64Offset) +{ + *pui64Offset = m_ui64CurrentPos; + return( NE_FLM_OK); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdl::read( + FLMUINT64 ui64Offset, + FLMUINT uiLength, + void * pvBuffer, + FLMUINT * puiBytesRead) +{ + if( m_bDoDirectIO) + { + return( directRead( ui64Offset, uiLength, pvBuffer, + NULL, puiBytesRead)); + } + else + { + return( lowLevelRead( ui64Offset, uiLength, pvBuffer, + NULL, puiBytesRead)); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdl::read( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + IF_IOBuffer * pIOBuffer) +{ + return( directRead( ui64ReadOffset, uiBytesToRead, + NULL, pIOBuffer, NULL)); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdl::write( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + FLMUINT * puiBytesWritten) +{ + if( m_bDoDirectIO) + { + return( directWrite( ui64WriteOffset, uiBytesToWrite, pvBuffer, + NULL, puiBytesWritten)); + } + else + { + return( lowLevelWrite( ui64WriteOffset, uiBytesToWrite, + pvBuffer, NULL, puiBytesWritten)); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_FileHdl::write( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + IF_IOBuffer * pIOBuffer) +{ + RCODE rc = NE_FLM_OK; + + if( m_bDoDirectIO) + { + if( RC_BAD( rc = directWrite( ui64WriteOffset, uiBytesToWrite, + NULL, pIOBuffer, NULL))) + { + goto Exit; + } + } + else + { + pIOBuffer->setPending(); + + rc = lowLevelWrite( ui64WriteOffset, uiBytesToWrite, + pIOBuffer->getBufferPtr(), NULL, NULL); + + pIOBuffer->notifyComplete( rc); + + if( RC_BAD( rc)) + { + goto Exit; + } + } + +Exit: + + return( rc); +} diff --git a/ftk/src/ftkftx.cpp b/ftk/src/ftkftx.cpp index 6a40cce..e43172f 100644 --- a/ftk/src/ftkftx.cpp +++ b/ftk/src/ftkftx.cpp @@ -445,17 +445,17 @@ FSTATIC FLMUINT ftxMapFlmColorToWin32( eColorType uiColor); #endif -RCODE _ftxBackgroundThread( +RCODE FLMAPI _ftxBackgroundThread( IF_Thread * pThread); FLMBOOL ftxKBTest( void); FLMUINT ftxKBGetChar( void); -RCODE _ftxDefaultDisplayHandler( +RCODE FLMAPI _ftxDefaultDisplayHandler( IF_Thread * pThread); -RCODE _ftxDefaultKeyboardHandler( +RCODE FLMAPI _ftxDefaultKeyboardHandler( IF_Thread * pThread); #if defined( FLM_UNIX) @@ -4817,7 +4817,7 @@ FSTATIC ftxWin32CharPair * ftxWin32GetExtendedKeycode( /**************************************************************************** Desc: ****************************************************************************/ -RCODE _ftxDefaultDisplayHandler( +RCODE FLMAPI _ftxDefaultDisplayHandler( IF_Thread * pThread) { #if defined( FLM_WIN) @@ -4862,7 +4862,7 @@ RCODE _ftxDefaultDisplayHandler( /**************************************************************************** Desc: ****************************************************************************/ -RCODE _ftxDefaultKeyboardHandler( +RCODE FLMAPI _ftxDefaultKeyboardHandler( IF_Thread * pThread) { FLMUINT uiChar; @@ -4965,7 +4965,7 @@ RCODE _ftxDefaultKeyboardHandler( /**************************************************************************** Desc: ****************************************************************************/ -RCODE _ftxBackgroundThread( +RCODE FLMAPI _ftxBackgroundThread( IF_Thread * pThread) { for( ;;) @@ -5652,7 +5652,7 @@ static FLMUINT ftxUnixHandleEsc( void) { c = FKB_ALT_F1 + c - KEY_F(1); } - else if( c2 == erasechar() || c2 == '' || c2 == 0127) + else if( c2 == erasechar() || c2 == 0127) { c = FKB_ESCAPE; } diff --git a/ftk/src/ftkiobuf.cpp b/ftk/src/ftkiobuf.cpp index c8f94c3..e056c9b 100644 --- a/ftk/src/ftkiobuf.cpp +++ b/ftk/src/ftkiobuf.cpp @@ -35,78 +35,80 @@ public: F_IOBufferMgr(); virtual ~F_IOBufferMgr(); + + RCODE setupBufferMgr( + FLMUINT uiMaxBuffers, + FLMUINT uiMaxBytes, + FLMBOOL bReuseBuffers); + + RCODE FLMAPI getBuffer( + FLMUINT uiBufferSize, + IF_IOBuffer ** ppIOBuffer); RCODE FLMAPI waitForAllPendingIO( void); - FINLINE void FLMAPI setMaxBuffers( - FLMUINT uiMaxBuffers) - { - m_uiMaxBuffers = uiMaxBuffers; - } - - FINLINE void FLMAPI setMaxBytes( - FLMUINT uiMaxBytes) - { - m_uiMaxBufferBytesToUse = uiMaxBytes; - } - - FINLINE void FLMAPI enableKeepBuffer( void) - { - m_bKeepBuffers = TRUE; - } - - RCODE FLMAPI getBuffer( - IF_IOBuffer ** ppIOBuffer, - FLMUINT uiBufferSize, - FLMUINT uiBlockSize); - - FINLINE FLMBOOL FLMAPI havePendingIO( void) + FINLINE FLMBOOL FLMAPI isIOPending( void) { return( m_pFirstPending ? TRUE : FALSE); } - FINLINE FLMBOOL FLMAPI haveUsed( void) - { - return( m_pFirstUsed ? TRUE : FALSE); - } - -private: - - // Private methods and variables - - F_IOBuffer * m_pFirstPending; - F_IOBuffer * m_pFirstAvail; - F_IOBuffer * m_pFirstUsed; - FLMUINT m_uiMaxBuffers; - FLMUINT m_uiMaxBufferBytesToUse; - FLMUINT m_uiBufferBytesInUse; - FLMUINT m_uiBuffersInUse; - RCODE m_completionRc; - FLMBOOL m_bKeepBuffers; - void linkToList( - F_IOBuffer ** ppListHead, - F_IOBuffer * pIOBuffer); + F_IOBuffer ** ppListHead, + F_IOBuffer * pIOBuffer); void unlinkFromList( - F_IOBuffer * pIOBuffer); + F_IOBuffer * pIOBuffer); + +private: -friend class F_IOBuffer; + FLMUINT m_uiMaxBuffers; + FLMUINT m_uiMaxBufferBytes; + FLMUINT m_uiTotalBuffers; + FLMUINT m_uiTotalBufferBytes; + F_IOBuffer * m_pFirstPending; + F_IOBuffer * m_pFirstAvail; + F_IOBuffer * m_pFirstUsed; + FLMBOOL m_bReuseBuffers; + RCODE m_completionRc; + friend class F_IOBuffer; }; /**************************************************************************** Desc: ****************************************************************************/ RCODE FLMAPI FlmAllocIOBufferMgr( - IF_IOBufferMgr ** ppIOBufferMgr) + FLMUINT uiMaxBuffers, + FLMUINT uiMaxBytes, + FLMBOOL bReuseBuffers, + IF_IOBufferMgr ** ppIOBufferMgr) { - if( (*ppIOBufferMgr = f_new F_IOBufferMgr) == NULL) + RCODE rc = NE_FLM_OK; + F_IOBufferMgr * pBufferMgr = NULL; + + if( (pBufferMgr = f_new F_IOBufferMgr) == NULL) { - return( RC_SET( NE_FLM_MEM)); + rc = RC_SET( NE_FLM_MEM); + goto Exit; } - return( NE_FLM_OK); + if( RC_BAD( pBufferMgr->setupBufferMgr( uiMaxBuffers, + uiMaxBytes, bReuseBuffers))) + { + goto Exit; + } + + *ppIOBufferMgr = pBufferMgr; + pBufferMgr = NULL; + +Exit: + + if( pBufferMgr) + { + pBufferMgr->Release(); + } + + return( rc); } /**************************************************************************** @@ -114,15 +116,18 @@ Desc: ****************************************************************************/ F_IOBufferMgr::F_IOBufferMgr() { + m_uiMaxBuffers = 0; + m_uiMaxBufferBytes = 0; + + m_uiTotalBuffers = 0; + m_uiTotalBufferBytes = 0; + m_pFirstPending = NULL; m_pFirstAvail = NULL; m_pFirstUsed = NULL; - m_uiMaxBuffers = 0; - m_uiMaxBufferBytesToUse = 0; - m_uiBufferBytesInUse = 0; - m_uiBuffersInUse = 0; + + m_bReuseBuffers = FALSE; m_completionRc = NE_FLM_OK; - m_bKeepBuffers = FALSE; } /**************************************************************************** @@ -130,21 +135,112 @@ Desc: ****************************************************************************/ F_IOBufferMgr::~F_IOBufferMgr() { - f_assert( !m_pFirstPending && !m_pFirstUsed); - while (m_pFirstPending) - { - m_pFirstPending->Release(); - } - - while (m_pFirstAvail) + f_assert( !m_pFirstPending); + f_assert( !m_pFirstUsed); + + while( m_pFirstAvail) { m_pFirstAvail->Release(); } +} - while (m_pFirstUsed) +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_IOBufferMgr::setupBufferMgr( + FLMUINT uiMaxBuffers, + FLMUINT uiMaxBytes, + FLMBOOL bReuseBuffers) +{ + f_assert( uiMaxBuffers); + f_assert( uiMaxBytes); + + m_uiMaxBuffers = uiMaxBuffers; + m_uiMaxBufferBytes = uiMaxBytes; + m_bReuseBuffers = bReuseBuffers; + + return( NE_FLM_OK); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_IOBufferMgr::getBuffer( + FLMUINT uiBufferSize, + IF_IOBuffer ** ppIOBuffer) +{ + RCODE rc = NE_FLM_OK; + F_IOBuffer * pIOBuffer = NULL; + + f_assert( *ppIOBuffer == NULL); + + if( RC_BAD( m_completionRc)) { - m_pFirstUsed->Release(); + rc = m_completionRc; + goto Exit; } + +Retry: + + if( m_pFirstAvail) + { + pIOBuffer = m_pFirstAvail; + unlinkFromList( pIOBuffer); + pIOBuffer->resetBuffer(); + f_assert( pIOBuffer->getBufferSize() == uiBufferSize); + } + else if( !m_uiTotalBuffers || + (m_uiTotalBufferBytes + uiBufferSize <= m_uiMaxBufferBytes && + m_uiTotalBuffers < m_uiMaxBuffers)) + { + if( m_uiTotalBufferBytes + uiBufferSize > m_uiMaxBufferBytes) + { + rc = RC_SET_AND_ASSERT( NE_FLM_MEM); + goto Exit; + } + + if( (pIOBuffer = f_new F_IOBuffer) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } + + if (RC_BAD( rc = pIOBuffer->setupBuffer( uiBufferSize, this))) + { + goto Exit; + } + + m_uiTotalBufferBytes += uiBufferSize; + m_uiTotalBuffers++; + } + else if( m_pFirstPending) + { + if( RC_BAD( rc = m_pFirstPending->waitToComplete())) + { + goto Exit; + } + + goto Retry; + } + else + { + rc = RC_SET_AND_ASSERT( NE_FLM_MEM); + goto Exit; + } + + pIOBuffer->AddRef(); + linkToList( &m_pFirstUsed, pIOBuffer); + *ppIOBuffer = pIOBuffer; + pIOBuffer = NULL; + +Exit: + + if( pIOBuffer) + { + pIOBuffer->Release(); + } + + return( rc); } /**************************************************************************** @@ -152,17 +248,24 @@ Desc: ****************************************************************************/ RCODE FLMAPI F_IOBufferMgr::waitForAllPendingIO( void) { - RCODE rc = NE_FLM_OK; + RCODE rc; + RCODE tmpRc; F_IOBuffer * pBuf; while( (pBuf = m_pFirstPending) != NULL) { - (void)pBuf->waitToComplete(); + if( RC_BAD( tmpRc = pBuf->waitToComplete())) + { + if( RC_OK( m_completionRc)) + { + m_completionRc = tmpRc; + } + } } - + rc = m_completionRc; m_completionRc = NE_FLM_OK; - + return( rc); } @@ -170,31 +273,29 @@ RCODE FLMAPI F_IOBufferMgr::waitForAllPendingIO( void) Desc: ****************************************************************************/ void F_IOBufferMgr::linkToList( - F_IOBuffer ** ppListHead, - F_IOBuffer * pIOBuffer) + F_IOBuffer ** ppListHead, + F_IOBuffer * pIOBuffer) { - f_assert( pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_NONE); + f_assert( pIOBuffer->m_eList == MGR_LIST_NONE); + pIOBuffer->m_pPrev = NULL; - if ((pIOBuffer->m_pNext = *ppListHead) != NULL) + + if( (pIOBuffer->m_pNext = *ppListHead) != NULL) { (*ppListHead)->m_pPrev = pIOBuffer; } + *ppListHead = pIOBuffer; - if (ppListHead == &m_pFirstPending || - ppListHead == &m_pFirstUsed) + + if( ppListHead == &m_pFirstPending || ppListHead == &m_pFirstUsed) { pIOBuffer->m_eList = (ppListHead == &m_pFirstPending - ? F_IOBuffer::MGR_LIST_PENDING - : F_IOBuffer::MGR_LIST_USED); - pIOBuffer->m_bDeleteOnNotify = (m_bKeepBuffers - ? FALSE - : TRUE); - m_uiBuffersInUse++; - m_uiBufferBytesInUse += pIOBuffer->m_uiBufferSize; + ? MGR_LIST_PENDING + : MGR_LIST_USED); } else { - pIOBuffer->m_eList = F_IOBuffer::MGR_LIST_AVAIL; + pIOBuffer->m_eList = MGR_LIST_AVAIL; } } @@ -204,296 +305,94 @@ Desc: void F_IOBufferMgr::unlinkFromList( F_IOBuffer * pIOBuffer) { - if (pIOBuffer->m_pNext) + if( pIOBuffer->m_pNext) { pIOBuffer->m_pNext->m_pPrev = pIOBuffer->m_pPrev; } - if (pIOBuffer->m_pPrev) + + if( pIOBuffer->m_pPrev) { pIOBuffer->m_pPrev->m_pNext = pIOBuffer->m_pNext; } - else if (pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_AVAIL) + else if( pIOBuffer->m_eList == MGR_LIST_AVAIL) { m_pFirstAvail = pIOBuffer->m_pNext; } - else if (pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_PENDING) + else if( pIOBuffer->m_eList == MGR_LIST_PENDING) { m_pFirstPending = pIOBuffer->m_pNext; } - else if (pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_USED) + else if( pIOBuffer->m_eList == MGR_LIST_USED) { m_pFirstUsed = pIOBuffer->m_pNext; } - else - { - f_assert( 0); - } - if (pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_PENDING || - pIOBuffer->m_eList == F_IOBuffer::MGR_LIST_USED) - { - m_uiBuffersInUse--; - f_assert( m_uiBufferBytesInUse >= pIOBuffer->m_uiBufferSize); - m_uiBufferBytesInUse -= pIOBuffer->m_uiBufferSize; - } - pIOBuffer->m_eList = F_IOBuffer::MGR_LIST_NONE; + + pIOBuffer->m_eList = MGR_LIST_NONE; } /**************************************************************************** Desc: ****************************************************************************/ -RCODE FLMAPI F_IOBufferMgr::getBuffer( - IF_IOBuffer ** ppIOBuffer, +FLMINT FLMAPI F_IOBuffer::Release( void) +{ + FLMINT iRefCnt; + + if( m_refCnt <= 2) + { + if( m_pBufferMgr && m_eList != MGR_LIST_NONE) + { + m_pBufferMgr->unlinkFromList( this); + } + } + + if( m_refCnt == 2) + { + if( m_pBufferMgr) + { + if( m_pBufferMgr->m_bReuseBuffers) + { + m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstAvail, this); + } + else + { + f_assert( m_pBufferMgr->m_uiTotalBuffers); + f_assert( m_pBufferMgr->m_uiTotalBufferBytes >= m_uiBufferSize); + + m_refCnt--; + m_pBufferMgr->m_uiTotalBuffers--; + m_pBufferMgr->m_uiTotalBufferBytes -= m_uiBufferSize; + m_pBufferMgr = NULL; + } + } + } + + iRefCnt = --m_refCnt; + + if( !iRefCnt) + { + delete this; + } + + return( iRefCnt); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_IOBuffer::setupBuffer( FLMUINT uiBufferSize, - FLMUINT uiBlockSize) + F_IOBufferMgr * pBufferMgr) { - RCODE rc = NE_FLM_OK; - F_IOBuffer * pIOBuffer = NULL; - F_IOBuffer * pBuf; + RCODE rc = NE_FLM_OK; - if( RC_BAD( m_completionRc)) + if( RC_BAD( rc = f_allocAlignedBuffer( uiBufferSize, + (void **)&m_pucBuffer))) { - rc = m_completionRc; goto Exit; } - - if ((m_uiBufferBytesInUse + uiBufferSize > m_uiMaxBufferBytesToUse && - m_pFirstPending) || - m_uiBuffersInUse == m_uiMaxBuffers) - { - pBuf = m_pFirstPending; - for (;;) - { - if( pBuf->isIOComplete()) - { - if( RC_BAD( rc = pBuf->waitToComplete())) - { - goto Exit; - } - pBuf = m_pFirstPending; - if (m_uiBufferBytesInUse + uiBufferSize > m_uiMaxBufferBytesToUse && - m_pFirstPending) - { - continue; - } - else - { - f_assert( m_uiBuffersInUse < m_uiMaxBuffers); - break; - } - } - - if ((pBuf = pBuf->m_pNext) == NULL) - { - f_yieldCPU(); - pBuf = m_pFirstPending; - } - } - } - - // If we are set up to keep buffers, caller better always ask - // for the same size. - - if (m_pFirstAvail) - { - pIOBuffer = m_pFirstAvail; - unlinkFromList( pIOBuffer); - f_assert( pIOBuffer->getBufferSize() == uiBufferSize); - } - else - { - if ((pIOBuffer = f_new F_IOBuffer) == NULL) - { - rc = RC_SET( NE_FLM_MEM); - goto Exit; - } - pIOBuffer->m_pIOBufferMgr = this; - if (RC_BAD( rc = pIOBuffer->setupBuffer( uiBufferSize, - uiBlockSize))) - { - goto Exit; - } - } - - // An F_IOBuffer object, once created must ALWAYS be linked - // into the buffer manager's used list. - - linkToList( &m_pFirstUsed, pIOBuffer); - -#ifdef FLM_RING_ZERO_NLM - f_assert( kSemaphoreExamineCount( pIOBuffer->m_hSem) == 0); -#endif - -Exit: - - if (RC_BAD( rc) && pIOBuffer) - { - pIOBuffer->Release(); - pIOBuffer = NULL; - } - *ppIOBuffer = pIOBuffer; - return( rc); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -F_IOBuffer::F_IOBuffer() -{ - m_pIOBufferMgr = NULL; - m_pucBuffer = NULL; -#ifdef FLM_DEBUG - f_memset( m_UserData, 0, sizeof( m_UserData)); -#endif - m_uiBufferSize = 0; - m_uiBlockSize = 0; - m_eList = MGR_LIST_NONE; - m_bDeleteOnNotify = TRUE; - m_pNext = NULL; - m_pPrev = NULL; - m_fnCompletion = NULL; - m_completionRc = NE_FLM_OK; -#if defined( FLM_WIN) - m_FileHandle = INVALID_HANDLE_VALUE; - m_Overlapped.hEvent = 0; -#elif defined( FLM_LINUX) || defined( FLM_SOLARIS) - m_aio.aio_fildes = -1; -#endif -#ifdef FLM_RING_ZERO_NLM - m_hSem = NULL; -#endif - m_pStats = NULL; -} - -/**************************************************************************** -Desc: -****************************************************************************/ -F_IOBuffer::~F_IOBuffer() -{ - // Unlink from list object is in, if any. - - if (m_eList != MGR_LIST_NONE) - { - f_assert( m_pIOBufferMgr); - m_pIOBufferMgr->unlinkFromList( this); - } - -#if defined( FLM_WIN) - if( m_Overlapped.hEvent) - { - CloseHandle( m_Overlapped.hEvent); - } -#endif - -#ifdef FLM_RING_ZERO_NLM - if( m_hSem) - { - (void)kSemaphoreFree( m_hSem); - m_hSem = NULL; - } -#endif - - if (m_pucBuffer) - { -#ifdef FLM_WIN - (void)VirtualFree( m_pucBuffer, 0, MEM_RELEASE); - m_pucBuffer = NULL; -#elif defined( FLM_LINUX) || defined( FLM_SOLARIS) - free( m_pucBuffer); - m_pucBuffer = NULL; -#else - f_free( &m_pucBuffer); -#endif - } -} - -/**************************************************************************** -Desc: -****************************************************************************/ -void FLMAPI F_IOBuffer::makePending( void) -{ - f_assert( m_eList == MGR_LIST_USED); - - // Unlink from used list - - m_pIOBufferMgr->unlinkFromList( this); - - // Link into pending list. - - m_pIOBufferMgr->linkToList( &m_pIOBufferMgr->m_pFirstPending, this); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FLMBOOL FLMAPI F_IOBuffer::isPending( void) -{ - if( m_eList == MGR_LIST_PENDING) - { - return( TRUE); - } - return( FALSE); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -RCODE FLMAPI F_IOBuffer::setupBuffer( - FLMUINT uiBufferSize, - FLMUINT uiBlockSize) -{ - RCODE rc = NE_FLM_OK; - -#if defined( FLM_WIN) - if( (m_Overlapped.hEvent = CreateEvent( NULL, TRUE, - FALSE, NULL)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } -#endif - -#ifdef FLM_RING_ZERO_NLM - if( (m_hSem = kSemaphoreAlloc( (BYTE *)"FTK_SEM", 0)) == NULL) - { - rc = RC_SET( NE_FLM_MEM); - goto Exit; - } -#endif - - // Allocate a buffer - -#ifdef FLM_WIN - if ((m_pucBuffer = (FLMBYTE *)VirtualAlloc( NULL, - (DWORD)uiBufferSize, - MEM_COMMIT, PAGE_READWRITE)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); - goto Exit; - } -#elif defined( FLM_LINUX) - if( posix_memalign( (void **)&m_pucBuffer, - sysconf( _SC_PAGESIZE), uiBufferSize) != 0) - { - rc = f_mapPlatformError( errno, NE_FLM_MEM); - goto Exit; - } -#elif defined( FLM_SOLARIS) - if( (m_pucBuffer = (FLMBYTE *)memalign( sysconf( _SC_PAGESIZE), - uiBufferSize)) == NULL) - { - rc = f_mapPlatformError( errno, NE_FLM_MEM); - goto Exit; - } -#else - if (RC_BAD( rc = f_alloc( uiBufferSize, &m_pucBuffer))) - { - goto Exit; - } -#endif - m_uiBufferSize = uiBufferSize; - m_uiBlockSize = uiBlockSize; + m_pBufferMgr = pBufferMgr; Exit: @@ -503,203 +402,131 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -void FLMAPI F_IOBuffer::notifyComplete( - RCODE rc) +void FLMAPI F_IOBuffer::setPending( void) { - f_assert( m_eList == MGR_LIST_PENDING || - m_eList == MGR_LIST_USED); + f_assert( !m_bPending); + + m_bPending = TRUE; + m_uiStartTime = FLM_GET_TIMER(); + + if( m_pBufferMgr) + { + f_assert( m_eList == MGR_LIST_USED); + + m_pBufferMgr->unlinkFromList( this); + m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstPending, this); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void FLMAPI F_IOBuffer::clearPending( void) +{ + f_assert( m_bPending); + + m_bPending = FALSE; + m_uiStartTime = 0; + + if( m_pBufferMgr) + { + f_assert( m_eList == MGR_LIST_PENDING); + + m_pBufferMgr->unlinkFromList( this); + m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void F_IOBuffer::notifyComplete( + RCODE completionRc) +{ + f_assert( m_bPending); + + m_bPending = FALSE; + m_bCompleted = TRUE; + m_completionRc = completionRc; + m_uiEndTime = FLM_GET_TIMER(); + m_uiElapsedTime = FLM_TIMER_UNITS_TO_MILLI( + FLM_ELAPSED_TIME( m_uiEndTime, m_uiStartTime)); - m_completionRc = rc; if( m_fnCompletion) { - m_fnCompletion( this); - - // Fix so completion callback won't be called twice. - + m_fnCompletion( this, m_pvData); m_fnCompletion = NULL; + m_pvData = NULL; } - - if (RC_BAD( rc) && RC_OK( m_pIOBufferMgr->m_completionRc)) + + if( m_pBufferMgr) { - m_pIOBufferMgr->m_completionRc = rc; - } - - if (m_bDeleteOnNotify) - { - Release(); - } - else - { - m_pIOBufferMgr->unlinkFromList( this); - m_pIOBufferMgr->linkToList( &m_pIOBufferMgr->m_pFirstAvail, this); + f_assert( m_eList == MGR_LIST_PENDING); + + m_pBufferMgr->unlinkFromList( this); + m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this); + + if( RC_OK( m_pBufferMgr->m_completionRc) && RC_BAD( completionRc)) + { + m_pBufferMgr->m_completionRc = completionRc; + } } } /**************************************************************************** Desc: ****************************************************************************/ -FLMBOOL F_IOBuffer::isIOComplete( void) +RCODE FLMAPI F_IOBuffer::addCallbackData( + void * pvData) { - FLMBOOL bComplete = FALSE; -#ifdef FLM_RING_ZERO_NLM - FLMUINT uiSemCount; -#endif - - if( m_eList != MGR_LIST_PENDING) + RCODE rc = NE_FLM_OK; + + if( m_uiCallbackDataCount >= m_uiMaxCallbackData) { - bComplete = TRUE; - goto Exit; + if( m_ppCallbackData == m_callbackData) + { + void ** pNewTable; + + if( RC_BAD( rc = f_alloc( + (m_uiCallbackDataCount + 1) * sizeof( void *), &pNewTable))) + { + goto Exit; + } + + f_memcpy( pNewTable, m_ppCallbackData, + m_uiMaxCallbackData * sizeof( void *)); + m_ppCallbackData = pNewTable; + } + else + { + if( RC_BAD( rc = f_realloc( + (m_uiCallbackDataCount + 1) * sizeof( void *), &m_ppCallbackData))) + { + goto Exit; + } + } + + m_uiMaxCallbackData = m_uiCallbackDataCount + 1; } - -#ifdef FLM_WIN - if (m_FileHandle == INVALID_HANDLE_VALUE || - HasOverlappedIoCompleted( &m_Overlapped)) - { - bComplete = TRUE; - } -#endif - -#if defined( FLM_LINUX) || defined( FLM_SOLARIS) - if( m_aio.aio_fildes == -1 || aio_error( &m_aio) != EINPROGRESS) - { - bComplete = TRUE; - } -#endif - -#ifdef FLM_RING_ZERO_NLM - if( (uiSemCount = (FLMUINT)kSemaphoreExamineCount( m_hSem)) != 0) - { - f_assert( uiSemCount == 1); - bComplete = TRUE; - } -#endif - + + m_ppCallbackData[ m_uiCallbackDataCount] = pvData; + m_uiCallbackDataCount++; + Exit: - return( bComplete); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -RCODE F_IOBuffer::waitToComplete( void) -{ - RCODE rc = NE_FLM_OK; - - // IMPORTANT NOTE! The call to notifyComplete will destroy this - // object, so nothing in the object can be accessed after notifyComplete - // is called. - -#ifdef FLM_WIN - if (m_FileHandle != INVALID_HANDLE_VALUE) - { - DWORD udBytesWritten; - - if (!GetOverlappedResult( m_FileHandle, &m_Overlapped, - &udBytesWritten, TRUE)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_WRITING_FILE); - } - - notifyComplete( rc); - } -#endif - -#if defined( FLM_LINUX) || defined( FLM_SOLARIS) - if( m_aio.aio_fildes != -1) - { - FLMINT iAsyncResult; - const struct aiocb * ppAio[ 1]; - - ppAio[ 0] = &m_aio; - - for( ;;) - { - aio_suspend( ppAio, 1, NULL); - iAsyncResult = aio_error( &m_aio); - - if( !iAsyncResult) - { - if( (iAsyncResult = aio_return( &m_aio)) < 0) - { - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto WriteComplete; - } - - break; - } - - if( iAsyncResult == EINTR || iAsyncResult == EINPROGRESS) - { - continue; - } - - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto WriteComplete; - } - -WriteComplete: - - notifyComplete( rc); - } -#endif - -#ifdef FLM_RING_ZERO_NLM - if( kSemaphoreWait( m_hSem) != 0) - { - f_assert( 0); - } - - f_assert( kSemaphoreExamineCount( m_hSem) == 0); - rc = m_completionRc; - notifyComplete( m_completionRc); -#endif - return( rc); } - + /**************************************************************************** Desc: ****************************************************************************/ -void FLMAPI F_IOBuffer::startTimer( - void * pStats) +void * FLMAPI F_IOBuffer::getCallbackData( + FLMUINT uiSlot) { - if ((m_pStats = pStats) != NULL) + if( uiSlot < m_uiCallbackDataCount) { - m_ui64ElapMilli = 0; - f_timeGetTimeStamp( &m_StartTime); + return( m_ppCallbackData[ uiSlot]); } -} - -/**************************************************************************** -Desc: -****************************************************************************/ -FLMUINT64 FLMAPI F_IOBuffer::getElapTime( void) -{ - return( m_ui64ElapMilli); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -void * FLMAPI F_IOBuffer::getStats( void) -{ - return( m_pStats); -} - -/**************************************************************************** -Desc: -****************************************************************************/ -void FLMAPI F_IOBuffer::signalComplete( - RCODE rc) -{ -#ifdef FLM_RING_ZERO_NLM - m_completionRc = rc; - f_assert( kSemaphoreExamineCount( m_hSem) == 0); - kSemaphoreSignal( m_hSem); -#else - F_UNREFERENCED_PARM( rc); -#endif + + return( NULL); } diff --git a/ftk/src/ftklock.cpp b/ftk/src/ftklock.cpp index 165e8d3..efa0c78 100644 --- a/ftk/src/ftklock.cpp +++ b/ftk/src/ftklock.cpp @@ -109,7 +109,7 @@ private: void cleanupLockObject( void); - static RCODE timeoutThread( + static RCODE FLMAPI timeoutThread( IF_Thread * pThread); void insertWaiter( @@ -267,7 +267,7 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -RCODE F_LockObject::timeoutThread( +RCODE FLMAPI F_LockObject::timeoutThread( IF_Thread * pThread) { RCODE rc = NE_FLM_OK; @@ -368,7 +368,10 @@ void FLMAPI F_LockObject::timeoutAllWaiters( void) { F_LOCK_WAITER * pLockWaiter; - f_mutexLock( m_hMutex); + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + } while( m_pFirstInList) { @@ -378,7 +381,10 @@ void FLMAPI F_LockObject::timeoutAllWaiters( void) f_semSignal( pLockWaiter->hWaitSem); } - f_mutexUnlock( m_hMutex); + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexUnlock( m_hMutex); + } } /**************************************************************************** diff --git a/ftk/src/ftkmem.cpp b/ftk/src/ftkmem.cpp index 10f32bd..61cb3ba 100644 --- a/ftk/src/ftkmem.cpp +++ b/ftk/src/ftkmem.cpp @@ -4429,7 +4429,7 @@ IF_FixedAlloc * F_MultiAlloc::getAllocator( /**************************************************************************** Desc: ****************************************************************************/ -RCODE FLMAPI f_allocAlignedBuffer( +RCODE FLMAPI f_allocAlignedBufferImp( FLMUINT uiMinSize, void ** ppvAlloc) { @@ -4472,7 +4472,7 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -void FLMAPI f_freeAlignedBuffer( +void FLMAPI f_freeAlignedBufferImp( void ** ppvAlloc) { if( *ppvAlloc) diff --git a/ftk/src/ftkmfh.cpp b/ftk/src/ftkmfh.cpp index 8355299..5d9f622 100644 --- a/ftk/src/ftkmfh.cpp +++ b/ftk/src/ftkmfh.cpp @@ -207,6 +207,7 @@ F_MultiFileHdl::F_MultiFileHdl( m_pLockFileHdl = NULL; f_memset( m_pFileHdlList, 0, sizeof( FH_INFO) * F_MULTI_FHDL_LIST_SIZE); m_uiMaxFileSize = uiMaxFileSize; + if( !m_uiMaxFileSize) { m_uiMaxFileSize = F_MULTI_FHDL_DEFAULT_MAX_FILE_SIZE; @@ -553,7 +554,7 @@ RCODE F_MultiFileHdl::open( // Find all data files to determine the EOF - for( rc = pDir->next(); !RC_BAD( rc) ; rc = pDir->next()) + for( rc = pDir->next(); !RC_BAD( rc); rc = pDir->next()) { if( RC_OK( getFileNum( pDir->currentItemName(), &uiTmp))) { @@ -626,6 +627,7 @@ RCODE F_MultiFileHdl::read( void * pvBuffer, // Buffer FLMUINT * puiBytesRead) // [out] Number of bytes read { + RCODE rc = NE_FLM_OK; FLMUINT uiFileNum = getFileNum( ui64Offset); FLMUINT uiFileOffset = getFileOffset( ui64Offset); FLMUINT uiTmp; @@ -633,7 +635,6 @@ RCODE F_MultiFileHdl::read( FLMUINT uiBytesToRead; FLMUINT uiMaxReadLen; IF_FileHdl * pFileHdl; - RCODE rc = NE_FLM_OK; // Handle the case of a 0-byte read diff --git a/ftk/src/ftkmisc.cpp b/ftk/src/ftkmisc.cpp index 01b20a4..79f2a1c 100644 --- a/ftk/src/ftkmisc.cpp +++ b/ftk/src/ftkmisc.cpp @@ -34,6 +34,11 @@ static IF_FileSystem * gv_pFileSystem = NULL; static FLMUINT gv_uiMaxFileSize = FLM_MAXIMUM_FILE_SIZE; static F_XML * gv_pXml = NULL; +FLMATOMIC gv_openFiles = 0; +F_MUTEX F_FileHdl::m_hAsyncListMutex = F_MUTEX_NULL; +F_FileAsyncClient * F_FileHdl::m_pFirstAvailAsync = NULL; +FLMUINT F_FileHdl::m_uiAvailAsyncCount = 0; + FSTATIC RCODE f_initRandomGenerator( void); FSTATIC void f_freeRandomGenerator( void); @@ -133,6 +138,11 @@ RCODE FLMAPI ftkStartup( void) goto Exit; } + if( RC_BAD( rc = f_initFileAsyncClientList())) + { + goto Exit; + } + if( RC_BAD( rc = f_allocThreadMgr( &gv_pThreadMgr))) { goto Exit; @@ -213,12 +223,16 @@ void FLMAPI ftkShutdown( void) return; } + f_assert( !gv_openFiles); + if( gv_pThreadMgr) { gv_pThreadMgr->Release(); gv_pThreadMgr = NULL; } + f_freeFileAsyncClientList(); + if( gv_pFileSystem) { gv_pFileSystem->Release(); @@ -1398,6 +1412,14 @@ IF_FileSystem * FLMAPI f_getFileSysPtr( void) return( gv_pFileSystem); } +/********************************************************************** +Desc: +**********************************************************************/ +FLMUINT FLMAPI f_getOpenFileCount( void) +{ + return( gv_openFiles); +} + /********************************************************************** Desc: **********************************************************************/ @@ -2141,10 +2163,10 @@ Desc: This routine allocates and initializes a hash table. ****************************************************************************/ RCODE FLMAPI f_allocHashTable( FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV) + F_BUCKET ** ppHashTblRV) { RCODE rc = NE_FLM_OK; - FBUCKET * pHashTbl = NULL; + F_BUCKET * pHashTbl = NULL; IF_RandomGenerator * pRandGen = NULL; FLMUINT uiCnt; FLMUINT uiRandVal; @@ -2153,7 +2175,7 @@ RCODE FLMAPI f_allocHashTable( // Allocate memory for the hash table if (RC_BAD( rc = f_calloc( - (FLMUINT)(sizeof( FBUCKET)) * uiHashTblSize, &pHashTbl))) + (FLMUINT)(sizeof( F_BUCKET)) * uiHashTblSize, &pHashTbl))) { goto Exit; } @@ -2204,7 +2226,7 @@ Desc: This routine determines the hash bucket for a string. ****************************************************************************/ FLMUINT FLMAPI f_strHashBucket( char * pszStr, - FBUCKET * pHashTbl, + F_BUCKET * pHashTbl, FLMUINT uiNumBuckets) { FLMUINT uiHashIndex; @@ -2234,7 +2256,7 @@ Desc: This routine determines the hash bucket for a binary array of FLMUINT FLMAPI f_binHashBucket( void * pBuf, FLMUINT uiBufLen, - FBUCKET * pHashTbl, + F_BUCKET * pHashTbl, FLMUINT uiNumBuckets) { FLMUINT uiHashIndex; @@ -2254,3 +2276,727 @@ FLMUINT FLMAPI f_binHashBucket( return( uiHashIndex); } +/**************************************************************************** +Desc: +****************************************************************************/ +F_HashTable::F_HashTable() +{ + m_hMutex = F_MUTEX_NULL; + m_pMRUObject = NULL; + m_pLRUObject = NULL; + m_ppHashTable = NULL; + m_uiBuckets = 0; + m_uiObjects = 0; + m_uiMaxObjects = 0; +} + +/**************************************************************************** +Desc: +****************************************************************************/ +F_HashTable::~F_HashTable() +{ + F_HashObject * pCur; + F_HashObject * pNext; + + pCur = m_pMRUObject; + while( pCur) + { + pNext = pCur->m_pNextInGlobal; + unlinkObject( pCur); + pCur->Release(); + pCur = pNext; + } + + f_assert( !m_uiObjects); + f_assert( !m_pMRUObject); + f_assert( !m_pLRUObject); + + if( m_ppHashTable) + { + f_free( &m_ppHashTable); + } + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexDestroy( &m_hMutex); + } +} + +/**************************************************************************** +Desc: Configures the hash table prior to first use +****************************************************************************/ +RCODE FLMAPI F_HashTable::setupHashTable( + FLMBOOL bMultithreaded, + FLMUINT uiNumBuckets, + FLMUINT uiMaxObjects) +{ + RCODE rc = NE_FLM_OK; + + flmAssert( uiNumBuckets); + + // Create the hash table + + if( RC_BAD( rc = f_alloc( + sizeof( F_HashObject *) * uiNumBuckets, &m_ppHashTable))) + { + goto Exit; + } + + m_uiObjects = 0; + m_uiMaxObjects = uiMaxObjects; + m_uiBuckets = uiNumBuckets; + f_memset( m_ppHashTable, 0, sizeof( F_HashObject *) * uiNumBuckets); + + if( bMultithreaded) + { + // Initialize the mutex + + if( RC_BAD( rc = f_mutexCreate( &m_hMutex))) + { + goto Exit; + } + } + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: Retrieves an object from the hash table with the specified key. + This routine assumes the table's mutex has already been locked. + A reference IS NOT added to the object for the caller. +****************************************************************************/ +RCODE F_HashTable::findObject( + const void * pvKey, + FLMUINT uiKeyLen, + F_HashObject ** ppObject) +{ + RCODE rc = NE_FLM_OK; + F_HashObject * pObject = NULL; + FLMUINT uiBucket; + FLMUINT32 ui32CRC = 0; + + *ppObject = NULL; + + // Calculate the hash bucket and mutex offset + + uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); + + // Search the bucket for an object with a matching + // key. + + pObject = m_ppHashTable[ uiBucket]; + while( pObject) + { + if( pObject->getKeyCRC() == ui32CRC) + { + const void * pvTmpKey = pObject->getKey(); + FLMUINT uiTmpKeyLen = pObject->getKeyLength(); + + if( uiTmpKeyLen == uiKeyLen && + f_memcmp( pvTmpKey, pvKey, uiKeyLen) == 0) + { + break; + } + } + + pObject = pObject->m_pNextInBucket; + } + + if( !pObject) + { + rc = RC_SET( NE_FLM_NOT_FOUND); + goto Exit; + } + + *ppObject = pObject; + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: Adds an object to the hash table +****************************************************************************/ +RCODE FLMAPI F_HashTable::addObject( + F_HashObject * pObject, + FLMBOOL bAllowDuplicates) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBucket; + F_HashObject * pTmp; + const void * pvKey; + FLMUINT uiKeyLen; + FLMUINT32 ui32CRC; + FLMBOOL bMutexLocked = FALSE; + + // Calculate and set the objects hash bucket + + flmAssert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); + + pvKey = pObject->getKey(); + uiKeyLen = pObject->getKeyLength(); + flmAssert( uiKeyLen); + + uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); + pObject->m_ui32KeyCRC = ui32CRC; + + // Lock the mutex + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + // Make sure the object doesn't already exist + + if( !bAllowDuplicates) + { + if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pTmp))) + { + if( rc != NE_FLM_NOT_FOUND) + { + goto Exit; + } + rc = NE_FLM_OK; + } + else + { + rc = RC_SET_AND_ASSERT( NE_FLM_EXISTS); + goto Exit; + } + } + + // Add a reference to the object + + pObject->AddRef(); + + // Link the object into the appropriate lists + + linkObject( pObject, uiBucket); + + // Make sure the maximum number of objects hasn't been exceeded + + if( m_uiMaxObjects) + { + while( m_uiObjects > m_uiMaxObjects) + { + if( (pTmp = m_pLRUObject) == NULL) + { + break; + } + + unlinkObject( pTmp); + } + } + +Exit: + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + + return( rc); +} + +/**************************************************************************** +Desc: Returns the next object in the linked list of objects in the hash + table. If *ppObject == NULL, the first object will be returned. +****************************************************************************/ +RCODE FLMAPI F_HashTable::getNextObjectInGlobal( + F_HashObject ** ppObject) +{ + RCODE rc = NE_FLM_OK; + FLMBOOL bMutexLocked = FALSE; + F_HashObject * pOldObj; + + // Lock the mutex + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + if( !(*ppObject)) + { + *ppObject = m_pMRUObject; + } + else + { + pOldObj = *ppObject; + *ppObject = (*ppObject)->m_pNextInGlobal; + pOldObj->Release(); + } + + if( *ppObject == NULL) + { + rc = RC_SET( NE_FLM_EOF_HIT); + goto Exit; + } + + (*ppObject)->AddRef(); + +Exit: + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_HashTable::getNextObjectInBucket( + F_HashObject ** ppObject) +{ + RCODE rc = NE_FLM_OK; + FLMBOOL bMutexLocked = FALSE; + F_HashObject * pOldObj; + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + if( !(*ppObject)) + { + rc = RC_SET( NE_FLM_EOF_HIT); + goto Exit; + } + + pOldObj = *ppObject; + *ppObject = (*ppObject)->m_pNextInBucket; + pOldObj->Release(); + + if( *ppObject == NULL) + { + rc = RC_SET( NE_FLM_EOF_HIT); + goto Exit; + } + + (*ppObject)->AddRef(); + +Exit: + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + + return( rc); +} + +/**************************************************************************** +Desc: Retrieves an object from the hash table with the specified key +****************************************************************************/ +RCODE FLMAPI F_HashTable::getObject( + const void * pvKey, + FLMUINT uiKeyLen, + F_HashObject ** ppObject, + FLMBOOL bRemove) +{ + RCODE rc = NE_FLM_OK; + F_HashObject * pObject; + FLMBOOL bMutexLocked = FALSE; + + // Lock the mutex + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + // Search for an object with a matching key. + + if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pObject))) + { + goto Exit; + } + + if( pObject && bRemove) + { + unlinkObject( pObject); + if( !ppObject) + { + pObject->Release(); + pObject = NULL; + } + } + + if( ppObject) + { + if( !bRemove) + { + pObject->AddRef(); + } + + *ppObject = pObject; + pObject = NULL; + } + +Exit: + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + + return( rc); +} + +/**************************************************************************** +Desc: Removes an object from the hash table by key +****************************************************************************/ +RCODE FLMAPI F_HashTable::removeObject( + void * pvKey, + FLMUINT uiKeyLen) +{ + return( getObject( pvKey, uiKeyLen, NULL, TRUE)); +} + +/**************************************************************************** +Desc: Removes an object from the hash table by object pointer +****************************************************************************/ +RCODE FLMAPI F_HashTable::removeObject( + F_HashObject * pObject) +{ + const void * pvKey = pObject->getKey(); + FLMUINT uiKeyLen = pObject->getKeyLength(); + + return( getObject( pvKey, uiKeyLen, NULL, TRUE)); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void FLMAPI F_HashTable::removeAllObjects( void) +{ + F_HashObject * pCur; + FLMBOOL bMutexLocked = FALSE; + + for( ;;) + { + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + if( (pCur = m_pMRUObject) == NULL) + { + break; + } + + unlinkObject( pCur); + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + bMutexLocked = FALSE; + } + + pCur->Release(); + } + + f_assert( !m_pMRUObject); + f_assert( !m_pLRUObject); + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void FLMAPI F_HashTable::removeAgedObjects( + FLMUINT uiMaxAge) +{ + F_HashObject * pCur; + FLMBOOL bMutexLocked = FALSE; + FLMUINT uiCurrentTime = FLM_GET_TIMER(); + + for( ;;) + { + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + if( (pCur = m_pLRUObject) == NULL) + { + break; + } + + if( FLM_TIMER_UNITS_TO_SECS( + FLM_ELAPSED_TIME( uiCurrentTime, pCur->m_uiTimeAdded)) < uiMaxAge) + { + break; + } + + unlinkObject( pCur); + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + bMutexLocked = FALSE; + } + + pCur->Release(); + } + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } +} + +/**************************************************************************** +Desc: +****************************************************************************/ +FLMUINT FLMAPI F_HashTable::getMaxObjects( void) +{ + FLMUINT uiMaxObjects; + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + } + + uiMaxObjects = m_uiMaxObjects; + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexUnlock( m_hMutex); + } + + return( m_uiMaxObjects); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_HashTable::setMaxObjects( + FLMUINT uiMaxObjects) +{ + F_HashObject * pCur; + FLMBOOL bMutexLocked = FALSE; + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + m_uiMaxObjects = uiMaxObjects; + + while( m_uiObjects > m_uiMaxObjects) + { + if( !bMutexLocked && m_hMutex != F_MUTEX_NULL) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + if( (pCur = m_pLRUObject) == NULL) + { + break; + } + + unlinkObject( pCur); + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + bMutexLocked = FALSE; + } + + pCur->Release(); + } + + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + + return( NE_FLM_OK); +} + +/**************************************************************************** +Desc: Calculates the hash bucket of a key and optionally returns the key's + CRC. +****************************************************************************/ +FLMUINT F_HashTable::getHashBucket( + const void * pvKey, + FLMUINT uiLen, + FLMUINT32 * pui32KeyCRC) +{ + FLMUINT32 ui32CRC = 0; + + f_updateCRC( (FLMBYTE *)pvKey, uiLen, &ui32CRC); + + if( pui32KeyCRC) + { + *pui32KeyCRC = ui32CRC; + } + + return( ui32CRC % m_uiBuckets); +} + +/**************************************************************************** +Desc: Links an object to the global list and also to its bucket +Notes: This routine assumes that the bucket's mutex is already locked + if the hash table is multi-threaded. +****************************************************************************/ +void F_HashTable::linkObject( + F_HashObject * pObject, + FLMUINT uiBucket) +{ + f_assert( uiBucket < m_uiBuckets); + f_assert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); + + // Set the object's bucket + + pObject->setHashBucket( uiBucket); + + // Link the object to its hash bucket + + pObject->m_pNextInBucket = m_ppHashTable[ uiBucket]; + if( m_ppHashTable[ uiBucket]) + { + m_ppHashTable[ uiBucket]->m_pPrevInBucket = pObject; + } + m_ppHashTable[ uiBucket] = pObject; + + // Link to the global list + + if( (pObject->m_pNextInGlobal = m_pMRUObject) != NULL) + { + m_pMRUObject->m_pPrevInGlobal = pObject; + } + else + { + m_pLRUObject = pObject; + } + + pObject->m_uiTimeAdded = FLM_GET_TIMER(); + m_pMRUObject = pObject; + m_uiObjects++; +} + +/**************************************************************************** +Desc: Unlinks an object from its bucket and the global list. +Notes: This routine assumes that the bucket's mutex is already locked + if the hash table is multi-threaded. +****************************************************************************/ +void F_HashTable::unlinkObject( + F_HashObject * pObject) +{ + FLMUINT uiBucket = pObject->getHashBucket(); + + // Is the bucket valid? + + flmAssert( uiBucket < m_uiBuckets); + + // Unlink from the hash bucket + + if( pObject->m_pNextInBucket) + { + pObject->m_pNextInBucket->m_pPrevInBucket = pObject->m_pPrevInBucket; + } + + if( pObject->m_pPrevInBucket) + { + pObject->m_pPrevInBucket->m_pNextInBucket = pObject->m_pNextInBucket; + } + else + { + m_ppHashTable[ uiBucket] = pObject->m_pNextInBucket; + } + + pObject->m_pPrevInBucket = NULL; + pObject->m_pNextInBucket = NULL; + pObject->setHashBucket( F_INVALID_HASH_BUCKET); + + // Unlink from the global list + + if( pObject->m_pNextInGlobal) + { + pObject->m_pNextInGlobal->m_pPrevInGlobal = pObject->m_pPrevInGlobal; + } + else + { + m_pLRUObject = pObject->m_pPrevInGlobal; + } + + if( pObject->m_pPrevInGlobal) + { + pObject->m_pPrevInGlobal->m_pNextInGlobal = pObject->m_pNextInGlobal; + } + else + { + m_pMRUObject = pObject->m_pNextInGlobal; + } + + pObject->m_pPrevInGlobal = NULL; + pObject->m_pNextInGlobal = NULL; + pObject->m_uiTimeAdded = 0; + + f_assert( m_uiObjects); + m_uiObjects--; +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE f_initFileAsyncClientList( void) +{ + RCODE rc = NE_FLM_OK; + + if( RC_BAD( rc = f_mutexCreate( &F_FileHdl::m_hAsyncListMutex))) + { + goto Exit; + } + + F_FileHdl::m_pFirstAvailAsync = NULL; + F_FileHdl::m_uiAvailAsyncCount = 0; + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +void f_freeFileAsyncClientList( void) +{ + F_FileAsyncClient * pAsyncClient; + + while( F_FileHdl::m_pFirstAvailAsync) + { + pAsyncClient = F_FileHdl::m_pFirstAvailAsync; + F_FileHdl::m_pFirstAvailAsync = F_FileHdl::m_pFirstAvailAsync->m_pNext; + pAsyncClient->m_pNext = NULL; + delete pAsyncClient; + } + + if( F_FileHdl::m_hAsyncListMutex != F_MUTEX_NULL) + { + f_mutexDestroy( &F_FileHdl::m_hAsyncListMutex); + } + + F_FileHdl::m_uiAvailAsyncCount = 0; +} diff --git a/ftk/src/ftknlm.cpp b/ftk/src/ftknlm.cpp index 8027c8e..d46e8c2 100644 --- a/ftk/src/ftknlm.cpp +++ b/ftk/src/ftknlm.cpp @@ -470,7 +470,7 @@ RCODE defaultRc); FLMUINT f_getNSSOpenFlags( - FLMUINT uiAccess, + FLMUINT uiIoFlags, FLMBOOL bDoDirectIo); typedef FLMINT (* zROOT_KEY_FUNC)( @@ -644,6 +644,8 @@ int iArgC, char ** ppszArgV); + extern FLMATOMIC gv_openFiles; + #endif /*************************************************************************** @@ -691,8 +693,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x08" "zRootKey")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -700,8 +701,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x06" "zClose")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -709,8 +709,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x07" "zCreate")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -718,8 +717,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x05" "zOpen")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -727,8 +725,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x07" "zDelete")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -736,8 +733,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x05" "zRead")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -745,8 +741,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x08" "zDIORead")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -754,8 +749,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x08" "zGetInfo")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -763,8 +757,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x0B" "zModifyInfo")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -772,8 +765,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x07" "zSetEOF")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -781,8 +773,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x06" "zWrite")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -790,8 +781,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x09" "zDIOWrite")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -799,8 +789,7 @@ RCODE f_nssInitialize( void) (unsigned long)f_getNLMHandle(), (unsigned char *)"\x07" "zRename")) == NULL) { - flmAssert( 0); - rc = RC_SET( NE_FLM_INITIALIZING_IO_SYSTEM); + rc = RC_SET_AND_ASSERT( NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } @@ -811,6 +800,7 @@ RCODE f_nssInitialize( void) rc = MapNSSError( lStatus, NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } + gv_bNSSKeyInitialized = TRUE; } @@ -869,7 +859,7 @@ FSTATIC RCODE MapNSSError( break; case zERR_OUT_OF_SPACE: - rc = RC_SET( NE_FLM_IO_DISK_FULL); + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); break; case zERR_NO_OPEN_PRIVILEGE: @@ -919,7 +909,7 @@ FSTATIC RCODE MapNSSError( rc = RC_SET( NE_FLM_MEM); break; case zERR_NOT_SUPPORTED: - rc = RC_SET( NE_FLM_NOT_IMPLEMENTED); + rc = RC_SET_AND_ASSERT( NE_FLM_NOT_IMPLEMENTED); break; case zERR_END_OF_FILE: case zERR_BEYOND_EOF: @@ -968,26 +958,26 @@ Desc: Map flaim I/O flags to NDS I/O flags for NSS volumes ****************************************************************************/ #if defined( FLM_RING_ZERO_NLM) FLMUINT f_getNSSOpenFlags( - FLMUINT uiAccess, - FLMBOOL bDoDirectIo) + FLMUINT uiIoFlags, + FLMBOOL bDoDirectIo) { - FLMUINT lFlags = zRR_ALLOW_SECURE_DIRECTORY_ACCESS | - zRR_CANT_DELETE_WHILE_OPEN; + FLMUINT lFlags = zRR_ALLOW_SECURE_DIRECTORY_ACCESS | + zRR_CANT_DELETE_WHILE_OPEN; - if (uiAccess & (FLM_IO_RDONLY | FLM_IO_RDWR)) + if (uiIoFlags & (FLM_IO_RDONLY | FLM_IO_RDWR)) { lFlags |= zRR_READ_ACCESS; } - if (uiAccess & FLM_IO_RDWR) + if (uiIoFlags & FLM_IO_RDWR) { lFlags |= zRR_WRITE_ACCESS; } - if (uiAccess & FLM_IO_SH_DENYRW) + if (uiIoFlags & FLM_IO_SH_DENYRW) { lFlags |= zRR_DENY_READ; } - if (uiAccess & (FLM_IO_SH_DENYWR | FLM_IO_SH_DENYRW)) + if (uiIoFlags & (FLM_IO_SH_DENYWR | FLM_IO_SH_DENYRW)) { lFlags |= zRR_DENY_WRITE; } @@ -1004,27 +994,27 @@ Desc: Map flaim I/O flags to NetWare I/O flags ****************************************************************************/ #if defined( FLM_RING_ZERO_NLM) LONG f_getNWOpenFlags( - FLMUINT uiAccess, + FLMUINT uiIoFlags, FLMBOOL bDoDirectIo) { LONG lFlags = 0; - if (uiAccess & (FLM_IO_RDONLY | FLM_IO_RDWR)) + if (uiIoFlags & (FLM_IO_RDONLY | FLM_IO_RDWR)) { lFlags |= READ_ACCESS_BIT; } - if (uiAccess & FLM_IO_RDWR) + if (uiIoFlags & FLM_IO_RDWR) { lFlags |= WRITE_ACCESS_BIT; } - if (uiAccess & FLM_IO_SH_DENYRW ) + if (uiIoFlags & FLM_IO_SH_DENYRW ) { lFlags |= DENY_READ_BIT; } - if (uiAccess & (FLM_IO_SH_DENYWR | FLM_IO_SH_DENYRW)) + if (uiIoFlags & (FLM_IO_SH_DENYWR | FLM_IO_SH_DENYRW)) { lFlags |= DENY_WRITE_BIT; } @@ -1034,7 +1024,55 @@ LONG f_getNWOpenFlags( lFlags |= NEVER_READ_AHEAD_BIT; } - return( lFlags ); + return( lFlags); +} +#endif + +/**************************************************************************** +Desc: Legacy async I/O completion callback +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +FSTATIC void DirectIONoWaitCallBack( + LONG unknownAlwaysZero, + LONG callbackData, + LONG completionCode) +{ + RCODE rc = NE_FLM_OK; + F_FileAsyncClient * pAsyncClient = (F_FileAsyncClient *)callbackData; + + F_UNREFERENCED_PARM( unknownAlwaysZero); + + if( completionCode != DFSNormalCompletion) + { + rc = DfsMapError( completionCode, NE_FLM_DIRECT_WRITING_FILE); + } + + f_assert( pAsyncClient->getBytesToDo()); + pAsyncClient->signalComplete( rc, 0); +} +#endif + +/**************************************************************************** +Desc: NSS async I/O completion callback +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +FSTATIC void nssDioCallback( + FLMUINT reserved, + FLMUINT callbackData, + FLMUINT completionCode) +{ + RCODE rc = NE_FLM_OK; + F_FileAsyncClient * pAsyncClient = (F_FileAsyncClient *)callbackData; + + F_UNREFERENCED_PARM( reserved); + + if( completionCode != zOK) + { + rc = MapNSSError( completionCode, NE_FLM_DIRECT_WRITING_FILE); + } + + f_assert( pAsyncClient->getBytesToDo()); + pAsyncClient->signalComplete( rc, 0); } #endif @@ -1044,21 +1082,12 @@ Desc: Default Constructor for F_FileHdl class #if defined( FLM_RING_ZERO_NLM) F_FileHdl::F_FileHdl() { - m_bFileOpened = FALSE; - m_bDeleteOnClose = FALSE; - m_bOpenedExclusive = FALSE; - m_bOpenedReadOnly = FALSE; + initCommonData(); m_lFileHandle = -1; m_lOpenAttr = 0; - m_uiCurrentPos = 0; m_lVolumeID = F_NW_DEFAULT_VOLUME_NUMBER; m_bDoSuballocation = FALSE; m_lLNamePathCount = 0; - m_pszIoPath = NULL; - m_uiExtendSize = 0; - m_uiMaxFileSize = f_getMaxFileSize(); - m_uiMaxAutoExtendSize = m_uiMaxFileSize; - m_bDoDirectIO = FALSE; m_lSectorsPerBlock = 0; m_lMaxBlocks = 0; m_NssKey = 0; @@ -1077,6 +1106,8 @@ F_FileHdl::~F_FileHdl( void) { (void)close(); } + + freeCommonData(); } #endif @@ -1086,7 +1117,7 @@ Desc: Open or create a file. #if defined( FLM_RING_ZERO_NLM) RCODE F_FileHdl::openOrCreate( const char * pFileName, - FLMUINT uiAccess, + FLMUINT uiIoFlags, FLMBOOL bCreateFlag) { RCODE rc = NE_FLM_OK; @@ -1094,86 +1125,55 @@ RCODE F_FileHdl::openOrCreate( void * unused2; char * pszQualifiedPath = NULL; LONG lErrorCode; - FLMBYTE * pTmpLNamePath; - char * pSaveFileName; FLMBYTE * pLNamePath; LONG * plLNamePathCount; - LONG LNamePathCount; struct VolumeInformationStructure * pVolumeInfo; char * pszTemp; char * pIoDirPath; FLMBOOL bNssVolume = FALSE; + FLMBOOL bDoDirectIO; + FLMBOOL bUsingAsync = FALSE; IF_FileSystem * pFileSystem = f_getFileSysPtr(); - m_bDoDirectIO = (uiAccess & FLM_IO_DIRECT) ? TRUE : FALSE; - - if( uiAccess & FLM_IO_DELETE_ON_RELEASE) + bDoDirectIO = (uiIoFlags & FLM_IO_DIRECT) ? TRUE : FALSE; + + if( bDoDirectIO) { - if( !m_pszIoPath) - { - if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszIoPath))) - { - goto Exit; - } - } - - f_strcpy( m_pszIoPath, pFileName); - m_bDeleteOnClose = TRUE; + bUsingAsync = TRUE; } - else + + // Save the file path + + if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) { - m_bDeleteOnClose = FALSE; + goto Exit; } - - if (RC_BAD( rc = f_alloc( - (FLMUINT)(F_PATH_MAX_SIZE + - F_PATH_MAX_SIZE + - F_PATH_MAX_SIZE + - F_PATH_MAX_SIZE + - sizeof( struct VolumeInformationStructure) + - F_PATH_MAX_SIZE), - &pszQualifiedPath))) + + f_strcpy( m_pszFileName, pFileName); + + // Allocate other temporary buffers + + if( RC_BAD( rc = f_alloc( (FLMUINT)(F_PATH_MAX_SIZE + F_PATH_MAX_SIZE + + F_PATH_MAX_SIZE + sizeof( struct VolumeInformationStructure) + + F_PATH_MAX_SIZE), &pszQualifiedPath))) { goto Exit; } - pTmpLNamePath = (((FLMBYTE *)pszQualifiedPath) + F_PATH_MAX_SIZE); - pSaveFileName = (((char *)pTmpLNamePath) + F_PATH_MAX_SIZE); - pIoDirPath = (((char *)pSaveFileName) + F_PATH_MAX_SIZE); + pIoDirPath = (((char *)pszQualifiedPath) + F_PATH_MAX_SIZE); pVolumeInfo = (struct VolumeInformationStructure *) (((char *)pIoDirPath) + F_PATH_MAX_SIZE); pszTemp = (char *)(((char *)(pVolumeInfo)) + sizeof( struct VolumeInformationStructure)); - - // Save the file name in case we have to create the directory - - if((bCreateFlag) && (uiAccess & FLM_IO_CREATE_DIR)) - { - f_strcpy( pSaveFileName, pFileName); - } - - if( !m_pszIoPath) - { - pLNamePath = pTmpLNamePath; - plLNamePathCount = &LNamePathCount; - } - else - { - pLNamePath = (FLMBYTE *)m_pszIoPath; - plLNamePathCount = &m_lLNamePathCount; - } + pLNamePath = (FLMBYTE *)m_pszFileName; + plLNamePathCount = &m_lLNamePathCount; ConvertToQualifiedNWPath( pFileName, pszQualifiedPath); - lErrorCode = ConvertPathToLNameFormat( - pszQualifiedPath, - &m_lVolumeID, - &bNssVolume, - pLNamePath, - plLNamePathCount); - if( lErrorCode != 0) + if( (lErrorCode = ConvertPathToLNameFormat( pszQualifiedPath, &m_lVolumeID, + &bNssVolume, pLNamePath, plLNamePathCount)) != 0) { rc = f_mapPlatformError( lErrorCode, NE_FLM_PARSING_FILE_NAME); goto Exit; @@ -1181,44 +1181,50 @@ RCODE F_FileHdl::openOrCreate( // Determine if the volume is NSS or not - if (gv_bNSSKeyInitialized && bNssVolume) + if( gv_bNSSKeyInitialized) { - m_bNSS = TRUE; + if( bNssVolume) + { + m_bNSS = TRUE; + } } - if ( m_bDoDirectIO ) + if( bDoDirectIO) { - if (!m_bNSS) + if( !m_bNSS) { - lErrorCode = - ReturnVolumeMappingInformation( m_lVolumeID, pVolumeInfo); - if (lErrorCode != 0) + if( (lErrorCode = ReturnVolumeMappingInformation( + m_lVolumeID, pVolumeInfo)) != 0) { rc = DfsMapError( lErrorCode, NE_FLM_INITIALIZING_IO_SYSTEM); goto Exit; } - m_lSectorsPerBlock = (LONG)(pVolumeInfo->VolumeAllocationUnitSizeInBytes / - FLM_NLM_SECTOR_SIZE); - m_lMaxBlocks = (LONG)(m_uiMaxFileSize / + m_lSectorsPerBlock = + (LONG)(pVolumeInfo->VolumeAllocationUnitSizeInBytes / + FLM_NLM_SECTOR_SIZE); + m_lMaxBlocks = (LONG)(f_getMaxFileSize() / (FLMUINT)pVolumeInfo->VolumeAllocationUnitSizeInBytes); } else { - m_lMaxBlocks = (LONG)(m_uiMaxFileSize / (FLMUINT)65536); + m_lMaxBlocks = (LONG)(f_getMaxFileSize() / (FLMUINT)65536); } } + m_uiBytesPerSector = FLM_NLM_SECTOR_SIZE; + m_ui64NotOnSectorBoundMask = m_uiBytesPerSector - 1; + m_ui64GetSectorBoundMask = ~m_ui64NotOnSectorBoundMask; + // Set up the file characteristics requested by caller. - if (bCreateFlag) + if( bCreateFlag) { - // File is to be created - if (f_netwareTestIfFileExists( pszQualifiedPath ) == NE_FLM_OK) + if( f_netwareTestIfFileExists( pszQualifiedPath ) == NE_FLM_OK) { - if (uiAccess & FLM_IO_EXCL) + if( uiIoFlags & FLM_IO_EXCL) { rc = RC_SET( NE_FLM_IO_ACCESS_DENIED); goto Exit; @@ -1230,11 +1236,11 @@ RCODE F_FileHdl::openOrCreate( // Try to create or open the file - if (m_bNSS) + if( m_bNSS) { FLMINT lStatus; - if (bCreateFlag) + if( bCreateFlag) { FLMUINT64 qFileAttr; @@ -1246,22 +1252,22 @@ RCODE F_FileHdl::openOrCreate( Retry_NSS_Create: - m_lOpenAttr = f_getNSSOpenFlags( uiAccess, m_bDoDirectIO); - if ((lStatus = gv_zCreateFunc( gv_NssRootKey, 1, 0, + m_lOpenAttr = f_getNSSOpenFlags( uiIoFlags, bDoDirectIO); + if( (lStatus = gv_zCreateFunc( gv_NssRootKey, 1, 0, zNSPACE_LONG | zMODE_UTF8, pszQualifiedPath, zFILE_REGULAR, qFileAttr, zCREATE_DELETE_IF_THERE, (FLMUINT)m_lOpenAttr, &m_NssKey)) != zOK) { - if (uiAccess & FLM_IO_CREATE_DIR) + if( uiIoFlags & FLM_IO_CREATE_DIR) { - uiAccess &= ~FLM_IO_CREATE_DIR; + uiIoFlags &= ~FLM_IO_CREATE_DIR; // Remove the file name for which we are creating the directory. - if( pFileSystem->pathReduce( pSaveFileName, + if( pFileSystem->pathReduce( m_pszFileName, pIoDirPath, pszTemp) == NE_FLM_OK) { - if (RC_OK( pFileSystem->createDir( pIoDirPath))) + if( RC_OK( pFileSystem->createDir( pIoDirPath))) { goto Retry_NSS_Create; } @@ -1269,27 +1275,30 @@ Retry_NSS_Create: } rc = MapNSSError( lStatus, - (RCODE)(m_bDoDirectIO + (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_CREATING_FILE : (RCODE)NE_FLM_CREATING_FILE)); goto Exit; } + + m_bNSSFileOpen = TRUE; } else { - m_lOpenAttr = f_getNSSOpenFlags( uiAccess, m_bDoDirectIO); - if ((lStatus = gv_zOpenFunc( gv_NssRootKey, 1, + m_lOpenAttr = f_getNSSOpenFlags( uiIoFlags, bDoDirectIO); + if( (lStatus = gv_zOpenFunc( gv_NssRootKey, 1, zNSPACE_LONG | zMODE_UTF8, pszQualifiedPath, (FLMUINT)m_lOpenAttr, &m_NssKey)) != zOK) { rc = MapNSSError( lStatus, - (RCODE)(m_bDoDirectIO + (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_OPENING_FILE : (RCODE)NE_FLM_OPENING_FILE)); goto Exit; } + + m_bNSSFileOpen = TRUE; } - m_bNSSFileOpen = TRUE; } else { @@ -1302,18 +1311,18 @@ Retry_NSS_Create: IMMEDIATE_PURGE_BIT); Retry_Create: + lErrorCode = CreateFile( 0, 1, m_lVolumeID, 0, (BYTE *)pLNamePath, *plLNamePathCount, LONGNameSpace, m_lOpenAttr, 0xff, - PrimaryDataStream, &m_lFileHandle, &unused, &unused2 - ); + PrimaryDataStream, &m_lFileHandle, &unused, &unused2); - if ((lErrorCode != 0) && (uiAccess & FLM_IO_CREATE_DIR)) + if( lErrorCode != 0 && (uiIoFlags & FLM_IO_CREATE_DIR)) { - uiAccess &= ~FLM_IO_CREATE_DIR; + uiIoFlags &= ~FLM_IO_CREATE_DIR; // Remove the file name for which we are creating the directory - if( pFileSystem->pathReduce( pSaveFileName, + if( pFileSystem->pathReduce( m_pszFileName, pIoDirPath, pszTemp) == NE_FLM_OK) { if( RC_OK( pFileSystem->createDir( pIoDirPath))) @@ -1334,7 +1343,7 @@ Retry_Create: } else { - m_lOpenAttr = f_getNWOpenFlags(uiAccess, m_bDoDirectIO); + m_lOpenAttr = f_getNWOpenFlags(uiIoFlags, bDoDirectIO); lErrorCode = OpenFile( 0, 1, m_lVolumeID, 0, (BYTE *)pLNamePath, *plLNamePathCount, LONGNameSpace, 0, m_lOpenAttr, PrimaryDataStream, &m_lFileHandle, &unused, &unused2); @@ -1351,20 +1360,20 @@ Retry_Create: // Check if the file operation was successful - if ( lErrorCode != 0) + if( lErrorCode != 0) { rc = f_mapPlatformError( lErrorCode, (RCODE)(bCreateFlag - ? (RCODE)(m_bDoDirectIO + ? (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_CREATING_FILE : (RCODE)NE_FLM_CREATING_FILE) - : (RCODE)(m_bDoDirectIO + : (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_OPENING_FILE : (RCODE)NE_FLM_OPENING_FILE))); goto Exit; } - if (bCreateFlag) + if( bCreateFlag) { // Revoke the file handle rights and close the file // (signified by passing 2 for the QueryFlag parameter). @@ -1384,20 +1393,21 @@ Retry_Create: { lErrorCode = CloseFile( 0, 1, m_lFileHandle); } + m_lOpenAttr = 0; - if ( lErrorCode != 0 ) + if( lErrorCode != 0) { rc = f_mapPlatformError(lErrorCode, NE_FLM_CLOSING_FILE); goto Exit; } - m_lOpenAttr = f_getNWOpenFlags(uiAccess, m_bDoDirectIO); + m_lOpenAttr = f_getNWOpenFlags(uiIoFlags, bDoDirectIO); lErrorCode = OpenFile( 0, 1, m_lVolumeID, 0, (BYTE *)pLNamePath, *plLNamePathCount, LONGNameSpace, 0, m_lOpenAttr, PrimaryDataStream, &m_lFileHandle, &unused, &unused2); - if ( lErrorCode != 0 ) + if( lErrorCode != 0) { // Too many error codes map to 255, so we put in a special // case check here. @@ -1409,7 +1419,7 @@ Retry_Create: else { rc = f_mapPlatformError( lErrorCode, - (RCODE)(m_bDoDirectIO + (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_OPENING_FILE : (RCODE)NE_FLM_OPENING_FILE)); } @@ -1417,12 +1427,12 @@ Retry_Create: } } - if ( m_bDoDirectIO) + if( bDoDirectIO) { lErrorCode = SwitchToDirectFileMode(0, m_lFileHandle); - if (lErrorCode != 0) + if( lErrorCode != 0) { - if (RevokeFileHandleRights( 0, 1, + if( RevokeFileHandleRights( 0, 1, m_lFileHandle, 2, m_lOpenAttr & 0x0000000F, &unused) == 0xFF) { (void)CloseFile( 0, 1, m_lFileHandle); @@ -1436,196 +1446,53 @@ Retry_Create: } } -Exit: - - if (RC_BAD( rc)) + if( uiIoFlags & FLM_IO_DELETE_ON_RELEASE) { - m_lFileHandle = -1; - m_lOpenAttr = 0; - m_bNSSFileOpen = FALSE; + m_bDeleteOnRelease = TRUE; + } + else + { + m_bDeleteOnRelease = FALSE; } - if (pszQualifiedPath) + // Allocate at least 64K - this will handle most read and write + // operations and will also be a multiple of the sector size most of + // the time. The calculation below rounds it up to the next sector + // boundary if it is not already on one. + + m_uiAlignedBuffSize = 64 * 1024; + if( bDoDirectIO) + { + m_uiAlignedBuffSize = (FLMUINT)roundToNextSector( m_uiAlignedBuffSize); + } + + if( RC_BAD( rc = f_allocAlignedBuffer( m_uiAlignedBuffSize, + &m_pucAlignedBuff))) + { + goto Exit; + } + + m_bFileOpened = TRUE; + m_bDoDirectIO = bDoDirectIO; + m_bOpenedInAsyncMode = bUsingAsync; + m_ui64CurrentPos = 0; + m_bOpenedReadOnly = (uiIoFlags & FLM_IO_RDONLY) ? TRUE : FALSE; + m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; + f_atomicInc( &gv_openFiles); + +Exit: + + if( RC_BAD( rc)) + { + close(); + } + + if( pszQualifiedPath) { f_free( &pszQualifiedPath); } - return( rc ); -} -#endif - -/**************************************************************************** -Desc: Create a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::create( - const char * pIoPath, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - - flmAssert( m_bFileOpened == FALSE); - - if( RC_BAD( rc = openOrCreate( pIoPath, uiIoFlags, TRUE))) - { - goto Exit; - } - - m_bFileOpened = TRUE; - m_uiCurrentPos = 0; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::createUnique( - char * pIoPath, - const char * pszFileExtension, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - char * pszTmp; - FLMBOOL bModext = TRUE; - FLMUINT uiBaseTime = 0; - FLMBYTE ucHighByte = 0; - char ucFileName[ F_FILENAME_SIZE]; - char szDirPath[ F_PATH_MAX_SIZE]; - char szTmpPath[ F_PATH_MAX_SIZE]; - FLMUINT uiCount; - IF_FileSystem * pFileSystem = f_getFileSysPtr(); - - f_memset( ucFileName, 0, sizeof( ucFileName)); - - flmAssert( m_bFileOpened == FALSE); - - f_strcpy( szDirPath, pIoPath); - - // Search backwards replacing trailing spaces with NULLs. - - pszTmp = szDirPath; - pszTmp += (f_strlen( pszTmp) - 1); - while ((*pszTmp == 0x20) && pszTmp >= szDirPath) - { - *pszTmp = 0; - pszTmp--; - } - - // Append a backslash if one isn't already there - - if (pszTmp >= szDirPath && *pszTmp != '\\') - { - pszTmp++; - *pszTmp++ = '\\'; - } - else - { - pszTmp++; - } - *pszTmp = 0; - - if ((pszFileExtension) && (f_strlen( pszFileExtension) >= 3)) - { - bModext = FALSE; - } - - uiCount = 0; - do - { - pFileSystem->pathCreateUniqueName( &uiBaseTime, ucFileName, - pszFileExtension, &ucHighByte, bModext); - - f_strcpy( szTmpPath, szDirPath); - pFileSystem->pathAppend( szTmpPath, ucFileName); - - rc = create( szTmpPath, uiIoFlags | FLM_IO_EXCL); - - if (rc == NE_FLM_IO_DISK_FULL) - { - (void)f_netwareDeleteFile( szTmpPath); - goto Exit; - } - - if ((rc == NE_FLM_IO_PATH_NOT_FOUND) || (rc == NE_FLM_IO_INVALID_PASSWORD)) - { - goto Exit; - } - } while ((rc != NE_FLM_OK) && (uiCount++ < 10)); - - // Check if the path was created - - if ((uiCount >= 10) && (rc != NE_FLM_OK)) - { - rc = RC_SET( NE_FLM_IO_PATH_CREATE_FAILURE); - goto Exit; - } - - m_bFileOpened = TRUE; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - - // Created file name needs to be returned. - - f_strcpy( pIoPath, szTmpPath); - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Open a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::open( - const char * pIoPath, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiStartTime; - FLMUINT ui15Secs; - FLMUINT uiCurrTime; - - flmAssert( m_bFileOpened == FALSE); - - ui15Secs = FLM_SECS_TO_TIMER_UNITS( 15); - uiStartTime = FLM_GET_TIMER(); - - do - { - if( RC_OK( rc = openOrCreate( pIoPath, uiIoFlags, FALSE))) - { - break; - } - - if( rc != NE_FLM_IO_TOO_MANY_OPEN_FILES) - { - goto Exit; - } - - f_sleep( 50); - uiCurrTime = FLM_GET_TIMER(); - } while( FLM_ELAPSED_TIME( uiCurrTime, uiStartTime) < ui15Secs); - - if ( RC_BAD(rc) ) - { - goto Exit; - } - - m_bFileOpened = TRUE; - m_uiCurrentPos = 0; - m_bOpenedReadOnly = (uiIoFlags & FLM_IO_RDONLY) ? TRUE : FALSE; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - -Exit: - - return( rc); + return( rc); } #endif @@ -1633,27 +1500,20 @@ Exit: Desc: Close a file ****************************************************************************/ #if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::close() +RCODE FLMAPI F_FileHdl::close( void) { - LONG unused; - FLMBOOL bDeleteAllowed = TRUE; - RCODE rc = NE_FLM_OK; - - if( !m_bFileOpened) + if( m_bNSS) { - goto Exit; - } - - if (m_bNSS) - { - if (m_bNSSFileOpen) + if( m_bNSSFileOpen) { (void)gv_zCloseFunc( m_NssKey); m_bNSSFileOpen = FALSE; } } - else + else if( m_lFileHandle != -1) { + LONG unused; + // Revoke the file handle rights and close the file // (signified by passing 2 for the QueryFlag parameter). // If this call fails and returns a 255 error, it may @@ -1672,563 +1532,47 @@ RCODE FLMAPI F_FileHdl::close() { (void)CloseFile( 0, 1, m_lFileHandle); } + + m_lFileHandle = -1; } - m_lOpenAttr = 0; - m_lFileHandle = -1; - m_bFileOpened = m_bOpenedReadOnly = m_bOpenedExclusive = FALSE; - - if( m_bDeleteOnClose) + if( m_bDeleteOnRelease) { - if( bDeleteAllowed) + if( m_bNSS) { - if (m_bNSS) - { - (void)gv_zDeleteFunc( gv_NssRootKey, 0, zNSPACE_LONG | zMODE_UTF8, - m_pszIoPath, zMATCH_ALL, 0); - } - else - { - (void)EraseFile( 0, 1, m_lVolumeID, 0, (BYTE *)m_pszIoPath, - m_lLNamePathCount, LONGNameSpace, 0); - } + (void)gv_zDeleteFunc( gv_NssRootKey, 0, zNSPACE_LONG | zMODE_UTF8, + m_pszFileName, zMATCH_ALL, 0); + } + else + { + (void)EraseFile( 0, 1, m_lVolumeID, 0, (BYTE *)m_pszFileName, + m_lLNamePathCount, LONGNameSpace, 0); } - m_bDeleteOnClose = FALSE; + m_bDeleteOnRelease = FALSE; m_lLNamePathCount = 0; } - - if( m_pszIoPath) - { - f_free( &m_pszIoPath); - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Read from a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::read( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - - if ( m_bDoDirectIO) - { - if( RC_BAD( rc = _directIORead( (FLMUINT)ui64Offset, uiLength, - pvBuffer, puiBytesRead))) - { - goto Exit; - } - } - else - { - if( RC_BAD( rc = _read( (FLMUINT)ui64Offset, uiLength, - pvBuffer, puiBytesRead))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Read from a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_read( - FLMUINT uiReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - FCBType * fcb; - LONG lBytesRead; - LONG lErr; - flmAssert( m_bFileOpened == TRUE); - - if( puiBytesReadRV) + if( m_bFileOpened) { - *puiBytesReadRV = 0; + f_atomicDec( &gv_openFiles); } + + freeCommonData(); - if (uiReadOffset == FLM_IO_CURRENT_POS) - uiReadOffset = m_uiCurrentPos; + m_bFileOpened = FALSE; + m_ui64CurrentPos = 0; + m_bOpenedReadOnly = FALSE; + m_bOpenedExclusive = FALSE; + m_bDoDirectIO = FALSE; + m_bOpenedInAsyncMode = FALSE; + m_lOpenAttr = 0; + m_lFileHandle = -1; - if (m_bNSS) - { - FLMINT lStatus; - FLMUINT nBytesRead; - - if ((lStatus = gv_zReadFunc( m_NssKey, 0, (FLMUINT64)uiReadOffset, - (FLMUINT)uiBytesToRead, pvBuffer, - &nBytesRead)) != zOK) - { - rc = MapNSSError( lStatus, NE_FLM_READING_FILE); - goto Exit; - } - - if( puiBytesReadRV) - { - *puiBytesReadRV = (FLMUINT)nBytesRead; - } - - if ((FLMUINT)nBytesRead < uiBytesToRead) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - } - m_uiCurrentPos = uiReadOffset + (FLMUINT)nBytesRead; - } - else - { - lErr = MapFileHandleToFCB( m_lFileHandle, &fcb ); - if ( lErr != 0 ) - { - rc = f_mapPlatformError( lErr, NE_FLM_SETTING_UP_FOR_READ); - goto Exit; - } - lErr = ReadFile( fcb->Station, m_lFileHandle, uiReadOffset, - uiBytesToRead, &lBytesRead, pvBuffer); - if ( lErr == 0 ) - { - if( puiBytesReadRV) - { - *puiBytesReadRV = (FLMUINT) lBytesRead; - } - - if (lBytesRead < (LONG)uiBytesToRead) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - } - m_uiCurrentPos = uiReadOffset + lBytesRead; - } - else - { - rc = f_mapPlatformError(lErr, NE_FLM_READING_FILE); - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Returns m_uiCurrentPos -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::tell( - FLMUINT64 * pui64Offset) -{ - *pui64Offset = m_uiCurrentPos; return( NE_FLM_OK); } #endif -/**************************************************************************** -Desc: Calls the Direct IO-style read routine -Note: Where possible, the caller should attempt to read on sector - boundaries and full sectors. This routine will do the - necessary work if this is not done, but it will be less - efficient. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_directIORead( - FLMUINT uiReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer; - LONG lStartSector; - LONG lSectorCount; - LONG lResult; - BYTE ucSectorBuf [FLM_NLM_SECTOR_SIZE]; - FLMUINT uiBytesToCopy; - FLMUINT uiSectorOffset; - FLMUINT uiTotal; - FLMINT lStatus; - - flmAssert( m_bFileOpened == TRUE); - - if( puiBytesReadRV) - { - *puiBytesReadRV = 0; - } - - if (uiReadOffset == FLM_IO_CURRENT_POS) - uiReadOffset = m_uiCurrentPos; - - // Calculate the starting sector. - - lStartSector = uiReadOffset / FLM_NLM_SECTOR_SIZE; - - // See if the offset is on a sector boundary. If not, we must read - // into the local sector buffer and then copy into the buffer. - // We must also read into the local buffer if our read size is less - // than the sector size. - - if ((uiReadOffset % FLM_NLM_SECTOR_SIZE != 0) || - (uiBytesToRead < FLM_NLM_SECTOR_SIZE)) - { - if (m_bNSS) - { - if ((lStatus = gv_zDIOReadFunc( m_NssKey, - (FLMUINT64)lStartSector, 1, - (FLMUINT)0, NULL, ucSectorBuf)) != zOK) - { - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - else - { - lResult = DirectReadFile( - 0, - m_lFileHandle, - lStartSector, - 1, - ucSectorBuf - ); - if (lResult != 0) - { - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - - // Copy the part of the sector that was requested into the buffer. - - uiSectorOffset = uiReadOffset % FLM_NLM_SECTOR_SIZE; - - if ((uiBytesToCopy = uiBytesToRead) > FLM_NLM_SECTOR_SIZE - uiSectorOffset) - uiBytesToCopy = FLM_NLM_SECTOR_SIZE - uiSectorOffset; - f_memcpy( pucBuffer, &ucSectorBuf [uiSectorOffset], uiBytesToCopy); - pucBuffer += uiBytesToCopy; - uiBytesToRead -= (FLMUINT)uiBytesToCopy; - m_uiCurrentPos += (FLMUINT)uiBytesToCopy; - - if( puiBytesReadRV) - { - (*puiBytesReadRV) += (FLMUINT)uiBytesToCopy; - } - - // See if we got everything we wanted to with this read. - - if (!uiBytesToRead) - goto Exit; - - // Go to the next sector boundary - - lStartSector++; - } - - // At this point, we are poised to read on a sector boundary. See if we - // have at least one full sector to read. If so, we can read it directly - // into the provided buffer. If not, we must use the temporary sector - // buffer. - - if (uiBytesToRead >= FLM_NLM_SECTOR_SIZE) - { - lSectorCount = (LONG)(uiBytesToRead / FLM_NLM_SECTOR_SIZE); -Try_Read: - if (m_bNSS) - { - if ((lStatus = gv_zDIOReadFunc( m_NssKey, - (FLMUINT64)lStartSector, - (FLMUINT)lSectorCount, - (FLMUINT)0, NULL, pucBuffer)) != zOK) - { - if ((lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) && - (lSectorCount > 1)) - { - - // See if we can read one less sector. We will return - // NE_FLM_IO_END_OF_FILE in this case. - - lSectorCount--; - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Try_Read; - } - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - else - { - lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, - lSectorCount, pucBuffer); - - if (lResult != 0) - { - if ((lResult == DFSOperationBeyondEndOfFile) && - (lSectorCount > 1)) - { - - // See if we can read one less sector. We will return - // NE_FLM_IO_END_OF_FILE in this case. - - lSectorCount--; - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Try_Read; - } - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - - uiTotal = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); - pucBuffer += uiTotal; - m_uiCurrentPos += uiTotal; - - if( puiBytesReadRV) - { - (*puiBytesReadRV) += uiTotal; - } - uiBytesToRead -= uiTotal; - - // See if we got everything we wanted to or could with this read. - - if ((!uiBytesToRead) || (rc == NE_FLM_IO_END_OF_FILE)) - goto Exit; - - // Go to the next sector after the ones we just read - - lStartSector += lSectorCount; - } - - // At this point, we have less than a sector's worth to read, so we must - // read it into a local buffer. - - if (m_bNSS) - { - if ((lStatus = gv_zDIOReadFunc( m_NssKey, - (FLMUINT64)lStartSector, 1, - (FLMUINT)0, NULL, ucSectorBuf)) != zOK) - { - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - else - { - lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, 1, ucSectorBuf); - if (lResult != 0) - { - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - - // Copy the part of the sector that was requested into the buffer. - - m_uiCurrentPos += uiBytesToRead; - - if( puiBytesReadRV) - { - (*puiBytesReadRV) += uiBytesToRead; - } - - f_memcpy( pucBuffer, ucSectorBuf, uiBytesToRead); - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Might call the direct IO routine in the future -Note: This function assumes that the pvBuffer that is passed in is - a multiple of a sector size (512 bytes). -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - - if( m_bDoDirectIO) - { - if( RC_BAD( rc = _directIOSectorRead( (FLMUINT)ui64ReadOffset, - uiBytesToRead, pvBuffer, puiBytesReadRV))) - { - goto Exit; - } - } - else - { - if( RC_BAD( rc = _read( (FLMUINT)ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesReadRV))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Calls the direct IO Read routine -Note: This function assumes that the pvBuffer that is passed in is - a multiple of a sector size (512 bytes). -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_directIOSectorRead( - FLMUINT uiReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - LONG lStartSector; - LONG lSectorCount; - LONG lResult; - FLMINT lStatus; - - flmAssert( m_bFileOpened == TRUE); - - if (uiReadOffset == FLM_IO_CURRENT_POS) - uiReadOffset = m_uiCurrentPos; - - if (uiReadOffset % FLM_NLM_SECTOR_SIZE != 0) - { - rc = _read( uiReadOffset, uiBytesToRead, pvBuffer, puiBytesReadRV); - goto Exit; - } - - // Calculate the starting sector - - lStartSector = uiReadOffset / FLM_NLM_SECTOR_SIZE; - lSectorCount = (LONG)(uiBytesToRead / FLM_NLM_SECTOR_SIZE); - if (uiBytesToRead % FLM_NLM_SECTOR_SIZE != 0) - lSectorCount++; - -Try_Read: - - if (m_bNSS) - { - if ((lStatus = gv_zDIOReadFunc( m_NssKey, - (FLMUINT64)lStartSector, - (FLMUINT)lSectorCount, - (FLMUINT)0, NULL, pvBuffer)) != zOK) - { - if ((lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) && - (lSectorCount > 1)) - { - - // See if we can read one less sector. We will return - // NE_FLM_IO_END_OF_FILE in this case. - - lSectorCount--; - uiBytesToRead = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Try_Read; - } - uiBytesToRead = 0; - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - else - { - lResult = DirectReadFile( 0, m_lFileHandle, - lStartSector, lSectorCount,(BYTE *)pvBuffer); - if (lResult != 0) - { - if ((lResult == DFSOperationBeyondEndOfFile) && - (lSectorCount > 1)) - { - // See if we can read one less sector. We will return - // NE_FLM_IO_END_OF_FILE in this case. - - lSectorCount--; - uiBytesToRead = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Try_Read; - } - uiBytesToRead = 0; - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - m_uiCurrentPos += uiBytesToRead; - -Exit: - - if( puiBytesReadRV) - { - *puiBytesReadRV = uiBytesToRead; - } - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Sets current position of file. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset) -{ - RCODE rc = NE_FLM_OK; - - switch (iWhence) - { - case FLM_IO_SEEK_CUR: - m_uiCurrentPos += (FLMUINT)ui64Offset; - break; - - case FLM_IO_SEEK_SET: - m_uiCurrentPos = (FLMUINT)ui64Offset; - break; - - case FLM_IO_SEEK_END: - if( RC_BAD( rc = size( &ui64Offset))) - { - goto Exit; - } - m_uiCurrentPos = (FLMUINT)ui64Offset; - break; - - default: - rc = RC_SET( NE_FLM_NOT_IMPLEMENTED); - goto Exit; - } - - *pui64NewOffset = m_uiCurrentPos; - -Exit: - - return( rc); -} -#endif - /**************************************************************************** Desc: Return the size of the file ****************************************************************************/ @@ -2240,12 +1584,12 @@ RCODE FLMAPI F_FileHdl::size( LONG lErr; LONG lSize; - if (m_bNSS) + if( m_bNSS) { FLMINT lStatus; zInfo_s Info; - if ((lStatus = gv_zGetInfoFunc( m_NssKey, + if( (lStatus = gv_zGetInfoFunc( m_NssKey, zGET_STORAGE_USED, sizeof( Info), zINFO_VERSION_A, &Info)) != zOK) @@ -2253,16 +1597,17 @@ RCODE FLMAPI F_FileHdl::size( rc = MapNSSError( lStatus, NE_FLM_GETTING_FILE_INFO); goto Exit; } - flmAssert( Info.infoVersion == zINFO_VERSION_A); + + f_assert( Info.infoVersion == zINFO_VERSION_A); *pui64Size = (FLMUINT64)Info.std.logicalEOF; } else { - lErr = GetFileSize( 0, m_lFileHandle, &lSize); - if ( lErr != 0 ) + if( (lErr = GetFileSize( 0, m_lFileHandle, &lSize)) != 0) { rc = f_mapPlatformError( lErr, NE_FLM_GETTING_FILE_SIZE); } + *pui64Size = (FLMUINT64)lSize; } @@ -2284,13 +1629,13 @@ RCODE FLMAPI F_FileHdl::truncate( RCODE rc = NE_FLM_OK; LONG lErr; - flmAssert( m_bFileOpened == TRUE); + f_assert( m_bFileOpened); - if (m_bNSS) + if( m_bNSS) { FLMINT lStatus; - if ((lStatus = gv_zSetEOFFunc( m_NssKey, 0, ui64Size, + if( (lStatus = gv_zSetEOFFunc( m_NssKey, 0, ui64Size, zSETSIZE_NON_SPARSE_FILE | zSETSIZE_NO_ZERO_FILL | zSETSIZE_UNDO_ON_ERR)) != zOK) @@ -2301,16 +1646,16 @@ RCODE FLMAPI F_FileHdl::truncate( } else { - if ((lErr = SetFileSize( 0, m_lFileHandle, (FLMUINT)ui64Size, TRUE)) != 0) + if( (lErr = SetFileSize( 0, m_lFileHandle, (FLMUINT)ui64Size, TRUE)) != 0) { rc = f_mapPlatformError( lErr, NE_FLM_TRUNCATING_FILE); goto Exit; } } - if (m_uiCurrentPos > ui64Size) + if( m_ui64CurrentPos > ui64Size) { - m_uiCurrentPos = (FLMUINT)ui64Size; + m_ui64CurrentPos = ui64Size; } Exit: @@ -2319,348 +1664,13 @@ Exit: } #endif -/**************************************************************************** -Desc: Write to a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::write( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - const void * pvBuffer, - FLMUINT * puiBytesWritten) -{ - RCODE rc = NE_FLM_OK; - - if( m_bDoDirectIO) - { - if( RC_BAD( rc = _directIOWrite( (FLMUINT)ui64Offset, uiLength, - pvBuffer, puiBytesWritten))) - { - goto Exit; - } - } - else - { - if( RC_BAD( rc = _write( (FLMUINT)ui64Offset, uiLength, - pvBuffer, puiBytesWritten))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Write to a file -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_write( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - LONG lErr; - FCBType * fcb; - - flmAssert( m_bFileOpened == TRUE); - - *puiBytesWrittenRV = 0; - - if (uiWriteOffset == FLM_IO_CURRENT_POS) - { - uiWriteOffset = m_uiCurrentPos; - } - else - { - m_uiCurrentPos = uiWriteOffset; - } - - if( m_bNSS) - { - FLMINT lStatus; - FLMUINT nBytesWritten; - - if( (lStatus = gv_zWriteFunc( m_NssKey, 0, (FLMUINT64)uiWriteOffset, - (FLMUINT)uiBytesToWrite, pvBuffer, &nBytesWritten)) != zOK) - { - rc = MapNSSError( lStatus, NE_FLM_WRITING_FILE); - goto Exit; - } - - if( nBytesWritten != (FLMUINT)uiBytesToWrite) - { - rc = RC_SET( NE_FLM_IO_DISK_FULL); - goto Exit; - } - } - else - { - if( (lErr = MapFileHandleToFCB( m_lFileHandle, &fcb )) != 0) - { - rc = f_mapPlatformError( lErr, NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - - if( (lErr = WriteFile( fcb->Station, m_lFileHandle, uiWriteOffset, - uiBytesToWrite, (void *)pvBuffer)) != 0) - { - rc = f_mapPlatformError( lErr, NE_FLM_WRITING_FILE); - goto Exit; - } - } - - *puiBytesWrittenRV = uiBytesToWrite; - m_uiCurrentPos = uiWriteOffset + uiBytesToWrite; - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Calls the direct IO Write routine. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_directIOWrite( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer; - LONG lStartSector; - LONG lSectorCount; - LONG lResult; - BYTE ucSectorBuf[ FLM_NLM_SECTOR_SIZE]; - FLMUINT uiBytesToCopy; - FLMUINT uiSectorOffset; - FLMUINT uiTotal; - FLMINT lStatus; - - flmAssert( m_bFileOpened == TRUE); - - *puiBytesWrittenRV = 0; - - if( uiWriteOffset == FLM_IO_CURRENT_POS) - { - uiWriteOffset = m_uiCurrentPos; - } - else - { - m_uiCurrentPos = uiWriteOffset; - } - - // Calculate the starting sector - - lStartSector = uiWriteOffset / FLM_NLM_SECTOR_SIZE; - - // See if the offset is on a sector boundary. If not, we must first read - // the sector into memory, overwrite it with data from the input - // buffer and write it back out again. - - if( (uiWriteOffset % FLM_NLM_SECTOR_SIZE != 0) || - (uiBytesToWrite < FLM_NLM_SECTOR_SIZE)) - { - if( m_bNSS) - { - if( (lStatus = gv_zDIOReadFunc( m_NssKey, - (FLMUINT64)lStartSector, - (FLMUINT)1, (FLMUINT)0, NULL, ucSectorBuf)) != zOK) - { - if (lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) - { - f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); - - // Expand the file - - if( RC_BAD( rc = expand( lStartSector, 1))) - { - goto Exit; - } - } - else - { - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - } - else - { - lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, - 1, ucSectorBuf); - - if( lResult == DFSHoleInFileError || - lResult == DFSOperationBeyondEndOfFile ) - { - f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); - - // Expand the file - - if( RC_BAD( rc = expand( lStartSector, 1))) - { - goto Exit; - } - } - else if( lResult != 0) - { - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - - // Copy the part of the buffer that is being written back into - // the sector buffer. - - uiSectorOffset = uiWriteOffset % FLM_NLM_SECTOR_SIZE; - - if( (uiBytesToCopy = uiBytesToWrite) > FLM_NLM_SECTOR_SIZE - uiSectorOffset) - { - uiBytesToCopy = FLM_NLM_SECTOR_SIZE - uiSectorOffset; - } - - f_memcpy( &ucSectorBuf [uiSectorOffset], pucBuffer, uiBytesToCopy); - pucBuffer += uiBytesToCopy; - uiBytesToWrite -= (FLMUINT)uiBytesToCopy; - m_uiCurrentPos += (FLMUINT)uiBytesToCopy; - (*puiBytesWrittenRV) += (FLMUINT)uiBytesToCopy; - - // Write the sector buffer back out - - if( RC_BAD( rc = writeSectors( &ucSectorBuf [0], lStartSector, 1, NULL))) - { - goto Exit; - } - - // See if we wrote everything we wanted to with this write - - if (!uiBytesToWrite) - { - goto Exit; - } - - // Go to the next sector boundary - - lStartSector++; - } - - // At this point, we are poised to write on a sector boundary. See if we - // have at least one full sector to write. If so, we can write it directly - // from the provided buffer. If not, we must use the temporary sector - // buffer. - - if( uiBytesToWrite >= FLM_NLM_SECTOR_SIZE) - { - lSectorCount = (LONG)(uiBytesToWrite / FLM_NLM_SECTOR_SIZE); - - if( RC_BAD( rc = writeSectors( (void *)pucBuffer, lStartSector, - lSectorCount, NULL))) - { - goto Exit; - } - - uiTotal = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); - pucBuffer += uiTotal; - m_uiCurrentPos += uiTotal; - (*puiBytesWrittenRV) += uiTotal; - uiBytesToWrite -= uiTotal; - - // See if we wrote everything we wanted to with this write - - if( !uiBytesToWrite) - { - goto Exit; - } - - // Go to the next sector after the ones we just wrote - - lStartSector += lSectorCount; - } - - // At this point, we have less than a sector's worth to write, so we must - // first read the sector from disk, alter it, and then write it back out. - - if( m_bNSS) - { - if( (lStatus = gv_zDIOReadFunc( m_NssKey, (FLMUINT64)lStartSector, - (FLMUINT)1, (FLMUINT)0, NULL, ucSectorBuf)) != zOK) - { - if( lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) - { - f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); - - // Expand the file - - if( RC_BAD( rc = expand( lStartSector, 1))) - { - goto Exit; - } - } - else - { - rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - } - else - { - lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, - 1, ucSectorBuf); - - if( lResult == DFSHoleInFileError) - { - f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); - - // Expand the file - - if( RC_BAD( rc = expand( lStartSector, 1))) - { - goto Exit; - } - } - else if( lResult != 0) - { - rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); - goto Exit; - } - } - - // Copy the rest of the output buffer into the sector buffer - - f_memcpy( ucSectorBuf, pucBuffer, uiBytesToWrite); - - // Write the sector back to disk - - if( RC_BAD( rc = writeSectors( &ucSectorBuf [0], lStartSector, 1, NULL))) - { - goto Exit; - } - - m_uiCurrentPos += uiBytesToWrite; - (*puiBytesWrittenRV) += uiBytesToWrite; - -Exit: - - return( rc); -} -#endif - /*************************************************************************** Desc: Expand a file for writing. ***************************************************************************/ #if defined( FLM_RING_ZERO_NLM) RCODE F_FileHdl::expand( - LONG lStartSector, - LONG lSectorsToAlloc) + LONG lStartSector, + LONG lSectorsToAlloc) { RCODE rc = NE_FLM_OK; LONG lResult; @@ -2702,7 +1712,7 @@ RCODE F_FileHdl::expand( // Last block number better be greater than or equal to // start block number. - flmAssert( lLastBlockNumber >= lStartBlockNumber); + f_assert( lLastBlockNumber >= lStartBlockNumber); lMinToAlloc = (lLastBlockNumber - lStartBlockNumber) + 1; if( lExtendSize < 5) @@ -2741,7 +1751,7 @@ RCODE F_FileHdl::expand( if( lTotalToAlloc < lMinToAlloc) { - rc = RC_SET( NE_FLM_IO_DISK_FULL); + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); goto Exit; } } @@ -2813,7 +1823,7 @@ RCODE F_FileHdl::expand( } else { - rc = RC_SET( NE_FLM_IO_DISK_FULL); + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); goto Exit; } } @@ -2845,7 +1855,7 @@ RCODE F_FileHdl::expand( continue; } } - else if (lResult != 0) + else if( lResult != 0) { rc = DfsMapError( lResult, NE_FLM_EXPANDING_FILE); goto Exit; @@ -2915,370 +1925,6 @@ Exit: } #endif -/**************************************************************************** -Desc: Calls the direct IO Write routine. Handles both asynchronous writes - and synchronous writes. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::writeSectors( - void * pvBuffer, - LONG lStartSector, - LONG lSectorCount, - IF_IOBuffer * pBufferObj, - FLMBOOL * pbDidAsync) -{ - RCODE rc = NE_FLM_OK; - LONG lResult; - FLMBOOL bAlreadyExpanded = FALSE; - FLMINT lStatus; - FLMBOOL bMadePending; - - // Keep trying write until we succeed or get an error we can't deal with. - // Actually, this will NOT loop forever. At most, it will try twice - - // and then it is only when we get a hole in the file error. - - bMadePending = FALSE; - for (;;) - { - if (m_bNSS) - { - if( pBufferObj) - { - if (!bMadePending) - { - flmAssert( pbDidAsync); - pBufferObj->makePending(); - bMadePending = TRUE; - } - lStatus = gv_zDIOWriteFunc( m_NssKey, - (FLMUINT64)lStartSector, - (FLMUINT)lSectorCount, - (FLMUINT)pBufferObj, - nssDioCallback, - pvBuffer); - } - else - { - lStatus = gv_zDIOWriteFunc( m_NssKey, - (FLMUINT64)lStartSector, - (FLMUINT)lSectorCount, (FLMUINT)0, NULL, pvBuffer); - } - - // We may need to allocate space to do this write - - if (lStatus == zERR_END_OF_FILE || - lStatus == zERR_BEYOND_EOF || - lStatus == zERR_HOLE_IN_DIO_FILE) - { - if (bAlreadyExpanded) - { - flmAssert( 0); - rc = MapNSSError( lStatus, NE_FLM_DIRECT_WRITING_FILE); - goto Exit; - } - - // Expand the file - - if (RC_BAD( rc = expand( lStartSector, lSectorCount))) - { - goto Exit; - } - bAlreadyExpanded = TRUE; - continue; - } - else if (lStatus != 0) - { - rc = MapNSSError( lStatus, NE_FLM_DIRECT_WRITING_FILE); - goto Exit; - } - else - { - if (pBufferObj) - { - *pbDidAsync = TRUE; - } - break; - } - } - else - { - LONG lSize; - FLMBOOL bNeedToWriteEOF; - - // Determine if this write will change the EOF. If so, pre-expand - // the file. - - lResult = GetFileSize( 0, m_lFileHandle, &lSize); - if (lResult != 0) - { - rc = f_mapPlatformError( lResult, NE_FLM_GETTING_FILE_SIZE); - goto Exit; - } - - bNeedToWriteEOF = (lSize < (lStartSector + lSectorCount) * FLM_NLM_SECTOR_SIZE) - ? TRUE - : FALSE; - - if( pBufferObj) - { - if (!bMadePending) - { - flmAssert( pbDidAsync); - pBufferObj->makePending(); - bMadePending = TRUE; - } - - lResult = DirectWriteFileNoWait( 0, m_lFileHandle, - lStartSector,lSectorCount, - (BYTE *)pvBuffer, DirectIONoWaitCallBack, - (LONG)pBufferObj); - } - else - { - lResult = DirectWriteFile( 0, m_lFileHandle, - lStartSector, lSectorCount, (BYTE *)pvBuffer); - } - - // We may need to allocate space to do this write - - if( lResult == DFSHoleInFileError || - lResult == DFSOperationBeyondEndOfFile) - { - if( bAlreadyExpanded) - { - flmAssert( 0); - rc = DfsMapError( lResult, NE_FLM_DIRECT_WRITING_FILE); - goto Exit; - } - - // Expand the file - - if( RC_BAD( rc = expand( lStartSector, lSectorCount))) - { - goto Exit; - } - - bAlreadyExpanded = TRUE; - - // The Expand method forces the file EOF in the directory - // entry to be written to disk. - - bNeedToWriteEOF = FALSE; - continue; - } - else if (lResult != 0) - { - rc = DfsMapError( lResult, NE_FLM_DIRECT_WRITING_FILE); - goto Exit; - } - else - { - if( pBufferObj) - { - *pbDidAsync = TRUE; - } - - // If bNeedToWriteEOF is TRUE, we need to force EOF to disk. - - if( bNeedToWriteEOF) - { - LONG lFileSizeInSectors; - LONG lExtraSectors; - - // Set the EOF to the nearest block boundary - so we don't - // have to do this very often. - - lFileSizeInSectors = lStartSector + lSectorCount; - lExtraSectors = lFileSizeInSectors % m_lSectorsPerBlock; - - if (lExtraSectors) - { - lFileSizeInSectors += (m_lSectorsPerBlock - lExtraSectors); - } - - if ((lResult = SetFileSize( 0, m_lFileHandle, - (FLMUINT)lFileSizeInSectors * FLM_NLM_SECTOR_SIZE, - FALSE)) != 0) - { - rc = DfsMapError( lResult, NE_FLM_TRUNCATING_FILE); - goto Exit; - } - } - - break; - } - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Legacy async I/O completion callback -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -FSTATIC void DirectIONoWaitCallBack( - LONG unknownAlwaysZero, - LONG callbackData, - LONG completionCode) -{ - IF_IOBuffer * pIOBuffer = (IF_IOBuffer *)callbackData; - - F_UNREFERENCED_PARM( unknownAlwaysZero); - - pIOBuffer->signalComplete( - (RCODE)(completionCode == DFSNormalCompletion - ? NE_FLM_OK - : DfsMapError( completionCode, NE_FLM_DIRECT_WRITING_FILE))); -} -#endif - -/**************************************************************************** -Desc: NSS async I/O completion callback -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -FSTATIC void nssDioCallback( - FLMUINT reserved, - FLMUINT callbackData, - FLMUINT completionCode) -{ - IF_IOBuffer * pIOBuffer = (IF_IOBuffer *)callbackData; - - F_UNREFERENCED_PARM( reserved); - - pIOBuffer->signalComplete( - (RCODE)(completionCode == zOK - ? NE_FLM_OK - : MapNSSError( completionCode, NE_FLM_DIRECT_WRITING_FILE))); -} -#endif - -/**************************************************************************** -Desc: Might call the direct IO Write routine in the future -Note: This routine assumes that the size of pvBuffer is a multiple of - sector size (512 bytes) and can be used to write out full - sectors. Even if uiBytesToWrite does not account for full sectors, - data from the buffer will still be written out - a partial sector - on disk will not be preserved. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::sectorWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - - if( m_bDoDirectIO) - { - if( RC_BAD( rc = _directIOSectorWrite( (FLMUINT)ui64WriteOffset, - uiBytesToWrite, pvBuffer, pBufferObj, puiBytesWrittenRV))) - { - goto Exit; - } - } - else - { - flmAssert( !pBufferObj); - - if( RC_BAD( rc = _write( (FLMUINT)ui64WriteOffset, - uiBytesToWrite, pvBuffer, puiBytesWrittenRV))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} -#endif - -/**************************************************************************** -Desc: Calls the direct IO-style write routine. -Note: This routine assumes that the size of pvBuffer is a multiple of - sector size (512 bytes) and can be used to write out full - sectors. Even if uiBytesToWrite does not account for full sectors, - data from the buffer will still be written out - a partial sector - on disk will not be preserved. -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -RCODE F_FileHdl::_directIOSectorWrite( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - LONG lStartSector; - LONG lSectorCount; - FLMBOOL bDidAsync = FALSE; - - flmAssert( m_bFileOpened == TRUE); - - if (uiWriteOffset == FLM_IO_CURRENT_POS) - { - uiWriteOffset = m_uiCurrentPos; - } - else - { - m_uiCurrentPos = uiWriteOffset; - } - - if (uiWriteOffset % FLM_NLM_SECTOR_SIZE != 0) - { - rc = write( uiWriteOffset, uiBytesToWrite, pvBuffer, - puiBytesWrittenRV); - goto Exit; - } - - // Calculate the starting sector and number of sectors to write - - lStartSector = uiWriteOffset / FLM_NLM_SECTOR_SIZE; - lSectorCount = (LONG)(uiBytesToWrite / FLM_NLM_SECTOR_SIZE); - if (uiBytesToWrite % FLM_NLM_SECTOR_SIZE != 0) - { - FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer; - - lSectorCount++; - - // Zero out the part of the buffer that was not included in - // uiBytesToWrite - because it will still be written to disk. - - f_memset( &pucBuffer [uiBytesToWrite], 0, - (FLMUINT)(FLM_NLM_SECTOR_SIZE - (uiBytesToWrite % FLM_NLM_SECTOR_SIZE))); - } - - if( RC_BAD( rc = writeSectors( (void *)pvBuffer, lStartSector, lSectorCount, - pBufferObj, &bDidAsync))) - { - goto Exit; - } - - m_uiCurrentPos += uiBytesToWrite; - - if( puiBytesWrittenRV) - { - *puiBytesWrittenRV = uiBytesToWrite; - } - -Exit: - - if( !bDidAsync && pBufferObj) - { - pBufferObj->notifyComplete( rc); - } - - return( rc); -} -#endif - /**************************************************************************** Desc: ****************************************************************************/ @@ -3289,16 +1935,6 @@ RCODE F_FileHdl::flush( void) } #endif -/**************************************************************************** -Desc: -****************************************************************************/ -#if defined( FLM_RING_ZERO_NLM) -FLMBOOL F_FileHdl::canDoAsync( void) -{ - return( m_bDoDirectIO); -} -#endif - /**************************************************************************** Desc: ****************************************************************************/ @@ -3465,7 +2101,7 @@ FSTATIC RCODE nssTurnOffRenameInhibit( goto Exit; } - flmAssert( Info.infoVersion == zINFO_VERSION_A); + f_assert( Info.infoVersion == zINFO_VERSION_A); // See if the rename inhibit bit is set. @@ -4353,3 +2989,898 @@ void gv_fnlm() { } #endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::lowLevelRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesRead = 0; + + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64ReadOffset == FLM_IO_CURRENT_POS) + { + ui64ReadOffset = m_ui64CurrentPos; + } + + if( !pvBuffer) + { + pvBuffer = pIOBuffer->getBufferPtr(); + } + + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + rc = internalBlockingRead( ui64ReadOffset, uiBytesToRead, pvBuffer, + &uiBytesRead); + + m_ui64CurrentPos += uiBytesRead; + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) + { + goto Exit; + } + + if( uiBytesRead < uiBytesToRead) + { + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + goto Exit; + } + +Exit: + + f_assert( uiBytesRead || RC_BAD( rc)); + f_assert( uiBytesRead <= uiBytesToRead); + + if( pIOBuffer && !pIOBuffer->isPending()) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); + } + + if( puiBytesRead) + { + *puiBytesRead = uiBytesRead; + } + + return( rc); +} +#endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::internalBlockingRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + FLMUINT * puiBytesRead) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesRead = 0; + FLMUINT uiBytesRemaining = uiBytesToRead; + + f_assert( uiBytesToRead); + + if( m_bDoDirectIO) + { + FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer; + LONG lStartSector; + LONG lSectorCount; + LONG lResult; + BYTE ucSectorBuf[ FLM_NLM_SECTOR_SIZE]; + FLMUINT uiBytesToCopy; + FLMUINT uiSectorOffset; + FLMUINT uiTotal; + FLMINT lStatus; + + // Calculate the starting sector. + + lStartSector = (LONG)(ui64ReadOffset / FLM_NLM_SECTOR_SIZE); + + // See if the offset is on a sector boundary. If not, we must read + // into the local sector buffer and then copy into the buffer. + // We must also read into the local buffer if our read size is less + // than the sector size. + + if( (ui64ReadOffset % FLM_NLM_SECTOR_SIZE != 0) || + (uiBytesRemaining < FLM_NLM_SECTOR_SIZE)) + { + if( m_bNSS) + { + if( (lStatus = gv_zDIOReadFunc( m_NssKey, + (FLMUINT64)lStartSector, 1, + (FLMUINT)0, NULL, ucSectorBuf)) != zOK) + { + rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + else + { + if( (lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, + 1, ucSectorBuf)) != 0) + { + rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + + // Copy the part of the sector that was requested into the buffer. + + uiSectorOffset = (FLMUINT)(ui64ReadOffset % FLM_NLM_SECTOR_SIZE); + + if( (uiBytesToCopy = uiBytesRemaining) > + FLM_NLM_SECTOR_SIZE - uiSectorOffset) + { + uiBytesToCopy = FLM_NLM_SECTOR_SIZE - uiSectorOffset; + } + + f_memcpy( pucBuffer, &ucSectorBuf[ uiSectorOffset], uiBytesToCopy); + pucBuffer += uiBytesToCopy; + uiBytesRemaining -= (FLMUINT)uiBytesToCopy; + uiBytesRead += uiBytesToCopy; + + // See if we got everything we wanted to with this read. + + if( !uiBytesRemaining) + { + goto Exit; + } + + // Go to the next sector boundary + + lStartSector++; + } + + // At this point, we are poised to read on a sector boundary. See if we + // have at least one full sector to read. If so, we can read it directly + // into the provided buffer. If not, we must use the temporary sector + // buffer. + + if( uiBytesRemaining >= FLM_NLM_SECTOR_SIZE) + { + lSectorCount = (LONG)(uiBytesRemaining / FLM_NLM_SECTOR_SIZE); + Try_Read: + if( m_bNSS) + { + if( (lStatus = gv_zDIOReadFunc( m_NssKey, + (FLMUINT64)lStartSector, (FLMUINT)lSectorCount, + (FLMUINT)0, NULL, pucBuffer)) != zOK) + { + if( (lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) && + (lSectorCount > 1)) + { + + // See if we can read one less sector. We will return + // NE_FLM_IO_END_OF_FILE in this case. + + lSectorCount--; + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + goto Try_Read; + } + + rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + else + { + if( (lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, + lSectorCount, pucBuffer)) != 0) + { + if( lResult == DFSOperationBeyondEndOfFile && lSectorCount > 1) + { + // See if we can read one less sector. We will return + // NE_FLM_IO_END_OF_FILE in this case. + + lSectorCount--; + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + goto Try_Read; + } + + rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + + uiTotal = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); + pucBuffer += uiTotal; + uiBytesRead += uiTotal; + uiBytesRemaining -= uiTotal; + + // See if we got everything we wanted to or could with this read. + + if( !uiBytesRemaining || rc == NE_FLM_IO_END_OF_FILE) + { + goto Exit; + } + + // Go to the next sector after the ones we just read + + lStartSector += lSectorCount; + } + + // At this point, we have less than a sector's worth to read, so we must + // read it into a local buffer. + + if( m_bNSS) + { + if( (lStatus = gv_zDIOReadFunc( m_NssKey, (FLMUINT64)lStartSector, 1, + (FLMUINT)0, NULL, ucSectorBuf)) != zOK) + { + rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + else + { + if( (lResult = DirectReadFile( 0, m_lFileHandle, + lStartSector, 1, ucSectorBuf)) != 0) + { + rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + + // Copy the part of the sector that was requested into the buffer. + + uiBytesRead += uiBytesRemaining; + f_memcpy( pucBuffer, ucSectorBuf, uiBytesRemaining); + } + else + { + FCBType * fcb; + LONG lBytesRead; + LONG lErr; + + if( m_bNSS) + { + FLMINT lStatus; + + if( (lStatus = gv_zReadFunc( m_NssKey, 0, ui64ReadOffset, + (FLMUINT)uiBytesRemaining, pvBuffer, &uiBytesRead)) != zOK) + { + f_assert( 0); + rc = MapNSSError( lStatus, NE_FLM_READING_FILE); + goto Exit; + } + } + else + { + if( (lErr = MapFileHandleToFCB( m_lFileHandle, &fcb)) != 0) + { + rc = f_mapPlatformError( lErr, NE_FLM_SETTING_UP_FOR_READ); + goto Exit; + } + + if( (lErr = ReadFile( fcb->Station, m_lFileHandle, + (LONG)ui64ReadOffset, uiBytesRemaining, + &lBytesRead, pvBuffer)) != 0) + { + rc = f_mapPlatformError( lErr, NE_FLM_READING_FILE); + } + + uiBytesRead = (FLMUINT)lBytesRead; + } + } + + if( uiBytesRead < uiBytesToRead) + { + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + goto Exit; + } + +Exit: + + f_assert( uiBytesRead <= uiBytesToRead); + + if( puiBytesRead) + { + *puiBytesRead = uiBytesRead; + } + + return( rc); +} +#endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::lowLevelWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesWritten = 0; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bWaitForWrite = FALSE; + + f_assert( uiBytesToWrite); + f_assert( !m_bDoDirectIO || (ui64WriteOffset % FLM_NLM_SECTOR_SIZE) == 0); + f_assert( !m_bDoDirectIO || (uiBytesToWrite % FLM_NLM_SECTOR_SIZE) == 0); + + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64WriteOffset == FLM_IO_CURRENT_POS) + { + ui64WriteOffset = m_ui64CurrentPos; + } + + if( !pvBuffer) + { + pvBuffer = pIOBuffer->getBufferPtr(); + } + + if( m_bOpenedInAsyncMode) + { + LONG lStartSector; + LONG lSectorCount; + + if( RC_BAD( rc = allocFileAsyncClient( &pAsyncClient))) + { + goto Exit; + } + + if( RC_BAD( rc = pAsyncClient->prepareForAsync( pIOBuffer))) + { + goto Exit; + } + + if( !pIOBuffer) + { + bWaitForWrite = TRUE; + } + + pAsyncClient->m_uiBytesToDo = uiBytesToWrite; + pIOBuffer = NULL; + + // Calculate the starting sector and number of sectors to write + + lStartSector = (LONG)(ui64WriteOffset / FLM_NLM_SECTOR_SIZE); + lSectorCount = (LONG)(uiBytesToWrite / FLM_NLM_SECTOR_SIZE); + + if( RC_BAD( rc = writeSectors( pvBuffer, pAsyncClient, + lStartSector, lSectorCount))) + { + pAsyncClient->notifyComplete( rc, 0, FALSE); + goto Exit; + } + + if( bWaitForWrite) + { + if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + { + if( rc != NE_FLM_IO_DISK_FULL) + { + goto Exit; + } + + rc = NE_FLM_OK; + } + + f_assert( pAsyncClient->m_uiBytesDone); + uiBytesWritten = pAsyncClient->m_uiBytesDone; + } + else + { + uiBytesWritten = uiBytesToWrite; + } + + m_ui64CurrentPos += uiBytesWritten; + } + else + { + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + rc = internalBlockingWrite( ui64WriteOffset, uiBytesToWrite, + pvBuffer, &uiBytesWritten); + + m_ui64CurrentPos += uiBytesWritten; + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) + { + goto Exit; + } + } + + if( uiBytesWritten < uiBytesToWrite) + { + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); + goto Exit; + } + +Exit: + + if( pAsyncClient) + { + pAsyncClient->Release(); + } + + if( pIOBuffer && !pIOBuffer->isPending()) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); + } + + if( puiBytesWritten) + { + *puiBytesWritten = uiBytesWritten; + } + + return( rc); +} +#endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::internalBlockingWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + FLMUINT * puiBytesWritten) +{ + RCODE rc = NE_FLM_OK; + LONG lErr; + FCBType * fcb; + FLMUINT uiBytesWritten = 0; + FLMUINT uiBytesRemaining = uiBytesToWrite; + + if( m_bDoDirectIO) + { + FLMBYTE * pucBuffer = (FLMBYTE *)pvBuffer; + LONG lStartSector; + LONG lSectorCount; + LONG lResult; + BYTE ucSectorBuf[ FLM_NLM_SECTOR_SIZE]; + FLMUINT uiBytesToCopy; + FLMUINT uiSectorOffset; + FLMUINT uiTotal; + FLMINT lStatus; + + // Calculate the starting sector + + lStartSector = (LONG)(ui64WriteOffset / FLM_NLM_SECTOR_SIZE); + + // See if the offset is on a sector boundary. If not, we must first read + // the sector into memory, overwrite it with data from the input + // buffer and write it back out again. + + if( (ui64WriteOffset % FLM_NLM_SECTOR_SIZE != 0) || + (uiBytesRemaining < FLM_NLM_SECTOR_SIZE)) + { + if( m_bNSS) + { + if( (lStatus = gv_zDIOReadFunc( m_NssKey, + (FLMUINT64)lStartSector, + (FLMUINT)1, (FLMUINT)0, NULL, ucSectorBuf)) != zOK) + { + if( lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) + { + f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, 1))) + { + goto Exit; + } + } + else + { + rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + } + else + { + lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, + 1, ucSectorBuf); + + if( lResult == DFSHoleInFileError || + lResult == DFSOperationBeyondEndOfFile ) + { + f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, 1))) + { + goto Exit; + } + } + else if( lResult != 0) + { + rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + + // Copy the part of the buffer that is being written back into + // the sector buffer. + + uiSectorOffset = (FLMUINT)(ui64WriteOffset % FLM_NLM_SECTOR_SIZE); + + if( (uiBytesToCopy = uiBytesRemaining) > + (FLM_NLM_SECTOR_SIZE - uiSectorOffset)) + { + uiBytesToCopy = FLM_NLM_SECTOR_SIZE - uiSectorOffset; + } + + f_memcpy( &ucSectorBuf [uiSectorOffset], pucBuffer, uiBytesToCopy); + pucBuffer += uiBytesToCopy; + uiBytesRemaining -= uiBytesToCopy; + uiBytesWritten += uiBytesToCopy; + + // Write the sector buffer back out + + if( RC_BAD( rc = writeSectors( &ucSectorBuf [0], NULL, + lStartSector, 1))) + { + goto Exit; + } + + // See if we wrote everything we wanted to with this write + + if( !uiBytesRemaining) + { + goto Exit; + } + + // Go to the next sector boundary + + lStartSector++; + } + + // At this point, we are poised to write on a sector boundary. See if we + // have at least one full sector to write. If so, we can write it directly + // from the provided buffer. If not, we must use the temporary sector + // buffer. + + if( uiBytesRemaining >= FLM_NLM_SECTOR_SIZE) + { + lSectorCount = (LONG)(uiBytesRemaining / FLM_NLM_SECTOR_SIZE); + + if( RC_BAD( rc = writeSectors( (const void *)pucBuffer, NULL, + lStartSector, lSectorCount))) + { + goto Exit; + } + + uiTotal = (FLMUINT)(lSectorCount * FLM_NLM_SECTOR_SIZE); + pucBuffer += uiTotal; + uiBytesWritten += uiTotal; + uiBytesRemaining -= uiTotal; + + // See if we wrote everything we wanted to with this write + + if( !uiBytesRemaining) + { + goto Exit; + } + + // Go to the next sector after the ones we just wrote + + lStartSector += lSectorCount; + } + + // At this point, we have less than a sector's worth to write, so we must + // first read the sector from disk, alter it, and then write it back out. + + if( m_bNSS) + { + if( (lStatus = gv_zDIOReadFunc( m_NssKey, (FLMUINT64)lStartSector, + (FLMUINT)1, (FLMUINT)0, NULL, ucSectorBuf)) != zOK) + { + if( lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF) + { + f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, 1))) + { + goto Exit; + } + } + else + { + rc = MapNSSError( lStatus, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + } + else + { + lResult = DirectReadFile( 0, m_lFileHandle, lStartSector, + 1, ucSectorBuf); + + if( lResult == DFSHoleInFileError) + { + f_memset( ucSectorBuf, 0, sizeof( ucSectorBuf)); + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, 1))) + { + goto Exit; + } + } + else if( lResult != 0) + { + rc = DfsMapError( lResult, NE_FLM_DIRECT_READING_FILE); + goto Exit; + } + } + + // Copy the rest of the output buffer into the sector buffer + + f_memcpy( ucSectorBuf, pucBuffer, uiBytesRemaining); + + // Write the sector back to disk + + if( RC_BAD( rc = writeSectors( &ucSectorBuf[ 0], NULL, lStartSector, 1))) + { + goto Exit; + } + + uiBytesWritten += uiBytesRemaining; + } + else + { + if( m_bNSS) + { + FLMINT lStatus; + + if( (lStatus = gv_zWriteFunc( m_NssKey, 0, ui64WriteOffset, + uiBytesRemaining, pvBuffer, &uiBytesWritten)) != zOK) + { + rc = MapNSSError( lStatus, NE_FLM_WRITING_FILE); + goto Exit; + } + } + else + { + if( (lErr = MapFileHandleToFCB( m_lFileHandle, &fcb)) != 0) + { + rc = f_mapPlatformError( lErr, NE_FLM_SETTING_UP_FOR_WRITE); + goto Exit; + } + + if( (lErr = WriteFile( fcb->Station, m_lFileHandle, + (LONG)ui64WriteOffset, uiBytesRemaining, (void *)pvBuffer)) != 0) + { + rc = f_mapPlatformError( lErr, NE_FLM_WRITING_FILE); + goto Exit; + } + + uiBytesWritten = uiBytesRemaining; + } + } + + if( uiBytesWritten < uiBytesToWrite) + { + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); + goto Exit; + } + +Exit: + + if( puiBytesWritten) + { + *puiBytesWritten = uiBytesWritten; + } + + return( rc); +} +#endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::writeSectors( + const void * pvBuffer, + F_FileAsyncClient * pAsyncClient, + LONG lStartSector, + LONG lSectorCount) +{ + RCODE rc = NE_FLM_OK; + LONG lResult; + FLMINT lStatus; + FLMBOOL bExpanded = FALSE; + + // Keep trying write until we succeed or get an error we can't deal with. + // Actually, this will NOT loop forever. At most, it will try twice - + // and then it is only when we get a hole in the file error. + + for( ;;) + { + if( m_bNSS) + { + if( pAsyncClient) + { + lStatus = gv_zDIOWriteFunc( m_NssKey, (FLMUINT64)lStartSector, + (FLMUINT)lSectorCount, (FLMUINT)pAsyncClient, + nssDioCallback, pvBuffer); + } + else + { + lStatus = gv_zDIOWriteFunc( m_NssKey, (FLMUINT64)lStartSector, + (FLMUINT)lSectorCount, (FLMUINT)0, NULL, pvBuffer); + } + + // We may need to allocate space to do this write + + if( lStatus == zERR_END_OF_FILE || lStatus == zERR_BEYOND_EOF || + lStatus == zERR_HOLE_IN_DIO_FILE) + { + if( bExpanded) + { + f_assert( 0); + rc = MapNSSError( lStatus, NE_FLM_DIRECT_WRITING_FILE); + goto Exit; + } + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, lSectorCount))) + { + goto Exit; + } + + bExpanded = TRUE; + continue; + } + else if( lStatus != 0) + { + rc = MapNSSError( lStatus, NE_FLM_DIRECT_WRITING_FILE); + goto Exit; + } + + break; + } + else + { + LONG lSize; + FLMBOOL bNeedToWriteEOF; + + // Determine if this write will change the EOF. If so, pre-expand + // the file. + + if( (lResult = GetFileSize( 0, m_lFileHandle, &lSize)) != 0) + { + rc = f_mapPlatformError( lResult, NE_FLM_GETTING_FILE_SIZE); + goto Exit; + } + + bNeedToWriteEOF = + (lSize < (lStartSector + lSectorCount) * FLM_NLM_SECTOR_SIZE) + ? TRUE + : FALSE; + + if( pAsyncClient) + { + lResult = DirectWriteFileNoWait( 0, m_lFileHandle, + lStartSector,lSectorCount, + (BYTE *)pvBuffer, DirectIONoWaitCallBack, + (LONG)pAsyncClient); + } + else + { + lResult = DirectWriteFile( 0, m_lFileHandle, + lStartSector, lSectorCount, (BYTE *)pvBuffer); + } + + // We may need to allocate space to do this write + + if( lResult == DFSHoleInFileError || + lResult == DFSOperationBeyondEndOfFile) + { + if( bExpanded) + { + f_assert( 0); + rc = DfsMapError( lResult, NE_FLM_DIRECT_WRITING_FILE); + goto Exit; + } + + // Expand the file + + if( RC_BAD( rc = expand( lStartSector, lSectorCount))) + { + goto Exit; + } + + bExpanded = TRUE; + + // The Expand method forces the file EOF in the directory + // entry to be written to disk. + + bNeedToWriteEOF = FALSE; + continue; + } + else if( lResult != 0) + { + rc = DfsMapError( lResult, NE_FLM_DIRECT_WRITING_FILE); + goto Exit; + } + else + { + // If bNeedToWriteEOF is TRUE, we need to force EOF to disk. + + if( bNeedToWriteEOF) + { + LONG lFileSizeInSectors; + LONG lExtraSectors; + + // Set the EOF to the nearest block boundary - so we don't + // have to do this very often. + + lFileSizeInSectors = lStartSector + lSectorCount; + lExtraSectors = lFileSizeInSectors % m_lSectorsPerBlock; + + if( lExtraSectors) + { + lFileSizeInSectors += (m_lSectorsPerBlock - lExtraSectors); + } + + if( (lResult = SetFileSize( 0, m_lFileHandle, + (FLMUINT)lFileSizeInSectors * FLM_NLM_SECTOR_SIZE, + FALSE)) != 0) + { + rc = DfsMapError( lResult, NE_FLM_TRUNCATING_FILE); + goto Exit; + } + } + + break; + } + } + } + +Exit: + + return( rc); +} +#endif diff --git a/ftk/src/ftksupr.cpp b/ftk/src/ftksupr.cpp index 4bf26bd..b304928 100644 --- a/ftk/src/ftksupr.cpp +++ b/ftk/src/ftksupr.cpp @@ -31,17 +31,15 @@ Desc: F_SuperFileHdl::F_SuperFileHdl( void) { m_pSuperFileClient = NULL; - f_memset( &m_CheckedOutFileHdls[ 0], 0, sizeof( m_CheckedOutFileHdls)); - m_pCheckedOutFileHdls = &m_CheckedOutFileHdls [0]; - m_uiCkoArraySize = MAX_CHECKED_OUT_FILE_HDLS + 1; + m_pCFileHdl = NULL; + m_pBlockFileHdl = NULL; + m_uiBlockFileNum = 0; + m_bBlockFileDirty = FALSE; + m_bCFileDirty = FALSE; m_uiBlockSize = 0; m_uiExtendSize = (8 * 1024 * 1024); m_uiMaxAutoExtendSize = f_getMaxFileSize(); - m_uiLowestDirtySlot = 1; - m_uiHighestDirtySlot = 0; - m_uiHighestUsedSlot = 0; - m_uiHighestFileNumber = 0; - m_bMinimizeFlushes = FALSE; + m_uiDirectIOFlag = 0; } /**************************************************************************** @@ -49,68 +47,129 @@ Desc: ****************************************************************************/ F_SuperFileHdl::~F_SuperFileHdl() { - releaseFiles( TRUE); + if( m_pCFileHdl) + { + if( m_bCFileDirty) + { + f_assert( 0); + m_pCFileHdl->flush(); + } + + m_pCFileHdl->Release(); + } + + if( m_pBlockFileHdl) + { + if( m_bBlockFileDirty) + { + m_pBlockFileHdl->flush(); + } + + m_pBlockFileHdl->Release(); + } if( m_pSuperFileClient) { m_pSuperFileClient->Release(); } + + if( m_pFileHdlCache) + { + m_pFileHdlCache->Release(); + } } /**************************************************************************** Desc: Configures the super file object ****************************************************************************/ -RCODE F_SuperFileHdl::setup( - IF_SuperFileClient * pSuperFileClient) +RCODE FLMAPI F_SuperFileHdl::setup( + IF_SuperFileClient * pSuperFileClient, + IF_FileHdlCache * pFileHdlCache, + FLMBOOL bUseDirectIO) { + RCODE rc = NE_FLM_OK; + f_assert( !m_pSuperFileClient); m_pSuperFileClient = pSuperFileClient; m_pSuperFileClient->AddRef(); + + if( (m_pFileHdlCache = pFileHdlCache) != NULL) + { + m_pFileHdlCache->AddRef(); + } + else + { + if( RC_BAD( rc = f_getFileSysPtr()->allocFileHandleCache( + 8, 120, &m_pFileHdlCache))) + { + goto Exit; + } + } - return( NE_FLM_OK); + if( bUseDirectIO) + { + m_uiDirectIOFlag |= FLM_IO_DIRECT; + } + +Exit: + + return( rc); } /**************************************************************************** Desc: Creates a file ****************************************************************************/ -RCODE F_SuperFileHdl::createFile( - FLMUINT uiFileNumber) +RCODE FLMAPI F_SuperFileHdl::createFile( + FLMUINT uiFileNumber, + IF_FileHdl ** ppFileHdl) { RCODE rc = NE_FLM_OK; char szFilePath[ F_PATH_MAX_SIZE]; IF_FileHdl * pFileHdl = NULL; - // Sanity checks - - flmAssert( m_uiBlockSize); - + f_assert( m_uiBlockSize); + // See if we already have an open file handle (or if we can open the file). // If so, truncate the file and use it. - if( RC_OK( rc = getFileHdl( uiFileNumber, TRUE, &pFileHdl))) + if( RC_BAD( rc = getFileHdl( uiFileNumber, TRUE, &pFileHdl))) { - rc = pFileHdl->truncate( 0); + if( rc != NE_FLM_IO_PATH_NOT_FOUND) + { + goto Exit; + } + + rc = NE_FLM_OK; + } + + if( !pFileHdl) + { + if( RC_BAD( rc = m_pSuperFileClient->getFilePath( + uiFileNumber, szFilePath))) + { + goto Exit; + } + + if( RC_BAD( rc = m_pFileHdlCache->createFile( szFilePath, + FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_SH_DENYNONE | m_uiDirectIOFlag, + &pFileHdl))) + { + goto Exit; + } + } + else + { + if( RC_BAD( rc = pFileHdl->truncate())) + { + goto Exit; + } + } + + if( ppFileHdl) + { + *ppFileHdl = pFileHdl; pFileHdl = NULL; - goto Exit; - } - else if( rc != NE_FLM_IO_PATH_NOT_FOUND) - { - goto Exit; - } - - // Build the file path - - if( RC_BAD( rc = m_pSuperFileClient->getFilePath( uiFileNumber, szFilePath))) - { - goto Exit; - } - - if( RC_BAD( rc = f_getFileSysPtr()->createFile( szFilePath, - FLM_IO_RDWR | FLM_IO_EXCL | FLM_IO_DIRECT | FLM_IO_SH_DENYNONE, - &pFileHdl))) - { - goto Exit; } Exit: @@ -126,7 +185,7 @@ Exit: /**************************************************************************** Desc: Reads a database block into a buffer ****************************************************************************/ -RCODE F_SuperFileHdl::readBlock( +RCODE FLMAPI F_SuperFileHdl::readBlock( FLMUINT uiBlkAddress, FLMUINT uiBytesToRead, void * pvBuffer, @@ -135,7 +194,7 @@ RCODE F_SuperFileHdl::readBlock( RCODE rc = NE_FLM_OK; IF_FileHdl * pFileHdl = NULL; - flmAssert( m_uiBlockSize); + f_assert( m_uiBlockSize); if( RC_BAD( rc = getFileHdl( m_pSuperFileClient->getFileNumber( uiBlkAddress), FALSE, &pFileHdl))) @@ -143,19 +202,20 @@ RCODE F_SuperFileHdl::readBlock( goto Exit; } - if( RC_BAD( rc = pFileHdl->sectorRead( + if( RC_BAD( rc = pFileHdl->read( m_pSuperFileClient->getFileOffset( uiBlkAddress), uiBytesToRead, pvBuffer, puiBytesRead))) { - if (rc != NE_FLM_IO_END_OF_FILE && rc != NE_FLM_MEM) - { - releaseFile( m_pSuperFileClient->getFileNumber( uiBlkAddress), TRUE); - } goto Exit; } Exit: + if( pFileHdl) + { + pFileHdl->Release(); + } + return( rc); } @@ -163,368 +223,150 @@ Exit: Desc: Writes a block to the database ****************************************************************************/ RCODE F_SuperFileHdl::writeBlock( - FLMUINT uiBlkAddress, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pIOBuffer, - FLMUINT * puiBytesWritten) + FLMUINT uiBlkAddress, + FLMUINT uiBytesToWrite, + IF_IOBuffer * pIOBuffer) { RCODE rc = NE_FLM_OK; IF_FileHdl * pFileHdl = NULL; - flmAssert( m_uiBlockSize); - -Get_Handle: + f_assert( m_uiBlockSize); if( RC_BAD( rc = getFileHdl( - m_pSuperFileClient->getFileNumber(uiBlkAddress), TRUE, &pFileHdl))) + m_pSuperFileClient->getFileNumber( uiBlkAddress), TRUE, &pFileHdl))) { - if (rc == NE_FLM_IO_PATH_NOT_FOUND) + if( rc != NE_FLM_IO_PATH_NOT_FOUND) { - if (RC_BAD( rc = createFile( m_pSuperFileClient->getFileNumber( - uiBlkAddress)))) - { - goto Exit; - } - else - { - goto Get_Handle; - } + goto Exit; + } + + if( RC_BAD( rc = createFile( + m_pSuperFileClient->getFileNumber( uiBlkAddress), &pFileHdl))) + { + goto Exit; } - goto Exit; } pFileHdl->setExtendSize( m_uiExtendSize); pFileHdl->setMaxAutoExtendSize( m_uiMaxAutoExtendSize); - if( RC_BAD( rc = pFileHdl->sectorWrite( - m_pSuperFileClient->getFileOffset( uiBlkAddress), uiBytesToWrite, - pvBuffer, pIOBuffer, puiBytesWritten))) - { - if (rc != NE_FLM_IO_DISK_FULL && rc != NE_FLM_MEM) - { - releaseFile( m_pSuperFileClient->getFileNumber( uiBlkAddress), TRUE); - } - goto Exit; - } + + rc = pFileHdl->write( m_pSuperFileClient->getFileOffset( uiBlkAddress), + uiBytesToWrite, pIOBuffer); -Exit: + pIOBuffer = NULL; - return( rc); -} - -/**************************************************************************** -Desc: Reads data from the database header -****************************************************************************/ -RCODE F_SuperFileHdl::readHeader( - FLMUINT uiOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - IF_FileHdl * pFileHdl; - -#ifdef FLM_DEBUG - if( m_uiBlockSize) - { - // Note: Block size may not be set because we are in the process of - // opening the file for the first time and we don't know the block - // size until after the header has been read. - - flmAssert( (FLMUINT)(uiOffset + uiBytesToRead) <= m_uiBlockSize); - } -#endif - - if( RC_BAD( rc = getFileHdl( 0, TRUE, &pFileHdl))) + if( RC_BAD( rc)) { goto Exit; } - if( RC_BAD( rc = pFileHdl->read( uiOffset, - uiBytesToRead, pvBuffer, puiBytesRead))) - { - if (rc != NE_FLM_IO_END_OF_FILE && rc != NE_FLM_MEM) - { - releaseFile( (FLMUINT)0, TRUE); - } - goto Exit; - } - Exit: - return( rc); -} - -/**************************************************************************** -Desc: Writes data to the database header -****************************************************************************/ -RCODE F_SuperFileHdl::writeHeader( - FLMUINT uiOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWritten) -{ - RCODE rc = NE_FLM_OK; - IF_FileHdl * pFileHdl; - -#ifdef FLM_DEBUG - if( m_uiBlockSize) - { - flmAssert( (FLMUINT)(uiOffset + uiBytesToWrite) <= m_uiBlockSize); - } -#endif - - if( RC_BAD( rc = getFileHdl( 0, TRUE, &pFileHdl))) - { - goto Exit; - } - - if( RC_BAD( rc = pFileHdl->write( uiOffset, - uiBytesToWrite, pvBuffer, puiBytesWritten))) - { - if (rc != NE_FLM_IO_DISK_FULL && rc != NE_FLM_MEM) - { - releaseFile( (FLMUINT)0, TRUE); - } - goto Exit; - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Releases all file handle objects and optionally closes the files -****************************************************************************/ -RCODE F_SuperFileHdl::releaseFile( - FLMUINT uiFileNum, - FLMBOOL bCloseFile) -{ - RCODE rc = NE_FLM_OK; - CHECKED_OUT_FILE_HDL * pCkoFileHdl; - FLMUINT uiSlot; - - pCkoFileHdl = getCkoFileHdlPtr( uiFileNum, &uiSlot); - if( pCkoFileHdl->uiFileNumber == uiFileNum) - { - if( RC_BAD( rc = releaseFile( pCkoFileHdl, bCloseFile))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Releases all file handle objects and optionally closes the files -****************************************************************************/ -RCODE F_SuperFileHdl::releaseFiles( - FLMBOOL bCloseFiles) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiLoop; - - for( uiLoop = 0; uiLoop <= m_uiHighestUsedSlot; uiLoop++) - { - if( RC_BAD( rc = releaseFile( - &m_CheckedOutFileHdls[ uiLoop], bCloseFiles))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Releases a file handle object -****************************************************************************/ -RCODE F_SuperFileHdl::releaseFile( - CHECKED_OUT_FILE_HDL * pCkoFileHdl, - FLMBOOL bCloseFile) -{ - RCODE rc = NE_FLM_OK; - IF_FileHdl * pFileHdl = pCkoFileHdl->pFileHdl; - if( pFileHdl) { - if( pCkoFileHdl->bDirty) - { - (void)pFileHdl->flush(); - } - - if( bCloseFile) - { - FLMUINT uiRefCnt; - - uiRefCnt = pFileHdl->Release(); - flmAssert( uiRefCnt == 0); - } - - clearCkoFileHdl( pCkoFileHdl); + pFileHdl->Release(); + } + + if( pIOBuffer) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); } return( rc); } /**************************************************************************** -Desc: Copy one CKO array into another. +Desc: Writes a block to the database ****************************************************************************/ -void F_SuperFileHdl::copyCkoFileHdls( - CHECKED_OUT_FILE_HDL * pSrcCkoArray, - FLMUINT uiSrcHighestUsedSlot) +RCODE F_SuperFileHdl::writeBlock( + FLMUINT uiBlkAddress, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + FLMUINT * puiBytesWritten) { - FLMUINT uiNewSlot; - FLMUINT uiSrcSlot; + RCODE rc = NE_FLM_OK; + IF_FileHdl * pFileHdl = NULL; - // Zeroeth element is always copied. + f_assert( m_uiBlockSize); - f_memcpy( m_pCheckedOutFileHdls, pSrcCkoArray, - sizeof( CHECKED_OUT_FILE_HDL)); - - // Memset the rest of the destination array to zero. - - f_memset( &m_pCheckedOutFileHdls[1], 0, sizeof( CHECKED_OUT_FILE_HDL) * - (m_uiCkoArraySize - 1)); - - m_uiHighestUsedSlot = 0; - m_uiLowestDirtySlot = 1; - m_uiHighestDirtySlot = 0; - - for (uiSrcSlot = 1, pSrcCkoArray++; - uiSrcSlot <= uiSrcHighestUsedSlot; - uiSrcSlot++, pSrcCkoArray++) + if( RC_BAD( rc = getFileHdl( + m_pSuperFileClient->getFileNumber( uiBlkAddress), TRUE, &pFileHdl))) { - if (pSrcCkoArray->pFileHdl && pSrcCkoArray->uiFileNumber) + if( rc != NE_FLM_IO_PATH_NOT_FOUND) { - uiNewSlot = pSrcCkoArray->uiFileNumber % (m_uiCkoArraySize - 1) + 1; - - // Only overwrite the destination one if the file number is - // lower than the one already there - - if (pSrcCkoArray->uiFileNumber < - m_pCheckedOutFileHdls [uiNewSlot].uiFileNumber || - !m_pCheckedOutFileHdls [uiNewSlot].uiFileNumber) - { - if (m_pCheckedOutFileHdls [uiNewSlot].uiFileNumber) - { - releaseFile( &m_pCheckedOutFileHdls [uiNewSlot], FALSE); - } - - f_memcpy( &m_pCheckedOutFileHdls [uiNewSlot], pSrcCkoArray, - sizeof( CHECKED_OUT_FILE_HDL)); - if (uiNewSlot > m_uiHighestUsedSlot) - { - m_uiHighestUsedSlot = uiNewSlot; - } - - if (m_uiHighestFileNumber < pSrcCkoArray->uiFileNumber) - { - m_uiHighestFileNumber = pSrcCkoArray->uiFileNumber; - } - - if (pSrcCkoArray->bDirty) - { - if (m_uiLowestDirtySlot > m_uiHighestDirtySlot) - { - m_uiLowestDirtySlot = - m_uiHighestDirtySlot = uiNewSlot; - } - else if( m_uiHighestDirtySlot < uiNewSlot) - { - m_uiHighestDirtySlot = uiNewSlot; - } - else if (m_uiLowestDirtySlot < uiNewSlot) - { - m_uiLowestDirtySlot = uiNewSlot; - } - } - } - else - { - releaseFile( pSrcCkoArray, FALSE); - } + goto Exit; + } + + if( RC_BAD( rc = createFile( + m_pSuperFileClient->getFileNumber( uiBlkAddress), &pFileHdl))) + { + goto Exit; } } -} -/**************************************************************************** -Desc: Disable flush minimizing. -****************************************************************************/ -void F_SuperFileHdl::disableFlushMinimize( void) -{ - - // Copy the allocated array back into the fixed array. - // This doesn't necessarily copy all of the file handles. - - if( m_pCheckedOutFileHdls != &m_CheckedOutFileHdls [0]) - { - CHECKED_OUT_FILE_HDL * pOldCkoArray = m_pCheckedOutFileHdls; - FLMUINT uiOldHighestUsedSlot = m_uiHighestUsedSlot; - - m_pCheckedOutFileHdls = &m_CheckedOutFileHdls [0]; - m_uiCkoArraySize = MAX_CHECKED_OUT_FILE_HDLS + 1; - copyCkoFileHdls( pOldCkoArray, uiOldHighestUsedSlot); - - f_free( &pOldCkoArray); - } + pFileHdl->setExtendSize( m_uiExtendSize); + pFileHdl->setMaxAutoExtendSize( m_uiMaxAutoExtendSize); - m_bMinimizeFlushes = FALSE; + if( RC_BAD( rc = pFileHdl->write( + m_pSuperFileClient->getFileOffset( uiBlkAddress), uiBytesToWrite, + pvBuffer, puiBytesWritten))) + { + goto Exit; + } + +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); } /**************************************************************************** Desc: Flush dirty files to disk. ****************************************************************************/ -RCODE F_SuperFileHdl::flush( void) +RCODE FLMAPI F_SuperFileHdl::flush( void) { RCODE rc = NE_FLM_OK; - FLMUINT uiLoop; - - // Flush all dirty files - - for( uiLoop = m_uiLowestDirtySlot; - uiLoop <= m_uiHighestDirtySlot; - uiLoop++) + + if( m_pCFileHdl && m_bCFileDirty) { - if( m_pCheckedOutFileHdls[ uiLoop].bDirty) + if( RC_BAD( rc = m_pCFileHdl->flush())) { - RCODE tmpRc; - - if( RC_BAD( tmpRc = - m_pCheckedOutFileHdls[ uiLoop].pFileHdl->flush())) - { - rc = tmpRc; - releaseFile( &m_pCheckedOutFileHdls [uiLoop], TRUE); - } - - m_pCheckedOutFileHdls[ uiLoop].bDirty = FALSE; + goto Exit; } + + m_bCFileDirty = FALSE; } - m_uiLowestDirtySlot = 1; - m_uiHighestDirtySlot = 0; + if( m_pBlockFileHdl && m_bBlockFileDirty) + { + if( RC_BAD( rc = m_pBlockFileHdl->flush())) + { + goto Exit; + } + + m_bBlockFileDirty = FALSE; + } +Exit: + return( rc); } /**************************************************************************** Desc: Truncates back to an end of file block address. - This may only be called from reduce() because there cannot - be any other cases to reduce a 3x block file. ****************************************************************************/ -RCODE F_SuperFileHdl::truncateFile( +RCODE FLMAPI F_SuperFileHdl::truncateFile( FLMUINT uiEOFBlkAddress) { RCODE rc = NE_FLM_OK; FLMUINT uiFileNumber = m_pSuperFileClient->getFileNumber( uiEOFBlkAddress); FLMUINT uiBlockOffset = m_pSuperFileClient->getFileOffset( uiEOFBlkAddress); - IF_FileHdl * pFileHdl; + IF_FileHdl * pFileHdl = NULL; // Truncate the current block file. @@ -535,244 +377,286 @@ RCODE F_SuperFileHdl::truncateFile( if( RC_BAD( rc = pFileHdl->truncate( uiBlockOffset))) { - releaseFile( uiFileNumber, TRUE); goto Exit; } - // Visit the rest of the high block files until a NULL file hdl is hit. + // Truncate all of the block files beyon the end-of-file address for( ;;) { + pFileHdl->Release(); + pFileHdl = NULL; + if( RC_BAD( getFileHdl( ++uiFileNumber, TRUE, &pFileHdl))) { break; } - if( RC_BAD( rc = pFileHdl->truncate( (FLMUINT)0 ))) - { - releaseFile( uiFileNumber, TRUE); - goto Exit; - } - - if( RC_BAD( rc = releaseFile( uiFileNumber, TRUE))) + if( RC_BAD( rc = pFileHdl->truncate())) { goto Exit; } } -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Truncate to zero length any files between the specified start - and end files. -****************************************************************************/ -void F_SuperFileHdl::truncateFiles( - FLMUINT uiStartFileNum, - FLMUINT uiEndFileNum) -{ - FLMUINT uiFileNumber; - IF_FileHdl * pFileHdl; - - for( uiFileNumber = uiStartFileNum; - uiFileNumber <= uiEndFileNum; - uiFileNumber++ ) - { - if( RC_OK( getFileHdl( uiFileNumber, TRUE, &pFileHdl ))) - { - (void)pFileHdl->truncate( (FLMUINT)0 ); - (void)releaseFile( uiFileNumber, TRUE); - } - } -} - -/**************************************************************************** -Desc: Returns the physical size of a file -****************************************************************************/ -RCODE F_SuperFileHdl::getFileSize( - FLMUINT uiFileNumber, - FLMUINT64 * pui64FileSize) -{ - RCODE rc = NE_FLM_OK; - IF_FileHdl * pFileHdl = NULL; - - *pui64FileSize = 0; - - // Get the file handle. - - if( RC_BAD( rc = getFileHdl( uiFileNumber, FALSE, &pFileHdl))) - { - goto Exit; - } - - if( RC_BAD( rc = pFileHdl->size( pui64FileSize))) - { - releaseFile( uiFileNumber, TRUE); - goto Exit; - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Returns the path of a file given its file number -****************************************************************************/ -RCODE F_SuperFileHdl::getFilePath( - FLMUINT uiFileNumber, - char * pszIoPath) -{ - return( m_pSuperFileClient->getFilePath( uiFileNumber, pszIoPath)); -} - -/**************************************************************************** -Desc: Reallocates the checked out file handle array. -****************************************************************************/ -RCODE F_SuperFileHdl::reallocCkoArray( - FLMUINT uiFileNum) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiNewSize; - CHECKED_OUT_FILE_HDL * pNewCkoArray; - CHECKED_OUT_FILE_HDL * pOldCkoArray; - FLMUINT uiOldHighestUsedSlot; - - if (uiFileNum < m_uiHighestFileNumber) - { - uiFileNum = m_uiHighestFileNumber; - } - - uiNewSize = uiFileNum + 128; - - if (RC_BAD( rc = f_calloc( sizeof( CHECKED_OUT_FILE_HDL) * uiNewSize, - &pNewCkoArray))) - { - goto Exit; - } - - pOldCkoArray = m_pCheckedOutFileHdls; - uiOldHighestUsedSlot = m_uiHighestUsedSlot; - - m_pCheckedOutFileHdls = pNewCkoArray; - m_uiCkoArraySize = uiNewSize; - - copyCkoFileHdls( pOldCkoArray, uiOldHighestUsedSlot); - - // Can't free the old one until after the copy! - - if (pOldCkoArray != &m_CheckedOutFileHdls [0]) - { - f_free( &pOldCkoArray); - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Returns a file handle given the file's number -****************************************************************************/ -RCODE F_SuperFileHdl::getFileHdl( - FLMUINT uiFileNum, - FLMBOOL bGetForUpdate, - IF_FileHdl ** ppFileHdl) -{ - RCODE rc = NE_FLM_OK; - IF_FileHdl * pFileHdl = NULL; - CHECKED_OUT_FILE_HDL * pCkoFileHdl; - char szFilePath[ F_PATH_MAX_SIZE]; - FLMUINT uiSlot; - - pCkoFileHdl = getCkoFileHdlPtr( uiFileNum, &uiSlot); - if( pCkoFileHdl->uiFileNumber != uiFileNum && - pCkoFileHdl->pFileHdl) - { - if( pCkoFileHdl->bDirty && m_bMinimizeFlushes) - { - flmAssert( pCkoFileHdl->uiFileNumber); - if (RC_BAD( reallocCkoArray( uiFileNum))) - { - goto Exit; - } - pCkoFileHdl = getCkoFileHdlPtr( uiFileNum, &uiSlot); - - // Better have reallocated so that the new slot for - // the file number has nothing in it. - - flmAssert( !pCkoFileHdl->uiFileNumber && - !pCkoFileHdl->pFileHdl); - } - else - { - if( RC_BAD( rc = releaseFile( pCkoFileHdl, FALSE))) - { - goto Exit; - } - } - } - - if( !pCkoFileHdl->pFileHdl) - { - if (!pFileHdl) - { - // Build the file path - - if( RC_BAD( rc = m_pSuperFileClient->getFilePath( - uiFileNum, szFilePath))) - { - goto Exit; - } - - // Open the file - - if( RC_BAD( rc = f_getFileSysPtr()->openFile( szFilePath, - FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, - &pFileHdl))) - { - goto Exit; - } - } - - pCkoFileHdl->pFileHdl = pFileHdl; - pFileHdl = NULL; - pCkoFileHdl->uiFileNumber = uiFileNum; - pCkoFileHdl->bDirty = FALSE; - - if( m_uiHighestUsedSlot < uiSlot) - { - m_uiHighestUsedSlot = uiSlot; - } - - if (m_uiHighestFileNumber < uiFileNum) - { - m_uiHighestFileNumber = uiFileNum; - } - } - - *ppFileHdl = pCkoFileHdl->pFileHdl; - if( bGetForUpdate) - { - pCkoFileHdl->bDirty = TRUE; - if (m_uiLowestDirtySlot > m_uiHighestDirtySlot) - - { - m_uiLowestDirtySlot = - m_uiHighestDirtySlot = uiSlot; - } - else if( m_uiHighestDirtySlot < uiSlot) - { - m_uiHighestDirtySlot = uiSlot; - } - else if (m_uiLowestDirtySlot < uiSlot) - { - m_uiLowestDirtySlot = uiSlot; - } - } - +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); +} + +/**************************************************************************** +Desc: Truncates back to an end of file block address. +****************************************************************************/ +RCODE FLMAPI F_SuperFileHdl::truncateFile( + FLMUINT uiFileNumber, + FLMUINT uiOffset) +{ + RCODE rc = NE_FLM_OK; + IF_FileHdl * pFileHdl = NULL; + + if( RC_BAD( rc = getFileHdl( uiFileNumber, TRUE, &pFileHdl))) + { + goto Exit; + } + + if( RC_BAD( rc = pFileHdl->truncate( uiOffset))) + { + goto Exit; + } + +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); +} + +/**************************************************************************** +Desc: Truncate to zero length any files between the specified start + and end files. +****************************************************************************/ +void FLMAPI F_SuperFileHdl::truncateFiles( + FLMUINT uiStartFileNum, + FLMUINT uiEndFileNum) +{ + FLMUINT uiFileNumber; + IF_FileHdl * pFileHdl = NULL; + + for( uiFileNumber = uiStartFileNum; + uiFileNumber <= uiEndFileNum; + uiFileNumber++) + { + if( RC_OK( getFileHdl( uiFileNumber, TRUE, &pFileHdl))) + { + pFileHdl->truncate(); + pFileHdl->Release(); + } + } +} + +/**************************************************************************** +Desc: Returns the physical size of a file +****************************************************************************/ +RCODE FLMAPI F_SuperFileHdl::getFileSize( + FLMUINT uiFileNumber, + FLMUINT64 * pui64FileSize) +{ + RCODE rc = NE_FLM_OK; + IF_FileHdl * pFileHdl = NULL; + + *pui64FileSize = 0; + + if( RC_BAD( rc = getFileHdl( uiFileNumber, FALSE, &pFileHdl))) + { + goto Exit; + } + + if( RC_BAD( rc = pFileHdl->size( pui64FileSize))) + { + goto Exit; + } + +Exit: + + if( pFileHdl) + { + pFileHdl->Release(); + } + + return( rc); +} + +/**************************************************************************** +Desc: Returns the path of a file given its file number +****************************************************************************/ +RCODE FLMAPI F_SuperFileHdl::getFilePath( + FLMUINT uiFileNumber, + char * pszIoPath) +{ + return( m_pSuperFileClient->getFilePath( uiFileNumber, pszIoPath)); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +FLMBOOL FLMAPI F_SuperFileHdl::canDoAsync( void) +{ + FLMBOOL bCanDoAsync = FALSE; + + if( m_pCFileHdl) + { + bCanDoAsync = m_pCFileHdl->canDoAsync(); + } + else + { + IF_FileHdl * pFileHdl = NULL; + + if( RC_OK( getFileHdl( 0, FALSE, &pFileHdl))) + { + bCanDoAsync = pFileHdl->canDoAsync(); + pFileHdl->Release(); + } + } + + return( bCanDoAsync); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE FLMAPI F_SuperFileHdl::releaseFiles( void) +{ + RCODE rc = NE_FLM_OK; + + if( RC_BAD( rc = flush())) + { + goto Exit; + } + + if( m_pCFileHdl) + { + m_pCFileHdl->Release(); + m_pCFileHdl = NULL; + } + + if( m_pBlockFileHdl) + { + m_pBlockFileHdl->Release(); + m_pBlockFileHdl = NULL; + m_uiBlockFileNum = 0; + } + + m_pFileHdlCache->closeUnusedFiles(); + +Exit: + + return( rc); +} + +/**************************************************************************** +Desc: Returns a file handle given the file's number +****************************************************************************/ +RCODE FLMAPI F_SuperFileHdl::getFileHdl( + FLMUINT uiFileNum, + FLMBOOL bForUpdate, + IF_FileHdl ** ppFileHdl) +{ + RCODE rc = NE_FLM_OK; + IF_FileHdl * pFileHdl = NULL; + char szFilePath[ F_PATH_MAX_SIZE]; + + f_assert( *ppFileHdl == NULL); + + if( !uiFileNum) + { + if( !m_pCFileHdl) + { + if( RC_BAD( rc = m_pSuperFileClient->getFilePath( + uiFileNum, szFilePath))) + { + goto Exit; + } + + if( RC_BAD( rc = m_pFileHdlCache->openFile( szFilePath, + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | m_uiDirectIOFlag, + &pFileHdl))) + { + goto Exit; + } + + m_pCFileHdl = pFileHdl; + m_pCFileHdl->AddRef(); + } + else + { + pFileHdl = m_pCFileHdl; + pFileHdl->AddRef(); + } + + if( bForUpdate) + { + m_bCFileDirty = TRUE; + } + } + else + { + if( m_pBlockFileHdl) + { + if( m_uiBlockFileNum != uiFileNum) + { + if( m_bBlockFileDirty) + { + m_pBlockFileHdl->flush(); + m_bBlockFileDirty = FALSE; + } + + m_pBlockFileHdl->Release(); + m_pBlockFileHdl = NULL; + m_uiBlockFileNum = 0; + } + } + + if( !m_pBlockFileHdl) + { + if( RC_BAD( rc = m_pSuperFileClient->getFilePath( + uiFileNum, szFilePath))) + { + goto Exit; + } + + if( RC_BAD( rc = m_pFileHdlCache->openFile( szFilePath, + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | m_uiDirectIOFlag, + &pFileHdl))) + { + goto Exit; + } + + m_uiBlockFileNum = uiFileNum; + m_pBlockFileHdl = pFileHdl; + m_pBlockFileHdl->AddRef(); + } + else + { + pFileHdl = m_pBlockFileHdl; + pFileHdl->AddRef(); + } + + if( bForUpdate) + { + m_bBlockFileDirty = TRUE; + } + } + + *ppFileHdl = pFileHdl; + pFileHdl = NULL; + Exit: if( pFileHdl) diff --git a/ftk/src/ftksys.h b/ftk/src/ftksys.h index 9e1d525..dc9ec38 100644 --- a/ftk/src/ftksys.h +++ b/ftk/src/ftksys.h @@ -42,11 +42,11 @@ class F_FileHdl; class F_Thread; class F_ThreadMgr; - class F_IOBufferMgr; class F_FileSystem; class F_ThreadMgr; class F_ResultSet; class F_ResultSetBlk; + class F_IOBufferMgr; /**************************************************************************** Desc: Global data @@ -104,6 +104,9 @@ // Function XXX not inlined #pragma warning( disable : 4710) + + // Flow in or out of inline asm code suppresses global optimization + #pragma warning( disable : 4740) #define ENDLINE ENDLINE_CRLF @@ -268,6 +271,19 @@ #define FLM_PRINTF_INT64_FLAG 0x0100 #define FLM_PRINTF_COMMA_FLAG 0x0200 + /**************************************************************************** + Desc: + ****************************************************************************/ + typedef enum + { + MGR_LIST_NONE, + MGR_LIST_AVAIL, + MGR_LIST_PENDING, + MGR_LIST_USED + } eBufferMgrList; + + #define F_DEFAULT_CBDATA_SLOTS 16 + /**************************************************************************** Desc: ****************************************************************************/ @@ -275,15 +291,54 @@ { public: - F_IOBuffer(); + F_IOBuffer() + { + m_pucBuffer = NULL; + m_uiBufferSize = 0; + m_pBufferMgr = NULL; + m_pAsyncClient = NULL; + m_fnCompletion = NULL; + m_pvData = NULL; + m_ppCallbackData = m_callbackData; + m_uiMaxCallbackData = F_DEFAULT_CBDATA_SLOTS; + m_pPrev = NULL; + m_pNext = NULL; + m_eList = MGR_LIST_NONE; + resetBuffer(); + } + + virtual ~F_IOBuffer() + { + if( m_pucBuffer) + { + cleanupBuffer(); + f_freeAlignedBuffer( (void **)&m_pucBuffer); + } + + if( m_pAsyncClient) + { + m_pAsyncClient->Release(); + } + } - virtual ~F_IOBuffer(); + FLMINT FLMAPI Release( void); + + RCODE setupBuffer( + FLMUINT uiBufferSize, + F_IOBufferMgr * pBufferMgr); + + FINLINE void resetBuffer( void) + { + f_assert( !m_pAsyncClient); + + cleanupBuffer(); + m_uiElapsedTime = 0; + m_completionRc = NE_FLM_OK; + m_bPending = FALSE; + m_bCompleted = FALSE; + } - RCODE FLMAPI setupBuffer( - FLMUINT uiBufferSize, - FLMUINT uiBlockSize); - - FINLINE FLMBYTE * FLMAPI getBuffer( void) + FINLINE FLMBYTE * FLMAPI getBufferPtr( void) { return( m_pucBuffer); } @@ -293,124 +348,218 @@ return( m_uiBufferSize); } - FINLINE FLMUINT FLMAPI getBlockSize( void) - { - return( m_uiBlockSize); - } - - void FLMAPI notifyComplete( - RCODE rc); - - void FLMAPI signalComplete( - RCODE rc); - FINLINE void FLMAPI setCompletionCallback( - WRITE_COMPLETION_CB fnCompletion) + F_BUFFER_COMPLETION_FUNC fnCompletion, + void * pvData) { m_fnCompletion = fnCompletion; + m_pvData = pvData; } - - FINLINE void FLMAPI setCompletionCallbackData( - FLMUINT uiBlockNumber, - void * pvData) + + RCODE FLMAPI addCallbackData( + void * pvData); + + void * FLMAPI getCallbackData( + FLMUINT uiSlot); + + FINLINE FLMUINT FLMAPI getCallbackDataCount( void) { - f_assert( uiBlockNumber < FLM_MAX_IO_BUFFER_BLOCKS); - m_UserData [uiBlockNumber] = pvData; + return( m_uiCallbackDataCount); } - - FINLINE void * FLMAPI getCompletionCallbackData( - FLMUINT uiBlockNumber) + + FINLINE void FLMAPI cleanupBuffer( void) { - f_assert( uiBlockNumber < FLM_MAX_IO_BUFFER_BLOCKS); - return( m_UserData [uiBlockNumber]); + if( m_fnCompletion) + { + m_fnCompletion( this, m_pvData); + } + + m_fnCompletion = NULL; + m_pvData = NULL; + + if( m_ppCallbackData && m_ppCallbackData != m_callbackData) + { + f_free( &m_ppCallbackData); + } + + m_uiMaxCallbackData = F_DEFAULT_CBDATA_SLOTS; + m_uiCallbackDataCount = 0; + m_ppCallbackData = m_callbackData; } - + + void FLMAPI setAsyncClient( + IF_AsyncClient * pAsyncClient) + { + if( m_pAsyncClient) + { + m_pAsyncClient->Release(); + } + + if( (m_pAsyncClient = pAsyncClient) != NULL) + { + m_pAsyncClient->AddRef(); + } + } + + void FLMAPI getAsyncClient( + IF_AsyncClient ** ppAsyncClient) + { + if( (*ppAsyncClient = m_pAsyncClient) != NULL) + { + (*ppAsyncClient)->AddRef(); + } + } + + void FLMAPI setPending( void); + + void FLMAPI clearPending( void); + + void FLMAPI notifyComplete( + RCODE completionRc); + + FINLINE FLMBOOL FLMAPI isPending( void) + { + return( m_bPending); + } + + FINLINE RCODE FLMAPI waitToComplete( void) + { + RCODE rc = NE_FLM_OK; + + f_assert( m_bPending); + + if( m_pAsyncClient) + { + IF_AsyncClient * pAsyncClient = m_pAsyncClient; + + m_pAsyncClient = NULL; + rc = pAsyncClient->waitToComplete( TRUE); + } + + return( rc); + } + + FINLINE FLMBOOL FLMAPI isComplete( void) + { + return( m_bCompleted); + } + FINLINE RCODE FLMAPI getCompletionCode( void) { + f_assert( m_bCompleted); return( m_completionRc); } - - FINLINE eBufferMgrList FLMAPI getList( void) + + FINLINE FLMUINT FLMAPI getElapsedTime( void) { - return( m_eList); + f_assert( m_bCompleted); + return( m_uiElapsedTime); } - - void FLMAPI makePending( void); - - FLMBOOL FLMAPI isPending( void); - - void FLMAPI startTimer( - void * pvStats); - void * FLMAPI getStats( void); - - FLMUINT64 FLMAPI getElapTime( void); - - #ifdef FLM_WIN - FINLINE OVERLAPPED * getOverlapped( void) - { - return( &m_Overlapped); - } - - FINLINE void setFileHandle( - HANDLE FileHandle) - { - m_FileHandle = FileHandle; - } - #endif - - #if defined( FLM_LINUX) || defined( FLM_SOLARIS) || defined( FLM_OSX) - FINLINE struct aiocb * getAIOStruct( void) - { - return( &m_aio); - } - #endif - private: - // Only called by the buffer manager + FLMBYTE * m_pucBuffer; + FLMUINT m_uiBufferSize; + F_IOBufferMgr * m_pBufferMgr; + IF_AsyncClient * m_pAsyncClient; + F_BUFFER_COMPLETION_FUNC m_fnCompletion; + void * m_pvData; + FLMUINT m_uiElapsedTime; + RCODE m_completionRc; + FLMBOOL m_bPending; + FLMBOOL m_bCompleted; + FLMUINT m_uiStartTime; + FLMUINT m_uiEndTime; + void * m_callbackData[ F_DEFAULT_CBDATA_SLOTS]; + void ** m_ppCallbackData; + FLMUINT m_uiCallbackDataCount; + FLMUINT m_uiMaxCallbackData; + F_IOBuffer * m_pPrev; + F_IOBuffer * m_pNext; + eBufferMgrList m_eList; + + friend class F_FileAsyncClient; + friend class F_IOBufferMgr; + }; - RCODE setupIOBuffer( - IF_IOBufferMgr * pIOBufferMgr); + /**************************************************************************** + Desc: + ****************************************************************************/ + class FLMEXP F_FileAsyncClient : public IF_AsyncClient + { + public: - FLMBOOL isIOComplete( void); + F_FileAsyncClient() + { + m_pFileHdl = NULL; + m_pIOBuffer = NULL; + m_completionRc = NE_FLM_OK; + m_uiBytesToDo = 0; + m_uiBytesDone = 0; + m_pNext = NULL; + #ifdef FLM_WIN + m_Overlapped.hEvent = 0; + #endif + #ifdef FLM_RING_ZERO_NLM + m_hSem = NULL; + #endif + } + + ~F_FileAsyncClient(); + + FLMINT FLMAPI Release(); + + RCODE FLMAPI waitToComplete( + FLMBOOL bRelease); + + RCODE FLMAPI getCompletionCode( void); + + FLMUINT FLMAPI getElapsedTime( void); + + F_FileAsyncClient * m_pNext; + + void signalComplete( + RCODE rc, + FLMUINT uiBytesDone); + + FLMUINT getBytesToDo( void) + { + return( m_uiBytesToDo); + } + + private: - RCODE waitToComplete( void); - - // Private methods and variables - - F_IOBufferMgr * m_pIOBufferMgr; - FLMBYTE * m_pucBuffer; - void * m_UserData[ FLM_MAX_IO_BUFFER_BLOCKS]; - FLMUINT m_uiBufferSize; - FLMUINT m_uiBlockSize; - eBufferMgrList m_eList; - FLMBOOL m_bDeleteOnNotify; - #ifdef FLM_WIN - HANDLE m_FileHandle; - OVERLAPPED m_Overlapped; + RCODE prepareForAsync( + IF_IOBuffer * pIOBuffer); + + void FLMAPI notifyComplete( + RCODE completionRc, + FLMUINT uiBytesDone, + FLMBOOL bRelease); + + F_FileHdl * m_pFileHdl; + IF_IOBuffer * m_pIOBuffer; + RCODE m_completionRc; + FLMUINT m_uiBytesToDo; + FLMUINT m_uiBytesDone; + FLMUINT m_uiStartTime; + FLMUINT m_uiEndTime; + #if defined( FLM_WIN) + OVERLAPPED m_Overlapped; #endif #if defined( FLM_LINUX) || defined( FLM_SOLARIS) || defined( FLM_OSX) - struct aiocb m_aio; + struct aiocb m_aio; + #endif + #ifdef FLM_RING_ZERO_NLM + SEMAPHORE m_hSem; #endif - F_IOBuffer * m_pNext; - F_IOBuffer * m_pPrev; - WRITE_COMPLETION_CB m_fnCompletion; - RCODE m_completionRc; - F_TMSTAMP m_StartTime; - FLMUINT64 m_ui64ElapMilli; - void * m_pStats; -#ifdef FLM_RING_ZERO_NLM - SEMAPHORE m_hSem; -#endif - friend class F_IOBufferMgr; + friend class F_FileHdl; }; /*************************************************************************** Desc: ***************************************************************************/ - #ifdef FLM_WIN class F_FileHdl : public IF_FileHdl { public: @@ -419,426 +568,55 @@ virtual ~F_FileHdl(); - RCODE FLMAPI close( void); - RCODE FLMAPI flush( void); - + RCODE FLMAPI read( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE FLMAPI seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset); - - RCODE FLMAPI size( - FLMUINT64 * pui64Size); - - RCODE FLMAPI tell( - FLMUINT64 * pui64Offset); - - RCODE FLMAPI truncate( - FLMUINT64 ui64Size); - + FLMUINT64 ui64Offset, + FLMUINT uiLength, + void * pvBuffer, + FLMUINT * puiBytesRead = NULL); + + RCODE FLMAPI read( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + IF_IOBuffer * pIOBuffer); + + RCODE FLMAPI write( + FLMUINT64 ui64Offset, + FLMUINT uiLength, + const void * pvBuffer, + FLMUINT * puiBytesWritten = NULL); + RCODE FLMAPI write( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - const void * pvBuffer, - FLMUINT * puiBytesWritten); - - FINLINE RCODE FLMAPI sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) - { - if (m_bDoDirectIO) - { - return( directRead( ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesReadRV)); - } - else - { - return( read( ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesReadRV)); - } - } - - FINLINE RCODE FLMAPI sectorWrite( FLMUINT64 ui64WriteOffset, FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) - { - if (m_bDoDirectIO) - { - return( directWrite( ui64WriteOffset, uiBytesToWrite, - pvBuffer, pBufferObj, puiBytesWrittenRV)); - } - else - { - f_assert( !pBufferObj); - return( write( ui64WriteOffset, uiBytesToWrite, pvBuffer, - puiBytesWrittenRV)); - } - } - + IF_IOBuffer * pIOBuffer); + + RCODE FLMAPI seek( + FLMUINT64 ui64Offset, + FLMINT iWhence, + FLMUINT64 * pui64NewOffset = NULL); + + RCODE FLMAPI size( + FLMUINT64 * pui64Size); + + RCODE FLMAPI tell( + FLMUINT64 * pui64Offset); + + RCODE FLMAPI truncate( + FLMUINT64 ui64Offset = 0); + + RCODE FLMAPI close( void); + FINLINE FLMBOOL FLMAPI canDoAsync( void) { return( m_bOpenedInAsyncMode); } - FINLINE void FLMAPI setExtendSize( - FLMUINT uiExtendSize) - { - m_uiExtendSize = uiExtendSize; - } - - FINLINE void FLMAPI setMaxAutoExtendSize( - FLMUINT uiMaxAutoExtendSize) - { - m_uiMaxAutoExtendSize = uiMaxAutoExtendSize; - } - - FINLINE FLMBOOL FLMAPI isReadOnly( void) - { - return( m_bOpenedReadOnly); - } - - RCODE FLMAPI lock( void); - - RCODE FLMAPI unlock( void); - - FINLINE FLMUINT FLMAPI getSectorSize( void) - { - return( m_uiBytesPerSector); - } - - private: - - RCODE create( - const char * pszFileName, - FLMUINT uiIoFlags); - - RCODE createUnique( - char * pszDirName, - const char * pszFileExtension, - FLMUINT uiIoFlags); - - RCODE open( - const char * pszFileName, - FLMUINT uiIoFlags); - - FINLINE HANDLE getFileHandle( void) - { - return m_FileHandle; - } - - RCODE openOrCreate( - const char * pszFileName, - FLMUINT uiAccess, - FLMBOOL bCreateFlag); - - RCODE doOneRead( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE directRead( - FLMUINT64 uiOffset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE directWrite( - FLMUINT64 uiOffset, - FLMUINT uiLength, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWritten); - - FINLINE FLMUINT64 roundToNextSector( - FLMUINT64 ui64Bytes) - { - return( (ui64Bytes + m_ui64NotOnSectorBoundMask) & - m_ui64GetSectorBoundMask); - } - - FINLINE FLMUINT64 truncateToPrevSector( - FLMUINT64 ui64Offset) - { - return( ui64Offset & m_ui64GetSectorBoundMask); - } - - RCODE extendFile( - FLMUINT64 ui64EndOfLastWrite, - FLMUINT uiMaxBytesToExtend, - FLMBOOL bFlush); - - RCODE allocAlignedBuffer( void); - - FLMBOOL m_bFileOpened; - FLMBOOL m_bDeleteOnRelease; - FLMBOOL m_bOpenedReadOnly; - FLMBOOL m_bOpenedExclusive; - char * m_pszFileName; - HANDLE m_FileHandle; - FLMUINT m_uiBytesPerSector; - FLMUINT64 m_ui64NotOnSectorBoundMask; - FLMUINT64 m_ui64GetSectorBoundMask; - FLMBOOL m_bDoDirectIO; - FLMUINT m_uiExtendSize; - FLMUINT m_uiMaxAutoExtendSize; - FLMBYTE * m_pucAlignedBuff; - FLMUINT m_uiAlignedBuffSize; - FLMUINT64 m_ui64CurrentPos; - FLMBOOL m_bOpenedInAsyncMode; - OVERLAPPED m_Overlapped; - - friend class F_FileSystem; - friend class F_MultiFileHdl; - }; - #endif - - /*************************************************************************** - Desc: - ***************************************************************************/ - #if defined( FLM_UNIX) || defined( FLM_LIBC_NLM) - class F_FileHdl : public IF_FileHdl - { - public: - - F_FileHdl(); - - ~F_FileHdl(); - - RCODE FLMAPI flush( void); - - RCODE FLMAPI read( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE FLMAPI seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset); - - RCODE FLMAPI size( - FLMUINT64 * pui64Size); - - RCODE FLMAPI tell( - FLMUINT64 * pui64Offset); - - RCODE FLMAPI truncate( - FLMUINT64 ui64Size); - - RCODE FLMAPI write( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - const void * pvBuffer, - FLMUINT * puiBytesWritten); - - RCODE FLMAPI sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV); - - RCODE FLMAPI sectorWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) - { - if( m_bDoDirectIO) - { - return( directWrite( ui64WriteOffset, uiBytesToWrite, - pvBuffer, pBufferObj, puiBytesWrittenRV)); - } - else - { - return( write( ui64WriteOffset, uiBytesToWrite, - pvBuffer, puiBytesWrittenRV)); - } - } - - RCODE FLMAPI close( void); - - FLMBOOL FLMAPI canDoAsync( void); - - FINLINE FLMBOOL FLMAPI usingDirectIo( void) - { - return( m_bDoDirectIO); - } - - FINLINE void FLMAPI setExtendSize( - FLMUINT uiExtendSize) - { - m_uiExtendSize = uiExtendSize; - } - - FINLINE void FLMAPI setMaxAutoExtendSize( - FLMUINT) - { - } - - RCODE FLMAPI lock( void); - - RCODE FLMAPI unlock( void); - - FINLINE FLMBOOL FLMAPI isReadOnly( void) - { - return( m_bOpenedReadOnly); - } - - FINLINE FLMUINT FLMAPI getSectorSize( void) - { - return( m_uiBytesPerSector); - } - - private: - - RCODE create( - const char * pszFileName, - FLMUINT uiIoFlags); - - RCODE createUnique( - char * pszDirName, - const char * pszFileExtension, - FLMUINT uiIoFlags); - - RCODE open( - const char * pszFileName, - FLMUINT uiIoFlags); - - RCODE openOrCreate( - const char * pszFileName, - FLMUINT uiAccess, - FLMBOOL bCreateFlag); - - FINLINE FLMUINT64 roundToNextSector( - FLMUINT64 ui64Bytes) - { - return( (ui64Bytes + m_ui64NotOnSectorBoundMask) & - m_ui64GetSectorBoundMask); - } - - FINLINE FLMUINT64 truncateToPrevSector( - FLMUINT64 ui64Offset) - { - return( ui64Offset & m_ui64GetSectorBoundMask); - } - - RCODE doOneRead( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE directRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE directWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV); - - RCODE allocAlignedBuffer( void); - - FLMBOOL m_bFileOpened; - FLMBOOL m_bDeleteOnRelease; - FLMBOOL m_bOpenedReadOnly; - FLMBOOL m_bOpenedExclusive; - char * m_pszFileName; - int m_fd; - FLMUINT m_uiBytesPerSector; - FLMUINT64 m_ui64NotOnSectorBoundMask; - FLMUINT64 m_ui64GetSectorBoundMask; - FLMUINT64 m_ui64CurrentPos; - FLMUINT m_uiExtendSize; - FLMBOOL m_bOpenedInAsyncMode; - FLMBOOL m_bDoDirectIO; - FLMBYTE * m_pucAlignedBuff; - FLMUINT m_uiAlignedBuffSize; - - friend class F_FileSystem; - friend class F_MultiFileHdl; - }; - #endif - - /*************************************************************************** - Desc: - ***************************************************************************/ - #if defined( FLM_RING_ZERO_NLM) - class F_FileHdl : public IF_FileHdl - { - public: - - F_FileHdl(); - - virtual ~F_FileHdl(); - - RCODE FLMAPI flush( void); - - RCODE FLMAPI read( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE FLMAPI seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset); - - RCODE FLMAPI size( - FLMUINT64 * pui64Size); - - RCODE FLMAPI tell( - FLMUINT64 * pui64Offset); - - RCODE FLMAPI truncate( - FLMUINT64 ui64Size); - - RCODE FLMAPI write( - FLMUINT64 ui64Offset, - FLMUINT uiLength, - const void * pvBuffer, - FLMUINT * puiBytesWritten); - - RCODE FLMAPI sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV); - - RCODE FLMAPI sectorWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV); - - RCODE FLMAPI close( void); - - FLMBOOL FLMAPI canDoAsync( void); - FINLINE void FLMAPI setExtendSize( FLMUINT uiExtendSize) { + f_assert( uiExtendSize < FLM_MAX_UINT); m_uiExtendSize = uiExtendSize; } @@ -848,291 +626,173 @@ m_uiMaxAutoExtendSize = uiMaxAutoExtendSize; } - FINLINE void FLMAPI setSuballocation( - FLMBOOL bDoSuballocation) - { - m_bDoSuballocation = bDoSuballocation; - } - - FINLINE FLMUINT FLMAPI getSectorSize( void) - { - return( FLM_NLM_SECTOR_SIZE); - } - FINLINE FLMBOOL FLMAPI isReadOnly( void) { return( m_bOpenedReadOnly); } + FINLINE FLMBOOL FLMAPI isOpen( void) + { + return( m_bFileOpened); + } + + FINLINE FLMUINT FLMAPI getSectorSize( void) + { + return( m_uiBytesPerSector); + } + RCODE FLMAPI lock( void); RCODE FLMAPI unlock( void); + static F_MUTEX m_hAsyncListMutex; + static F_FileAsyncClient * m_pFirstAvailAsync; + static FLMUINT m_uiAvailAsyncCount; + private: + FINLINE FLMUINT64 roundToNextSector( + FLMUINT64 ui64Bytes) + { + f_assert( m_ui64GetSectorBoundMask); + f_assert( m_ui64NotOnSectorBoundMask); + + return( (ui64Bytes + m_ui64NotOnSectorBoundMask) & + m_ui64GetSectorBoundMask); + } + + FINLINE FLMUINT64 truncateToPrevSector( + FLMUINT64 ui64Offset) + { + return( ui64Offset & m_ui64GetSectorBoundMask); + } + + FINLINE const char * getFileName( void) + { + return( m_pszFileName); + } + + RCODE allocFileAsyncClient( + F_FileAsyncClient ** ppAsyncClient); + + void initCommonData( void); + + void freeCommonData( void); + + RCODE create( + const char * pszFileName, + FLMUINT uiIoFlags); + + RCODE createUnique( + char * pszDirName, + const char * pszFileExtension, + FLMUINT uiIoFlags); + + RCODE open( + const char * pszFileName, + FLMUINT uiIoFlags); + + RCODE openOrCreate( + const char * pszFileName, + FLMUINT uiAccess, + FLMBOOL bCreateFlag); + + RCODE lowLevelRead( + FLMUINT64 ui64Offset, + FLMUINT uiLength, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead); + + RCODE lowLevelWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten); + + RCODE directRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead); + + RCODE directWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten); + + #if defined( FLM_RING_ZERO_NLM) + RCODE setup( void); - RCODE create( - const char * pszFileName, - FLMUINT uiIoFlags); - - RCODE createUnique( - char * pszDirName, - const char * pszFileExtension, - FLMUINT uiIoFlags); - - RCODE open( - const char * pszFileName, - FLMUINT uiIoFlags); - - RCODE openOrCreate( - const char * pszFileName, - FLMUINT uiAccess, - FLMBOOL bCreateFlag); - - RCODE _read( - FLMUINT uiOffset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE _directIORead( - FLMUINT uiOffset, - FLMUINT uiLength, - void * pvBuffer, - FLMUINT * puiBytesRead); - - RCODE _directIOSectorRead( - FLMUINT uiReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV); - - RCODE _write( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV); - - RCODE _directIOWrite( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV); - RCODE expand( - LONG lStartSector, - LONG lSectorsToAlloc); + LONG lStartSector, + LONG lSectorsToAlloc); + RCODE internalBlockingRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + FLMUINT * puiBytesRead); + + RCODE internalBlockingWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + FLMUINT * puiBytesWritten); + RCODE writeSectors( - void * pvBuffer, - LONG lStartSector, - LONG lSectorCount, - IF_IOBuffer * pBufferObj, - FLMBOOL * pbDidAsync = NULL); - - RCODE _directIOSectorWrite( - FLMUINT uiWriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV); - - char * m_pszIoPath; - FLMBOOL m_bDeleteOnClose; - FLMUINT m_uiMaxFileSize; - FLMBOOL m_bFileOpened; - FLMBOOL m_bOpenedExclusive; - FLMBOOL m_bOpenedReadOnly; - LONG m_lFileHandle; - LONG m_lOpenAttr; - LONG m_lVolumeID; - LONG m_lLNamePathCount; - FLMBOOL m_bDoSuballocation; - FLMUINT m_uiExtendSize; - FLMUINT m_uiMaxAutoExtendSize; - FLMBOOL m_bDoDirectIO; - LONG m_lSectorsPerBlock; - LONG m_lMaxBlocks; - FLMUINT m_uiCurrentPos; - FLMBOOL m_bNSS; - FLMINT64 m_NssKey; - FLMBOOL m_bNSSFileOpen; + const void * pvBuffer, + F_FileAsyncClient * pAsyncClient, + LONG lStartSector, + LONG lSectorCount); + + #endif + + char * m_pszFileName; + FLMUINT m_uiBytesPerSector; + FLMUINT64 m_ui64NotOnSectorBoundMask; + FLMUINT64 m_ui64GetSectorBoundMask; + FLMUINT m_uiExtendSize; + FLMUINT m_uiMaxAutoExtendSize; + FLMBYTE * m_pucAlignedBuff; + FLMUINT m_uiAlignedBuffSize; + FLMUINT64 m_ui64CurrentPos; + FLMBOOL m_bFileOpened; + FLMBOOL m_bDeleteOnRelease; + FLMBOOL m_bOpenedReadOnly; + FLMBOOL m_bOpenedExclusive; + FLMBOOL m_bDoDirectIO; + FLMBOOL m_bOpenedInAsyncMode; + + #if defined( FLM_WIN) + HANDLE m_hFile; + FLMBOOL m_bFlushRequired; + #elif defined( FLM_UNIX) || defined( FLM_LIBC_NLM) + int m_fd; + #elif defined( FLM_RING_ZERO_NLM) + LONG m_lFileHandle; + LONG m_lOpenAttr; + LONG m_lVolumeID; + LONG m_lLNamePathCount; + FLMBOOL m_bDoSuballocation; + LONG m_lSectorsPerBlock; + LONG m_lMaxBlocks; + FLMBOOL m_bNSS; + FLMINT64 m_NssKey; + FLMBOOL m_bNSSFileOpen; + #endif friend class F_FileSystem; friend class F_MultiFileHdl; + friend class F_FileHdlCache; + friend class F_FileAsyncClient; }; - #endif - - /*************************************************************************** - Desc: - ***************************************************************************/ - #if 0 - class F_FileHdlMgr : public IF_FileHdlMgr - { - public: - F_FileHdlMgr(); - - virtual FINLINE ~F_FileHdlMgr() - { - if (m_hMutex != F_MUTEX_NULL) - { - lockMutex( FALSE); - freeUsedList( TRUE); - freeAvailList( TRUE); - unlockMutex( FALSE); - f_mutexDestroy( &m_hMutex); - } - } - - FINLINE void FLMAPI setOpenThreshold( - FLMUINT uiOpenThreshold) - { - if (m_bIsSetup) - { - lockMutex( FALSE); - m_uiOpenThreshold = uiOpenThreshold; - unlockMutex( FALSE); - } - } - - FINLINE void FLMAPI setMaxAvailTime( - FLMUINT uiMaxAvailTime) - { - if (m_bIsSetup) - { - lockMutex( FALSE); - m_uiMaxAvailTime = uiMaxAvailTime; - unlockMutex( FALSE); - } - } - - FINLINE FLMUINT FLMAPI getUniqueId( void) - { - FLMUINT uiTemp; - - lockMutex( FALSE); - uiTemp = ++m_uiFileIdCounter; - unlockMutex( FALSE); - return( uiTemp); - } - - void FLMAPI findAvail( - FLMUINT uiFileId, - IF_FileHdl ** ppFileHdl); - - void FLMAPI removeFileHdls( - FLMUINT uiFileId); - - void FLMAPI checkAgedFileHdls( - FLMUINT uiMinSecondsOpened); - - FINLINE FLMUINT FLMAPI getOpenThreshold( void) - { - return( m_uiOpenThreshold); - } - - FINLINE FLMUINT FLMAPI getOpenedFiles( void) - { - FLMUINT uiTemp; - - lockMutex( FALSE); - uiTemp = m_uiNumUsed + m_uiNumAvail; - unlockMutex( FALSE); - return( uiTemp); - } - - FINLINE FLMUINT FLMAPI getMaxAvailTime( void) - { - return( m_uiMaxAvailTime); - } - - private: - - RCODE setupFileHdlMgr( - FLMUINT uiOpenThreshold = FLM_DEFAULT_OPEN_THRESHOLD, - FLMUINT uiMaxAvailTime = FLM_DEFAULT_MAX_AVAIL_TIME); - - void freeAvailList( - FLMBOOL bMutexAlreadyLocked); - - void freeUsedList( - FLMBOOL bMutexAlreadyLocked); - - FINLINE void insertInUsedList( - FLMBOOL bMutexAlreadyLocked, - IF_FileHdl * pFileHdl, - FLMBOOL bInsertAtEnd) - { - insertInList( bMutexAlreadyLocked, - pFileHdl, bInsertAtEnd, - &m_pFirstUsed, &m_pLastUsed, &m_uiNumUsed); - } - - void makeAvailAndRelease( - FLMBOOL bMutexAlreadyLocked, - IF_FileHdl * pFileHdl); - - void FINLINE releaseOneAvail( - FLMBOOL bMutexAlreadyLocked) - { - lockMutex( bMutexAlreadyLocked); - if (m_pFirstAvail) - { - removeFromList( TRUE, - m_pFirstAvail, &m_pFirstAvail, &m_pLastAvail, &m_uiNumAvail); - } - unlockMutex( bMutexAlreadyLocked); - } - - void insertInList( - FLMBOOL bMutexAlreadyLocked, - IF_FileHdl * pFileHdl, - FLMBOOL bInsertAtEnd, - IF_FileHdl ** ppFirst, - IF_FileHdl ** ppLast, - FLMUINT * puiCount); - - void removeFromList( - FLMBOOL bMutexAlreadyLocked, - IF_FileHdl * pFileHdl, - IF_FileHdl ** ppFirst, - IF_FileHdl ** ppLast, - FLMUINT * puiCount); - - FINLINE void lockMutex( - FLMBOOL bMutexAlreadyLocked) - { - if (m_hMutex != F_MUTEX_NULL && !bMutexAlreadyLocked) - { - f_mutexLock( m_hMutex); - } - } - - FINLINE void unlockMutex( - FLMBOOL bMutexAlreadyLocked) - { - if (m_hMutex != F_MUTEX_NULL && !bMutexAlreadyLocked) - { - f_mutexUnlock( m_hMutex); - } - } - - F_MUTEX m_hMutex; - FLMUINT m_uiOpenThreshold; - FLMUINT m_uiMaxAvailTime; - IF_FileHdl * m_pFirstUsed; - IF_FileHdl * m_pLastUsed; - FLMUINT m_uiNumUsed; - IF_FileHdl * m_pFirstAvail; - IF_FileHdl * m_pLastAvail; - FLMUINT m_uiNumAvail; - FLMBOOL m_bIsSetup; - FLMUINT m_uiFileIdCounter; - }; - #endif - /**************************************************************************** Desc: ****************************************************************************/ @@ -1301,7 +961,6 @@ F_FileSystem() { - m_bCanDoAsync = FALSE; } virtual ~F_FileSystem() @@ -1369,6 +1028,10 @@ const char * pszFileName, FLMUINT * puiTimeStamp); + RCODE FLMAPI getFileSize( + const char * pszFileName, + FLMUINT64 * pui64FileSize); + RCODE FLMAPI deleteFile( const char * pszFileName); @@ -1435,11 +1098,28 @@ FLMBOOL FLMAPI canDoAsync( void); + RCODE FLMAPI getFileId( + const char * pszFileName, + FLMUINT64 * pui64FileId); + + RCODE FLMAPI allocIOBuffer( + FLMUINT uiMinSize, + IF_IOBuffer ** ppIOBuffer); + + RCODE FLMAPI allocFileHandleCache( + FLMUINT uiMaxCachedFiles, + FLMUINT uiIdleTimeoutSecs, + IF_FileHdlCache ** ppFileHdlCache); + private: RCODE removeEmptyDir( const char * pszDirName); + RCODE allocFileAsyncClient( + F_FileHdl * pFileHdl, + F_FileAsyncClient ** ppAsyncClient); + #if defined( FLM_UNIX) || defined( FLM_LIBC_NLM) RCODE renameSafe( const char * pszSrcFile, @@ -1504,6 +1184,10 @@ void f_freeCRCTable( void); + RCODE f_initFileAsyncClientList( void); + + void f_freeFileAsyncClientList( void); + RCODE f_allocFileSystem( IF_FileSystem ** ppFileSystem); diff --git a/ftk/src/ftkthrd.cpp b/ftk/src/ftkthrd.cpp index 27a2e12..ff5aa58 100644 --- a/ftk/src/ftkthrd.cpp +++ b/ftk/src/ftkthrd.cpp @@ -852,18 +852,6 @@ void FLMAPI F_Thread::setThreadStatus( pszStatus = "Terminating"; break; - case FLM_THREAD_STATUS_STARTING_TRANS: - pszStatus = "Starting transaction"; - break; - - case FLM_THREAD_STATUS_COMMITTING_TRANS: - pszStatus = "Committing transaction"; - break; - - case FLM_THREAD_STATUS_ABORTING_TRANS: - pszStatus = "Aborting transaction"; - break; - case FLM_THREAD_STATUS_UNKNOWN: default: pszStatus = "Unknown"; diff --git a/ftk/src/ftkunix.cpp b/ftk/src/ftkunix.cpp index e05ebc4..943f057 100644 --- a/ftk/src/ftkunix.cpp +++ b/ftk/src/ftkunix.cpp @@ -70,28 +70,15 @@ #endif static pthread_mutex_t gv_atomicMutex = PTHREAD_MUTEX_INITIALIZER; +extern FLMATOMIC gv_openFiles; /****************************************************************************** Desc: *******************************************************************************/ F_FileHdl::F_FileHdl() { - m_bFileOpened = FALSE; - m_bDeleteOnRelease = FALSE; - m_bOpenedReadOnly = FALSE; - m_pszFileName = NULL; - + initCommonData(); m_fd = -1; - m_uiExtendSize = 0; - m_uiBytesPerSector = 0; - m_ui64NotOnSectorBoundMask = 0; - m_ui64GetSectorBoundMask = 0; - m_uiExtendSize = 0; - m_ui64CurrentPos = 0; - m_bDoDirectIO = FALSE; - m_bOpenedInAsyncMode = FALSE; - m_pucAlignedBuff = NULL; - m_uiAlignedBuffSize = 0; } /****************************************************************************** @@ -104,33 +91,29 @@ F_FileHdl::~F_FileHdl() (void)close(); } - if( m_pucAlignedBuff) - { - free( m_pucAlignedBuff); - } - - if (m_pszFileName) - { - f_free( &m_pszFileName); - } + freeCommonData(); } /*************************************************************************** Desc: Open or create a file. ***************************************************************************/ RCODE F_FileHdl::openOrCreate( - const char * pszFileName, - FLMUINT uiAccess, - FLMBOOL bCreateFlag) + const char * pszFileName, + FLMUINT uiIoFlags, + FLMBOOL bCreateFlag) { RCODE rc = NE_FLM_OK; FLMBOOL bDoDirectIO = FALSE; - char szSaveFileName[ F_PATH_MAX_SIZE]; + FLMBOOL bUsingAsync = FALSE; int openFlags = O_RDONLY; IF_FileSystem * pFileSystem = f_getFileSysPtr(); + + f_assert( m_fd == -1); + f_assert( !m_bFileOpened); + f_assert( !m_pszFileName); #if defined( FLM_LINUX) || defined( FLM_SOLARIS) || defined( FLM_OSX) - bDoDirectIO = (uiAccess & FLM_IO_DIRECT) ? TRUE : FALSE; + bDoDirectIO = (uiIoFlags & FLM_IO_DIRECT) ? TRUE : FALSE; #endif // HPUX needs this defined to access files larger than 2 GB. The Linux @@ -141,17 +124,21 @@ RCODE F_FileHdl::openOrCreate( openFlags |= O_LARGEFILE; #endif - // Save the file name in case we have to create the directory + // Save the file path - if( bCreateFlag && (uiAccess & FLM_IO_CREATE_DIR)) + if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) { - f_strcpy( szSaveFileName, pszFileName); + goto Exit; } + f_strcpy( m_pszFileName, pszFileName); + + // Determine the i/o flags + if( bCreateFlag) { openFlags |= O_CREAT; - if( uiAccess & FLM_IO_EXCL) + if( uiIoFlags & FLM_IO_EXCL) { openFlags |= O_EXCL; } @@ -161,23 +148,20 @@ RCODE F_FileHdl::openOrCreate( } } - if( !(uiAccess & FLM_IO_RDONLY)) + if( !(uiIoFlags & FLM_IO_RDONLY)) { openFlags |= O_RDWR; } - if( !(uiAccess & FLM_IO_RDONLY)) + if( !(uiIoFlags & FLM_IO_RDONLY)) { openFlags |= O_RDWR; } - // If doing direct IO, need to get the sector size. + // Determine if direct and async i/o are supported if( bDoDirectIO) { - // Can't do direct IO if the block size isn't a multiple of - // the sector size. - #if defined( FLM_LINUX) { FLMUINT uiMajor; @@ -190,10 +174,7 @@ RCODE F_FileHdl::openOrCreate( (uiMajor == 2 && uiMinor == 6 && uiRevision >= 5)) { openFlags |= O_DIRECT; - if( pFileSystem->canDoAsync()) - { - m_bOpenedInAsyncMode = TRUE; - } + bUsingAsync = TRUE; } else { @@ -201,10 +182,7 @@ RCODE F_FileHdl::openOrCreate( } } #elif defined( FLM_SOLARIS) || defined( FLM_OSX) - if( pFileSystem->canDoAsync()) - { - m_bOpenedInAsyncMode = TRUE; - } + bUsingAsync = TRUE; #endif } @@ -214,17 +192,17 @@ Retry_Create: if ((m_fd = ::open( pszFileName, openFlags, 0600)) == -1) { - if ((errno == ENOENT) && (uiAccess & FLM_IO_CREATE_DIR)) + if ((errno == ENOENT) && (uiIoFlags & FLM_IO_CREATE_DIR)) { char szTemp[ F_PATH_MAX_SIZE]; char szIoDirPath[ F_PATH_MAX_SIZE]; - uiAccess &= ~FLM_IO_CREATE_DIR; + uiIoFlags &= ~FLM_IO_CREATE_DIR; // Remove the file name for which we are creating the directory - if( RC_OK( pFileSystem->pathReduce( szSaveFileName, - szIoDirPath, szTemp))) + if( RC_OK( pFileSystem->pathReduce( + m_pszFileName, szIoDirPath, szTemp))) { if( RC_OK( rc = pFileSystem->createDir( szIoDirPath))) { @@ -241,7 +219,7 @@ Retry_Create: { openFlags &= ~O_DIRECT; bDoDirectIO = FALSE; - m_bOpenedInAsyncMode = FALSE; + bUsingAsync = FALSE; goto Retry_Create; } #endif @@ -250,6 +228,15 @@ Retry_Create: goto Exit; } + if( uiIoFlags & FLM_IO_DELETE_ON_RELEASE) + { + m_bDeleteOnRelease = TRUE; + } + else + { + m_bDeleteOnRelease = FALSE; + } + #if defined( FLM_SOLARIS) if( bDoDirectIO) { @@ -257,6 +244,8 @@ Retry_Create: } #endif + // Get the sector size + #if defined( FLM_SOLARIS) || defined( FLM_LINUX) m_uiBytesPerSector = DEV_BSIZE; #else @@ -275,272 +264,74 @@ Retry_Create: m_ui64NotOnSectorBoundMask = m_uiBytesPerSector - 1; m_ui64GetSectorBoundMask = ~m_ui64NotOnSectorBoundMask; + + // Allocate at least 64K - this will handle most read and write + // operations and will also be a multiple of the sector size most of + // the time. The calculation below rounds it up to the next sector + // boundary if it is not already on one. + + m_uiAlignedBuffSize = 64 * 1024; + if( bDoDirectIO) + { + m_uiAlignedBuffSize = roundToNextSector( m_uiAlignedBuffSize); + } + + if( RC_BAD( rc = f_allocAlignedBuffer( m_uiAlignedBuffSize, + &m_pucAlignedBuff))) + { + goto Exit; + } + + m_bFileOpened = TRUE; m_bDoDirectIO = bDoDirectIO; + m_bOpenedInAsyncMode = bUsingAsync; + m_ui64CurrentPos = 0; + m_bOpenedReadOnly = (uiIoFlags & FLM_IO_RDONLY) ? TRUE : FALSE; + m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; + f_atomicInc( &gv_openFiles); Exit: if( RC_BAD( rc)) { - m_fd = -1; - m_bDoDirectIO = FALSE; - m_bOpenedInAsyncMode = FALSE; + close(); } return( rc); } -/****************************************************************************** -Desc: Create a file -******************************************************************************/ -RCODE F_FileHdl::create( - const char * pszFileName, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - - f_assert( !m_bFileOpened); - - if( m_bDeleteOnRelease) - { - // This file handle had better not been used for another file - // before. Otherwise, we will get a memory leak. - - f_assert( m_pszFileName == NULL); - - // Note: 'OpenOrCreate' will set m_pszFileName - - if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) - { - goto Exit; - } - - f_strcpy( m_pszFileName, pszFileName); - } - - if( RC_BAD( rc = openOrCreate( pszFileName, uiIoFlags, TRUE))) - { - goto Exit; - } - - m_bFileOpened = TRUE; - m_ui64CurrentPos = 0; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - -Exit: - - if( RC_BAD( rc) && m_bDeleteOnRelease && m_pszFileName) - { - f_free( &m_pszFileName); - } - - return( rc); -} - -/****************************************************************************** -Desc: -******************************************************************************/ -RCODE F_FileHdl::createUnique( - char * pszDirName, - const char * pszFileExtension, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - char * pszTmp; - FLMBOOL bModext = TRUE; - FLMUINT uiBaseTime = 0; - FLMBYTE ucHighByte = 0; - char szFileName[ F_FILENAME_SIZE]; - char * pszDirPath; - char szDirPath[ F_PATH_MAX_SIZE]; - char szTmpPath[ F_PATH_MAX_SIZE]; - FLMUINT uiCount; - IF_FileSystem * pFileSystem = f_getFileSysPtr(); - - f_assert( !m_bFileOpened); - f_memset( szFileName, 0, sizeof( szFileName)); - - if( m_bDeleteOnRelease) - { - // This file handle had better not been used for another file - // before. Otherwise, we will get a memory leak. - - f_assert( !m_pszFileName); - } - - if( !pszDirName || pszDirName[ 0] == '\0') - { - f_strcpy( szDirPath, "./"); - } - else - { - f_strcpy( szDirPath, pszDirName); - } - pszDirPath = &szDirPath [0]; - - // Search backwards replacing trailing spaces with NULLs. - - pszTmp = pszDirPath; - pszTmp += (f_strlen( pszTmp) - 1); - while (*pszTmp == ' ' && pszTmp >= pszDirPath) - { - *pszTmp = 0; - pszTmp--; - } - - // Append a slash if one isn't already there - - if (pszTmp >= pszDirPath && *pszTmp != '/') - { - pszTmp++; - *pszTmp++ = '/'; - } - else - { - pszTmp++; - } - *pszTmp = 0; - - if( pszFileExtension && f_strlen( pszFileExtension) >= 3) - { - bModext = FALSE; - } - - uiCount = 0; - do - { - pFileSystem->pathCreateUniqueName( &uiBaseTime, szFileName, - pszFileExtension, - &ucHighByte, bModext); - - f_strcpy( szTmpPath, pszDirPath); - pFileSystem->pathAppend( szTmpPath, szFileName); - if( m_pszFileName) - { - f_free( &m_pszFileName); - } - - rc = create( szTmpPath, uiIoFlags | FLM_IO_EXCL); - - if (rc == NE_FLM_IO_DISK_FULL) - { - pFileSystem->deleteFile( pszDirPath); - goto Exit; - } - - if( rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_PASSWORD) - { - goto Exit; - } - } while ((rc != NE_FLM_OK) && (uiCount++ < 10)); - - // Check if the path was created - - if( uiCount >= 10 && rc != NE_FLM_OK) - { - rc = RC_SET( NE_FLM_IO_PATH_CREATE_FAILURE); - goto Exit; - } - - m_bFileOpened = TRUE; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - - // Created file name needs to be returned. - - f_strcpy( pszDirName, szTmpPath); - -Exit: - - if( RC_BAD( rc) && m_pszFileName) - { - f_free( &m_pszFileName); - m_pszFileName = NULL; - } - - return( rc); -} - -/****************************************************************************** -Desc: Open a file -******************************************************************************/ -RCODE F_FileHdl::open( - const char * pszFileName, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - - f_assert( !m_bFileOpened); - - if( m_bDeleteOnRelease) - { - // This file handle had better not been used for another file - // before. Otherwise, we will get a memory leak. - - f_assert( !m_pszFileName); - - if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) - { - goto Exit; - } - } - - if( RC_BAD( rc = openOrCreate( pszFileName, uiIoFlags, FALSE))) - { - goto Exit; - } - - m_bFileOpened = TRUE; - m_ui64CurrentPos = 0; - m_bOpenedReadOnly = (uiIoFlags & FLM_IO_RDONLY) ? TRUE : FALSE; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - -Exit: - - if( RC_BAD( rc) && m_bDeleteOnRelease && m_pszFileName) - { - f_free( &m_pszFileName); - m_pszFileName = NULL; - } - - return( rc); -} - /****************************************************************************** Desc: Close a file ******************************************************************************/ RCODE FLMAPI F_FileHdl::close( void) { - FLMBOOL bDeleteAllowed = TRUE; - RCODE rc = NE_FLM_OK; - - if( !m_bFileOpened) + if( m_fd != -1) { - goto Exit; + ::close( m_fd); + m_fd = -1; } - - ::close( m_fd); - m_fd = -1; - m_bFileOpened = FALSE; - m_bOpenedReadOnly = FALSE; - m_bOpenedExclusive = FALSE; - if( m_bDeleteOnRelease) { - f_assert( m_pszFileName); - - if( bDeleteAllowed) - { - f_getFileSysPtr()->deleteFile( m_pszFileName); - } + f_getFileSysPtr()->deleteFile( m_pszFileName); m_bDeleteOnRelease = FALSE; - - f_free( &m_pszFileName); - m_pszFileName = NULL; } + + if( m_bFileOpened) + { + f_atomicDec( &gv_openFiles); + } + + freeCommonData(); + + m_bFileOpened = FALSE; + m_ui64CurrentPos = 0; + m_bOpenedReadOnly = FALSE; + m_bOpenedExclusive = FALSE; + m_bDoDirectIO = FALSE; + m_bOpenedInAsyncMode = FALSE; -Exit: - - return( rc); + return( NE_FLM_OK); } /****************************************************************************** @@ -593,395 +384,6 @@ RCODE FLMAPI F_FileHdl::flush( void) return( NE_FLM_OK); } -/**************************************************************************** -Desc: Position and do a single read operation. -****************************************************************************/ -RCODE F_FileHdl::doOneRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvReadBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - FLMINT iTmp; - FLMUINT uiBytesRead = 0; - - if( !m_bOpenedInAsyncMode) - { - if( (iTmp = pread( m_fd, pvReadBuffer, - uiBytesToRead, ui64ReadOffset)) == -1) - { - rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); - goto Exit; - } - - uiBytesRead = (FLMUINT)iTmp; - } - else -#ifdef FLM_LIBC_NLM - { - rc = RC_SET_AND_ASSERT( NE_FLM_READING_FILE); - goto Exit; - } -#else - { - struct aiocb tmpAio; - struct aiocb * ppAioList[ 1]; - - f_memset( &tmpAio, 0, sizeof( struct aiocb)); - tmpAio.aio_lio_opcode = LIO_READ; - tmpAio.aio_sigevent.sigev_notify = SIGEV_NONE; - tmpAio.aio_fildes = m_fd; - tmpAio.aio_offset = ui64ReadOffset; - tmpAio.aio_nbytes = uiBytesToRead; - tmpAio.aio_buf = pvReadBuffer; - - if( aio_read( &tmpAio) != 0) - { - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); - goto Exit; - } - - ppAioList[ 0] = &tmpAio; - - for( ;;) - { - FLMINT iAsyncResult; - - if( aio_suspend( ppAioList, 1, NULL) != 0) - { - if( errno == EINTR) - { - continue; - } - - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); - goto Exit; - } - - iAsyncResult = aio_error( &tmpAio); - - if( !iAsyncResult) - { - if( (iAsyncResult = aio_return( &tmpAio)) < 0) - { - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); - goto Exit; - } - - uiBytesRead = (FLMUINT)iAsyncResult; - break; - } - - if( iAsyncResult == EINTR || iAsyncResult == EINPROGRESS) - { - continue; - } - - f_assert( 0); - rc = f_mapPlatformError( iAsyncResult, NE_FLM_READING_FILE); - goto Exit; - } - } -#endif - - if( uiBytesRead < uiBytesToRead) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Exit; - } - -Exit: - - if( puiBytesRead) - { - *puiBytesRead = uiBytesRead; - } - - return( rc); -} - -/****************************************************************************** -Desc: Read from a file -******************************************************************************/ -RCODE F_FileHdl::directRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesRead; - FLMBYTE * pucReadBuffer; - FLMBYTE * pucDestBuffer; - FLMUINT uiMaxBytesToRead; - FLMBOOL bHitEOF; - - f_assert( m_bFileOpened); - f_assert( m_bDoDirectIO); - - if( puiBytesRead) - { - *puiBytesRead = 0; - } - - if( ui64ReadOffset == FLM_IO_CURRENT_POS) - { - ui64ReadOffset = m_ui64CurrentPos; - } - - // This loop does multiple reads (if necessary) to get all of the - // data. It uses aligned buffers and reads at sector offsets. - - pucDestBuffer = (FLMBYTE *)pvBuffer; - for (;;) - { - // See if we are using an aligned buffer. If not, allocate - // one (if not already allocated), and use it. - - if( (ui64ReadOffset & m_ui64NotOnSectorBoundMask) || - (uiBytesToRead & m_ui64NotOnSectorBoundMask) || - (((FLMUINT64)(FLMUINT)pucDestBuffer) & m_ui64NotOnSectorBoundMask)) - { - if( !m_pucAlignedBuff) - { - if( RC_BAD( rc = allocAlignedBuffer())) - { - goto Exit; - } - } - pucReadBuffer = m_pucAlignedBuff; - - // Must read enough bytes to cover all of the sectors that - // contain the data we are trying to read. The value of - // (ui64ReadOffset & m_ui64NotOnSectorBoundMask) will give us the - // number of additional bytes that are in the sector prior to - // the read offset. We then round that up to the next sector - // to get the total number of bytes we are going to read. - - uiMaxBytesToRead = (FLMUINT)roundToNextSector( - uiBytesToRead + (ui64ReadOffset & m_ui64NotOnSectorBoundMask)); - - // Can't read more than the aligned buffer will hold. - - if( uiMaxBytesToRead > m_uiAlignedBuffSize) - { - uiMaxBytesToRead = m_uiAlignedBuffSize; - } - } - else - { - uiMaxBytesToRead = (FLMUINT)roundToNextSector( uiBytesToRead); - f_assert( uiMaxBytesToRead >= uiBytesToRead); - pucReadBuffer = pucDestBuffer; - } - - bHitEOF = FALSE; - - if( RC_BAD( rc = doOneRead( truncateToPrevSector( ui64ReadOffset), - uiMaxBytesToRead, pucReadBuffer, &uiBytesRead))) - { - if( rc != NE_FLM_IO_END_OF_FILE) - { - goto Exit; - } - - rc = NE_FLM_OK; - } - - if( uiBytesRead < uiMaxBytesToRead) - { - bHitEOF = TRUE; - } - - // If the offset we want to read from is not on a sector - // boundary, increment the read buffer pointer to the - // offset where the data we need starts and decrement the - // bytes read by the difference between the start of the - // sector and the actual read offset. - - if( ui64ReadOffset & m_ui64NotOnSectorBoundMask) - { - pucReadBuffer += (ui64ReadOffset & m_ui64NotOnSectorBoundMask); - f_assert( uiBytesRead >= m_uiBytesPerSector); - uiBytesRead -= (FLMUINT)(ui64ReadOffset & m_ui64NotOnSectorBoundMask); - } - - // If bytes read is more than we actually need, truncate it back - // so that we only copy what we actually need. - - if( uiBytesRead > uiBytesToRead) - { - uiBytesRead = uiBytesToRead; - } - - uiBytesToRead -= uiBytesRead; - - if( puiBytesRead) - { - (*puiBytesRead) += uiBytesRead; - } - - m_ui64CurrentPos = ui64ReadOffset + uiBytesRead; - - // If using a different buffer for reading, copy the - // data read into the destination buffer. - - if( pucDestBuffer != pucReadBuffer) - { - f_memcpy( pucDestBuffer, pucReadBuffer, uiBytesRead); - } - - if( !uiBytesToRead) - { - break; - } - - // Still more to read - did we hit EOF above? - - if( bHitEOF) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - break; - } - - pucDestBuffer += uiBytesRead; - ui64ReadOffset += uiBytesRead; - } - -Exit: - - return( rc); -} - -/****************************************************************************** -Desc: Read from a file -******************************************************************************/ -RCODE FLMAPI F_FileHdl::read( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - FLMINT iBytesRead; - - f_assert( m_bFileOpened); - - if( m_bDoDirectIO || m_bOpenedInAsyncMode) - { - rc = directRead( ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesRead); - goto Exit; - } - - if( ui64ReadOffset == FLM_IO_CURRENT_POS) - { - ui64ReadOffset = m_ui64CurrentPos; - } - - if( (iBytesRead = pread( m_fd, pvBuffer, - uiBytesToRead, ui64ReadOffset)) == -1) - { - rc = f_mapPlatformError(errno, NE_FLM_READING_FILE); - goto Exit; - } - - if( puiBytesRead) - { - *puiBytesRead = (FLMUINT)iBytesRead; - } - - m_ui64CurrentPos = ui64ReadOffset + (FLMUINT)iBytesRead; - - if( (FLMUINT)iBytesRead < uiBytesToRead) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - goto Exit; - } - -Exit: - - return( rc); -} - -/****************************************************************************** -Note: This function assumes that the pvBuffer that is passed in is - a multiple of a the sector size. -******************************************************************************/ -RCODE FLMAPI F_FileHdl::sectorRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesRead) -{ - if( m_bDoDirectIO || m_bOpenedInAsyncMode) - { - return( directRead( ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesRead)); - } - else - { - return( read( ui64ReadOffset, uiBytesToRead, pvBuffer, puiBytesRead)); - } -} - -/****************************************************************************** -Desc: Sets current position of file. -******************************************************************************/ -RCODE FLMAPI F_FileHdl::seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset) -{ - RCODE rc = NE_FLM_OK; - - f_assert( m_bFileOpened); - - switch( iWhence) - { - case FLM_IO_SEEK_CUR: - { - m_ui64CurrentPos += ui64Offset; - break; - } - - case FLM_IO_SEEK_SET: - { - m_ui64CurrentPos = ui64Offset; - break; - } - - case FLM_IO_SEEK_END: - { - if( RC_BAD( rc = size( &m_ui64CurrentPos))) - { - goto Exit; - } - - break; - } - - default: - { - rc = RC_SET_AND_ASSERT( NE_FLM_NOT_IMPLEMENTED); - goto Exit; - } - } - - if( pui64NewOffset) - { - *pui64NewOffset = m_ui64CurrentPos; - } - -Exit: - - return( rc); -} - /****************************************************************************** Desc: Return the size of the file ******************************************************************************/ @@ -1006,17 +408,6 @@ Exit: return( rc); } -/****************************************************************************** -Desc: -******************************************************************************/ -RCODE FLMAPI F_FileHdl::tell( - FLMUINT64 * pui64Offset) -{ - f_assert( m_bFileOpened); - *pui64Offset = m_ui64CurrentPos; - return( NE_FLM_OK); -} - /****************************************************************************** Desc: Truncate the file to the indicated size ******************************************************************************/ @@ -1038,24 +429,177 @@ Exit: return( rc); } -/****************************************************************************** -Desc: Write to a file -******************************************************************************/ -RCODE FLMAPI F_FileHdl::write( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV) +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdl::lowLevelRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead) { - RCODE rc = NE_FLM_OK; - FLMINT iBytesWritten = 0; - - f_assert( m_bFileOpened); + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesRead = 0; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bWaitForRead = FALSE; - if( m_bDoDirectIO || m_bOpenedInAsyncMode) + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) { - rc = directWrite( ui64WriteOffset, uiBytesToWrite, pvBuffer, - NULL, puiBytesWrittenRV); + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64ReadOffset == FLM_IO_CURRENT_POS) + { + ui64ReadOffset = m_ui64CurrentPos; + } + + if( !pvBuffer) + { + pvBuffer = pIOBuffer->getBufferPtr(); + } + +#ifndef FLM_LIBC_NLM + if( m_bOpenedInAsyncMode) + { + struct aiocb * pAIO; + + if( RC_BAD( rc = allocFileAsyncClient( &pAsyncClient))) + { + goto Exit; + } + + if( RC_BAD( rc = pAsyncClient->prepareForAsync( pIOBuffer))) + { + goto Exit; + } + + if( !pIOBuffer) + { + f_assert( pvBuffer); + bWaitForRead = TRUE; + } + + pAsyncClient->m_uiBytesToDo = uiBytesToRead; + pAIO = &pAsyncClient->m_aio; + + pAIO->aio_lio_opcode = LIO_READ; + pAIO->aio_sigevent.sigev_notify = SIGEV_NONE; + pAIO->aio_fildes = m_fd; + pAIO->aio_offset = ui64ReadOffset; + pAIO->aio_nbytes = uiBytesToRead; + pAIO->aio_buf = pvBuffer; + pIOBuffer = NULL; + + if( aio_read( pAIO) != 0) + { + f_assert( 0); + rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); + pAsyncClient->notifyComplete( rc, uiBytesRead, FALSE); + goto Exit; + } + + if( bWaitForRead) + { + if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + { + if( rc != NE_FLM_IO_END_OF_FILE) + { + goto Exit; + } + + rc = NE_FLM_OK; + } + + uiBytesRead = pAsyncClient->m_uiBytesDone; + } + else + { + uiBytesRead = uiBytesToRead; + } + } + else +#endif + { + FLMINT iBytesRead; + + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + if( (iBytesRead = pread( m_fd, pvBuffer, + uiBytesToRead, ui64ReadOffset)) == -1) + { + rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); + } + else + { + uiBytesRead = (FLMUINT)iBytesRead; + } + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) + { + goto Exit; + } + } + + m_ui64CurrentPos += uiBytesRead; + + if( uiBytesRead < uiBytesToRead) + { + rc = RC_SET( NE_FLM_IO_END_OF_FILE); + goto Exit; + } + +Exit: + + f_assert( uiBytesRead || RC_BAD( rc)); + + if( pAsyncClient) + { + pAsyncClient->Release(); + } + + if( pIOBuffer && !pIOBuffer->isPending()) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); + } + + if( puiBytesRead) + { + *puiBytesRead = uiBytesRead; + } + + return( rc); +} + +/**************************************************************************** +Desc: +****************************************************************************/ +RCODE F_FileHdl::lowLevelWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten) +{ + RCODE rc = NE_FLM_OK; + FLMUINT uiBytesWritten = 0; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bWaitForWrite = FALSE; + + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) + { + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); goto Exit; } @@ -1064,389 +608,129 @@ RCODE FLMAPI F_FileHdl::write( ui64WriteOffset = m_ui64CurrentPos; } - if( (iBytesWritten = pwrite( m_fd, pvBuffer, - uiBytesToWrite, ui64WriteOffset)) == -1) + if( !pvBuffer) { - rc = f_mapPlatformError(errno, NE_FLM_WRITING_FILE); - goto Exit; + pvBuffer = pIOBuffer->getBufferPtr(); } - if( puiBytesWrittenRV) +#ifndef FLM_LIBC_NLM + if( m_bOpenedInAsyncMode) { - *puiBytesWrittenRV = (FLMUINT)iBytesWritten; + struct aiocb * pAIO; + + if( RC_BAD( rc = allocFileAsyncClient( &pAsyncClient))) + { + goto Exit; + } + + if( RC_BAD( rc = pAsyncClient->prepareForAsync( pIOBuffer))) + { + goto Exit; + } + + if( !pIOBuffer) + { + bWaitForWrite = TRUE; + } + + pAsyncClient->m_uiBytesToDo = uiBytesToWrite; + pAIO = &pAsyncClient->m_aio; + pAIO->aio_lio_opcode = LIO_WRITE; + pAIO->aio_sigevent.sigev_notify = SIGEV_NONE; + pAIO->aio_fildes = m_fd; + pAIO->aio_offset = ui64WriteOffset; + pAIO->aio_nbytes = uiBytesToWrite; + pAIO->aio_buf = (void *)pvBuffer; + pIOBuffer = NULL; + + if( aio_write( pAIO) != 0) + { + f_assert( 0); + rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); + pAsyncClient->notifyComplete( rc, uiBytesWritten, FALSE); + goto Exit; + } + + if( bWaitForWrite) + { + if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + { + if( rc != NE_FLM_IO_DISK_FULL) + { + goto Exit; + } + + rc = NE_FLM_OK; + } + + uiBytesWritten = pAsyncClient->m_uiBytesDone; + } + else + { + uiBytesWritten = uiBytesToWrite; + } + } + else +#endif + { + FLMINT iBytesWritten; + + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + if( (iBytesWritten = pwrite( m_fd, + pvBuffer, uiBytesToWrite, ui64WriteOffset)) == -1) + { + rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); + } + else + { + uiBytesWritten = (FLMUINT)iBytesWritten; + } + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) + { + goto Exit; + } } - m_ui64CurrentPos = ui64WriteOffset + (FLMUINT)iBytesWritten; - - if( (FLMUINT)iBytesWritten < uiBytesToWrite) + m_ui64CurrentPos += uiBytesWritten; + + if( uiBytesWritten < uiBytesToWrite) { rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); goto Exit; } - -Exit: - - return( rc); -} - -/****************************************************************************** -Desc: Allocate an aligned buffer. -******************************************************************************/ -RCODE F_FileHdl::allocAlignedBuffer( void) -{ - RCODE rc = NE_FLM_OK; - - if( m_pucAlignedBuff) - { - goto Exit; - } - - // Allocate at least 64K - this will handle most read and write - // operations and will also be a multiple of the sector size most of - // the time. The calculation below rounds it up to the next sector - // boundary if it is not already on one. - - m_uiAlignedBuffSize = (FLMUINT)roundToNextSector( 64 * 1024); - f_assert( m_uiAlignedBuffSize >= m_uiBytesPerSector); - -#if defined( FLM_SOLARIS) - if( (m_pucAlignedBuff = (FLMBYTE *)memalign( - sysconf( _SC_PAGESIZE), m_uiAlignedBuffSize)) == NULL) -#elif defined( FLM_OSX) || defined( FLM_LIBC_NLM) - if( (m_pucAlignedBuff = (FLMBYTE *)malloc( m_uiAlignedBuffSize)) == NULL) -#else - if( posix_memalign( (void **)&m_pucAlignedBuff, - sysconf( _SC_PAGESIZE), m_uiAlignedBuffSize) == -1) -#endif - { - m_uiAlignedBuffSize = 0; - rc = f_mapPlatformError( errno, NE_FLM_MEM); - goto Exit; - } Exit: - return( rc); -} - -/****************************************************************************** -Note: This routine assumes that the size of pvBuffer is a multiple of - sector size and can be used to write out full sectors. Even if - uiBytesToWrite does not account for full sectors, data from the - buffer will still be written out - a partial sector on disk will - not be preserved. -******************************************************************************/ -RCODE F_FileHdl::directWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesRead = 0; - FLMBYTE * pucWriteBuffer; - FLMBYTE * pucSrcBuffer; - FLMUINT uiTotalBytesToWrite; - FLMUINT uiBufBytesToWrite; - FLMUINT uiBytesWritten = 0; - FLMBOOL bWaitForWrite = (pBufferObj == NULL) - ? TRUE - : FALSE; - FLMUINT64 ui64LastWriteOffset; - - f_assert( m_bFileOpened); - - if( !bWaitForWrite) + if( pAsyncClient) { - f_assert( m_bOpenedInAsyncMode); + pAsyncClient->Release(); } - if( puiBytesWrittenRV) + if( pIOBuffer && !pIOBuffer->isPending()) { - *puiBytesWrittenRV = 0; + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); } - if( ui64WriteOffset == FLM_IO_CURRENT_POS) + if( puiBytesWritten) { - ui64WriteOffset = m_ui64CurrentPos; + *puiBytesWritten = uiBytesWritten; } - - // This loop is for direct IO - must make sure we use - // aligned buffers. - - pucSrcBuffer = (FLMBYTE *)pvBuffer; - for (;;) - { - - // See if we are using an aligned buffer. If not, allocate - // one (if not already allocated), and use it. - - if ((ui64WriteOffset & m_ui64NotOnSectorBoundMask) || - (uiBytesToWrite & m_ui64NotOnSectorBoundMask) || - (((FLMUINT)pucSrcBuffer) & m_ui64NotOnSectorBoundMask)) - { - - // Cannot do an async write if we have to use a temporary buffer - - bWaitForWrite = TRUE; - - if (!m_pucAlignedBuff) - { - if (RC_BAD( rc = allocAlignedBuffer())) - { - goto Exit; - } - } - pucWriteBuffer = m_pucAlignedBuff; - - // Must write enough bytes to cover all of the sectors that - // contain the data we are trying to write out. The value of - // (ui64WriteOffset & m_ui64NotOnSectorBoundMask) will give us the - // number of additional bytes that are in the sector prior to - // the read offset. We then round to the next sector to get the - // total number of bytes we are going to write. - - uiTotalBytesToWrite = (FLMUINT)roundToNextSector( uiBytesToWrite + - (ui64WriteOffset & m_ui64NotOnSectorBoundMask)); - - // Can't write more than the aligned buffer will hold. - - if (uiTotalBytesToWrite > m_uiAlignedBuffSize) - { - uiTotalBytesToWrite = m_uiAlignedBuffSize; - uiBufBytesToWrite = (FLMUINT)(uiTotalBytesToWrite - - (ui64WriteOffset & m_ui64NotOnSectorBoundMask)); - } - else - { - uiBufBytesToWrite = uiBytesToWrite; - } - - // If the write offset is not on a sector boundary, we must - // read at least the first sector into the buffer. - - if( (ui64WriteOffset & m_ui64NotOnSectorBoundMask) || - uiBufBytesToWrite < m_uiBytesPerSector) - { - - // Read the first sector that is to be written out. - // Read one sector's worth of data - so that we will - // preserve what is already in the sector before - // writing it back out again. - - if (RC_BAD( rc = doOneRead( truncateToPrevSector( ui64WriteOffset), - m_uiBytesPerSector, pucWriteBuffer, &uiBytesRead))) - { - if( rc != NE_FLM_IO_END_OF_FILE) - { - goto Exit; - } - - rc = NE_FLM_OK; - f_memset( &pucWriteBuffer[ uiBytesRead], 0, - m_uiBytesPerSector - uiBytesRead); - } - } - - // If the last sector's worth of data we are writing out is only a - // partial sector, we must read in this sector as well. - - if( uiTotalBytesToWrite > m_uiBytesPerSector && - ((ui64WriteOffset + uiBufBytesToWrite) & m_ui64NotOnSectorBoundMask)) - { - FLMBYTE * pucReadBuf; - - pucReadBuf = &pucWriteBuffer[ - uiTotalBytesToWrite - m_uiBytesPerSector]; - - - // Read the last sector that is to be written out. - // Read one sector's worth of data - so that we will - // preserve what is already in the sector before - // writing it back out again. - - if( RC_BAD( rc = doOneRead( - truncateToPrevSector( ui64WriteOffset + uiBufBytesToWrite), - m_uiBytesPerSector, pucReadBuf, &uiBytesRead))) - { - if( rc != NE_FLM_IO_END_OF_FILE) - { - goto Exit; - } - - rc = NE_FLM_OK; - f_memset( &pucReadBuf[ uiBytesRead], 0, - m_uiBytesPerSector - uiBytesRead); - } - } - - // Finally, copy the data from the source buffer into the - // write buffer. - - f_memcpy( &pucWriteBuffer[ ui64WriteOffset & m_ui64NotOnSectorBoundMask], - pucSrcBuffer, uiBufBytesToWrite); - } - else - { - pucWriteBuffer = pucSrcBuffer; - uiTotalBytesToWrite = uiBytesToWrite; - uiBufBytesToWrite = uiBytesToWrite; - } - - // Position the file to the nearest sector below the write offset. - - ui64LastWriteOffset = (FLMUINT)truncateToPrevSector( ui64WriteOffset); - - if( !m_bOpenedInAsyncMode) - { - FLMINT iBytesWritten; - - if( (iBytesWritten = pwrite( m_fd, - pucWriteBuffer, uiTotalBytesToWrite, ui64LastWriteOffset)) == -1) - { - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto Exit; - } - - uiBytesWritten = (FLMUINT)iBytesWritten; - f_assert( uiBytesWritten == uiTotalBytesToWrite); - } - else -#ifdef FLM_LIBC_NLM - { - rc = RC_SET_AND_ASSERT( NE_FLM_WRITING_FILE); - goto Exit; - } -#else - { - struct aiocb * pAio; - struct aiocb tmpAio; - - if( pBufferObj) - { - pAio = ((F_IOBuffer *)pBufferObj)->getAIOStruct(); - } - else - { - pAio = &tmpAio; - f_assert( bWaitForWrite); - } - - f_memset( pAio, 0, sizeof( struct aiocb)); - pAio->aio_lio_opcode = LIO_WRITE; - pAio->aio_sigevent.sigev_notify = SIGEV_NONE; - pAio->aio_fildes = m_fd; - pAio->aio_offset = ui64LastWriteOffset; - pAio->aio_nbytes = uiTotalBytesToWrite; - pAio->aio_buf = pucWriteBuffer; - - if( aio_write( pAio) != 0) - { - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto Exit; - } - - if( bWaitForWrite) - { - struct aiocb * ppAioList[ 1]; - - ppAioList[ 0] = pAio; - - for( ;;) - { - FLMINT iAsyncResult; - - if( aio_suspend( ppAioList, 1, NULL) != 0) - { - if( errno == EINTR) - { - continue; - } - - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto Exit; - } - - iAsyncResult = aio_error( pAio); - - if( !iAsyncResult) - { - if( (iAsyncResult = aio_return( pAio)) < 0) - { - f_assert( 0); - rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); - goto Exit; - } - - uiBytesWritten = (FLMUINT)iAsyncResult; - f_assert( uiBytesWritten == uiTotalBytesToWrite); - break; - } - - if( iAsyncResult == EINTR || iAsyncResult == EINPROGRESS) - { - continue; - } - - f_assert( 0); - rc = f_mapPlatformError( iAsyncResult, NE_FLM_WRITING_FILE); - goto Exit; - } - } - else - { - pBufferObj->makePending(); - uiBytesWritten = uiTotalBytesToWrite; - } - } -#endif - - if (uiBytesWritten < uiTotalBytesToWrite) - { - rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); - goto Exit; - } - - uiBytesToWrite -= uiBufBytesToWrite; - - if( puiBytesWrittenRV) - { - (*puiBytesWrittenRV) += uiBufBytesToWrite; - } - - m_ui64CurrentPos = ui64WriteOffset + uiBufBytesToWrite; - - if (!uiBytesToWrite) - { - break; - } - - pucSrcBuffer += uiBufBytesToWrite; - ui64WriteOffset += uiBufBytesToWrite; - } - -Exit: - - if( pBufferObj && !pBufferObj->isPending()) - { - pBufferObj->notifyComplete( rc); - } - + return( rc); } -/****************************************************************************** -Desc: Returns flag indicating whether or not we can do async writes. -******************************************************************************/ -FLMBOOL FLMAPI F_FileHdl::canDoAsync() -{ - f_assert( m_bFileOpened); - return( m_bOpenedInAsyncMode); -} - /****************************************************************************** Desc: Attempts to lock byte 0 of the file. This method is used to lock byte 0 of the .lck file to ensure that only one process diff --git a/ftk/src/ftkwin.cpp b/ftk/src/ftkwin.cpp index 20bf152..d908791 100644 --- a/ftk/src/ftkwin.cpp +++ b/ftk/src/ftkwin.cpp @@ -27,27 +27,16 @@ #if defined( FLM_WIN) +extern FLMATOMIC gv_openFiles; + /**************************************************************************** Desc: ****************************************************************************/ F_FileHdl::F_FileHdl() { - m_bFileOpened = FALSE; - m_bDeleteOnRelease = FALSE; - m_bOpenedReadOnly = FALSE; - m_pszFileName = NULL; - m_FileHandle = INVALID_HANDLE_VALUE; - m_uiBytesPerSector = 0; - m_ui64NotOnSectorBoundMask = 0; - m_ui64GetSectorBoundMask = 0; - m_bDoDirectIO = FALSE; - m_uiExtendSize = 0; - m_uiMaxAutoExtendSize = FLM_MAXIMUM_FILE_SIZE; - m_pucAlignedBuff = NULL; - m_uiAlignedBuffSize = 0; - m_ui64CurrentPos = 0; - m_bOpenedInAsyncMode = FALSE; - m_Overlapped.hEvent = NULL; + initCommonData(); + m_hFile = INVALID_HANDLE_VALUE; + m_bFlushRequired = FALSE; } /**************************************************************************** @@ -55,60 +44,46 @@ Desc: ****************************************************************************/ F_FileHdl::~F_FileHdl() { - if( m_bFileOpened) - { - (void)close(); - } - - if (m_pucAlignedBuff) - { - (void)VirtualFree( m_pucAlignedBuff, 0, MEM_RELEASE); - m_pucAlignedBuff = NULL; - m_uiAlignedBuffSize = 0; - } - - if (m_Overlapped.hEvent) - { - CloseHandle( m_Overlapped.hEvent); - } - - if (m_pszFileName) - { - f_free( &m_pszFileName); - } + close(); } /*************************************************************************** Desc: Open or create a file. ***************************************************************************/ RCODE F_FileHdl::openOrCreate( - const char * pszFileName, - FLMUINT uiAccess, - FLMBOOL bCreateFlag) + const char * pszFileName, + FLMUINT uiIoFlags, + FLMBOOL bCreateFlag) { RCODE rc = NE_FLM_OK; - char szSaveFileName[ F_PATH_MAX_SIZE]; DWORD udAccessMode = 0; DWORD udShareMode = 0; DWORD udCreateMode = 0; DWORD udAttrFlags = 0; DWORD udErrCode; + FLMBOOL bOpenInAsyncMode = FALSE; + FLMBOOL bDoDirectIO; IF_FileSystem * pFileSystem = f_getFileSysPtr(); - m_bDoDirectIO = (uiAccess & FLM_IO_DIRECT) ? TRUE : FALSE; + f_assert( !m_bFileOpened); + f_assert( !m_pszFileName); - // Save the file name in case we have to create the directory + bDoDirectIO = (uiIoFlags & FLM_IO_DIRECT) ? TRUE : FALSE; - if ((bCreateFlag) && (uiAccess & FLM_IO_CREATE_DIR)) + // Save the file name + + if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) { - f_strcpy( szSaveFileName, pszFileName); + goto Exit; } + f_strcpy( m_pszFileName, pszFileName); + // If doing direct IO, need to get the sector size. - if (m_bDoDirectIO) + if( bDoDirectIO) { - if (RC_BAD( rc = pFileSystem->getSectorSize( + if( RC_BAD( rc = pFileSystem->getSectorSize( pszFileName, &m_uiBytesPerSector))) { goto Exit; @@ -120,27 +95,27 @@ RCODE F_FileHdl::openOrCreate( // Only enable asynchronous writes if direct I/O is enabled. - if (m_bDoDirectIO && pFileSystem->canDoAsync()) + if( bDoDirectIO && f_getFileSysPtr()->canDoAsync()) { - m_bOpenedInAsyncMode = TRUE; + bOpenInAsyncMode = TRUE; } // Set up the file characteristics requested by caller. - if (uiAccess & FLM_IO_SH_DENYRW) + if( uiIoFlags & FLM_IO_SH_DENYRW) { udShareMode = 0; - uiAccess &= ~FLM_IO_SH_DENYRW; + uiIoFlags &= ~FLM_IO_SH_DENYRW; } - else if (uiAccess & FLM_IO_SH_DENYWR) + else if( uiIoFlags & FLM_IO_SH_DENYWR) { udShareMode = FILE_SHARE_READ; - uiAccess &= ~FLM_IO_SH_DENYWR; + uiIoFlags &= ~FLM_IO_SH_DENYWR; } - else if (uiAccess & FLM_IO_SH_DENYNONE) + else if (uiIoFlags & FLM_IO_SH_DENYNONE) { udShareMode = (FILE_SHARE_READ | FILE_SHARE_WRITE); - uiAccess &= ~FLM_IO_SH_DENYNONE; + uiIoFlags &= ~FLM_IO_SH_DENYNONE; } else { @@ -150,19 +125,27 @@ RCODE F_FileHdl::openOrCreate( // Begin setting the CreateFile flags and fields udAttrFlags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS; - if (m_bDoDirectIO) + + if( bDoDirectIO) { - udAttrFlags |= FILE_FLAG_NO_BUFFERING; + // Specifying FILE_FLAG_NO_BUFFERING and FILE_FLAG_WRITE_THROUGH + // results in the data being immediately flushed to disk without + // going through the system cache. The operating system also + // requests a write-through the hard disk cache to persistent + // media. However, not all hardware supports this write-through + // capability. + + udAttrFlags |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH; } - if (m_bOpenedInAsyncMode) + if( bOpenInAsyncMode) { udAttrFlags |= FILE_FLAG_OVERLAPPED; } - if (bCreateFlag) + if( bCreateFlag) { - if (uiAccess & FLM_IO_EXCL) + if( uiIoFlags & FLM_IO_EXCL) { udCreateMode = CREATE_NEW; } @@ -178,30 +161,28 @@ RCODE F_FileHdl::openOrCreate( udAccessMode = GENERIC_READ | GENERIC_WRITE; - if( (!bCreateFlag) && (uiAccess & FLM_IO_RDONLY)) + if( (!bCreateFlag) && (uiIoFlags & FLM_IO_RDONLY)) { udAccessMode = GENERIC_READ; } Retry_Create: - // Try to create or open the file - - if( (m_FileHandle = CreateFile( (LPCTSTR)pszFileName, udAccessMode, + if( (m_hFile = CreateFile( (LPCTSTR)pszFileName, udAccessMode, udShareMode, NULL, udCreateMode, udAttrFlags, NULL)) == INVALID_HANDLE_VALUE) { udErrCode = GetLastError(); - if ((udErrCode == ERROR_PATH_NOT_FOUND) && (uiAccess & FLM_IO_CREATE_DIR)) + if( (udErrCode == ERROR_PATH_NOT_FOUND) && (uiIoFlags & FLM_IO_CREATE_DIR)) { char szTemp[ F_PATH_MAX_SIZE]; char szDirPath[ F_PATH_MAX_SIZE]; - uiAccess &= ~FLM_IO_CREATE_DIR; + uiIoFlags &= ~FLM_IO_CREATE_DIR; // Remove the file name for which we are creating the directory. - if( RC_OK( pFileSystem->pathReduce( szSaveFileName, + if( RC_OK( pFileSystem->pathReduce( m_pszFileName, szDirPath, szTemp))) { if( RC_OK( rc = pFileSystem->createDir( szDirPath))) @@ -217,46 +198,17 @@ Retry_Create: rc = f_mapPlatformError( udErrCode, (RCODE)(bCreateFlag - ? (RCODE)(m_bDoDirectIO + ? (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_CREATING_FILE : (RCODE)NE_FLM_CREATING_FILE) - : (RCODE)(m_bDoDirectIO + : (RCODE)(bDoDirectIO ? (RCODE)NE_FLM_DIRECT_OPENING_FILE : (RCODE)NE_FLM_OPENING_FILE))); goto Exit; } -Exit: - - if( RC_BAD( rc)) - { - m_FileHandle = INVALID_HANDLE_VALUE; - } - - return( rc); -} - -/**************************************************************************** -Desc: Create a file -****************************************************************************/ -RCODE F_FileHdl::create( - const char * pszFileName, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - - f_assert( m_bFileOpened == FALSE); - if( uiIoFlags & FLM_IO_DELETE_ON_RELEASE) { - f_assert( m_pszFileName == NULL); - - if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) - { - goto Exit; - } - - f_strcpy( m_pszFileName, pszFileName); m_bDeleteOnRelease = TRUE; } else @@ -264,183 +216,40 @@ RCODE F_FileHdl::create( m_bDeleteOnRelease = FALSE; } - if( RC_BAD( rc = openOrCreate( pszFileName, uiIoFlags, TRUE))) + // Allocate at least 64K - this will handle most read and write + // operations and will also be a multiple of the sector size most of + // the time. The calculation below rounds it up to the next sector + // boundary if it is not already on one. + + m_uiAlignedBuffSize = 64 * 1024; + if( bDoDirectIO) + { + m_uiAlignedBuffSize = roundToNextSector( m_uiAlignedBuffSize); + } + + if( RC_BAD( rc = f_allocAlignedBuffer( m_uiAlignedBuffSize, + &m_pucAlignedBuff))) { goto Exit; } - m_bFileOpened = TRUE; - m_ui64CurrentPos = 0; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - -Exit: - - if( RC_BAD( rc) && m_bDeleteOnRelease && m_pszFileName) - { - f_free( &m_pszFileName); - } - - return rc; -} - -/**************************************************************************** -Desc: Create a unique file name in the specified directory -****************************************************************************/ -RCODE F_FileHdl::createUnique( - char * pszDirName, - const char * pszFileExtension, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - char * pszTmp; - FLMBOOL bModext = TRUE; - FLMUINT uiBaseTime = 0; - FLMBYTE ucHighByte = 0; - char szFileName[ F_FILENAME_SIZE]; - char szDirPath[ F_PATH_MAX_SIZE]; - char szTmpPath[ F_PATH_MAX_SIZE]; - FLMUINT uiCount; - IF_FileSystem * pFileSystem = f_getFileSysPtr(); - - szFileName[0] = '\0'; - szTmpPath[0] = '\0'; - f_assert( m_bFileOpened == FALSE); - - if( uiIoFlags & FLM_IO_DELETE_ON_RELEASE) - { - f_assert( m_pszFileName == NULL); - m_bDeleteOnRelease = TRUE; - } - else - { - m_bDeleteOnRelease = FALSE; - } - - f_strcpy( szDirPath, pszDirName); - - // Search backwards replacing trailing spaces with NULLs. - - pszTmp = (char *) szDirPath; - pszTmp += (f_strlen( pszTmp) - 1); - while( pszTmp >= (char *) szDirPath && (*pszTmp == 0x20)) - { - *pszTmp = 0; - pszTmp--; - } - - // Append a backslash if one isn't already there - - if (pszTmp >= (char *) szDirPath && *pszTmp != '\\') - { - pszTmp++; - *pszTmp++ = '\\'; - } - else - { - pszTmp++; - } - *pszTmp = 0; - - if ((pszFileExtension) && (f_strlen( pszFileExtension) >= 3)) - { - bModext = FALSE; - } - - uiCount = 0; - do - { - pFileSystem->pathCreateUniqueName( &uiBaseTime, szFileName, - pszFileExtension, &ucHighByte, bModext); - - f_strcpy( szTmpPath, szDirPath); - pFileSystem->pathAppend( szTmpPath, szFileName); - if( m_pszFileName) - { - f_free( &m_pszFileName); - } - - rc = create( szTmpPath, uiIoFlags | FLM_IO_EXCL); - if (rc == NE_FLM_IO_DISK_FULL) - { - DeleteFile( (LPTSTR)szTmpPath); - goto Exit; - } - if ((rc == NE_FLM_IO_PATH_NOT_FOUND) || (rc == NE_FLM_IO_INVALID_PASSWORD)) - { - goto Exit; - } - } while ((rc != NE_FLM_OK) && (uiCount++ < 10)); - - // Check if the path was created - - if ((uiCount >= 10) && (rc != NE_FLM_OK)) - { - rc = RC_SET( NE_FLM_IO_PATH_CREATE_FAILURE); - goto Exit; - } - m_bFileOpened = TRUE; - m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; - - // Created file name needs to be returned - - f_strcpy( pszDirName, szTmpPath); - -Exit: - - if( RC_BAD( rc) && m_pszFileName) - { - f_free( &m_pszFileName); - } - - return( rc); -} - -/**************************************************************************** -Desc: Open a file -****************************************************************************/ -RCODE F_FileHdl::open( - const char * pszFileName, - FLMUINT uiIoFlags) -{ - RCODE rc = NE_FLM_OK; - - f_assert( m_bFileOpened == FALSE); - - if( uiIoFlags & FLM_IO_DELETE_ON_RELEASE) - { - f_assert( m_pszFileName == NULL); - - if( RC_BAD( rc = f_alloc( F_PATH_MAX_SIZE, &m_pszFileName))) - { - goto Exit; - } - - f_strcpy( m_pszFileName, pszFileName); - m_bDeleteOnRelease = TRUE; - } - else - { - m_bDeleteOnRelease = FALSE; - } - - if( RC_BAD( rc = openOrCreate( pszFileName, uiIoFlags, FALSE))) - { - goto Exit; - } - m_bFileOpened = TRUE; m_ui64CurrentPos = 0; m_bOpenedReadOnly = (uiIoFlags & FLM_IO_RDONLY) ? TRUE : FALSE; m_bOpenedExclusive = (uiIoFlags & FLM_IO_SH_DENYRW) ? TRUE : FALSE; + m_bDoDirectIO = bDoDirectIO; + m_bOpenedInAsyncMode = bOpenInAsyncMode; + m_bFlushRequired = FALSE; + f_atomicInc( &gv_openFiles); Exit: - if( RC_BAD( rc) && m_bDeleteOnRelease && m_pszFileName) + if( RC_BAD( rc)) { - f_free( &m_pszFileName); + close(); } - - return rc; + + return( rc); } /**************************************************************************** @@ -448,413 +257,417 @@ Desc: Close a file ****************************************************************************/ RCODE FLMAPI F_FileHdl::close( void) { - FLMBOOL bDeleteAllowed = TRUE; - RCODE rc = NE_FLM_OK; - - if( !m_bFileOpened) + if( m_bFlushRequired) { - goto Exit; + flush(); } - - if( !CloseHandle( m_FileHandle)) + + if( m_hFile != INVALID_HANDLE_VALUE) { - rc = f_mapPlatformError( GetLastError(), NE_FLM_CLOSING_FILE); - goto Exit; + CloseHandle( m_hFile); + m_hFile = INVALID_HANDLE_VALUE; } - - m_FileHandle = INVALID_HANDLE_VALUE; - m_bFileOpened = m_bOpenedReadOnly = m_bOpenedExclusive = FALSE; - + if( m_bDeleteOnRelease) { - f_assert( NULL != m_pszFileName ); - - if( bDeleteAllowed) - { - DeleteFile( (LPTSTR)m_pszFileName); - } - + DeleteFile( (LPTSTR)m_pszFileName); m_bDeleteOnRelease = FALSE; - f_free( &m_pszFileName); } - -Exit: - - return( rc); + + if( m_bFileOpened) + { + f_atomicDec( &gv_openFiles); + } + + freeCommonData(); + + m_bFileOpened = FALSE; + m_ui64CurrentPos = 0; + m_bOpenedReadOnly = FALSE; + m_bOpenedExclusive = FALSE; + m_bDoDirectIO = FALSE; + m_bOpenedInAsyncMode = FALSE; + m_bFlushRequired = FALSE; + + return( NE_FLM_OK); } /**************************************************************************** -Desc: Flush IO to disk +Desc: ****************************************************************************/ RCODE FLMAPI F_FileHdl::flush( void) { RCODE rc = NE_FLM_OK; - if( !m_bDoDirectIO) + if( !m_bDoDirectIO || m_bFlushRequired) { - if( !FlushFileBuffers( m_FileHandle)) + if( !FlushFileBuffers( m_hFile)) { rc = f_mapPlatformError( GetLastError(), NE_FLM_FLUSHING_FILE); } + + m_bFlushRequired = FALSE; } + return( rc); } /**************************************************************************** -Desc: Allocate an aligned buffer. +Desc: ****************************************************************************/ -RCODE F_FileHdl::allocAlignedBuffer( void) +RCODE F_FileHdl::lowLevelRead( + FLMUINT64 ui64ReadOffset, + FLMUINT uiBytesToRead, + void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesRead) { - RCODE rc = NE_FLM_OK; + RCODE rc = NE_FLM_OK; + DWORD uiBytesRead = 0; + OVERLAPPED * pOverlapped = NULL; + LARGE_INTEGER liTmp; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bWaitForRead = FALSE; - // Allocate at least 64K - this will handle most read and write - // operations and will also be a multiple of the sector size most of - // the time. The calculation below rounds it up to the next sector - // boundary if it is not already on one. - - m_uiAlignedBuffSize = roundToNextSector( 64 * 1024); - if ((m_pucAlignedBuff = (FLMBYTE *)VirtualAlloc( NULL, - (DWORD)m_uiAlignedBuffSize, - MEM_COMMIT, PAGE_READWRITE)) == NULL) + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) { - rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); goto Exit; } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Position and do a single read operation. -****************************************************************************/ -RCODE F_FileHdl::doOneRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvReadBuffer, - FLMUINT * puiBytesRead) -{ - RCODE rc = NE_FLM_OK; - OVERLAPPED * pOverlapped; - LARGE_INTEGER liTmp; - - // Position the file to the specified offset. - - if (!m_bOpenedInAsyncMode) - { - liTmp.QuadPart = ui64ReadOffset; - if( !SetFilePointerEx( m_FileHandle, liTmp, NULL, FILE_BEGIN)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_POSITIONING_IN_FILE); - goto Exit; - } - - pOverlapped = NULL; - } - else - { - if (!m_Overlapped.hEvent) - { - if ((m_Overlapped.hEvent = CreateEvent( NULL, TRUE, - FALSE, NULL)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_READ); - goto Exit; - } - } - - pOverlapped = &m_Overlapped; - pOverlapped->Offset = (DWORD)(ui64ReadOffset & 0xFFFFFFFF); - pOverlapped->OffsetHigh = (DWORD)(ui64ReadOffset >> 32); - - if( !ResetEvent( pOverlapped->hEvent)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_SETTING_UP_FOR_READ); - goto Exit; - } - } - - // Do the read - - if( !ReadFile( m_FileHandle, pvReadBuffer, uiBytesToRead, - puiBytesRead, pOverlapped)) - { - DWORD udErr = GetLastError(); - - if( udErr == ERROR_IO_PENDING && m_bOpenedInAsyncMode) - { - if( !GetOverlappedResult( m_FileHandle, - pOverlapped, puiBytesRead, TRUE)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_READING_FILE); - goto Exit; - } - } - else - { - rc = f_mapPlatformError( udErr, NE_FLM_READING_FILE); - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Read from a file - reads using aligned buffers and offsets - only - sector boundaries -****************************************************************************/ -RCODE F_FileHdl::directRead( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesRead; - FLMBYTE * pucReadBuffer; - FLMBYTE * pucDestBuffer; - FLMUINT uiMaxBytesToRead; - FLMBOOL bHitEOF; - - f_assert( m_bFileOpened); - - if( puiBytesReadRV) - { - *puiBytesReadRV = 0; - } if( ui64ReadOffset == FLM_IO_CURRENT_POS) { ui64ReadOffset = m_ui64CurrentPos; } - - // This loop does multiple reads (if necessary) to get all of the - // data. It uses aligned buffers and reads at sector offsets. - - pucDestBuffer = (FLMBYTE *)pvBuffer; - for (;;) + + if( !pvBuffer) { + pvBuffer = pIOBuffer->getBufferPtr(); + } - // See if we are using an aligned buffer. If not, allocate - // one (if not already allocated), and use it. - - if ((ui64ReadOffset & m_ui64NotOnSectorBoundMask) || - (((FLMUINT64)pucDestBuffer) & m_ui64NotOnSectorBoundMask) || - (((FLMUINT64)uiBytesToRead & m_ui64NotOnSectorBoundMask))) + if( m_bOpenedInAsyncMode) + { + if( RC_BAD( rc = allocFileAsyncClient( &pAsyncClient))) { - if (!m_pucAlignedBuff) + goto Exit; + } + + if( RC_BAD( rc = pAsyncClient->prepareForAsync( pIOBuffer))) + { + goto Exit; + } + + if( !pIOBuffer) + { + f_assert( pvBuffer); + bWaitForRead = TRUE; + } + + pAsyncClient->m_uiBytesToDo = uiBytesToRead; + pOverlapped = &pAsyncClient->m_Overlapped; + pOverlapped->Offset = (DWORD)(ui64ReadOffset & 0xFFFFFFFF); + pOverlapped->OffsetHigh = (DWORD)(ui64ReadOffset >> 32); + pIOBuffer = NULL; + + if( !ReadFile( m_hFile, pvBuffer, uiBytesToRead, + &uiBytesRead, pOverlapped)) + { + DWORD udErrCode = GetLastError(); + + if( udErrCode != ERROR_IO_PENDING) { - if (RC_BAD( rc = allocAlignedBuffer())) + rc = f_mapPlatformError( udErrCode, NE_FLM_READING_FILE); + pAsyncClient->notifyComplete( rc, uiBytesRead, FALSE); + goto Exit; + } + } + + if( bWaitForRead) + { + if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + { + if( rc != NE_FLM_IO_END_OF_FILE) { goto Exit; } + + rc = NE_FLM_OK; } - pucReadBuffer = m_pucAlignedBuff; - - // Must read enough bytes to cover all of the sectors that - // contain the data we are trying to read. The value of - // (ui64ReadOffset & m_ui64NotOnSectorBoundMask) will give us the - // number of additional bytes that are in the sector prior to - // the read offset. We then round that up to the next sector - // to get the total number of bytes we are going to read. - - uiMaxBytesToRead = roundToNextSector( uiBytesToRead + - (ui64ReadOffset & m_ui64NotOnSectorBoundMask)); - - // Can't read more than the aligned buffer will hold. - - if (uiMaxBytesToRead > m_uiAlignedBuffSize) - { - uiMaxBytesToRead = m_uiAlignedBuffSize; - } + + uiBytesRead = pAsyncClient->m_uiBytesDone; } else { - uiMaxBytesToRead = roundToNextSector( uiBytesToRead); - f_assert( uiMaxBytesToRead >= uiBytesToRead); - pucReadBuffer = pucDestBuffer; + uiBytesRead = uiBytesToRead; } - - bHitEOF = FALSE; - if (RC_BAD( rc = doOneRead( truncateToPrevSector( ui64ReadOffset), - uiMaxBytesToRead, pucReadBuffer, &uiBytesRead))) + } + else + { + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + liTmp.QuadPart = ui64ReadOffset; + if( !SetFilePointerEx( m_hFile, liTmp, NULL, FILE_BEGIN)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_POSITIONING_IN_FILE); + } + else + { + if( !ReadFile( m_hFile, pvBuffer, uiBytesToRead, &uiBytesRead, NULL)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_READING_FILE); + } + } + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) { goto Exit; } - - if( uiBytesRead < uiMaxBytesToRead) - { - bHitEOF = TRUE; - } - - // If the offset we want to read from is not on a sector - // boundary, increment the read buffer pointer to the - // offset where the data we need starts and decrement the - // bytes read by the difference between the start of the - // sector and the actual read offset. - - if (ui64ReadOffset & m_ui64NotOnSectorBoundMask) - { - pucReadBuffer += (ui64ReadOffset & m_ui64NotOnSectorBoundMask); - f_assert( uiBytesRead >= m_uiBytesPerSector); - uiBytesRead -= (ui64ReadOffset & m_ui64NotOnSectorBoundMask); - } - - // If bytes read is more than we actually need, truncate it back - // so that we only copy what we actually need. - - if( uiBytesRead > uiBytesToRead) - { - uiBytesRead = uiBytesToRead; - } - - uiBytesToRead -= uiBytesRead; - - if( puiBytesReadRV) - { - (*puiBytesReadRV) += uiBytesRead; - } - - m_ui64CurrentPos = ui64ReadOffset + uiBytesRead; - - // If using a different buffer for reading, copy the - // data read into the destination buffer. - - if (pucDestBuffer != pucReadBuffer) - { - f_memcpy( pucDestBuffer, pucReadBuffer, uiBytesRead); - } - - if (!uiBytesToRead) - { - break; - } - - // Still more to read - did we hit EOF above? - - if (bHitEOF) - { - rc = RC_SET( NE_FLM_IO_END_OF_FILE); - break; - } - - pucDestBuffer += uiBytesRead; - ui64ReadOffset += uiBytesRead; } + + m_ui64CurrentPos += uiBytesRead; -Exit: - return( rc ); -} - -/**************************************************************************** -Desc: Read from a file -****************************************************************************/ -RCODE FLMAPI F_FileHdl::read( - FLMUINT64 ui64ReadOffset, - FLMUINT uiBytesToRead, - void * pvBuffer, - FLMUINT * puiBytesReadRV) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesRead; - - // Do the direct IO call if enabled. - - if (m_bDoDirectIO) - { - rc = directRead( ui64ReadOffset, uiBytesToRead, - pvBuffer, puiBytesReadRV); - goto Exit; - } - - // If not doing direct IO, a single read call will do. - - f_assert( m_bFileOpened); - if( puiBytesReadRV) - { - *puiBytesReadRV = 0; - } - - if( ui64ReadOffset == FLM_IO_CURRENT_POS) - { - ui64ReadOffset = m_ui64CurrentPos; - } - - if( RC_BAD( rc = doOneRead( ui64ReadOffset, uiBytesToRead, - pvBuffer, &uiBytesRead))) - { - goto Exit; - } - - if( puiBytesReadRV) - { - *puiBytesReadRV = uiBytesRead; - } - - m_ui64CurrentPos = ui64ReadOffset + uiBytesRead; - - if (uiBytesRead < uiBytesToRead) + if( uiBytesRead < uiBytesToRead) { rc = RC_SET( NE_FLM_IO_END_OF_FILE); goto Exit; } - + Exit: - return( rc ); + + f_assert( uiBytesRead || RC_BAD( rc)); + + if( pAsyncClient) + { + pAsyncClient->Release(); + } + + if( pIOBuffer && !pIOBuffer->isPending()) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); + } + + if( puiBytesRead) + { + *puiBytesRead = uiBytesRead; + } + + return( rc); } /**************************************************************************** -Desc: Sets current position of file. +Desc: ****************************************************************************/ -RCODE FLMAPI F_FileHdl::seek( - FLMUINT64 ui64Offset, - FLMINT iWhence, - FLMUINT64 * pui64NewOffset) +RCODE F_FileHdl::lowLevelWrite( + FLMUINT64 ui64WriteOffset, + FLMUINT uiBytesToWrite, + const void * pvBuffer, + IF_IOBuffer * pIOBuffer, + FLMUINT * puiBytesWritten) { - RCODE rc = NE_FLM_OK; - - switch (iWhence) + RCODE rc = NE_FLM_OK; + OVERLAPPED * pOverlapped = NULL; + LARGE_INTEGER liTmp; + DWORD uiBytesWritten = 0; + F_FileAsyncClient * pAsyncClient = NULL; + FLMBOOL bWaitForWrite = FALSE; + + if( pIOBuffer && pvBuffer && pvBuffer != pIOBuffer->getBufferPtr()) { - case FLM_IO_SEEK_CUR: + rc = RC_SET_AND_ASSERT( NE_FLM_ILLEGAL_OP); + goto Exit; + } + + if( ui64WriteOffset == FLM_IO_CURRENT_POS) + { + ui64WriteOffset = m_ui64CurrentPos; + } + + if( m_bDoDirectIO) + { + FLMUINT64 ui64CurrFileSize; + FLMUINT uiTotalBytesToExtend; + LARGE_INTEGER liTmp; + + // Determine if the write will extend the file beyond its + // current size. + + if( RC_BAD( rc = size( &ui64CurrFileSize))) { - m_ui64CurrentPos += ui64Offset; - break; + goto Exit; } - case FLM_IO_SEEK_SET: + if( ui64WriteOffset + uiBytesToWrite > ui64CurrFileSize) { - m_ui64CurrentPos = ui64Offset; - break; - } - - case FLM_IO_SEEK_END: - { - if( RC_BAD( rc = size( &m_ui64CurrentPos ))) + m_bFlushRequired = TRUE; + + if( (uiTotalBytesToExtend = m_uiExtendSize) != 0) { + if( ui64CurrFileSize > m_uiMaxAutoExtendSize) + { + uiTotalBytesToExtend = 0; + } + else + { + // Don't extend beyond maximum file size. + + if( m_uiMaxAutoExtendSize - ui64CurrFileSize < uiTotalBytesToExtend) + { + uiTotalBytesToExtend = m_uiMaxAutoExtendSize - ui64CurrFileSize; + } + + // If the extend size is not on a sector boundary, round it down. + + uiTotalBytesToExtend = truncateToPrevSector( uiTotalBytesToExtend); + } + } + + if( uiTotalBytesToExtend) + { + liTmp.QuadPart = ui64CurrFileSize + uiTotalBytesToExtend; + if( !SetFilePointerEx( m_hFile, liTmp, NULL, FILE_BEGIN)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_POSITIONING_IN_FILE); + goto Exit; + } + + if( !SetEndOfFile( m_hFile)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_SETTING_FILE_INFO); + goto Exit; + } + } + } + } + + if( !pvBuffer) + { + pvBuffer = pIOBuffer->getBufferPtr(); + } + + if( m_bOpenedInAsyncMode) + { + if( RC_BAD( rc = allocFileAsyncClient( &pAsyncClient))) + { + goto Exit; + } + + if( RC_BAD( rc = pAsyncClient->prepareForAsync( pIOBuffer))) + { + goto Exit; + } + + if( !pIOBuffer) + { + bWaitForWrite = TRUE; + } + + pAsyncClient->m_uiBytesToDo = uiBytesToWrite; + pOverlapped = &pAsyncClient->m_Overlapped; + pOverlapped->Offset = (DWORD)(ui64WriteOffset & 0xFFFFFFFF); + pOverlapped->OffsetHigh = (DWORD)(ui64WriteOffset >> 32); + pIOBuffer = NULL; + + if( !WriteFile( m_hFile, pvBuffer, + uiBytesToWrite, &uiBytesWritten, pOverlapped)) + { + DWORD udErrCode = GetLastError(); + + if( udErrCode != ERROR_IO_PENDING) + { + rc = f_mapPlatformError( udErrCode, NE_FLM_WRITING_FILE); + pAsyncClient->notifyComplete( rc, uiBytesWritten, FALSE); goto Exit; } - break; } - default: + if( bWaitForWrite) + { + if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + { + if( rc != NE_FLM_IO_DISK_FULL) + { + goto Exit; + } + + rc = NE_FLM_OK; + } + + uiBytesWritten = pAsyncClient->m_uiBytesDone; + } + else + { + uiBytesWritten = uiBytesToWrite; + } + } + else + { + if( pIOBuffer) + { + pIOBuffer->setPending(); + } + + liTmp.QuadPart = ui64WriteOffset; + if( !SetFilePointerEx( m_hFile, liTmp, NULL, FILE_BEGIN)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_POSITIONING_IN_FILE); + } + else + { + if( !WriteFile( m_hFile, pvBuffer, uiBytesToWrite, + &uiBytesWritten, NULL)) + { + rc = f_mapPlatformError( GetLastError(), NE_FLM_WRITING_FILE); + } + } + + if( pIOBuffer) + { + pIOBuffer->notifyComplete( rc); + pIOBuffer = NULL; + } + + if( RC_BAD( rc)) { - rc = RC_SET_AND_ASSERT( NE_FLM_NOT_IMPLEMENTED); goto Exit; } } - if( pui64NewOffset) + m_ui64CurrentPos += uiBytesWritten; + + if( uiBytesWritten < uiBytesToWrite) { - *pui64NewOffset = m_ui64CurrentPos; + rc = RC_SET_AND_ASSERT( NE_FLM_IO_DISK_FULL); + goto Exit; } Exit: + if( pAsyncClient) + { + pAsyncClient->Release(); + } + + if( pIOBuffer && !pIOBuffer->isPending()) + { + f_assert( RC_BAD( rc)); + pIOBuffer->notifyComplete( rc); + } + + if( puiBytesWritten) + { + *puiBytesWritten = uiBytesWritten; + } + return( rc); } @@ -867,7 +680,7 @@ RCODE FLMAPI F_FileHdl::size( RCODE rc = NE_FLM_OK; LARGE_INTEGER liTmp; - if( !GetFileSizeEx( m_FileHandle, &liTmp)) + if( !GetFileSizeEx( m_hFile, &liTmp)) { rc = f_mapPlatformError( GetLastError(), NE_FLM_GETTING_FILE_SIZE); goto Exit; @@ -880,16 +693,6 @@ Exit: return( rc); } -/**************************************************************************** -Desc: -****************************************************************************/ -RCODE FLMAPI F_FileHdl::tell( - FLMUINT64 * pui64Offset) -{ - *pui64Offset = m_ui64CurrentPos; - return( NE_FLM_OK); -} - /**************************************************************************** Desc: Truncate the file to the indicated size WARNING: Direct IO methods are calling this method. Make sure that all changes @@ -906,7 +709,7 @@ RCODE FLMAPI F_FileHdl::truncate( // Position the file to the nearest sector below the read offset. liTmp.QuadPart = ui64Size; - if( !SetFilePointerEx( m_FileHandle, liTmp, NULL, FILE_BEGIN)) + if( !SetFilePointerEx( m_hFile, liTmp, NULL, FILE_BEGIN)) { rc = f_mapPlatformError( GetLastError(), NE_FLM_POSITIONING_IN_FILE); goto Exit; @@ -914,7 +717,7 @@ RCODE FLMAPI F_FileHdl::truncate( // Set the new file size. - if( !SetEndOfFile( m_FileHandle)) + if( !SetEndOfFile( m_hFile)) { rc = f_mapPlatformError( GetLastError(), NE_FLM_TRUNCATING_FILE); goto Exit; @@ -925,600 +728,6 @@ Exit: return( rc); } -/**************************************************************************** -Desc: Handles when a file is extended in direct IO mode. May extend the - file some more. Will always call FlushFileBuffers to ensure that - the new file size gets written out. -****************************************************************************/ -RCODE F_FileHdl::extendFile( - FLMUINT64 ui64EndOfLastWrite, - FLMUINT uiMaxBytesToExtend, - FLMBOOL bFlush) -{ - RCODE rc = NE_FLM_OK; - OVERLAPPED * pOverlapped; - FLMUINT uiTotalBytesToExtend; - FLMUINT uiBytesToWrite; - FLMUINT uiBytesWritten; - LARGE_INTEGER liTmp; - - if ((uiTotalBytesToExtend = uiMaxBytesToExtend) != 0) - { - if (ui64EndOfLastWrite > m_uiMaxAutoExtendSize) - { - uiTotalBytesToExtend = 0; - } - else - { - // Don't extend beyond maximum file size. - - if (m_uiMaxAutoExtendSize - ui64EndOfLastWrite < uiTotalBytesToExtend) - { - uiTotalBytesToExtend = m_uiMaxAutoExtendSize - ui64EndOfLastWrite; - } - - // If the extend size is not on a sector boundary, round it down. - - uiTotalBytesToExtend = truncateToPrevSector( uiTotalBytesToExtend); - } - } - - if (uiTotalBytesToExtend) - { - // Allocate an aligned buffer if we haven't already. - - if (!m_pucAlignedBuff) - { - if (RC_BAD( rc = allocAlignedBuffer())) - { - goto Exit; - } - } - - f_memset( m_pucAlignedBuff, 0, m_uiAlignedBuffSize); - } - - // Extend the file until we run out of bytes to write. - - while (uiTotalBytesToExtend) - { - if ((uiBytesToWrite = m_uiAlignedBuffSize) > uiTotalBytesToExtend) - { - uiBytesToWrite = uiTotalBytesToExtend; - } - - if (!m_bOpenedInAsyncMode) - { - liTmp.QuadPart = ui64EndOfLastWrite; - if( !SetFilePointerEx( m_FileHandle, liTmp, NULL, FILE_BEGIN)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_POSITIONING_IN_FILE); - goto Exit; - } - - pOverlapped = NULL; - } - else - { - pOverlapped = &m_Overlapped; - if (!pOverlapped->hEvent) - { - if ((pOverlapped->hEvent = CreateEvent( NULL, TRUE, - FALSE, NULL)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - pOverlapped->Offset = (DWORD)(ui64EndOfLastWrite & 0xFFFFFFFF); - pOverlapped->OffsetHigh = (DWORD)(ui64EndOfLastWrite >> 32); - - if (!ResetEvent( pOverlapped->hEvent)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - // Do the write - - if( !WriteFile( m_FileHandle, m_pucAlignedBuff, - uiBytesToWrite, &uiBytesWritten, pOverlapped)) - { - flmAssert( 0); - rc = f_mapPlatformError( GetLastError(), NE_FLM_WRITING_FILE); - - // Don't care if it is a disk full error, because - // extending the file is optional work. - - if( rc == NE_FLM_IO_DISK_FULL) - { - rc = NE_FLM_OK; - break; - } - - goto Exit; - } - - // NO more room on disk, but that's OK because we were only - // extending the file beyond where it needed to be. If that - // fails, we will just flush what we have done so far. - - if( uiBytesWritten < uiBytesToWrite) - { - break; - } - - uiTotalBytesToExtend -= uiBytesToWrite; - ui64EndOfLastWrite += uiBytesToWrite; - } - - // Flush the file buffers to ensure that the file size gets written - // out. - - if( bFlush) - { - if( !FlushFileBuffers( m_FileHandle)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_FLUSHING_FILE); - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Write to a file using direct IO -****************************************************************************/ -RCODE F_FileHdl::directWrite( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - IF_IOBuffer * pBufferObj, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesRead; - FLMUINT uiBytesWritten; - FLMBYTE * pucWriteBuffer; - FLMBYTE * pucSrcBuffer; - FLMUINT uiMaxBytesToWrite; - FLMUINT64 ui64CurrFileSize; - FLMUINT uiBytesBeingOutput; - OVERLAPPED * pOverlapped; - DWORD udErr; - FLMBOOL bExtendFile = FALSE; - FLMBOOL bWaitForWrite = (pBufferObj == NULL) - ? TRUE - : FALSE; - FLMUINT64 ui64LastWriteOffset; - FLMUINT uiLastWriteSize; - LARGE_INTEGER liTmp; - - f_assert( m_bFileOpened); - - if( !bWaitForWrite) - { - f_assert( m_bOpenedInAsyncMode); - } - - if( puiBytesWrittenRV) - { - *puiBytesWrittenRV = 0; - } - - if( ui64WriteOffset == FLM_IO_CURRENT_POS) - { - ui64WriteOffset = m_ui64CurrentPos; - } - - // Determine if the write will extend the file beyond its - // current size. If so, we will need to call FlushFileBuffers - - if( !GetFileSizeEx( m_FileHandle, &liTmp)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_GETTING_FILE_SIZE); - goto Exit; - } - - ui64CurrFileSize = liTmp.QuadPart; - - if( ui64WriteOffset + uiBytesToWrite > ui64CurrFileSize && - m_uiExtendSize != (FLMUINT)(~0)) - { - bExtendFile = TRUE; - - if( ui64WriteOffset > ui64CurrFileSize) - { - - // Fill in the empty space. - - if (RC_BAD( rc = extendFile( ui64CurrFileSize, - roundToNextSector( ui64WriteOffset - ui64CurrFileSize), FALSE))) - { - goto Exit; - } - } - - // Can't do asynchronous if we are going to extend the file. - - bWaitForWrite = TRUE; - } - - // This loop is for direct IO - must make sure we use - // aligned buffers. - - pucSrcBuffer = (FLMBYTE *)pvBuffer; - for (;;) - { - - // See if we are using an aligned buffer. If not, allocate - // one (if not already allocated), and use it. - - if ((ui64WriteOffset & m_ui64NotOnSectorBoundMask) || - (((FLMUINT)pucSrcBuffer) & m_ui64NotOnSectorBoundMask) || - (uiBytesToWrite & m_ui64NotOnSectorBoundMask)) - { - - // Cannot do an async write if we have to use a temporary buffer - - bWaitForWrite = TRUE; - - if (!m_pucAlignedBuff) - { - if (RC_BAD( rc = allocAlignedBuffer())) - { - goto Exit; - } - } - pucWriteBuffer = m_pucAlignedBuff; - - // Must write enough bytes to cover all of the sectors that - // contain the data we are trying to write out. The value of - // (ui64WriteOffset & m_ui64NotOnSectorBoundMask) will give us the - // number of additional bytes that are in the sector prior to - // the read offset. We then round to the next sector to get the - // total number of bytes we are going to write. - - uiMaxBytesToWrite = roundToNextSector( uiBytesToWrite + - (ui64WriteOffset & m_ui64NotOnSectorBoundMask)); - - // Can't write more than the aligned buffer will hold. - - if (uiMaxBytesToWrite > m_uiAlignedBuffSize) - { - uiMaxBytesToWrite = m_uiAlignedBuffSize; - uiBytesBeingOutput = uiMaxBytesToWrite - - (ui64WriteOffset & m_ui64NotOnSectorBoundMask); - } - else - { - uiBytesBeingOutput = uiBytesToWrite; - } - - // If the write offset is not on a sector boundary, we must - // read at least the first sector into the buffer. - - if (ui64WriteOffset & m_ui64NotOnSectorBoundMask) - { - - // Read the first sector that is to be written out. - // Read one sector's worth of data - so that we will - // preserve what is already in the sector before - // writing it back out again. - - if (RC_BAD( rc = doOneRead( truncateToPrevSector( ui64WriteOffset), - m_uiBytesPerSector, pucWriteBuffer, &uiBytesRead))) - { - goto Exit; - } - } - - // If we are writing more than one sector, and the last sector's - // worth of data we are writing out is only a partial sector, - // we must read in this sector as well. - - if ((uiMaxBytesToWrite > m_uiBytesPerSector) && - (uiMaxBytesToWrite > uiBytesToWrite)) - { - - // Read the last sector that is to be written out. - // Read one sector's worth of data - so that we will - // preserve what is already in the sector before - // writing it back out again. - - if (RC_BAD( rc = doOneRead( - (truncateToPrevSector( ui64WriteOffset)) + - (uiMaxBytesToWrite - m_uiBytesPerSector), - m_uiBytesPerSector, - (&pucWriteBuffer [uiMaxBytesToWrite - m_uiBytesPerSector]), - &uiBytesRead))) - { - if (rc == NE_FLM_IO_END_OF_FILE) - { - rc = NE_FLM_OK; - f_memset( &pucWriteBuffer [uiMaxBytesToWrite - m_uiBytesPerSector], - 0, m_uiBytesPerSector); - } - else - { - goto Exit; - } - } - } - - // Finally, copy the data from the source buffer into the - // write buffer. - - f_memcpy( &pucWriteBuffer[ ui64WriteOffset & m_ui64NotOnSectorBoundMask], - pucSrcBuffer, uiBytesBeingOutput); - } - else - { - pucWriteBuffer = pucSrcBuffer; - uiMaxBytesToWrite = uiBytesToWrite; - uiBytesBeingOutput = uiBytesToWrite; - } - - // Position the file to the nearest sector below the write offset. - - ui64LastWriteOffset = truncateToPrevSector( ui64WriteOffset); - if( !m_bOpenedInAsyncMode) - { - liTmp.QuadPart = ui64LastWriteOffset; - if( !SetFilePointerEx( m_FileHandle, liTmp, NULL, FILE_BEGIN)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_POSITIONING_IN_FILE); - goto Exit; - } - - pOverlapped = NULL; - } - else - { - if (!pBufferObj) - { - pOverlapped = &m_Overlapped; - } - else - { - pOverlapped = ((F_IOBuffer *)pBufferObj)->getOverlapped(); - ((F_IOBuffer *)pBufferObj)->setFileHandle( m_FileHandle); - } - - if (!pOverlapped->hEvent) - { - if ((pOverlapped->hEvent = CreateEvent( NULL, TRUE, - FALSE, NULL)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - pOverlapped->Offset = (DWORD)(ui64LastWriteOffset & 0xFFFFFFFF); - pOverlapped->OffsetHigh = (DWORD)(ui64LastWriteOffset >> 32); - - if (!ResetEvent( pOverlapped->hEvent)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - // Do the write - - uiLastWriteSize = uiMaxBytesToWrite; - if( !WriteFile( m_FileHandle, (LPVOID)pucWriteBuffer, - (DWORD)uiMaxBytesToWrite, &uiBytesWritten, - pOverlapped)) - { - udErr = GetLastError(); - if( udErr == ERROR_IO_PENDING && m_bOpenedInAsyncMode) - { - // If an async structure was passed in, we better have - // been able to finish in a single write operation. - // Otherwise, we are in deep trouble because we are not - // set up to do multiple async write operations within - // a single call. - - if( !bWaitForWrite) - { - pBufferObj->makePending(); - break; - } - - if (!GetOverlappedResult( m_FileHandle, pOverlapped, - &uiBytesWritten, TRUE)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_WRITING_FILE); - goto Exit; - } - } - else - { - flmAssert( 0); - rc = f_mapPlatformError( udErr, NE_FLM_WRITING_FILE); - goto Exit; - } - } - - if (uiBytesWritten < uiMaxBytesToWrite) - { - rc = RC_SET( NE_FLM_IO_DISK_FULL); - goto Exit; - } - - uiBytesToWrite -= uiBytesBeingOutput; - - if( puiBytesWrittenRV) - { - (*puiBytesWrittenRV) += uiBytesBeingOutput; - } - - m_ui64CurrentPos = ui64WriteOffset + uiBytesBeingOutput; - - if (!uiBytesToWrite) - { - break; - } - - pucSrcBuffer += uiBytesBeingOutput; - ui64WriteOffset += uiBytesBeingOutput; - } - - // See if we extended the file. If so, we may want to extend it some - // more and then also do a flush. - - if (bExtendFile) - { - // NOTE: ui64LastWriteOffset + uiLastWrite is guaranteed to be - // on a sector boundary. - - if (RC_BAD( rc = extendFile( - ui64LastWriteOffset + uiLastWriteSize, - m_uiExtendSize, TRUE))) - { - goto Exit; - } - } - -Exit: - - if( pBufferObj && !pBufferObj->isPending()) - { - pBufferObj->notifyComplete( rc); - } - - return( rc); -} - -/**************************************************************************** -Desc: Write to a file -****************************************************************************/ -RCODE FLMAPI F_FileHdl::write( - FLMUINT64 ui64WriteOffset, - FLMUINT uiBytesToWrite, - const void * pvBuffer, - FLMUINT * puiBytesWrittenRV) -{ - RCODE rc = NE_FLM_OK; - FLMUINT uiBytesWritten; - OVERLAPPED * pOverlapped; - DWORD udErr; - LARGE_INTEGER liTmp; - - if (m_bDoDirectIO) - { - rc = directWrite( ui64WriteOffset, uiBytesToWrite, pvBuffer, - NULL, puiBytesWrittenRV); - goto Exit; - } - - // If not doing direct IO, a single write call will do. - - f_assert( m_bFileOpened); - - if( puiBytesWrittenRV) - { - *puiBytesWrittenRV = 0; - } - - if( ui64WriteOffset == FLM_IO_CURRENT_POS) - { - ui64WriteOffset = m_ui64CurrentPos; - } - - // Position the file. - - if (!m_bOpenedInAsyncMode) - { - liTmp.QuadPart = ui64WriteOffset; - if( !SetFilePointerEx( m_FileHandle, liTmp, NULL, FILE_BEGIN)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_POSITIONING_IN_FILE); - goto Exit; - } - - pOverlapped = NULL; - } - else - { - if (!m_Overlapped.hEvent) - { - if ((m_Overlapped.hEvent = CreateEvent( NULL, TRUE, - FALSE, NULL)) == NULL) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - pOverlapped = &m_Overlapped; - pOverlapped->Offset = (DWORD)(ui64WriteOffset & 0xFFFFFFFF); - pOverlapped->OffsetHigh = (DWORD)(ui64WriteOffset >> 32); - - if( !ResetEvent( pOverlapped->hEvent)) - { - rc = f_mapPlatformError( GetLastError(), - NE_FLM_SETTING_UP_FOR_WRITE); - goto Exit; - } - } - - if (!WriteFile( m_FileHandle, (LPVOID)pvBuffer, - (DWORD)uiBytesToWrite, &uiBytesWritten, - pOverlapped)) - { - udErr = GetLastError(); - if (udErr == ERROR_IO_PENDING && m_bOpenedInAsyncMode) - { - if (!GetOverlappedResult( m_FileHandle, pOverlapped, - &uiBytesWritten, TRUE)) - { - flmAssert( 0); - rc = f_mapPlatformError( GetLastError(), NE_FLM_WRITING_FILE); - goto Exit; - } - } - else - { - flmAssert( 0); - rc = f_mapPlatformError( udErr, NE_FLM_WRITING_FILE); - goto Exit; - } - } - - if( puiBytesWrittenRV) - { - *puiBytesWrittenRV = uiBytesWritten; - } - - m_ui64CurrentPos = ui64WriteOffset + uiBytesWritten; - - if (uiBytesWritten < uiBytesToWrite) - { - rc = RC_SET( NE_FLM_IO_DISK_FULL); - goto Exit; - } - -Exit: - return( rc ); -} - /**************************************************************************** Desc: ****************************************************************************/ @@ -1526,9 +735,7 @@ RCODE FLMAPI F_FileHdl::lock( void) { RCODE rc = NE_FLM_OK; - // Lock the first byte in file - - if( !LockFile( m_FileHandle, 0, 0, 1, 1)) + if( !LockFile( m_hFile, 0, 0, 1, 1)) { rc = RC_SET( NE_FLM_IO_FILE_LOCK_ERR); goto Exit; @@ -1538,7 +745,7 @@ Exit: return( rc); } - + /**************************************************************************** Desc: ****************************************************************************/ @@ -1546,9 +753,7 @@ RCODE FLMAPI F_FileHdl::unlock( void) { RCODE rc = NE_FLM_OK; - // Unlock the first byte in file - - if( !UnlockFile( m_FileHandle, 0, 0, 1, 1)) + if( !UnlockFile( m_hFile, 0, 0, 1, 1)) { rc = RC_SET( NE_FLM_IO_FILE_LOCK_ERR); goto Exit; @@ -1558,7 +763,7 @@ Exit: return( rc); } - + /**************************************************************************** Desc: ****************************************************************************/ diff --git a/xflaim/src/fdbcopy.cpp b/xflaim/src/fdbcopy.cpp index 79d00dd..1920941 100644 --- a/xflaim/src/fdbcopy.cpp +++ b/xflaim/src/fdbcopy.cpp @@ -25,14 +25,10 @@ #include "flaimsys.h" -// Local prototypes - -typedef struct Copied_Name * COPIED_NAME_p; - -typedef struct Copied_Name +typedef struct COPIED_NAME { char szPath[ F_PATH_MAX_SIZE]; - COPIED_NAME_p pNext; + COPIED_NAME * pNext; } COPIED_NAME; typedef struct @@ -228,11 +224,20 @@ RCODE F_DbSystem::copyDb( goto Exit; } - if (RC_BAD( rc = pSrcSFileHdl->setup( pSrcSFileClient))) + if( RC_BAD( rc = pSrcSFileHdl->setup( pSrcSFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } + // Close all unused file handles + + if( gv_XFlmSysData.pFileHdlCache) + { + gv_XFlmSysData.pFileHdlCache->closeUnusedFiles(); + } + // Lock the destination database, if not already locked. // This is so we can overwrite it without necessarily // deleting it. May unlock and re-lock the global mutex. @@ -352,7 +357,9 @@ retry: goto Exit; } - if (RC_BAD( rc = pDestSFileHdl->setup( pDestSFileClient))) + if( RC_BAD( rc = pDestSFileHdl->setup( pDestSFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -469,8 +476,8 @@ retry: // Close all file handles in the source and destination - pSrcSFileHdl->releaseFiles( TRUE); - pDestSFileHdl->releaseFiles( TRUE); + pSrcSFileHdl->releaseFiles(); + pDestSFileHdl->releaseFiles(); // Copy the database files. @@ -696,7 +703,7 @@ Exit: while (pCopiedList) { - COPIED_NAME_p pNext = pCopiedList->pNext; + COPIED_NAME * pNext = pCopiedList->pNext; // If the overall copy failed, delete the copied file. @@ -822,7 +829,7 @@ FSTATIC RCODE flmCopyFile( // Read data from source file. - if (RC_BAD( rc = pSrcFileHdl->sectorRead( uiOffset, uiBytesToRead, + if (RC_BAD( rc = pSrcFileHdl->read( uiOffset, uiBytesToRead, pucBuffer, &uiBytesRead))) { if (rc == NE_FLM_IO_END_OF_FILE) @@ -900,7 +907,7 @@ FSTATIC RCODE flmCopyFile( if (ppCopiedListRV) { - COPIED_NAME_p pCopyName; + COPIED_NAME * pCopyName; if( RC_BAD( rc = f_alloc( (FLMUINT)sizeof( COPIED_NAME), &pCopyName))) { diff --git a/xflaim/src/fdbremov.cpp b/xflaim/src/fdbremov.cpp index 788f994..9359305 100644 --- a/xflaim/src/fdbremov.cpp +++ b/xflaim/src/fdbremov.cpp @@ -77,6 +77,13 @@ RCODE F_DbSystem::dbRemove( goto Exit; } + // Close all unused file handles + + if( gv_XFlmSysData.pFileHdlCache) + { + gv_XFlmSysData.pFileHdlCache->closeUnusedFiles(); + } + if (pszDataDir && *pszDataDir) { if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->pathReduce( diff --git a/xflaim/src/fdbrenam.cpp b/xflaim/src/fdbrenam.cpp index 58fffa7..6d84a8a 100644 --- a/xflaim/src/fdbrenam.cpp +++ b/xflaim/src/fdbrenam.cpp @@ -122,7 +122,9 @@ RCODE F_DbSystem::dbRename( rc = RC_SET( NE_XFLM_INVALID_PARM); goto Exit; } + f_strcpy( pszNewName, pszOldName); + if (RC_BAD( rc = gv_XFlmSysData.pFileSystem->pathAppend( pszNewName, szNewBase))) { @@ -160,10 +162,18 @@ RCODE F_DbSystem::dbRename( { goto Exit; } + if (RC_BAD( rc = checkDatabaseClosed( pszFullNewName, pszDataDir))) { goto Exit; } + + // Close all unused file handles + + if( gv_XFlmSysData.pFileHdlCache) + { + gv_XFlmSysData.pFileHdlCache->closeUnusedFiles(); + } // Start renaming files, beginning with the main DB file. diff --git a/xflaim/src/ffilehdr.cpp b/xflaim/src/ffilehdr.cpp index 67e0f2b..2e75f9a 100644 --- a/xflaim/src/ffilehdr.cpp +++ b/xflaim/src/ffilehdr.cpp @@ -379,6 +379,40 @@ Exit: return( rc); } +/*************************************************************************** +Desc: This routine reads the header information in a FLAIM database, + verifies the password, and returns the file header and log + header information. +*****************************************************************************/ +RCODE flmGetHdrInfo( + F_SuperFileHdl * pSFileHdl, + XFLM_DB_HDR * pDbHdr, + FLMUINT32 * pui32CalcCRC) +{ + RCODE rc = NE_XFLM_OK; + IF_FileHdl * pCFileHdl = NULL; + + if( RC_BAD( rc = pSFileHdl->getFileHdl( 0, FALSE, &pCFileHdl))) + { + goto Exit; + } + + if( RC_BAD( rc = flmReadAndVerifyHdrInfo( NULL, pCFileHdl, + pDbHdr, pui32CalcCRC))) + { + goto Exit; + } + +Exit: + + if( pCFileHdl) + { + pCFileHdl->Release(); + } + + return( rc); +} + /*************************************************************************** Desc: This routine reads and verifies the information contained in the file header and log header of a FLAIM database. diff --git a/xflaim/src/filesys.h b/xflaim/src/filesys.h index 0c2eb92..a1df157 100644 --- a/xflaim/src/filesys.h +++ b/xflaim/src/filesys.h @@ -152,10 +152,6 @@ RCODE flmCreateLckFile( const char * pszFilePath, IF_FileHdl ** ppLockFileHdl); -RCODE flmAllocHashTbl( - FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV); - RCODE flmWaitNotifyReq( F_MUTEX hMutex, F_SEM hSem, diff --git a/xflaim/src/flaimsys.h b/xflaim/src/flaimsys.h index 301c25d..a9554c5 100644 --- a/xflaim/src/flaimsys.h +++ b/xflaim/src/flaimsys.h @@ -5261,14 +5261,12 @@ private: const char * pszDestRflDir, IF_DbCopyStatus * ifpStatus); - static RCODE monitorThrd( + static RCODE FLMAPI monitorThrd( IF_Thread * pThread); - static RCODE cacheCleanupThrd( + static RCODE FLMAPI cacheCleanupThrd( IF_Thread * pThread); - static void checkNotUsedObjects( void); - FLMATOMIC m_refCnt; friend class F_Db; @@ -8470,6 +8468,10 @@ public: FLMUINT FLMAPI getFileOffset( FLMUINT uiBlockAddr); + FLMUINT FLMAPI getBlockAddress( + FLMUINT uiFileNumber, + FLMUINT uiFileOffset); + RCODE FLMAPI getFilePath( FLMUINT uiFileNumber, char * pszPath); diff --git a/xflaim/src/flbackup.cpp b/xflaim/src/flbackup.cpp index 79e6e37..042dc18 100644 --- a/xflaim/src/flbackup.cpp +++ b/xflaim/src/flbackup.cpp @@ -80,20 +80,16 @@ public: private: - // Methods - RCODE signalThread( void); RCODE _setup( void); - static RCODE readThread( + static RCODE FLMAPI readThread( IF_Thread * pThread); - static RCODE writeThread( + static RCODE FLMAPI writeThread( IF_Thread * pThread); - // Data - FLMBOOL m_bSetup; FLMBOOL m_bFirstRead; FLMBOOL m_bFinalRead; @@ -1095,7 +1091,9 @@ RCODE F_DbSystem::dbRestore( goto Exit; } - if( RC_BAD( rc = pSFile->setup( &SFileClient))) + if( RC_BAD( rc = pSFile->setup( &SFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1619,7 +1617,7 @@ FSTATIC RCODE flmRestoreFile( // Compare the incremental backup sequence number to the value in the // database's DB header. - if( RC_BAD( rc = pSFile->readHeader( 0, sizeof( XFLM_DB_HDR), + if( RC_BAD( rc = pSFile->readBlock( 0, sizeof( XFLM_DB_HDR), &dbHdr, &uiTmp))) { goto Exit; @@ -1681,7 +1679,7 @@ FSTATIC RCODE flmRestoreFile( // Write the database header - if( RC_BAD( rc = pSFile->writeHeader( 0, + if( RC_BAD( rc = pSFile->writeBlock( 0, uiBlockSize, pucBlkBuf, &uiBytesWritten))) { goto Exit; @@ -1755,22 +1753,8 @@ FSTATIC RCODE flmRestoreFile( // Write the block to the database -#ifdef FLM_UNIX - - // Unix systems can have sector sizes that are larger than our - // typical 4K database blocks. The Unix implementation of SectorWrite - // (called by writeBlock) will write the passed-in block and clobber any - // additional data beyond the end of the block to the end of the sector if - // it has enough room in the block buffer to write a full sector. If the - // block buffer is less than a full sector, the Unix SectorWrite will only - // write out the amount requested, not a full sector. - if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) -#else - if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) -#endif + uiBlockSize, pucBlkBuf, &uiBytesWritten))) { if( rc == NE_FLM_IO_PATH_NOT_FOUND || rc == NE_FLM_IO_INVALID_FILENAME) @@ -1788,13 +1772,8 @@ FSTATIC RCODE flmRestoreFile( goto Exit; } -#ifdef FLM_UNIX if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) -#else - if( RC_BAD( rc = pSFile->writeBlock( uiBlkAddr, - uiBlockSize, pucBlkBuf, NULL, &uiBytesWritten))) -#endif + uiBlockSize, pucBlkBuf, &uiBytesWritten))) { goto Exit; } @@ -2474,7 +2453,7 @@ Exit: /**************************************************************************** Desc: This thread reads data in the background ****************************************************************************/ -RCODE F_BackerStream::readThread( +RCODE FLMAPI F_BackerStream::readThread( IF_Thread * pThread) { F_BackerStream * pBackerStream = (F_BackerStream *)pThread->getParm1(); @@ -2513,7 +2492,7 @@ Exit: /**************************************************************************** Desc: This thread writes data in the background ****************************************************************************/ -RCODE F_BackerStream::writeThread( +RCODE FLMAPI F_BackerStream::writeThread( IF_Thread * pThread) { F_BackerStream * pBackerStream = (F_BackerStream *)pThread->getParm1(); diff --git a/xflaim/src/flblddb.cpp b/xflaim/src/flblddb.cpp index a7bb7a6..dbca1c0 100644 --- a/xflaim/src/flblddb.cpp +++ b/xflaim/src/flblddb.cpp @@ -146,7 +146,6 @@ public: private: RCODE readBlock( - IF_FileHdl * pFileHdl, FLMUINT uiFileNumber, FLMUINT uiFileOffset, F_SCAN_STATE * pScanState); @@ -486,7 +485,9 @@ Retry: goto Exit; } - if( RC_BAD( rc = m_pSFileHdl->setup( &SFileClient))) + if( RC_BAD( rc = m_pSFileHdl->setup( &SFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1893,7 +1894,6 @@ RCODE F_RebuildNodeIStream::close( void) Desc: *****************************************************************************/ RCODE F_RebuildNodeIStream::readBlock( - IF_FileHdl * pFileHdl, FLMUINT uiFileNumber, FLMUINT uiFileOffset, F_SCAN_STATE * pScanState) @@ -1907,17 +1907,9 @@ RCODE F_RebuildNodeIStream::readBlock( F_BLK_HDR * pBlkHdr = pScanState->blkUnion.pBlkHdr; FLMBYTE * pucBlk = pScanState->blkUnion.pucBlk; - if( !pFileHdl) - { - if( RC_BAD( rc = m_pDbRebuild->m_pSFileHdl->getFileHdl( - uiFileNumber, FALSE, &pFileHdl))) - { - goto Exit; - } - } - - if( RC_BAD( rc = pFileHdl->sectorRead( uiFileOffset, uiBlockSize, - pucBlk, NULL))) + if( RC_BAD( rc = m_pDbRebuild->m_pSFileHdl->readBlock( + FSBlkAddress( uiFileNumber, uiFileOffset), + uiBlockSize, pucBlk, NULL))) { goto Exit; } @@ -2020,7 +2012,6 @@ RCODE F_RebuildNodeIStream::readNextSequentialBlock( { RCODE rc = NE_XFLM_OK; FLMUINT uiBlkCollectionNum; - IF_FileHdl * pFileHdl = NULL; FLMUINT uiBlockSize = m_pDbRebuild->getBlockSize(); FLMUINT uiTryNextCount = 0; @@ -2048,32 +2039,20 @@ TryNextFile: rc = RC_SET( NE_XFLM_EOF_HIT); goto Exit; } - - if( RC_BAD( rc = m_pDbRebuild->m_pSFileHdl->getFileHdl( - pScanState->uiFileNumber, FALSE, &pFileHdl))) - { - if( rc == NE_FLM_IO_PATH_NOT_FOUND || - rc == NE_FLM_IO_INVALID_FILENAME) - { - rc = NE_XFLM_OK; - uiTryNextCount++; - goto TryNextFile; - } - - goto Exit; - } } else { pScanState->uiFileOffset += uiBlockSize; } - if( RC_BAD( rc = readBlock( pFileHdl, pScanState->uiFileNumber, + if( RC_BAD( rc = readBlock( pScanState->uiFileNumber, pScanState->uiFileOffset, pScanState))) { - if( rc == NE_FLM_IO_END_OF_FILE) + if( rc == NE_FLM_IO_END_OF_FILE || + rc == NE_FLM_IO_PATH_NOT_FOUND) { rc = NE_XFLM_OK; + uiTryNextCount++; goto TryNextFile; } else if( rc == NE_XFLM_DATA_ERROR) @@ -2236,7 +2215,7 @@ RCODE F_RebuildNodeIStream::readContinuationElm( void) { F_BLK_HDR * pBlkHdr = m_pCurState->blkUnion.pBlkHdr; - if( RC_BAD( rc = readBlock( NULL, + if( RC_BAD( rc = readBlock( FSGetFileNumber( pBlkHdr->ui32NextBlkInChain), FSGetFileOffset( pBlkHdr->ui32NextBlkInChain), &m_tmpState))) { @@ -2319,7 +2298,7 @@ RCODE F_RebuildNodeIStream::readFirstDataOnlyBlock( void) flmAssert( pElmInfo->uiDataOnlyBlkAddr); - if( RC_BAD( rc = readBlock( NULL, + if( RC_BAD( rc = readBlock( FSGetFileNumber( pElmInfo->uiDataOnlyBlkAddr), FSGetFileOffset( pElmInfo->uiDataOnlyBlkAddr), &m_tmpState))) { @@ -2394,7 +2373,7 @@ RCODE F_RebuildNodeIStream::readNextDataOnlyBlock( void) goto Exit; } - if( RC_BAD( rc = readBlock( NULL, + if( RC_BAD( rc = readBlock( FSGetFileNumber( ui32NextBlkAddr), FSGetFileOffset( ui32NextBlkAddr), &m_tmpState))) { @@ -2686,7 +2665,7 @@ RCODE F_RebuildNodeIStream::readNode( } f_mutexUnlock( gv_XFlmSysData.hNodeCacheMutex); - if( RC_BAD( rc = readBlock( NULL, FSGetFileNumber( ui32BlkAddr), + if( RC_BAD( rc = readBlock( FSGetFileNumber( ui32BlkAddr), FSGetFileOffset( ui32BlkAddr), &m_firstElmState))) { goto Exit; @@ -2783,30 +2762,19 @@ RCODE F_DbRebuild::determineBlkSize( TryNextFile: uiOffset = 0; uiFileNumber++; - - if( RC_BAD( rc = m_pSFileHdl->getFileHdl( uiFileNumber, - FALSE, &pFileHdl))) - { - if( rc == NE_FLM_IO_PATH_NOT_FOUND) - { - rc = NE_XFLM_OK; - break; - } - - goto Exit; - } } if( RC_BAD( rc = pFileHdl->read( uiOffset, SIZEOF_STD_BLK_HDR, &blkHdr, &uiBytesRead))) { - if( rc != NE_XFLM_EOF_HIT) + if( rc == NE_XFLM_EOF_HIT || + rc == NE_FLM_IO_PATH_NOT_FOUND) { - goto Exit; + rc = NE_XFLM_OK; + goto TryNextFile; } - - rc = NE_XFLM_OK; - goto TryNextFile; + + goto Exit; } ui64BytesDone += (FLMUINT64)XFLM_MIN_BLOCK_SIZE; diff --git a/xflaim/src/flclose.cpp b/xflaim/src/flclose.cpp index 7227dfd..4d07ef3 100644 --- a/xflaim/src/flclose.cpp +++ b/xflaim/src/flclose.cpp @@ -136,7 +136,7 @@ RCODE FLMAPI F_DbSystem::waitToClose( const char * pszDbPath) { RCODE rc = NE_XFLM_OK; - FBUCKET * pBucket; + F_BUCKET * pBucket; FLMUINT uiBucket; F_Database * pDatabase = NULL; char szDbPathStr1[ F_PATH_MAX_SIZE]; diff --git a/xflaim/src/flcreate.cpp b/xflaim/src/flcreate.cpp index fb744cc..d8aa45b 100644 --- a/xflaim/src/flcreate.cpp +++ b/xflaim/src/flcreate.cpp @@ -91,11 +91,6 @@ RCODE FLMAPI F_DbSystem::dbCreate( f_mutexLock( gv_XFlmSysData.hShareMutex); bMutexLocked = TRUE; - // Free any unused structures that have been unused for the maximum - // amount of time. May unlock and re-lock the global mutex. - - checkNotUsedObjects(); - for( ;;) { @@ -404,9 +399,8 @@ RCODE F_Db::initDbFiles( if (!m_pDatabase->m_bTempDb) { pBlkHdr->ui32BlkCRC = calcBlkCRC( pBlkHdr, SIZEOF_STD_BLK_HDR); - if (RC_BAD( rc = m_pSFileHdl->writeBlock( - (FLMUINT)pBlkHdr->ui32BlkAddr, - uiBlkSize, pucBuf, NULL, &uiWriteBytes))) + if (RC_BAD( rc = m_pSFileHdl->writeBlock( pBlkHdr->ui32BlkAddr, + uiBlkSize, pucBuf, &uiWriteBytes))) { goto Exit; } diff --git a/xflaim/src/flgethdr.cpp b/xflaim/src/flgethdr.cpp deleted file mode 100644 index 6bc54f4..0000000 --- a/xflaim/src/flgethdr.cpp +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------------------------ -// Desc: This file contains the flmGetHdrInfo routine -- a routine which -// reads the header information from a FLAIM database, verifies it -// and returns the header information in a structure. -// -// 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: flgethdr.cpp 3113 2006-01-19 13:20:35 -0700 (Thu, 19 Jan 2006) dsanders $ -//------------------------------------------------------------------------------ - -#include "flaimsys.h" - -/*************************************************************************** -Desc: This routine reads the header information in a FLAIM database, - verifies the password, and returns the file header and log - header information. -*****************************************************************************/ -RCODE flmGetHdrInfo( - F_SuperFileHdl * pSFileHdl, - XFLM_DB_HDR * pDbHdr, - FLMUINT32 * pui32CalcCRC) -{ - RCODE rc = NE_XFLM_OK; - IF_FileHdl * pCFileHdl; - - if( RC_BAD( rc = pSFileHdl->getFileHdl( 0, FALSE, &pCFileHdl))) - { - goto Exit; - } - - rc = flmReadAndVerifyHdrInfo( NULL, pCFileHdl, pDbHdr, pui32CalcCRC); - -Exit: - - return( rc); -} diff --git a/xflaim/src/flindex.cpp b/xflaim/src/flindex.cpp index 028b3c5..2a9cf91 100644 --- a/xflaim/src/flindex.cpp +++ b/xflaim/src/flindex.cpp @@ -25,7 +25,7 @@ #include "flaimsys.h" -FSTATIC RCODE flmBackgroundIndexBuildThrd( +FSTATIC RCODE FLMAPI flmBackgroundIndexBuildThrd( IF_Thread * pThread); /**************************************************************************** @@ -891,7 +891,6 @@ RCODE F_Db::backgroundIndexBuild( m_uiFlags |= FDB_BACKGROUND_INDEXING; uiIndexNum = pBackgroundIx->indexStatus.uiIndexNum; - m_pSFileHdl->enableFlushMinimize(); for (;;) { @@ -984,8 +983,6 @@ RCODE F_Db::backgroundIndexBuild( goto Exit; } - pThread->setThreadStatus( FLM_THREAD_STATUS_COMMITTING_TRANS); - // Commit the transaction (even if we didn't do any indexing work). bStartedTrans = FALSE; @@ -1018,7 +1015,7 @@ Desc: Thread that will build an index in the background. Caller will create a pDb to use. This pDb must be freed at the conclusion of the routine. ****************************************************************************/ -FSTATIC RCODE flmBackgroundIndexBuildThrd( +FSTATIC RCODE FLMAPI flmBackgroundIndexBuildThrd( IF_Thread * pThread) { RCODE rc = NE_XFLM_OK; diff --git a/xflaim/src/flopen.cpp b/xflaim/src/flopen.cpp index 5623fa2..e371fb5 100644 --- a/xflaim/src/flopen.cpp +++ b/xflaim/src/flopen.cpp @@ -30,7 +30,7 @@ FSTATIC void flmFreeCPInfo( CP_INFO ** ppCPInfoRV); -FSTATIC RCODE flmCPThread( +FSTATIC RCODE FLMAPI flmCPThread( IF_Thread * pThread); /*************************************************************************** @@ -306,11 +306,6 @@ RCODE F_DbSystem::openDatabase( f_mutexLock( gv_XFlmSysData.hShareMutex); bMutexLocked = TRUE; - // Free any unused structures that have been unused for the maximum - // amount of time. May unlock and re-lock the global mutex. - - checkNotUsedObjects(); - // Look up the file using findDatabase to see if we already // have the file open. @@ -692,23 +687,24 @@ RCODE F_Database::physOpen( IF_RestoreClient * pRestoreObj, IF_RestoreStatus * pRestoreStatus) { - RCODE rc = NE_XFLM_OK; + RCODE rc = NE_XFLM_OK; // See if we need to read in the database header. If the database was // already open (bNewDatabase == FALSE), we don't need to again. - if (bNewDatabase) + if( bNewDatabase) { // Read in the database header. - if (RC_BAD( rc = readDbHdr( pDb->m_pDbStats, pDb->m_pSFileHdl, - (FLMBYTE *)pszPassword, - (uiOpenFlags & XFLM_ALLOW_LIMITED_MODE) ? TRUE : FALSE))) + if (RC_BAD( rc = readDbHdr( pszFilePath, pDb->m_pDbStats, + (FLMBYTE *)pszPassword, (uiOpenFlags & XFLM_ALLOW_LIMITED_MODE) + ? TRUE + : FALSE))) { goto Exit; } - + // Allocate the pRfl object. Could not do this until this point // because we need to have the version number, block size, etc. // setup in the database header. @@ -727,6 +723,8 @@ RCODE F_Database::physOpen( } } + pDb->m_pSFileHdl->setBlockSize( m_uiBlockSize); + // We must have exclusive access. Create a lock file for that // purpose, if there is not already a lock file. @@ -754,7 +752,7 @@ Exit: if (RC_BAD( rc)) { - (void)pDb->m_pSFileHdl->releaseFiles( TRUE); + (void)pDb->m_pSFileHdl->releaseFiles(); } return( rc); @@ -800,7 +798,7 @@ RCODE F_DbSystem::findDatabase( F_Database ** ppDatabase) { RCODE rc = NE_XFLM_OK; - FBUCKET * pBucket; + F_BUCKET * pBucket; FLMUINT uiBucket; FLMBOOL bMutexLocked = TRUE; F_Database * pDatabase; @@ -1015,7 +1013,7 @@ F_Database::F_Database( f_memset( &m_lastCommittedDbHdr, 0, sizeof( m_lastCommittedDbHdr)); f_memset( &m_checkpointDbHdr, 0, sizeof( m_checkpointDbHdr)); f_memset( &m_uncommittedDbHdr, 0, sizeof( m_uncommittedDbHdr)); - + m_pBufferMgr = NULL; m_pCurrLogBuffer = NULL; m_uiCurrLogWriteOffset = 0; @@ -1235,7 +1233,7 @@ F_Database::~F_Database() m_pBufferMgr->Release(); m_pBufferMgr = NULL; } - + // Free the log header write buffer if (m_pDbHdrWriteBuf) @@ -1397,14 +1395,12 @@ RCODE F_Database::setupDatabase( // Setup the write buffer managers. - if( RC_BAD( rc = FlmAllocIOBufferMgr( &m_pBufferMgr))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( MAX_PENDING_WRITES, + MAX_WRITE_BUFFER_BYTES, FALSE, &m_pBufferMgr))) { goto Exit; } - m_pBufferMgr->setMaxBuffers( MAX_PENDING_WRITES); - m_pBufferMgr->setMaxBytes( MAX_WRITE_BUFFER_BYTES); - // Initialize members of F_Database object. m_uiBucket = 0xFFFF; @@ -1493,32 +1489,35 @@ Desc: This routine reads the header information for an existing flaim database and makes sure we have a valid database. *****************************************************************************/ RCODE F_Database::readDbHdr( + const char * pszDbPath, XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, FLMBYTE * pszPassword, FLMBOOL bAllowLimited) { - RCODE rc = NE_XFLM_OK; - IF_FileHdl * pCFileHdl = NULL; + RCODE rc = NE_XFLM_OK; + IF_FileHdl * pFileHdl = NULL; - if (RC_BAD( rc = pSFileHdl->getFileHdl( 0, FALSE, &pCFileHdl))) + if( RC_BAD( rc = gv_XFlmSysData.pFileSystem->openFile( pszDbPath, + FLM_IO_RDWR | FLM_IO_SH_DENYNONE | FLM_IO_DIRECT, &pFileHdl))) { goto Exit; } // Read and verify the database header. - if (RC_BAD( rc = flmReadAndVerifyHdrInfo( pDbStats, pCFileHdl, + if (RC_BAD( rc = flmReadAndVerifyHdrInfo( pDbStats, pFileHdl, &m_lastCommittedDbHdr))) { goto Exit; } + m_uiBlockSize = (FLMUINT)m_lastCommittedDbHdr.ui16BlockSize; m_uiDefaultLanguage = (FLMUINT)m_lastCommittedDbHdr.ui8DefaultLanguage; m_uiMaxFileSize = (FLMUINT)m_lastCommittedDbHdr.ui32MaxFileSize; m_uiSigBitsInBlkSize = calcSigBits( m_uiBlockSize); // Initialize the master database key from the database header + m_bAllowLimitedMode = bAllowLimited; if (pszPassword && *pszPassword) @@ -1571,13 +1570,9 @@ RCODE F_Database::readDbHdr( Exit: - // Need to close the .db file so that we can set the block size. - // This will allow direct I/O to be used when accessing the file later. - - if (pCFileHdl) + if( pFileHdl) { - (void)pSFileHdl->releaseFile( (FLMUINT)0, TRUE); - pSFileHdl->setBlockSize( m_uiBlockSize); + pFileHdl->Release(); } return( rc); @@ -1662,7 +1657,9 @@ RCODE F_Database::startCPThread( void) // Set up the super file - if (RC_BAD( rc = pCPInfo->pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = pCPInfo->pSFileHdl->setup( pSFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -1860,7 +1857,7 @@ Desc: This routine functions as a thread. It monitors open files and frees up files which have been closed longer than the maximum close time. ****************************************************************************/ -FSTATIC RCODE flmCPThread( +FSTATIC RCODE FLMAPI flmCPThread( IF_Thread * pThread) { CP_INFO * pCPInfo = (CP_INFO *)pThread->getParm1(); diff --git a/xflaim/src/flreduce.cpp b/xflaim/src/flreduce.cpp index 49b33e3..c07c1fc 100644 --- a/xflaim/src/flreduce.cpp +++ b/xflaim/src/flreduce.cpp @@ -132,18 +132,12 @@ RCODE FLMAPI F_Db::reduceSize( if( FSGetFileOffset( uiLogicalEOF) == 0) { - IF_FileHdl * pFileHdl; FLMUINT uiFileNumber = FSGetFileNumber( uiLogicalEOF) - 1; FLMUINT64 ui64FileSize; FLMUINT64 ui64Temp; - - if (RC_BAD( rc = m_pSFileHdl->getFileHdl( - uiFileNumber, TRUE, &pFileHdl))) - { - goto Exit; - } - - if (RC_BAD( rc = pFileHdl->size( &ui64FileSize))) + + if (RC_BAD( rc = m_pSFileHdl->getFileSize( + uiFileNumber, &ui64FileSize))) { goto Exit; } @@ -205,7 +199,6 @@ RCODE FLMAPI F_Db::reduceSize( { FLMUINT uiFileNumber = FSGetFileNumber( uiLogicalEOF); FLMUINT64 ui64FileOffset; - IF_FileHdl * pFileHdl; if (uiFileNumber <= 1) { @@ -219,13 +212,8 @@ RCODE FLMAPI F_Db::reduceSize( // Compute the end of the previous block file. - if (RC_BAD( rc = m_pSFileHdl->getFileHdl( - uiFileNumber, TRUE, &pFileHdl))) - { - goto Exit; - } - - if (RC_BAD( rc = pFileHdl->size( &ui64FileOffset))) + if (RC_BAD( rc = m_pSFileHdl->getFileSize( + uiFileNumber, &ui64FileOffset))) { goto Exit; } @@ -323,7 +311,6 @@ RCODE F_Db::readBlkHdr( RCODE rc = NE_XFLM_OK; FLMUINT uiBytesRead; FLMUINT uiNumLooks; - IF_FileHdl * pTmpFileHdl = NULL; F_CachedBlock * pBlkSCache; XFLM_LFILE_STATS * pLFileStats; F_TMSTAMP StartTime; @@ -351,12 +338,8 @@ RCODE F_Db::readBlkHdr( f_timeGetTimeStamp( &StartTime); } - if (RC_OK( rc = m_pSFileHdl->getFileHdl( - FSGetFileNumber( uiBlkAddress), TRUE, &pTmpFileHdl))) - { - rc = pTmpFileHdl->read( FSGetFileOffset( uiBlkAddress), - SIZEOF_LARGEST_BLK_HDR, pBlkHdr, &uiBytesRead); - } + rc = m_pSFileHdl->readBlock( uiBlkAddress, + SIZEOF_LARGEST_BLK_HDR, pBlkHdr, &uiBytesRead); if (m_pDbStats) { @@ -414,9 +397,9 @@ RCODE F_Db::readBlkHdr( { if (rc != NE_FLM_IO_END_OF_FILE && rc != NE_XFLM_MEM) { - m_pSFileHdl->releaseFile( FSGetFileNumber( uiBlkAddress), - TRUE); + m_pSFileHdl->releaseFiles(); } + goto Exit; } } diff --git a/xflaim/src/frestore.cpp b/xflaim/src/frestore.cpp index d1b702b..f88dacf 100644 --- a/xflaim/src/frestore.cpp +++ b/xflaim/src/frestore.cpp @@ -118,7 +118,7 @@ RCODE F_FSRestore::openRflFile( char szRflPath[ F_PATH_MAX_SIZE]; char szBaseName[ F_FILENAME_SIZE]; FLMUINT uiBaseNameSize; - XFLM_DB_HDR dbHdr; + XFLM_DB_HDR dbHdr; IF_FileHdl * pFileHdl = NULL; flmAssert( m_bSetupCalled); diff --git a/xflaim/src/fslfileu.cpp b/xflaim/src/fslfileu.cpp index ac686de..443105d 100644 --- a/xflaim/src/fslfileu.cpp +++ b/xflaim/src/fslfileu.cpp @@ -2606,7 +2606,7 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -RCODE F_Database::maintenanceThread( +RCODE FLMAPI F_Database::maintenanceThread( IF_Thread * pThread) { RCODE rc = NE_XFLM_OK; diff --git a/xflaim/src/fstructs.h b/xflaim/src/fstructs.h index 97c2a82..845fccc 100644 --- a/xflaim/src/fstructs.h +++ b/xflaim/src/fstructs.h @@ -155,8 +155,7 @@ FINLINE void blkSetNativeFormat( Desc: Test to see if a block type is a B-Tree block type. ****************************************************************************/ FINLINE FLMBOOL blkIsBTree( - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { return( (pBlkHdr->ui8BlkType != BT_FREE && pBlkHdr->ui8BlkType != BT_LFH_BLK) @@ -168,8 +167,7 @@ FINLINE FLMBOOL blkIsBTree( Desc: Test to see if a block type is a NEW B-Tree block type. ****************************************************************************/ FINLINE FLMBOOL blkIsNewBTree( - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { return( (pBlkHdr->ui8BlkType >= BT_LEAF) ? TRUE @@ -182,8 +180,7 @@ Desc: Determine where the block ends. FINLINE FLMUINT blkGetEnd( FLMUINT uiBlockSize, FLMUINT uiBlkHdrSize, - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { return( (FLMUINT)(blkIsNewBTree( pBlkHdr) ? uiBlockSize @@ -195,22 +192,19 @@ FINLINE FLMUINT blkGetEnd( } FINLINE void setBlockEncrypted( - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { pBlkHdr->ui8BlkFlags |= BLK_IS_ENCRYPTED; } FINLINE void unsetBlockEncrypted( - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { pBlkHdr->ui8BlkFlags &= (~(BLK_IS_ENCRYPTED)); } FINLINE FLMBOOL isEncryptedBlk( - F_BLK_HDR * pBlkHdr - ) + F_BLK_HDR * pBlkHdr) { return( (pBlkHdr->ui8BlkFlags & BLK_IS_ENCRYPTED) ? TRUE : FALSE); } @@ -956,8 +950,8 @@ private: FLMINT iLineNumber); RCODE readDbHdr( + const char * pszDbPath, XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, FLMBYTE * pszPassword, FLMBOOL bAllowLimited); @@ -1029,13 +1023,6 @@ private: F_SuperFileHdl * pSFileHdl, FLMUINT * puiBlocksFlushed); - RCODE writeContiguousBlocks( - XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - IF_IOBuffer * pIOBuffer, - FLMUINT uiBlkAddress, - FLMBOOL bDoAsync); - RCODE writeSortedBlocks( XFLM_DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, @@ -1043,7 +1030,6 @@ private: FLMUINT * puiDirtyCacheLeft, FLMBOOL * pbForceCheckpoint, FLMBOOL bIsCPThread, - FLMBOOL bDoAsync, FLMUINT uiNumSortedBlocks, FLMBOOL * pbWroteAll); @@ -1081,15 +1067,13 @@ private: RCODE lgFlushLogBuffer( XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - FLMBOOL bDoAsync); + F_SuperFileHdl * pSFileHdl); RCODE lgOutputBlock( XFLM_DB_STATS * pDbStats, F_SuperFileHdl * pSFileHdl, F_CachedBlock * pLogBlock, F_BLK_HDR * pBlkHdr, - FLMBOOL bDoAsync, FLMUINT * puiLogEofRV); FLMUINT lFileFindEmpty( @@ -1129,7 +1113,7 @@ private: FLMBOOL bCounts, FLMBOOL bHaveData); - static RCODE maintenanceThread( + static RCODE FLMAPI maintenanceThread( IF_Thread * pThread); F_Database * m_pNext; // Next F_Database structure in in name hash @@ -1370,151 +1354,6 @@ typedef struct F_Event_Hdr // the event list. } FEVENT_HDR; -typedef enum -{ - HASH_SESSION_OBJ = 0, - HASH_DB_OBJ -} eHashObjType; - -/*=========================================================================== -Desc: FLAIM object base class -===========================================================================*/ -class F_HashObject : public F_Object -{ -public: - -#define F_INVALID_HASH_BUCKET (~((FLMUINT)0)) - - F_HashObject() - { - m_pNextInBucket = NULL; - m_pPrevInBucket = NULL; - m_pNextInGlobal = NULL; - m_pPrevInGlobal = NULL; - m_uiHashBucket = F_INVALID_HASH_BUCKET; - m_ui32CRC = 0xFFFFFFFF; - } - - virtual ~F_HashObject() - { - flmAssert( !m_pNextInBucket); - flmAssert( !m_pPrevInBucket); - flmAssert( !m_pNextInGlobal); - flmAssert( !m_pPrevInGlobal); - flmAssert( !getRefCount()); - } - - virtual void * getKey( - FLMUINT * puiKeyLen) = 0; - - FLMUINT getHashBucket( void) - { - return( m_uiHashBucket); - } - - FLMUINT32 getKeyCRC( void) - { - return( m_ui32CRC); - } - - FINLINE F_HashObject * getNextInGlobal( void) - { - return( m_pNextInGlobal); - } - - virtual eHashObjType objectType( void) = 0; - -protected: - - // Methods - - void setHashBucket( - FLMUINT uiHashBucket) - { - m_uiHashBucket = uiHashBucket; - } - - void setKeyCRC( - FLMUINT32 ui32CRC) - { - m_ui32CRC = ui32CRC; - } - - // Data - - F_HashObject * m_pNextInBucket; - F_HashObject * m_pPrevInBucket; - F_HashObject * m_pNextInGlobal; - F_HashObject * m_pPrevInGlobal; - FLMUINT m_uiHashBucket; - FLMUINT32 m_ui32CRC; - -friend class F_HashTable; -}; - -/*=========================================================================== -Desc: FLAIM hash table -===========================================================================*/ -class F_HashTable : public F_Object -{ -public: - - F_HashTable(); - - ~F_HashTable(); - - RCODE setupHashTable( - FLMBOOL bMultithreaded, - FLMUINT uiNumBuckets); - - RCODE addObject( - F_HashObject * pObject); - - RCODE getNextObjectInGlobal( - F_HashObject ** ppObject); - - RCODE getObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject, - FLMBOOL bRemove = FALSE); - - RCODE removeObject( - void * pvKey, - FLMUINT uiKeyLen); - - RCODE removeObject( - F_HashObject * pObject); - -private: - - // Methods - - FLMUINT getHashBucket( - void * pvKey, - FLMUINT uiLen, - FLMUINT32 * pui32KeyCRC = NULL); - - void linkObject( - F_HashObject * pObject, - FLMUINT uiBucket); - - void unlinkObject( - F_HashObject * pObject); - - RCODE findObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject); - - // Data - - F_MUTEX m_hMutex; - F_HashObject * m_pGlobalList; - F_HashObject ** m_ppHashTable; - FLMUINT m_uiBuckets; -}; - typedef struct node_loc { FLMUINT32 ui32DatabaseId; @@ -1532,7 +1371,7 @@ Desc: This is the FLAIM Shared System Data Structure. It is the anchor ***************************************************************************/ typedef struct FlmSystemData { - FBUCKET * pDatabaseHashTbl; // Database name hash table (array of FBUCKET). + F_BUCKET * pDatabaseHashTbl; // Database name hash table (array of FBUCKET). #define FILE_HASH_ENTRIES 256 F_MUTEX hShareMutex; // Mutex for controlling access to @@ -1620,9 +1459,11 @@ typedef struct FlmSystemData IF_XML * pXml; IF_FileSystem * pFileSystem; IF_ThreadMgr * pThreadMgr; + IF_FileHdlCache * pFileHdlCache; FLMUINT uiIndexingThreadGroup; FLMUINT uiDbThreadGroup; FLMUINT uiCheckpointThreadGroup; + FLMUINT uiFileOpenFlags; } FLMSYSDATA; diff --git a/xflaim/src/fsysdata.cpp b/xflaim/src/fsysdata.cpp index 0a85a56..30fd492 100644 --- a/xflaim/src/fsysdata.cpp +++ b/xflaim/src/fsysdata.cpp @@ -96,69 +96,6 @@ FSTATIC RCODE flmGetIniFileName( FLMBYTE * pszIniFileName, FLMUINT uiBufferSz); -/**************************************************************************** -Desc: This routine allocates and initializes a hash table. -****************************************************************************/ -RCODE flmAllocHashTbl( - FLMUINT uiHashTblSize, - FBUCKET ** ppHashTblRV) -{ - RCODE rc = NE_XFLM_OK; - FBUCKET * pHashTbl = NULL; - IF_RandomGenerator * pRandGen = NULL; - FLMUINT uiCnt; - FLMUINT uiRandVal; - FLMUINT uiTempVal; - - // Allocate memory for the hash table - - if (RC_BAD( rc = f_calloc( - (FLMUINT)(sizeof( FBUCKET)) * uiHashTblSize, &pHashTbl))) - { - goto Exit; - } - - // Set up the random number generator - - if( RC_BAD( rc = FlmAllocRandomGenerator( &pRandGen))) - { - goto Exit; - } - - pRandGen->setSeed( 1); - - for (uiCnt = 0; uiCnt < uiHashTblSize; uiCnt++) - { - pHashTbl [uiCnt].uiHashValue = (FLMBYTE)uiCnt; - pHashTbl [uiCnt].pFirstInBucket = NULL; - } - - if( uiHashTblSize <= 256) - { - for( uiCnt = 0; uiCnt < uiHashTblSize - 1; uiCnt++) - { - uiRandVal = (FLMBYTE) pRandGen->getUINT32( (FLMUINT32)uiCnt, - (FLMUINT32)(uiHashTblSize - 1)); - if( uiRandVal != uiCnt) - { - uiTempVal = (FLMBYTE)pHashTbl [uiCnt].uiHashValue; - pHashTbl [uiCnt].uiHashValue = pHashTbl [uiRandVal].uiHashValue; - pHashTbl [uiRandVal].uiHashValue = uiTempVal; - } - } - } - -Exit: - - if( pRandGen) - { - pRandGen->Release(); - } - - *ppHashTblRV = pHashTbl; - return( rc); -} - /**************************************************************************** Desc: This routine determines the number of cache bytes to use for caching based on a percentage of available physical memory or a percentage @@ -711,7 +648,7 @@ RCODE F_Database::linkToBucket( void) { RCODE rc = NE_XFLM_OK; F_Database * pTmpDatabase; - FBUCKET * pBucket; + F_BUCKET * pBucket; FLMUINT uiBucket; pBucket = gv_XFlmSysData.pDatabaseHashTbl; @@ -731,17 +668,6 @@ RCODE F_Database::linkToBucket( void) return( rc); } -/**************************************************************************** -Desc: This routine checks unused structures to see if any have been unused - longer than the maximum unused time. If so, it frees them up. -Note: This routine assumes that the calling routine has locked the global - mutex prior to calling this routine. The mutex may be unlocked and - re-locked by one of the called routines. -****************************************************************************/ -void F_DbSystem::checkNotUsedObjects( void) -{ -} - /**************************************************************************** Desc: This routine links an FDB structure to an F_Database structure. NOTE: This routine assumes that the global mutex has been @@ -793,7 +719,9 @@ RCODE F_Db::linkToDatabase( goto Exit; } - if( RC_BAD( rc = m_pSFileHdl->setup( pSFileClient))) + if( RC_BAD( rc = m_pSFileHdl->setup( pSFileClient, + gv_XFlmSysData.pFileHdlCache, + (gv_XFlmSysData.uiFileOpenFlags & FLM_IO_DIRECT) ? TRUE : FALSE))) { goto Exit; } @@ -916,10 +844,9 @@ Desc: This routine functions as a thread. It monitors open files and frees up files which have been closed longer than the maximum close time. ****************************************************************************/ -RCODE F_DbSystem::monitorThrd( +RCODE FLMAPI F_DbSystem::monitorThrd( IF_Thread * pThread) { - FLMUINT uiLastUnusedCleanupTime = 0; FLMUINT uiCurrTime; FLMUINT uiLastCacheAdjustTime = 0; @@ -934,30 +861,12 @@ RCODE F_DbSystem::monitorThrd( uiCurrTime = FLM_GET_TIMER(); - // Check the not used stuff and lock timeouts. - - if ( FLM_ELAPSED_TIME( uiCurrTime, uiLastUnusedCleanupTime) >= - gv_XFlmSysData.pGlobalCacheMgr->m_uiUnusedCleanupInterval) - { - // See if any unused structures have bee unused longer than the - // maximum unused time. Free them if they have. - // May unlock and re-lock the global mutex. - - f_mutexLock( gv_XFlmSysData.hShareMutex); - F_DbSystem::checkNotUsedObjects(); - f_mutexUnlock( gv_XFlmSysData.hShareMutex); - - // Reset the timer - - uiCurrTime = uiLastUnusedCleanupTime = FLM_GET_TIMER(); - } - // Check the adjusting cache limit (void)gv_XFlmSysData.pGlobalCacheMgr->adjustCache( &uiCurrTime, &uiLastCacheAdjustTime); - f_sleep( 1000); + f_sleep( 250); } return( NE_XFLM_OK); @@ -1099,441 +1008,6 @@ void F_Database::setMustCloseFlags( } } -/**************************************************************************** -Desc: Constructor -****************************************************************************/ -F_HashTable::F_HashTable() -{ - m_hMutex = F_MUTEX_NULL; - m_pGlobalList = NULL; - m_ppHashTable = NULL; - m_uiBuckets = 0; -} - -/**************************************************************************** -Desc: Destructor -****************************************************************************/ -F_HashTable::~F_HashTable() -{ - F_HashObject * pCur; - F_HashObject * pNext; - - pCur = m_pGlobalList; - while( pCur) - { - pNext = pCur->m_pNextInGlobal; - unlinkObject( pCur); - pCur->Release(); - pCur = pNext; - } - - if( m_ppHashTable) - { - f_free( &m_ppHashTable); - } - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexDestroy( &m_hMutex); - } -} - -/**************************************************************************** -Desc: Configures the hash table prior to first use -****************************************************************************/ -RCODE F_HashTable::setupHashTable( - FLMBOOL bMultithreaded, - FLMUINT uiNumBuckets) -{ - RCODE rc = NE_XFLM_OK; - - flmAssert( uiNumBuckets); - - // Create the hash table - - if( RC_BAD( rc = f_alloc( - sizeof( F_HashObject *) * uiNumBuckets, &m_ppHashTable))) - { - goto Exit; - } - - m_uiBuckets = uiNumBuckets; - f_memset( m_ppHashTable, 0, sizeof( F_HashObject *) * uiNumBuckets); - - if( bMultithreaded) - { - // Initialize the mutex - - if( RC_BAD( rc = f_mutexCreate( &m_hMutex))) - { - goto Exit; - } - } - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Retrieves an object from the hash table with the specified key. - This routine assumes the table's mutex has already been locked. - A reference IS NOT added to the object for the caller. -****************************************************************************/ -RCODE F_HashTable::findObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject) -{ - F_HashObject * pObject = NULL; - FLMUINT uiBucket; - FLMUINT32 ui32CRC = 0; - RCODE rc = NE_XFLM_OK; - - *ppObject = NULL; - - // Calculate the hash bucket and mutex offset - - uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); - - // Search the bucket for an object with a matching - // key. - - pObject = m_ppHashTable[ uiBucket]; - while( pObject) - { - if( pObject->getKeyCRC() == ui32CRC) - { - void * pvTmpKey; - FLMUINT uiTmpKeyLen; - - pvTmpKey = pObject->getKey( &uiTmpKeyLen); - if( uiTmpKeyLen == uiKeyLen && - f_memcmp( pvTmpKey, pvKey, uiKeyLen) == 0) - { - break; - } - } - pObject = pObject->m_pNextInBucket; - } - - if( !pObject) - { - rc = RC_SET( NE_XFLM_NOT_FOUND); - goto Exit; - } - - *ppObject = pObject; - -Exit: - - return( rc); -} - -/**************************************************************************** -Desc: Adds an object to the hash table -****************************************************************************/ -RCODE F_HashTable::addObject( - F_HashObject * pObject) -{ - FLMUINT uiBucket; - F_HashObject * pTmp; - void * pvKey; - FLMUINT uiKeyLen; - FLMUINT32 ui32CRC; - FLMBOOL bMutexLocked = FALSE; - RCODE rc = NE_XFLM_OK; - - // Calculate and set the objects hash bucket - - flmAssert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); - - pvKey = pObject->getKey( &uiKeyLen); - flmAssert( uiKeyLen); - - uiBucket = getHashBucket( pvKey, uiKeyLen, &ui32CRC); - pObject->setKeyCRC( ui32CRC); - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - // Make sure the object doesn't already exist - - if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pTmp))) - { - if( rc != NE_XFLM_NOT_FOUND) - { - goto Exit; - } - rc = NE_XFLM_OK; - } - else - { - rc = RC_SET_AND_ASSERT( NE_XFLM_EXISTS); - goto Exit; - } - - // Add a reference to the object - - pObject->AddRef(); - - // Link the object into the appropriate lists - - linkObject( pObject, uiBucket); - -Exit: - - // Unlock the mutex - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Returns the next object in the linked list of objects in the hash - table. If *ppObject == NULL, the first object will be returned. -****************************************************************************/ -RCODE F_HashTable::getNextObjectInGlobal( - F_HashObject ** ppObject) -{ - FLMBOOL bMutexLocked = FALSE; - F_HashObject * pOldObj; - RCODE rc = NE_XFLM_OK; - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - if( !(*ppObject)) - { - *ppObject = m_pGlobalList; - } - else - { - pOldObj = *ppObject; - *ppObject = (*ppObject)->m_pNextInGlobal; - pOldObj->Release(); - } - - if( *ppObject == NULL) - { - rc = RC_SET( NE_XFLM_EOF_HIT); - goto Exit; - } - - (*ppObject)->AddRef(); - -Exit: - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Retrieves an object from the hash table with the specified key -****************************************************************************/ -RCODE F_HashTable::getObject( - void * pvKey, - FLMUINT uiKeyLen, - F_HashObject ** ppObject, - FLMBOOL bRemove) -{ - F_HashObject * pObject; - FLMBOOL bMutexLocked = FALSE; - RCODE rc = NE_XFLM_OK; - - // Lock the mutex - - if( m_hMutex != F_MUTEX_NULL) - { - f_mutexLock( m_hMutex); - bMutexLocked = TRUE; - } - - // Search for an object with a matching key. - - if( RC_BAD( rc = findObject( pvKey, uiKeyLen, &pObject))) - { - goto Exit; - } - - if( pObject && bRemove) - { - unlinkObject( pObject); - if( !ppObject) - { - pObject->Release(); - pObject = NULL; - } - } - - if( ppObject) - { - if( !bRemove) - { - pObject->AddRef(); - } - *ppObject = pObject; - pObject = NULL; - } - -Exit: - - if( bMutexLocked) - { - f_mutexUnlock( m_hMutex); - } - - return( rc); -} - -/**************************************************************************** -Desc: Removes an object from the hash table by key -****************************************************************************/ -RCODE F_HashTable::removeObject( - void * pvKey, - FLMUINT uiKeyLen) -{ - return( getObject( pvKey, uiKeyLen, NULL, TRUE)); -} - -/**************************************************************************** -Desc: Removes an object from the hash table by object pointer -****************************************************************************/ -RCODE F_HashTable::removeObject( - F_HashObject * pObject) -{ - FLMUINT uiKeyLen; - void * pvKey = pObject->getKey( &uiKeyLen); - - return( getObject( pvKey, uiKeyLen, NULL, TRUE)); -} - -/**************************************************************************** -Desc: Calculates the hash bucket of a key and optionally returns the key's - CRC. -****************************************************************************/ -FLMUINT F_HashTable::getHashBucket( - void * pvKey, - FLMUINT uiLen, - FLMUINT32 * pui32KeyCRC) -{ - FLMUINT32 ui32CRC = 0; - - f_updateCRC( (FLMBYTE *)pvKey, uiLen, &ui32CRC); - if( pui32KeyCRC) - { - *pui32KeyCRC = ui32CRC; - } - return( ui32CRC % m_uiBuckets); -} - -/**************************************************************************** -Desc: Links an object to the global list and also to its bucket -Notes: This routine assumes that the bucket's mutex is already locked - if the hash table is multi-threaded. -****************************************************************************/ -void F_HashTable::linkObject( - F_HashObject * pObject, - FLMUINT uiBucket) -{ - flmAssert( uiBucket < m_uiBuckets); - flmAssert( pObject->getHashBucket() == F_INVALID_HASH_BUCKET); - - // Set the object's bucket - - pObject->setHashBucket( uiBucket); - - // Link the object to its hash bucket - - pObject->m_pNextInBucket = m_ppHashTable[ uiBucket]; - if( m_ppHashTable[ uiBucket]) - { - m_ppHashTable[ uiBucket]->m_pPrevInBucket = pObject; - } - m_ppHashTable[ uiBucket] = pObject; - - // Link to the global list - - pObject->m_pNextInGlobal = m_pGlobalList; - if( m_pGlobalList) - { - m_pGlobalList->m_pPrevInGlobal = pObject; - } - m_pGlobalList = pObject; -} - -/**************************************************************************** -Desc: Unlinks an object from its bucket and the global list. -Notes: This routine assumes that the bucket's mutex is already locked - if the hash table is multi-threaded. -****************************************************************************/ -void F_HashTable::unlinkObject( - F_HashObject * pObject) -{ - FLMUINT uiBucket = pObject->getHashBucket(); - - // Is the bucket valid? - - flmAssert( uiBucket < m_uiBuckets); - - // Unlink from the hash bucket - - if( pObject->m_pNextInBucket) - { - pObject->m_pNextInBucket->m_pPrevInBucket = pObject->m_pPrevInBucket; - } - - if( pObject->m_pPrevInBucket) - { - pObject->m_pPrevInBucket->m_pNextInBucket = pObject->m_pNextInBucket; - } - else - { - m_ppHashTable[ uiBucket] = pObject->m_pNextInBucket; - } - - pObject->m_pPrevInBucket = NULL; - pObject->m_pNextInBucket = NULL; - pObject->setHashBucket( F_INVALID_HASH_BUCKET); - - // Unlink from the global list - - if( pObject->m_pNextInGlobal) - { - pObject->m_pNextInGlobal->m_pPrevInGlobal = pObject->m_pPrevInGlobal; - } - - if( pObject->m_pPrevInGlobal) - { - pObject->m_pPrevInGlobal->m_pNextInGlobal = pObject->m_pNextInGlobal; - } - else - { - m_pGlobalList = pObject->m_pNextInGlobal; - } - - pObject->m_pPrevInGlobal = NULL; - pObject->m_pNextInGlobal = NULL; -} - /*************************************************************************** Desc: Lock the system data structure for access - called only by startup and shutdown. NOTE: On platforms that do not support atomic exchange @@ -1796,6 +1270,15 @@ RCODE F_DbSystem::init( void) goto Exit; } + // Set up a file handle cache + // VISIT + + if( RC_BAD( rc = gv_XFlmSysData.pFileSystem->allocFileHandleCache( 32, 120, + &gv_XFlmSysData.pFileHdlCache))) + { + goto Exit; + } + gv_XFlmSysData.uiIndexingThreadGroup = gv_XFlmSysData.pThreadMgr->allocGroupId(); @@ -1927,7 +1410,7 @@ RCODE F_DbSystem::init( void) // Allocate memory for the file name hash table. - if (RC_BAD(rc = flmAllocHashTbl( FILE_HASH_ENTRIES, + if (RC_BAD(rc = f_allocHashTable( FILE_HASH_ENTRIES, &gv_XFlmSysData.pDatabaseHashTbl))) { goto Exit; @@ -2075,7 +1558,7 @@ void F_DbSystem::cleanup( void) if (gv_XFlmSysData.pDatabaseHashTbl) { - FBUCKET * pDatabaseHashTbl; + F_BUCKET * pDatabaseHashTbl; // F_Database destructor expects the global mutex to be locked // IMPORTANT NOTE: pDatabaseHashTbl is ALWAYS allocated @@ -2173,6 +1656,14 @@ void F_DbSystem::cleanup( void) gv_XFlmSysData.pThreadMgr->Release(); gv_XFlmSysData.pThreadMgr = NULL; } + + // Release the file handle cache + + if( gv_XFlmSysData.pFileHdlCache) + { + gv_XFlmSysData.pFileHdlCache->Release(); + gv_XFlmSysData.pFileHdlCache = NULL; + } // Release the file system object @@ -2463,7 +1954,7 @@ void F_GlobalCacheMgr::getCacheInfo( } /**************************************************************************** -Desc: Close all files in the file handle manager that have not been +Desc: Close all files in the file handle cache that have not been used for the specified number of seconds. ****************************************************************************/ RCODE FLMAPI F_DbSystem::closeUnusedFiles( @@ -2493,10 +1984,15 @@ RCODE FLMAPI F_DbSystem::closeUnusedFiles( // May unlock and re-lock the global mutex. - checkNotUsedObjects(); gv_XFlmSysData.uiMaxUnusedTime = uiSave; f_mutexUnlock( gv_XFlmSysData.hShareMutex); + if( gv_XFlmSysData.pFileHdlCache) + { + // VISIT: check timeout value + gv_XFlmSysData.pFileHdlCache->closeUnusedFiles(); + } + return( rc); } @@ -3720,6 +3216,7 @@ FSTATIC RCODE flmGetIniFileName( if (pDirHdl->currentItemIsDir()) { // Directory exists. We will look there. + f_strcpy( (char *)pszIniFileName, "data"); } else @@ -4077,6 +3574,16 @@ FLMUINT FLMAPI F_SuperFileClient::getFileOffset( return( FSGetFileOffset( uiBlockAddr)); } +/**************************************************************************** +Desc: +****************************************************************************/ +FLMUINT FLMAPI F_SuperFileClient::getBlockAddress( + FLMUINT uiFileNumber, + FLMUINT uiFileOffset) +{ + return( FSBlkAddress( uiFileNumber, uiFileOffset)); +} + /**************************************************************************** Desc: ****************************************************************************/ diff --git a/xflaim/src/recover.cpp b/xflaim/src/recover.cpp index 8a77db3..57c9848 100644 --- a/xflaim/src/recover.cpp +++ b/xflaim/src/recover.cpp @@ -249,7 +249,7 @@ RCODE F_Db::processBeforeImage( m_pSFileHdl->setMaxAutoExtendSize( m_pDatabase->m_uiMaxFileSize); m_pSFileHdl->setExtendSize( m_pDatabase->m_uiFileExtendSize); rc = m_pSFileHdl->writeBlock( uiBlkAddress, uiBlkLength, pBlkHdr, - NULL, &uiBytesWritten); + &uiBytesWritten); #ifdef FLM_DBG_LOG flmDbgLogWrite( m_pDatabase, uiBlkAddress, 0, ui64TransID, "ROLLBACK"); @@ -290,7 +290,6 @@ RCODE F_Database::writeDbHdr( { RCODE rc = NE_XFLM_OK; FLMUINT uiBytesWritten; - IF_FileHdl * pCFileHdl = NULL; XFLM_DB_HDR * pTmpDbHdr; F_TMSTAMP StartTime; @@ -354,13 +353,8 @@ RCODE F_Database::writeDbHdr( f_timeGetTimeStamp( &StartTime); } - if( RC_BAD( rc = pSFileHdl->getFileHdl( 0, TRUE, &pCFileHdl))) - { - goto Exit; - } - - if( RC_BAD( rc = pCFileHdl->sectorWrite( 0, - uiBytesWritten, pTmpDbHdr, NULL, &uiBytesWritten))) + if( RC_BAD( rc = pSFileHdl->writeBlock( 0, + uiBytesWritten, pTmpDbHdr, &uiBytesWritten))) { if (pDbStats) { @@ -377,7 +371,7 @@ RCODE F_Database::writeDbHdr( // Finally, force the header to disk. - if (RC_BAD( rc = pCFileHdl->flush())) + if (RC_BAD( rc = pSFileHdl->flush())) { goto Exit; } @@ -435,7 +429,6 @@ RCODE F_Db::physRollback( // blocks along the way. uiCurrAddr = uiFirstLogBlkAddr; - m_pSFileHdl->enableFlushMinimize(); while (FSAddrIsBelow( uiCurrAddr, uiLogEOF)) { if (RC_BAD( rc = processBeforeImage( uiLogEOF, &uiCurrAddr, @@ -454,7 +447,6 @@ RCODE F_Db::physRollback( } Exit: - m_pSFileHdl->disableFlushMinimize(); // Free the memory handle, if one was allocated. diff --git a/xflaim/src/rfl.cpp b/xflaim/src/rfl.cpp index 1dbf2c3..a73e214 100644 --- a/xflaim/src/rfl.cpp +++ b/xflaim/src/rfl.cpp @@ -156,16 +156,14 @@ F_Rfl::~F_Rfl() if( m_Buf1.pBufferMgr) { - flmAssert( !m_Buf1.pBufferMgr->havePendingIO() && - !m_Buf1.pBufferMgr->haveUsed()); + flmAssert( !m_Buf1.pBufferMgr->isIOPending()); m_Buf1.pBufferMgr->Release(); m_Buf1.pBufferMgr = NULL; } if( m_Buf2.pBufferMgr) { - flmAssert( !m_Buf2.pBufferMgr->havePendingIO() && - !m_Buf2.pBufferMgr->haveUsed()); + flmAssert( !m_Buf2.pBufferMgr->isIOPending()); m_Buf2.pBufferMgr->Release(); m_Buf2.pBufferMgr = NULL; } @@ -399,9 +397,9 @@ RCODE F_Rfl::positionTo( m_pCurrentBuf->uiRflBufBytes = MOD_512( uiFileOffset); if (m_pCurrentBuf->uiRflBufBytes) { - if (RC_BAD( rc = m_pFileHdl->sectorRead( + if (RC_BAD( rc = m_pFileHdl->read( m_pCurrentBuf->uiRflFileOffset, m_pCurrentBuf->uiRflBufBytes, - m_pCurrentBuf->pIOBuffer->getBuffer(), &uiBytesRead))) + m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { if (rc == NE_FLM_IO_END_OF_FILE) { @@ -642,32 +640,27 @@ RCODE F_Rfl::setup( goto Exit; } - if( RC_BAD( rc = FlmAllocIOBufferMgr( &m_Buf1.pBufferMgr))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( + m_uiRflWriteBufs, m_uiRflWriteBufs * m_uiBufferSize, + TRUE, &m_Buf1.pBufferMgr))) { goto Exit; } - if( RC_BAD( rc = FlmAllocIOBufferMgr( &m_Buf2.pBufferMgr))) + if( RC_BAD( rc = FlmAllocIOBufferMgr( m_uiRflWriteBufs, + m_uiRflWriteBufs * m_uiBufferSize, TRUE, &m_Buf2.pBufferMgr))) { goto Exit; } - m_Buf1.pBufferMgr->enableKeepBuffer(); - m_Buf1.pBufferMgr->setMaxBuffers( m_uiRflWriteBufs); - m_Buf1.pBufferMgr->setMaxBytes( m_uiRflWriteBufs * m_uiBufferSize); - - if( RC_BAD( rc = m_Buf1.pBufferMgr->getBuffer( &m_Buf1.pIOBuffer, - m_uiBufferSize, m_uiBufferSize))) + if( RC_BAD( rc = m_Buf1.pBufferMgr->getBuffer( + m_uiBufferSize, &m_Buf1.pIOBuffer))) { goto Exit; } - m_Buf2.pBufferMgr->enableKeepBuffer(); - m_Buf2.pBufferMgr->setMaxBuffers( m_uiRflWriteBufs); - m_Buf2.pBufferMgr->setMaxBytes( m_uiRflWriteBufs * m_uiBufferSize); - - if( RC_BAD( rc = m_Buf2.pBufferMgr->getBuffer( &m_Buf2.pIOBuffer, - m_uiBufferSize, m_uiBufferSize))) + if( RC_BAD( rc = m_Buf2.pBufferMgr->getBuffer( + m_uiBufferSize, &m_Buf2.pIOBuffer))) { goto Exit; } @@ -838,8 +831,7 @@ RCODE F_Rfl::writeHeader( // Write out the header - if (RC_BAD( rc = m_pFileHdl->sectorWrite( 0L, 512, - ucBuf, NULL, &uiBytesWritten))) + if (RC_BAD( rc = m_pFileHdl->write( 0, 512, ucBuf, &uiBytesWritten))) { // Remap disk full error @@ -1006,8 +998,7 @@ RCODE F_Rfl::openFile( // Read the header. - if (RC_BAD( rc = m_pFileHdl->sectorRead( 0, 512, ucBuf, - &uiBytesRead))) + if (RC_BAD( rc = m_pFileHdl->read( 0, 512, ucBuf, &uiBytesRead))) { if (rc == NE_FLM_IO_END_OF_FILE) { @@ -1276,14 +1267,13 @@ RCODE F_Rfl::flush( goto Exit; } - pucOldBuffer = pBuffer->pIOBuffer->getBuffer(); + pucOldBuffer = pBuffer->pIOBuffer->getBufferPtr(); uiFileOffset = pBuffer->uiRflFileOffset; uiBufBytes = pBuffer->uiRflBufBytes; if (m_uiRflWriteBufs > 1) { - if( RC_BAD( rc = pBuffer->pBufferMgr->getBuffer( - &pNewBuffer, - m_uiBufferSize, m_uiBufferSize))) + if( RC_BAD( rc = pBuffer->pBufferMgr->getBuffer( + m_uiBufferSize, &pNewBuffer))) { goto Exit; } @@ -1295,13 +1285,21 @@ RCODE F_Rfl::flush( if (!bFinalWrite) { - copyLastSector( pBuffer, pucOldBuffer, pNewBuffer->getBuffer(), + copyLastSector( pBuffer, pucOldBuffer, pNewBuffer->getBufferPtr(), uiCurrPacketLen, bStartingNewFile); } } - rc = m_pFileHdl->sectorWrite( uiFileOffset, uiBufBytes, - pucOldBuffer, pAsyncBuf, &uiBytesWritten); + if( pAsyncBuf) + { + rc = m_pFileHdl->write( uiFileOffset, uiBufBytes, pAsyncBuf); + } + else + { + rc = m_pFileHdl->write( uiFileOffset, uiBufBytes, + pucOldBuffer, &uiBytesWritten); + } + if( m_uiRflWriteBufs == 1) { @@ -1326,7 +1324,7 @@ RCODE F_Rfl::flush( { // No need to call copyLastSector, because it was called - // above before calling SectorWrite. The part of the + // above before calling write. The part of the // old buffer that needs to be transferred to the new // buffer has already been transferred. @@ -1334,6 +1332,7 @@ RCODE F_Rfl::flush( { pBuffer->pIOBuffer->notifyComplete( rc); } + pBuffer->pIOBuffer = pNewBuffer; } @@ -1378,8 +1377,8 @@ void F_Rfl::switchBuffers( void) if (pOldBuffer->uiRflBufBytes) { - copyLastSector( m_pCurrentBuf, pOldBuffer->pIOBuffer->getBuffer(), - m_pCurrentBuf->pIOBuffer->getBuffer(), 0, FALSE); + copyLastSector( m_pCurrentBuf, pOldBuffer->pIOBuffer->getBufferPtr(), + m_pCurrentBuf->pIOBuffer->getBufferPtr(), 0, FALSE); } } @@ -2273,7 +2272,7 @@ RCODE F_Rfl::finishPacket( // Get a pointer to packet header. - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes]); // Set the packet address in the packet header. @@ -7542,8 +7541,8 @@ RCODE F_Rfl::readPacket( // Move the bytes left in the buffer down to the beginning // of the buffer. - f_memmove( m_pCurrentBuf->pIOBuffer->getBuffer(), - &(m_pCurrentBuf->pIOBuffer->getBuffer()[ m_uiRflReadOffset]), + f_memmove( m_pCurrentBuf->pIOBuffer->getBufferPtr(), + &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_uiRflReadOffset]), m_pCurrentBuf->uiRflBufBytes - m_uiRflReadOffset); m_pCurrentBuf->uiRflBufBytes -= m_uiRflReadOffset; m_pCurrentBuf->uiRflFileOffset += m_uiRflReadOffset; @@ -7581,7 +7580,7 @@ RCODE F_Rfl::readPacket( // Read enough to get the entire packet. if( RC_BAD( rc = m_pRestore->read( uiReadLen, - &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes]), &uiBytesRead))) { if( rc == NE_FLM_IO_END_OF_FILE) @@ -7669,8 +7668,8 @@ RCODE F_Rfl::readPacket( // Read to get the entire packet. - if( RC_BAD( rc = m_pFileHdl->sectorRead( m_pCurrentBuf->uiRflFileOffset, - uiReadLen, m_pCurrentBuf->pIOBuffer->getBuffer(), + if( RC_BAD( rc = m_pFileHdl->read( m_pCurrentBuf->uiRflFileOffset, + uiReadLen, m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { if( rc == NE_FLM_IO_END_OF_FILE) @@ -7920,7 +7919,7 @@ Get_Next_File: // Verify the packet address. m_uiPacketAddress = m_pCurrentBuf->uiRflFileOffset + m_uiRflReadOffset; - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[m_uiRflReadOffset]); + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[m_uiRflReadOffset]); if ((FLMUINT)FB2UD( &pucPacket [RFL_PACKET_ADDRESS_OFFSET]) != m_uiPacketAddress) { @@ -7942,7 +7941,7 @@ Get_Next_File: { goto Exit; } - pucPacket = &(m_pCurrentBuf->pIOBuffer->getBuffer()[m_uiRflReadOffset]); + pucPacket = &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[m_uiRflReadOffset]); // At this point, we are guaranteed to have the entire packet // in the buffer. @@ -8316,7 +8315,7 @@ Retry_Open: } if( RC_BAD( rc = m_pRestore->read( uiReadLen, - m_pCurrentBuf->pIOBuffer->getBuffer(), &uiBytesRead))) + m_pCurrentBuf->pIOBuffer->getBufferPtr(), &uiBytesRead))) { goto Exit; } diff --git a/xflaim/src/rfl.h b/xflaim/src/rfl.h index 2fef584..26d53ed 100644 --- a/xflaim/src/rfl.h +++ b/xflaim/src/rfl.h @@ -421,7 +421,7 @@ public: FINLINE FLMBYTE * getPacketPtr( void) { - return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + return( &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes])); } @@ -431,7 +431,7 @@ public: { if( m_pCurrentBuf->pBufferMgr) { - flmAssert( !m_pCurrentBuf->pBufferMgr->havePendingIO()); + flmAssert( !m_pCurrentBuf->pBufferMgr->isIOPending()); } if (m_pFileHdl) { @@ -532,7 +532,7 @@ private: FINLINE FLMBYTE * getPacketBodyPtr( void) { - return( &(m_pCurrentBuf->pIOBuffer->getBuffer()[ + return( &(m_pCurrentBuf->pIOBuffer->getBufferPtr()[ m_pCurrentBuf->uiRflBufBytes + RFL_PACKET_OVERHEAD])); } diff --git a/xflaim/src/scache.cpp b/xflaim/src/scache.cpp index 546ce08..8663bc3 100644 --- a/xflaim/src/scache.cpp +++ b/xflaim/src/scache.cpp @@ -26,6 +26,7 @@ #include "flaimsys.h" #define MAX_BLOCKS_TO_SORT 500 +#define FLM_MAX_IO_BUFFER_BLOCKS 16 FSTATIC void ScaNotify( FNOTIFY * pNotify, @@ -1205,15 +1206,11 @@ RCODE F_Database::flushLogBlocks( : (F_CachedBlock **)NULL); FLMUINT uiTotalLoggedBlocks = 0; FLMBOOL bForceCheckpoint = *pbForceCheckpoint; - FLMBOOL bDoAsync; #ifdef FLM_DBG_LOG FLMUINT16 ui16OldFlags; #endif m_uiCurrLogWriteOffset = 0; - bDoAsync = (gv_XFlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; // Get the correct log header. If we are in an update transaction, // need to use the uncommitted log header. Otherwise, use the last @@ -1453,7 +1450,7 @@ RCODE F_Database::flushLogBlocks( if (RC_BAD( rc = lgOutputBlock( pDbStats, pSFileHdl, pLastBlockToLog, pLastBlockToLog->m_pPrevInVersionList->m_pBlkHdr, - bDoAsync, &uiLogEof))) + &uiLogEof))) { goto Exit; } @@ -1523,8 +1520,7 @@ Write_Log_Blocks: if (m_uiCurrLogWriteOffset) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - bDoAsync))) + if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl))) { goto Exit; } @@ -1533,12 +1529,9 @@ Write_Log_Blocks: // If doing async, wait for pending writes to complete before writing // the log header. - if (bDoAsync) + if (RC_BAD( rc = m_pBufferMgr->waitForAllPendingIO())) { - if (RC_BAD( rc = m_pBufferMgr->waitForAllPendingIO())) - { - goto Exit; - } + goto Exit; } // Must wait for all RFL writes before writing out log header. @@ -1737,24 +1730,21 @@ Exit: // Don't care what rc is at this point. Just calling // lgFlushLogBuffer to clear the buffer. - (void)lgFlushLogBuffer( pDbStats, pSFileHdl, bDoAsync); + (void)lgFlushLogBuffer( pDbStats, pSFileHdl); } // Need to wait for any async writes to complete. - if (bDoAsync) + if (bMutexLocked) { - if (bMutexLocked) - { - f_mutexUnlock( gv_XFlmSysData.hBlockCacheMutex); - bMutexLocked = FALSE; - } - - // Don't care about rc here, but we don't want to leave - // this routine until all pending IO is taken care of. - - (void)m_pBufferMgr->waitForAllPendingIO(); + f_mutexUnlock( gv_XFlmSysData.hBlockCacheMutex); + bMutexLocked = FALSE; } + + // Don't care about rc here, but we don't want to leave + // this routine until all pending IO is taken care of. + + (void)m_pBufferMgr->waitForAllPendingIO(); if (!bMutexLocked) { @@ -1832,7 +1822,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !m_pBufferMgr->havePendingIO()); + flmAssert( !m_pBufferMgr->isIOPending()); flmAssert( m_pCurrLogBuffer == NULL); *pbForceCheckpoint = bForceCheckpoint; @@ -1842,35 +1832,39 @@ Exit: /**************************************************************************** Desc: This routine is called whenever a write of a dirty block completes. ****************************************************************************/ -FSTATIC void scaWriteComplete( - IF_IOBuffer * pIOBuffer) +FSTATIC void FLMAPI scaWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData) { - RCODE rc = pIOBuffer->getCompletionCode(); - FLMUINT uiNumBlocks = pIOBuffer->getBufferSize() / - pIOBuffer->getBlockSize(); - F_CachedBlock * pSCache; + RCODE rc; + FLMUINT uiNumBlocks = 0; + F_CachedBlock * pSCache = NULL; F_Database * pDatabase; - XFLM_DB_STATS * pDbStats = (XFLM_DB_STATS *)pIOBuffer->getStats(); + XFLM_DB_STATS * pDbStats = (XFLM_DB_STATS *)pvData; FLMUINT uiMilliPerBlock = 0; FLMUINT uiExtraMilli = 0; - #ifdef FLM_DBG_LOG - FLMUINT16 ui16OldFlags; + FLMUINT16 ui16OldFlags; #endif - if (pDbStats) + f_assert( pIOBuffer->isComplete()); + + rc = pIOBuffer->getCompletionCode(); + uiNumBlocks = pIOBuffer->getCallbackDataCount(); + + if( pDbStats) { - FLMUINT64 ui64ElapMilli = pIOBuffer->getElapTime(); + FLMUINT64 ui64ElapMilli = pIOBuffer->getElapsedTime(); uiMilliPerBlock = (FLMUINT)(ui64ElapMilli / (FLMUINT64)uiNumBlocks); uiExtraMilli = (FLMUINT)(ui64ElapMilli % (FLMUINT64)uiNumBlocks); } f_mutexLock( gv_XFlmSysData.hBlockCacheMutex); - while (uiNumBlocks) + while( uiNumBlocks) { uiNumBlocks--; - pSCache = (F_CachedBlock *)pIOBuffer->getCompletionCallbackData( uiNumBlocks); + pSCache = (F_CachedBlock *)pIOBuffer->getCallbackData( uiNumBlocks); pDatabase = pSCache->getDatabase(); if (pDbStats) @@ -3764,77 +3758,6 @@ Do_Free_Pass: f_mutexUnlock( gv_XFlmSysData.hBlockCacheMutex); } -/**************************************************************************** -Desc: Write an IO buffer to disk. -****************************************************************************/ -RCODE F_Database::writeContiguousBlocks( - XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - IF_IOBuffer * pIOBuffer, - FLMUINT uiBlkAddress, - FLMBOOL bDoAsync) -{ - RCODE rc = NE_XFLM_OK; - FLMBYTE * pucWriteBuffer; - IF_IOBuffer * pAsyncBuffer; - FLMUINT uiBytesWritten; - FLMUINT uiWriteLen; - - pucWriteBuffer = pIOBuffer->getBuffer(); - - if (!bDoAsync) - { - pAsyncBuffer = NULL; - } - else - { - pAsyncBuffer = pIOBuffer; - } - - // Determine how many bytes to write - - uiWriteLen = pIOBuffer->getBufferSize(); - pSFileHdl->setMaxAutoExtendSize( m_uiMaxFileSize); - pSFileHdl->setExtendSize( m_uiFileExtendSize); - - pIOBuffer->startTimer( pDbStats); - - // NOTE: No guarantee that pIOBuffer will still be around - // after the call to writeBlock, unless we are doing - // non-asynchronous write. - - rc = pSFileHdl->writeBlock( uiBlkAddress, uiWriteLen, - pucWriteBuffer, pAsyncBuffer, &uiBytesWritten); - if (!pAsyncBuffer) - { - pIOBuffer->notifyComplete( rc); - } - pIOBuffer = NULL; - - if (RC_BAD( rc)) - { - if (pDbStats) - { - pDbStats->bHaveStats = TRUE; - pDbStats->uiWriteErrors++; - } - - goto Exit; - } - -Exit: - - // If we allocated a write buffer, but did not do a write with it - // still need to do the notify to clean up cache blocks. - - if (pIOBuffer) - { - flmAssert( RC_BAD( rc)); - pIOBuffer->notifyComplete( rc); - } - return( rc); -} - /**************************************************************************** Desc: Prepares a block to be written out. Calculates the checksum and converts the block to native format if not currently in native @@ -3883,7 +3806,6 @@ RCODE F_Database::writeSortedBlocks( FLMUINT * puiDirtyCacheLeft, FLMBOOL * pbForceCheckpoint, FLMBOOL bIsCPThread, - FLMBOOL bDoAsync, FLMUINT uiNumSortedBlocks, FLMBOOL * pbWroteAll) { @@ -4078,13 +4000,12 @@ Add_Contiguous_Block: // Ask for a buffer of the size needed. flmAssert( pIOBuffer == NULL); - if (RC_BAD( rc = m_pBufferMgr->getBuffer( - &pIOBuffer, uiContiguousBlocks * m_uiBlockSize, - m_uiBlockSize))) + if (RC_BAD( rc = m_pBufferMgr->getBuffer( + uiContiguousBlocks * m_uiBlockSize, &pIOBuffer))) { goto Exit; } - pIOBuffer->setCompletionCallback( scaWriteComplete); + pIOBuffer->setCompletionCallback( scaWriteComplete, pDbStats); // Callback will now take care of everything between // uiStartOffset and uiStartOffset + uiNumSortedBlocksProcessed - 1 @@ -4132,7 +4053,7 @@ Add_Contiguous_Block: // Set callback data so we will release these and clear // the pending flag if we don't do the I/O. - pIOBuffer->setCompletionCallbackData( uiLoop, pSCache); + pIOBuffer->addCallbackData( pSCache); } if (bMutexLocked) @@ -4143,7 +4064,7 @@ Add_Contiguous_Block: // Copy blocks into the IO buffer. - pucBuffer = pIOBuffer->getBuffer(); + pucBuffer = pIOBuffer->getBufferPtr(); for (uiLoop = 0; uiLoop < uiBlockCount; uiLoop++, pucBuffer += m_uiBlockSize) @@ -4171,10 +4092,26 @@ Add_Contiguous_Block: goto Exit; } } - - rc = writeContiguousBlocks( pDbStats, pSFileHdl, - pIOBuffer, uiStartBlkAddr, bDoAsync); + + pSFileHdl->setMaxAutoExtendSize( m_uiMaxFileSize); + pSFileHdl->setExtendSize( m_uiFileExtendSize); + + rc = pSFileHdl->writeBlock( uiStartBlkAddr, + pIOBuffer->getBufferSize(), pIOBuffer); + + pIOBuffer->Release(); pIOBuffer = NULL; + + if( RC_BAD( rc)) + { + if (pDbStats) + { + pDbStats->bHaveStats = TRUE; + pDbStats->uiWriteErrors++; + } + + goto Exit; + } // See if we should give up our write lock. Will do so if we // are not forcing a checkpoint and we have not exceeded the @@ -4274,7 +4211,6 @@ RCODE F_Database::flushDirtyBlocks( RCODE rc = NE_XFLM_OK; RCODE rc2; F_CachedBlock * pSCache; - FLMBOOL bDoAsync; FLMBOOL bMutexLocked = FALSE; FLMUINT uiSortedBlocks = 0; FLMUINT uiBlockCount = 0; @@ -4292,12 +4228,6 @@ RCODE F_Database::flushDirtyBlocks( unlockMutex(); } - // See if we can do async IO. - - bDoAsync = (gv_XFlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; - flmAssert( !m_pPendingWriteList); uiDirtyCacheLeft = m_uiDirtyCacheCount * m_uiBlockSize; @@ -4451,7 +4381,7 @@ Force_Checkpoint: rc = writeSortedBlocks( pDbStats, pSFileHdl, uiMaxDirtyCache, &uiDirtyCacheLeft, &bForceCheckpoint, bIsCPThread, - bDoAsync, uiSortedBlocks, pbWroteAll); + uiSortedBlocks, pbWroteAll); } else { @@ -4516,17 +4446,13 @@ Exit: bMutexLocked = FALSE; } - if (bDoAsync) + // Wait for writes to complete. + + if (RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) { - - // Wait for writes to complete. - - if (RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) + if (RC_OK( rc)) { - if (RC_OK( rc)) - { - rc = rc2; - } + rc = rc2; } } @@ -4534,7 +4460,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !m_pBufferMgr->havePendingIO()); + flmAssert( !m_pBufferMgr->isIOPending()); // Don't keep around a large block array if we happened to // allocate one that is bigger than our normal size. It may @@ -4558,7 +4484,6 @@ RCODE F_Database::reduceDirtyCache( RCODE rc = NE_XFLM_OK; RCODE rc2; F_CachedBlock * pSCache; - FLMBOOL bDoAsync; FLMBOOL bMutexLocked = FALSE; FLMUINT uiDirtyCacheLeft; FLMUINT uiSortedBlocks = 0; @@ -4568,13 +4493,6 @@ RCODE F_Database::reduceDirtyCache( flmAssert( !m_uiLogCacheCount); - // See if we can do async IO. - - bDoAsync = (gv_XFlmSysData.bOkToDoAsyncWrites && - pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; - flmAssert( !m_pPendingWriteList); if( m_uiDirtyCacheCount > m_uiBlocksDoneArraySize * 2) @@ -4631,7 +4549,7 @@ RCODE F_Database::reduceDirtyCache( bWroteAll = TRUE; rc = writeSortedBlocks( pDbStats, pSFileHdl, 0, &uiDirtyCacheLeft, - &bForceCheckpoint, FALSE, bDoAsync, uiSortedBlocks, &bWroteAll); + &bForceCheckpoint, FALSE, uiSortedBlocks, &bWroteAll); uiSortedBlocks = 0; @@ -4666,16 +4584,13 @@ Exit: bMutexLocked = FALSE; } - if( bDoAsync) - { - // Wait for writes to complete. + // Wait for writes to complete. - if( RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) + if( RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) + { + if( RC_OK( rc)) { - if( RC_OK( rc)) - { - rc = rc2; - } + rc = rc2; } } @@ -4683,7 +4598,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !m_pBufferMgr->havePendingIO()); + flmAssert( !m_pBufferMgr->isIOPending()); // Don't keep around a large block array if we happened to // allocate one that is bigger than our normal size. It may @@ -4722,7 +4637,6 @@ RCODE F_Database::reduceNewBlocks( RCODE rc = NE_XFLM_OK; RCODE rc2; F_CachedBlock * pSCache; - FLMBOOL bDoAsync = FALSE; FLMBOOL bMutexLocked = FALSE; FLMUINT uiSortedBlocks = 0; FLMUINT uiDirtyCacheLeft; @@ -4736,12 +4650,6 @@ RCODE F_Database::reduceNewBlocks( unlockMutex(); } - // See if we can do async IO. - - bDoAsync = (gv_XFlmSysData.bOkToDoAsyncWrites && pSFileHdl->canDoAsync()) - ? TRUE - : FALSE; - flmAssert( !m_pPendingWriteList); uiDirtyCacheLeft = m_uiDirtyCacheCount * m_uiBlockSize; @@ -4813,7 +4721,7 @@ RCODE F_Database::reduceNewBlocks( rc = writeSortedBlocks( pDbStats, pSFileHdl, ~((FLMUINT)0), &uiDirtyCacheLeft, &bForceCheckpoint, FALSE, - bDoAsync, uiSortedBlocks, &bDummy); + uiSortedBlocks, &bDummy); if( RC_OK( rc)) { @@ -4864,17 +4772,13 @@ Exit: bMutexLocked = FALSE; } - if (bDoAsync) + // Wait for writes to complete. + + if (RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) { - - // Wait for writes to complete. - - if (RC_BAD( rc2 = m_pBufferMgr->waitForAllPendingIO())) + if (RC_OK( rc)) { - if (RC_OK( rc)) - { - rc = rc2; - } + rc = rc2; } } @@ -4882,7 +4786,7 @@ Exit: // Better not be any incomplete writes at this point. - flmAssert( !m_pBufferMgr->havePendingIO()); + flmAssert( !m_pBufferMgr->isIOPending()); // Don't keep around a large block array if we happened to // allocate one that is bigger than our normal size. It may @@ -6930,8 +6834,6 @@ RCODE F_Database::finishCheckpoint( } else if (bTruncateLog) { - IF_FileHdl * pCFileHdl; - if (uiHighLogFileNumber) { (void)pSFileHdl->truncateFiles( @@ -6939,10 +6841,7 @@ RCODE F_Database::finishCheckpoint( uiHighLogFileNumber); } - if (RC_OK( pSFileHdl->getFileHdl( 0, TRUE, &pCFileHdl))) - { - (void)pCFileHdl->truncate( LOG_THRESHOLD_SIZE); - } + pSFileHdl->truncateFile( 0, LOG_THRESHOLD_SIZE); } #ifdef FLM_DBG_LOG @@ -7056,6 +6955,11 @@ RCODE F_Database::finishCheckpoint( goto Exit; } } + + if( RC_BAD( rc = pSFileHdl->flush())) + { + goto Exit; + } // Re-enable the RFL volume OK flag - in case it was turned off somewhere. @@ -7154,8 +7058,6 @@ RCODE F_Database::doCheckpoint( F_CachedBlock * pSCache; FLMUINT uiTimestamp; - pSFileHdl->enableFlushMinimize(); - if (m_pCPInfo) { lockMutex(); @@ -7255,14 +7157,14 @@ Exit: // the checkpoint thread to force checkpoints whenever it is woke // up until it succeeds (see flopen.cpp). - if (RC_BAD( rc) && bForceCheckpoint) + if( RC_BAD( rc) && bForceCheckpoint) { m_CheckpointRc = rc; } // Timestamp all of the items in the free list - if (bForceCheckpoint) + if( bForceCheckpoint) { uiTimestamp = FLM_GET_TIMER(); @@ -7276,15 +7178,13 @@ Exit: f_mutexUnlock( gv_XFlmSysData.hBlockCacheMutex); } - if (m_pCPInfo) + if( m_pCPInfo) { lockMutex(); m_pCPInfo->bDoingCheckpoint = FALSE; unlockMutex(); } - - pSFileHdl->disableFlushMinimize(); - + return( rc); } diff --git a/xflaim/src/translog.cpp b/xflaim/src/translog.cpp index e96bcbc..5e90ada 100644 --- a/xflaim/src/translog.cpp +++ b/xflaim/src/translog.cpp @@ -25,8 +25,9 @@ #include "flaimsys.h" -FSTATIC void lgWriteComplete( - IF_IOBuffer * pIOBuffer); +FSTATIC void FLMAPI lgWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData); #ifdef FLM_DBG_LOG /**************************************************************************** @@ -69,17 +70,18 @@ void scaLogWrite( Desc: This is the callback routine that is called when a disk write is completed. ****************************************************************************/ -FSTATIC void lgWriteComplete( - IF_IOBuffer * pIOBuffer) +FSTATIC void FLMAPI lgWriteComplete( + IF_IOBuffer * pIOBuffer, + void * pvData) { F_Database * pDatabase = - (F_Database *)pIOBuffer->getCompletionCallbackData( 0); + (F_Database *)pIOBuffer->getCallbackData( 0); #ifdef FLM_DBG_LOG FLMUINT uiBlockSize = pDatabase->getBlockSize(); FLMUINT uiLength = pIOBuffer->getBufferSize(); char * pszEvent; #endif - XFLM_DB_STATS * pDbStats = (XFLM_DB_STATS *)pIOBuffer->getStats(); + XFLM_DB_STATS * pDbStats = (XFLM_DB_STATS *)pvData; #ifdef FLM_DBG_LOG pszEvent = (char *)(RC_OK( pIOBuffer->getCompletionCode()) @@ -96,7 +98,7 @@ FSTATIC void lgWriteComplete( // completion at any time. pDatabase->lockMutex(); - pDbStats->LogBlockWrites.ui64ElapMilli += pIOBuffer->getElapTime(); + pDbStats->LogBlockWrites.ui64ElapMilli += pIOBuffer->getElapsedTime(); pDatabase->unlockMutex(); } } @@ -106,21 +108,9 @@ Desc: This routine flushes a log buffer to the log file. ****************************************************************************/ RCODE F_Database::lgFlushLogBuffer( XFLM_DB_STATS * pDbStats, - F_SuperFileHdl * pSFileHdl, - FLMBOOL bDoAsync) + F_SuperFileHdl * pSFileHdl) { RCODE rc = NE_XFLM_OK; - FLMUINT uiBytesWritten; - IF_IOBuffer * pAsyncBuffer; - - if (!bDoAsync) - { - pAsyncBuffer = NULL; - } - else - { - pAsyncBuffer = m_pCurrLogBuffer; - } if (pDbStats) { @@ -129,39 +119,32 @@ RCODE F_Database::lgFlushLogBuffer( pDbStats->LogBlockWrites.ui64TotalBytes += m_uiCurrLogWriteOffset; } - m_pCurrLogBuffer->setCompletionCallback( lgWriteComplete); - m_pCurrLogBuffer->setCompletionCallbackData( 0, (void *)this); + m_pCurrLogBuffer->setCompletionCallback( lgWriteComplete, pDbStats); + m_pCurrLogBuffer->addCallbackData( (void *)this); pSFileHdl->setMaxAutoExtendSize( m_uiMaxFileSize); pSFileHdl->setExtendSize( m_uiFileExtendSize); - m_pCurrLogBuffer->startTimer( pDbStats); // NOTE: No guarantee that m_pCurrLogBuffer will still be around // after the call to writeBlock, unless we are doing // non-asynchronous write. - rc = pSFileHdl->writeBlock( m_uiCurrLogBlkAddr, - m_uiCurrLogWriteOffset, - m_pCurrLogBuffer->getBuffer(), - pAsyncBuffer, &uiBytesWritten); - if (!pAsyncBuffer) - { - m_pCurrLogBuffer->notifyComplete( rc); - } - m_pCurrLogBuffer = NULL; - - if (RC_BAD( rc)) + if( RC_BAD( rc = pSFileHdl->writeBlock( m_uiCurrLogBlkAddr, + m_uiCurrLogWriteOffset, m_pCurrLogBuffer))) { if (pDbStats) { pDbStats->uiWriteErrors++; } + goto Exit; } Exit: m_uiCurrLogWriteOffset = 0; + m_pCurrLogBuffer->Release(); m_pCurrLogBuffer = NULL; + return( rc); } @@ -176,7 +159,6 @@ RCODE F_Database::lgOutputBlock( // block in cache. This block will be // modified to the logged version of // the block - FLMBOOL bDoAsync, // Do asynchronous writes? FLMUINT * puiLogEofRV) // Returns log EOF { RCODE rc = NE_XFLM_OK; @@ -196,8 +178,7 @@ RCODE F_Database::lgOutputBlock( if (m_uiCurrLogWriteOffset) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - bDoAsync))) + if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl))) { goto Exit; } @@ -242,7 +223,7 @@ RCODE F_Database::lgOutputBlock( for( ;;) { if (RC_BAD( rc = m_pBufferMgr->getBuffer( - &m_pCurrLogBuffer, uiLogBufferSize, uiLogBufferSize))) + uiLogBufferSize, &m_pCurrLogBuffer))) { // If we failed to get a buffer of the requested size, // reduce the buffer size by half and try again. @@ -265,7 +246,7 @@ RCODE F_Database::lgOutputBlock( // Copy data from log block to the log buffer - pucLogBlk = m_pCurrLogBuffer->getBuffer() + m_uiCurrLogWriteOffset; + pucLogBlk = m_pCurrLogBuffer->getBufferPtr() + m_uiCurrLogWriteOffset; pLogBlkHdr = (F_BLK_HDR *)pucLogBlk; f_memcpy( pLogBlkHdr, pLogBlock->m_pBlkHdr, m_uiBlockSize); @@ -302,8 +283,7 @@ RCODE F_Database::lgOutputBlock( if (m_uiCurrLogWriteOffset == m_pCurrLogBuffer->getBufferSize()) { - if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl, - bDoAsync))) + if (RC_BAD( rc = lgFlushLogBuffer( pDbStats, pSFileHdl))) { goto Exit; }