diff --git a/flaim/src/flbackup.cpp b/flaim/src/flbackup.cpp index f09f7f6..afd70ba 100644 --- a/flaim/src/flbackup.cpp +++ b/flaim/src/flbackup.cpp @@ -2678,7 +2678,7 @@ RCODE F_BackerStream::flush( void) // Wait for the background thread to become idle. When it // does, we know that all writes have completed. - if( RC_BAD( rc = f_semWait( m_hIdleSem, F_SEM_WAITFOREVER))) + if( RC_BAD( rc = f_semWait( m_hIdleSem, F_WAITFOREVER))) { goto Exit; } @@ -2732,7 +2732,7 @@ RCODE F_BackerStream::signalThread( void) // Wait for the thread to become idle - if( RC_BAD( rc = f_semWait( m_hIdleSem, F_SEM_WAITFOREVER))) + if( RC_BAD( rc = f_semWait( m_hIdleSem, F_WAITFOREVER))) { goto Exit; } @@ -2800,7 +2800,7 @@ RCODE FLMAPI F_BackerStream::readThread( f_semSignal( pBackerStream->m_hIdleSem); if( RC_BAD( rc = f_semWait( pBackerStream->m_hDataSem, - F_SEM_WAITFOREVER))) + F_WAITFOREVER))) { goto Exit; } @@ -2844,7 +2844,7 @@ RCODE FLMAPI F_BackerStream::writeThread( f_semSignal( pBackerStream->m_hIdleSem); if( RC_BAD( rc = f_semWait( pBackerStream->m_hDataSem, - F_SEM_WAITFOREVER))) + F_WAITFOREVER))) { goto Exit; } diff --git a/flaim/src/fslfileu.cpp b/flaim/src/fslfileu.cpp index fe31552..1efc2da 100644 --- a/flaim/src/fslfileu.cpp +++ b/flaim/src/fslfileu.cpp @@ -2928,7 +2928,7 @@ FSTATIC RCODE FLMAPI flmMaintThread( // Wait for work to become available - if( RC_BAD( rc = f_semWait( pFile->hMaintSem, F_SEM_WAITFOREVER))) + if( RC_BAD( rc = f_semWait( pFile->hMaintSem, F_WAITFOREVER))) { goto Exit; } diff --git a/flaim/src/rfl.cpp b/flaim/src/rfl.cpp index 1c1d2be..84c30fe 100644 --- a/flaim/src/rfl.cpp +++ b/flaim/src/rfl.cpp @@ -732,7 +732,7 @@ 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_WAITFOREVER))) { flmAssert( 0); rc = TempRc; diff --git a/flaim/src/scache.cpp b/flaim/src/scache.cpp index 2eb77c5..59fd435 100644 --- a/flaim/src/scache.cpp +++ b/flaim/src/scache.cpp @@ -5173,12 +5173,14 @@ Add_Contiguous_Block: ppSCacheBucket = ScaHash( pFile->FileHdr.uiSigBitsInBlkSize, uiBlkAddress); pTmpSCache = *ppSCacheBucket; + while (pTmpSCache && (pTmpSCache->uiBlkAddress != uiBlkAddress || pTmpSCache->pFile != pFile)) { pTmpSCache = pTmpSCache->pNextInHashBucket; } + if (!pTmpSCache || (pTmpSCache->ui16Flags & (CA_READ_PENDING | CA_WRITE_PENDING | CA_WRITE_INHIBIT)) || diff --git a/flaim/util/gigatest.cpp b/flaim/util/gigatest.cpp index d07f524..0e66d05 100644 --- a/flaim/util/gigatest.cpp +++ b/flaim/util/gigatest.cpp @@ -32,19 +32,19 @@ #define DATA_COLUMN 35 #define MAX_CACHE_ROW 1 -#define USED_CACHE_ROW (MAX_CACHE_ROW + 1) -#define ITEMS_CACHED_ROW (USED_CACHE_ROW + 1) -#define DIRTY_CACHE_ROW (ITEMS_CACHED_ROW + 1) -#define LOG_CACHE_ROW (DIRTY_CACHE_ROW + 1) -#define FREE_CACHE_ROW (LOG_CACHE_ROW + 1) -#define CP_STATE_ROW (FREE_CACHE_ROW + 1) -#define DB_NAME_ROW (CP_STATE_ROW + 1) -#define TOTAL_TO_LOAD_ROW (DB_NAME_ROW + 1) -#define TRANS_SIZE_ROW (TOTAL_TO_LOAD_ROW + 1) -#define TOTAL_LOADED_ROW (TRANS_SIZE_ROW + 1) -#define ADDS_PER_SEC_CURRENT (TOTAL_LOADED_ROW + 1) -#define ADDS_PER_SEC_OVERALL (ADDS_PER_SEC_CURRENT + 1) -#define ELAPSED_TIME_ROW (ADDS_PER_SEC_OVERALL + 1) +#define USED_CACHE_ROW 2 +#define ITEMS_CACHED_ROW 3 +#define DIRTY_CACHE_ROW 4 +#define LOG_CACHE_ROW 5 +#define FREE_CACHE_ROW 6 +#define CP_STATE_ROW 7 +#define DB_NAME_ROW 8 +#define TOTAL_TO_LOAD_ROW 9 +#define TRANS_SIZE_ROW 10 +#define TOTAL_LOADED_ROW 11 +#define ADDS_PER_SEC_CURRENT 12 +#define ADDS_PER_SEC_OVERALL 13 +#define ELAPSED_TIME_ROW 14 char gv_szDibName[ 200]; char gv_szDataDir[ 200]; diff --git a/ftk/src/ftk.h b/ftk/src/ftk.h index 2368d89..43a744b 100644 --- a/ftk/src/ftk.h +++ b/ftk/src/ftk.h @@ -290,13 +290,13 @@ #elif _MSC_VER >= 1300 typedef unsigned long __w64 FLMUINT; typedef long __w64 FLMINT; - typedef unsigned int FLMUINT32; + typedef __w64 unsigned int FLMUINT32; typedef __w64 unsigned int FLMSIZET; #else typedef unsigned long FLMUINT; typedef long FLMINT; typedef unsigned int FLMUINT32; - typedef __w64 unsigned int FLMSIZET; + typedef unsigned int FLMSIZET; #endif #elif defined( FLM_NLM) @@ -341,6 +341,7 @@ #define F_FILENAME_SIZE 256 #define F_PATH_MAX_SIZE 256 + #define F_WAITFOREVER (0xFFFFFFFF) #define FLM_MAX_UINT ((FLMUINT)(-1L)) #define FLM_MAX_INT ((FLMINT)(((FLMUINT)(-1L)) >> 1)) @@ -1506,6 +1507,9 @@ ****************************************************************************/ flminterface FLMEXP IF_IOStream : public IF_IStream, public IF_OStream { + #if defined( FLM_WIN) && _MSC_VER < 1300 + using IF_IStream::operator delete; + #endif }; /**************************************************************************** @@ -2013,8 +2017,7 @@ ****************************************************************************/ flminterface FLMEXP IF_AsyncClient : virtual public F_Object { - virtual RCODE FLMAPI waitToComplete( - FLMBOOL bRelease) = 0; + virtual RCODE FLMAPI waitToComplete( void) = 0; virtual RCODE FLMAPI getCompletionCode( void) = 0; @@ -2357,7 +2360,6 @@ ****************************************************************************/ typedef void * F_SEM; #define F_SEM_NULL NULL - #define F_SEM_WAITFOREVER (0xFFFFFFFF) RCODE FLMAPI f_semCreate( F_SEM * phSem); @@ -2372,6 +2374,9 @@ void FLMAPI f_semSignal( F_SEM hSem); + FLMUINT FLMAPI f_semGetSignalCount( + F_SEM hSem); + /**************************************************************************** Desc: Notify Lists ****************************************************************************/ @@ -4788,7 +4793,7 @@ FLMBYTE ucChar) { RCODE rc = NE_FLM_OK; - FLMBYTE * pucTmp; + FLMBYTE * pucTmp = NULL; if( RC_BAD( rc = allocSpace( 1, (void **)&pucTmp))) { @@ -4806,7 +4811,7 @@ FLMUNICODE uChar) { RCODE rc = NE_FLM_OK; - FLMUNICODE * puTmp; + FLMUNICODE * puTmp = NULL; if( RC_BAD( rc = allocSpace( sizeof( FLMUNICODE), (void **)&puTmp))) { diff --git a/ftk/src/ftkfsys.cpp b/ftk/src/ftkfsys.cpp index bb3bfd4..0a2c966 100644 --- a/ftk/src/ftkfsys.cpp +++ b/ftk/src/ftkfsys.cpp @@ -36,7 +36,7 @@ FSTATIC const char * f_findFileNameStart( FSTATIC char * f_getPathComponent( char ** ppszPath, FLMUINT * puiEndChar); - + /**************************************************************************** Desc: ****************************************************************************/ @@ -62,7 +62,7 @@ public: FLMINT FLMAPI AddRef( void) { - return( ++m_refCnt); + return( f_atomicInc( &m_refCnt)); } FLMINT FLMAPI Release( void); @@ -1430,6 +1430,7 @@ Exit: return( NE_FLM_OK); #else + RCODE rc = NE_FLM_OK; int hFile = -1; struct stat filestats; @@ -2667,7 +2668,7 @@ Desc: ****************************************************************************/ FLMINT FLMAPI F_CachedFileHdl::Release( void) { - FLMINT iRefCnt = --m_refCnt; + FLMINT iRefCnt = f_atomicDec( &m_refCnt); F_FileHdlCache * pFileHdlCache = m_pFileHdlCache; if( !iRefCnt) @@ -2996,39 +2997,81 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -FLMINT FLMAPI F_FileAsyncClient::Release() +FLMINT FLMAPI F_FileAsyncClient::Release( + FLMBOOL bOkToReuse) { FLMINT iRefCnt; if( m_refCnt == 1) { - f_assert( !m_pFileHdl); +#if !defined( FLM_UNIX) + FLMUINT uiSignalCount = f_semGetSignalCount( m_hSem); +#endif + +#if !defined( FLM_UNIX) + f_assert( uiSignalCount <= 1); +#endif + f_assert( !m_pIOBuffer); + f_assert( !m_pFileHdl); - f_mutexLock( F_FileHdl::m_hAsyncListMutex); - - if( F_FileHdl::m_uiAvailAsyncCount < 32) +#if !defined( FLM_UNIX) + if( uiSignalCount == 1) { - f_assert( !m_pNext); - m_pNext = F_FileHdl::m_pFirstAvailAsync; - F_FileHdl::m_pFirstAvailAsync = this; - F_FileHdl::m_uiAvailAsyncCount++; + // The application may not have cared to wait on this + // individual write to complete. Since the + // semaphore has been signaled, we need to consume + // the signal so that the next time this + // async client is used, the semaphore will + // block until that I/O operation is complete. - m_completionRc = NE_FLM_OK; - m_uiBytesToDo = 0; - m_uiBytesDone = 0; - iRefCnt = m_refCnt; + f_semWait( m_hSem, F_WAITFOREVER); + } +#endif + + if( m_pIOBuffer) + { + m_pIOBuffer->Release(); + m_pIOBuffer = NULL; + } + + if( m_pFileHdl) + { + m_pFileHdl->Release(); + m_pFileHdl = NULL; + } + + if( bOkToReuse) + { + 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 = f_atomicDec( &m_refCnt); + } + + f_mutexUnlock( F_FileHdl::m_hAsyncListMutex); } else { - iRefCnt = --m_refCnt; + iRefCnt = f_atomicDec( &m_refCnt); } - - f_mutexUnlock( F_FileHdl::m_hAsyncListMutex); } else { - iRefCnt = --m_refCnt; + iRefCnt = f_atomicDec( &m_refCnt); } if( !m_refCnt) @@ -3045,22 +3088,15 @@ Desc: F_FileAsyncClient::~F_FileAsyncClient() { f_assert( !m_pNext); + f_assert( !m_refCnt); -#ifdef FLM_WIN - if( m_Overlapped.hEvent) +#if !defined( FLM_UNIX) + if( m_hSem != F_SEM_NULL) { - CloseHandle( m_Overlapped.hEvent); + f_semDestroy( &m_hSem); } #endif - -#ifdef FLM_RING_ZERO_NLM - if( m_hSem) - { - (void)kSemaphoreFree( m_hSem); - m_hSem = NULL; - } -#endif - + if( m_pFileHdl) { m_pFileHdl->Release(); @@ -3081,40 +3117,22 @@ RCODE F_FileAsyncClient::prepareForAsync( goto Exit; } -#ifdef FLM_WIN - if( !m_Overlapped.hEvent) +#if !defined( FLM_UNIX) + if( m_hSem == F_SEM_NULL) { - if( (m_Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL)) == NULL) + if( RC_BAD( rc = f_semCreate( &m_hSem))) { - rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); - goto Exit; - } - } - else - { - if( !ResetEvent( m_Overlapped.hEvent)) - { - rc = f_mapPlatformError( GetLastError(), NE_FLM_MEM); goto Exit; } } + + f_assert( f_semGetSignalCount( m_hSem) == 0); #endif #if defined( FLM_UNIX) && defined( FLM_HAS_ASYNC_IO) 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; @@ -3139,25 +3157,13 @@ Exit: /**************************************************************************** Desc: ****************************************************************************/ -RCODE FLMAPI F_FileAsyncClient::waitToComplete( - FLMBOOL bRelease) +RCODE FLMAPI F_FileAsyncClient::waitToComplete( void) { 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_UNIX) + FLMUINT uiBytesDone = 0; + #if defined( FLM_HAS_ASYNC_IO) { FLMINT iAsyncResult; @@ -3199,29 +3205,26 @@ RCODE FLMAPI F_FileAsyncClient::waitToComplete( } } #endif + + notifyComplete( completionRc, uiBytesDone); +#else + if( RC_BAD( completionRc = f_semWait( m_hSem, F_WAITFOREVER))) + { + return( completionRc); + } + + f_assert( f_semGetSignalCount( m_hSem) == 0); + + if( m_pIOBuffer) + { + f_assert( !m_pIOBuffer->isPending()); + } + + f_assert( m_completionRc != NE_FLM_IO_PENDING); + + completionRc = m_completionRc; #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); } @@ -3230,21 +3233,21 @@ Desc: ****************************************************************************/ void FLMAPI F_FileAsyncClient::notifyComplete( RCODE completionRc, - FLMUINT uiBytesDone, - FLMBOOL bRelease) + FLMUINT uiBytesDone) { + f_assert( m_completionRc == NE_FLM_IO_PENDING); + f_assert( !m_pIOBuffer || m_pIOBuffer->isPending()); + + AddRef(); + + m_completionRc = completionRc; + m_uiBytesDone = uiBytesDone; + 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) { f_assert( m_pFileHdl->m_numAsyncPending); @@ -3253,10 +3256,23 @@ void FLMAPI F_FileAsyncClient::notifyComplete( m_pFileHdl = NULL; } - if( bRelease) + if( m_pIOBuffer) { - Release(); + IF_IOBuffer * pIOBuffer = m_pIOBuffer; + + m_pIOBuffer = NULL; + pIOBuffer->notifyComplete( m_completionRc); + pIOBuffer->Release(); + pIOBuffer = NULL; } + +#if !defined( FLM_UNIX) + f_semSignal( m_hSem); + f_assert( f_semGetSignalCount( m_hSem) == 1); +#endif + + f_assert( !m_pIOBuffer || !m_pIOBuffer->isPending()); + Release(); } /**************************************************************************** @@ -3276,25 +3292,6 @@ 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: ****************************************************************************/ diff --git a/ftk/src/ftkiobuf.cpp b/ftk/src/ftkiobuf.cpp index e056c9b..63be8cb 100644 --- a/ftk/src/ftkiobuf.cpp +++ b/ftk/src/ftkiobuf.cpp @@ -61,6 +61,10 @@ public: private: + F_MUTEX m_hMutex; +#ifndef FLM_UNIX + F_SEM m_hAvailSem; +#endif FLMUINT m_uiMaxBuffers; FLMUINT m_uiMaxBufferBytes; FLMUINT m_uiTotalBuffers; @@ -69,6 +73,7 @@ private: F_IOBuffer * m_pFirstAvail; F_IOBuffer * m_pFirstUsed; FLMBOOL m_bReuseBuffers; + F_NOTIFY_LIST_ITEM * m_pAvailNotify; RCODE m_completionRc; friend class F_IOBuffer; @@ -116,6 +121,11 @@ Desc: ****************************************************************************/ F_IOBufferMgr::F_IOBufferMgr() { + m_hMutex = F_MUTEX_NULL; +#ifndef FLM_UNIX + m_hAvailSem = F_SEM_NULL; +#endif + m_uiMaxBuffers = 0; m_uiMaxBufferBytes = 0; @@ -126,6 +136,7 @@ F_IOBufferMgr::F_IOBufferMgr() m_pFirstAvail = NULL; m_pFirstUsed = NULL; + m_pAvailNotify = NULL; m_bReuseBuffers = FALSE; m_completionRc = NE_FLM_OK; } @@ -137,11 +148,24 @@ F_IOBufferMgr::~F_IOBufferMgr() { f_assert( !m_pFirstPending); f_assert( !m_pFirstUsed); + f_assert( !m_pAvailNotify); while( m_pFirstAvail) { m_pFirstAvail->Release(); } + + if( m_hMutex != F_MUTEX_NULL) + { + f_mutexDestroy( &m_hMutex); + } + +#ifndef FLM_UNIX + if( m_hAvailSem != F_SEM_NULL) + { + f_semDestroy( &m_hAvailSem); + } +#endif } /**************************************************************************** @@ -152,14 +176,30 @@ RCODE F_IOBufferMgr::setupBufferMgr( FLMUINT uiMaxBytes, FLMBOOL bReuseBuffers) { + RCODE rc = NE_FLM_OK; + f_assert( uiMaxBuffers); f_assert( uiMaxBytes); + if( RC_BAD( rc = f_mutexCreate( &m_hMutex))) + { + goto Exit; + } + +#ifndef FLM_UNIX + if( RC_BAD( rc = f_semCreate( &m_hAvailSem))) + { + goto Exit; + } +#endif + m_uiMaxBuffers = uiMaxBuffers; m_uiMaxBufferBytes = uiMaxBytes; m_bReuseBuffers = bReuseBuffers; - return( NE_FLM_OK); +Exit: + + return( rc); } /**************************************************************************** @@ -171,6 +211,7 @@ RCODE FLMAPI F_IOBufferMgr::getBuffer( { RCODE rc = NE_FLM_OK; F_IOBuffer * pIOBuffer = NULL; + FLMBOOL bMutexLocked = FALSE; f_assert( *ppIOBuffer == NULL); @@ -180,6 +221,9 @@ RCODE FLMAPI F_IOBufferMgr::getBuffer( goto Exit; } + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + Retry: if( m_pFirstAvail) @@ -215,11 +259,31 @@ Retry: } else if( m_pFirstPending) { - if( RC_BAD( rc = m_pFirstPending->waitToComplete())) + #ifndef FLM_UNIX + if( RC_BAD( rc = f_notifyWait( m_hMutex, m_hAvailSem, + NULL, &m_pAvailNotify))) { goto Exit; } - + #else + F_IOBuffer * pPending = m_pFirstPending; + + pPending->AddRef(); + f_mutexUnlock( m_hMutex); + bMutexLocked = FALSE; + + rc = pPending->waitToComplete(); + + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + pPending->Release(); + + if( RC_BAD( rc)) + { + goto Exit; + } + #endif + goto Retry; } else @@ -240,6 +304,11 @@ Exit: pIOBuffer->Release(); } + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + return( rc); } @@ -248,24 +317,49 @@ Desc: ****************************************************************************/ RCODE FLMAPI F_IOBufferMgr::waitForAllPendingIO( void) { - RCODE rc; + RCODE rc = NE_FLM_OK; RCODE tmpRc; F_IOBuffer * pBuf; + FLMBOOL bMutexLocked = FALSE; + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + while( (pBuf = m_pFirstPending) != NULL) { + pBuf->AddRef(); + + f_mutexUnlock( m_hMutex); + bMutexLocked = FALSE; + if( RC_BAD( tmpRc = pBuf->waitToComplete())) { if( RC_OK( m_completionRc)) { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; m_completionRc = tmpRc; } } + + if( !bMutexLocked) + { + f_mutexLock( m_hMutex); + bMutexLocked = TRUE; + } + + pBuf->Release( TRUE); + pBuf = NULL; } rc = m_completionRc; m_completionRc = NE_FLM_OK; + if( bMutexLocked) + { + f_mutexUnlock( m_hMutex); + } + return( rc); } @@ -276,6 +370,7 @@ void F_IOBufferMgr::linkToList( F_IOBuffer ** ppListHead, F_IOBuffer * pIOBuffer) { + f_assertMutexLocked( m_hMutex); f_assert( pIOBuffer->m_eList == MGR_LIST_NONE); pIOBuffer->m_pPrev = NULL; @@ -287,11 +382,14 @@ void F_IOBufferMgr::linkToList( *ppListHead = pIOBuffer; - if( ppListHead == &m_pFirstPending || ppListHead == &m_pFirstUsed) + if( ppListHead == &m_pFirstPending) { - pIOBuffer->m_eList = (ppListHead == &m_pFirstPending - ? MGR_LIST_PENDING - : MGR_LIST_USED); + f_assert( !pIOBuffer->m_bPending); + pIOBuffer->m_eList = MGR_LIST_PENDING; + } + else if( ppListHead == &m_pFirstUsed) + { + pIOBuffer->m_eList = MGR_LIST_USED; } else { @@ -305,6 +403,8 @@ Desc: void F_IOBufferMgr::unlinkFromList( F_IOBuffer * pIOBuffer) { + f_assertMutexLocked( m_hMutex); + if( pIOBuffer->m_pNext) { pIOBuffer->m_pNext->m_pPrev = pIOBuffer->m_pPrev; @@ -333,21 +433,37 @@ void F_IOBufferMgr::unlinkFromList( /**************************************************************************** Desc: ****************************************************************************/ -FLMINT FLMAPI F_IOBuffer::Release( void) +FLMINT F_IOBuffer::Release( + FLMBOOL bMutexAlreadyLocked) { - FLMINT iRefCnt; + FLMINT iRefCnt; + F_MUTEX hMutex = F_MUTEX_NULL; + F_IOBufferMgr * pBufferMgr = NULL; + if( m_pBufferMgr && !bMutexAlreadyLocked) + { + hMutex = m_pBufferMgr->m_hMutex; + f_mutexLock( hMutex); + } + if( m_refCnt <= 2) { if( m_pBufferMgr && m_eList != MGR_LIST_NONE) { + f_assert( m_eList != MGR_LIST_PENDING); m_pBufferMgr->unlinkFromList( this); } } if( m_refCnt == 2) { - if( m_pBufferMgr) + if( m_pAsyncClient) + { + m_pAsyncClient->Release(); + m_pAsyncClient = NULL; + } + + if( (pBufferMgr = m_pBufferMgr) != NULL) { if( m_pBufferMgr->m_bReuseBuffers) { @@ -358,15 +474,26 @@ FLMINT FLMAPI F_IOBuffer::Release( void) f_assert( m_pBufferMgr->m_uiTotalBuffers); f_assert( m_pBufferMgr->m_uiTotalBufferBytes >= m_uiBufferSize); - m_refCnt--; + f_atomicDec( &m_refCnt); m_pBufferMgr->m_uiTotalBuffers--; m_pBufferMgr->m_uiTotalBufferBytes -= m_uiBufferSize; m_pBufferMgr = NULL; } + + if( pBufferMgr->m_pAvailNotify) + { + f_notifySignal( pBufferMgr->m_pAvailNotify, NE_FLM_OK); + pBufferMgr->m_pAvailNotify = NULL; + } } } - iRefCnt = --m_refCnt; + iRefCnt = f_atomicDec( &m_refCnt); + + if( hMutex != F_MUTEX_NULL) + { + f_mutexUnlock( hMutex); + } if( !iRefCnt) { @@ -406,16 +533,24 @@ void FLMAPI F_IOBuffer::setPending( void) { f_assert( !m_bPending); - m_bPending = TRUE; - m_uiStartTime = FLM_GET_TIMER(); - if( m_pBufferMgr) { f_assert( m_eList == MGR_LIST_USED); + f_mutexLock( m_pBufferMgr->m_hMutex); m_pBufferMgr->unlinkFromList( this); m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstPending, this); + f_mutexUnlock( m_pBufferMgr->m_hMutex); } + +#ifndef FLM_UNIX + f_assert( !m_pAsyncClient || + f_semGetSignalCount( ((F_FileAsyncClient *)m_pAsyncClient)->m_hSem) == 0); +#endif + + m_bPending = TRUE; + m_uiStartTime = FLM_GET_TIMER(); + m_uiEndTime = 0; } /**************************************************************************** @@ -425,16 +560,18 @@ 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); + f_mutexLock( m_pBufferMgr->m_hMutex); m_pBufferMgr->unlinkFromList( this); m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this); + f_mutexUnlock( m_pBufferMgr->m_hMutex); } + + m_bPending = FALSE; + m_uiStartTime = 0; } /**************************************************************************** @@ -458,10 +595,11 @@ void F_IOBuffer::notifyComplete( m_fnCompletion = NULL; m_pvData = NULL; } - + if( m_pBufferMgr) { f_assert( m_eList == MGR_LIST_PENDING); + f_mutexLock( m_pBufferMgr->m_hMutex); m_pBufferMgr->unlinkFromList( this); m_pBufferMgr->linkToList( &m_pBufferMgr->m_pFirstUsed, this); @@ -470,6 +608,8 @@ void F_IOBuffer::notifyComplete( { m_pBufferMgr->m_completionRc = completionRc; } + + f_mutexUnlock( m_pBufferMgr->m_hMutex); } } diff --git a/ftk/src/ftklock.cpp b/ftk/src/ftklock.cpp index 240d7ed..87ff09e 100644 --- a/ftk/src/ftklock.cpp +++ b/ftk/src/ftklock.cpp @@ -591,13 +591,13 @@ RCODE FLMAPI F_LockObject::lock( LockWait.iPriority = iPriority; LockWait.uiWaitStartTime = (FLMUINT)FLM_GET_TIMER(); - if (bExclReq && pLockStats) + if( bExclReq && pLockStats) { f_timeGetTimeStamp( &LockWait.StartTime); LockWait.pLockStats = pLockStats; } - if (uiMaxWaitSecs >= 0xFF) + if( uiMaxWaitSecs >= 0xFF) { LockWait.uiWaitTime = 0; } @@ -615,7 +615,7 @@ RCODE FLMAPI F_LockObject::lock( // Now just wait to be signaled. - if( RC_BAD( TempRc = f_semWait( hWaitSem, F_SEM_WAITFOREVER))) + if( RC_BAD( TempRc = f_semWait( hWaitSem, F_WAITFOREVER))) { RC_UNEXPECTED_ASSERT( TempRc); rc = TempRc; diff --git a/ftk/src/ftkmem.cpp b/ftk/src/ftkmem.cpp index a937872..ef4f2c4 100644 --- a/ftk/src/ftkmem.cpp +++ b/ftk/src/ftkmem.cpp @@ -2580,7 +2580,7 @@ void * F_SlabManager::allocSlabFromSystem( void) #elif defined( FLM_RING_ZERO_NLM) - pSlab = Alloc( m_uiSlabSize, gv_lAllocRTag) + pSlab = Alloc( m_uiSlabSize, gv_lAllocRTag); #elif defined( FLM_SOLARIS) @@ -4792,7 +4792,11 @@ RCODE FLMAPI f_allocAlignedBufferImp( #elif defined( FLM_RING_ZERO_NLM) - pSlab = Alloc( m_uiSlabSize, gv_lAllocRTag) + if( (*ppvAlloc = Alloc( uiMinSize, gv_lAllocRTag)) == NULL) + { + rc = RC_SET( NE_FLM_MEM); + goto Exit; + } #elif defined( FLM_SOLARIS) @@ -4867,7 +4871,7 @@ void FLMAPI f_freeAlignedBufferImp( #elif defined( FLM_RING_ZERO_NLM) - Free( *ppvAlloc) + Free( *ppvAlloc); *ppvAlloc = NULL; #elif defined( FLM_UNIX) diff --git a/ftk/src/ftkmisc.cpp b/ftk/src/ftkmisc.cpp index bf6ddbd..0d2bfc4 100644 --- a/ftk/src/ftkmisc.cpp +++ b/ftk/src/ftkmisc.cpp @@ -298,7 +298,7 @@ Desc: void FLMAPI f_sleep( FLMUINT uiMilliseconds) { - Sleep( (DWORD)uiMilliseconds); + SleepEx( (DWORD)uiMilliseconds, true); } #endif @@ -3023,7 +3023,7 @@ void f_freeFileAsyncClientList( void) pAsyncClient = F_FileHdl::m_pFirstAvailAsync; F_FileHdl::m_pFirstAvailAsync = F_FileHdl::m_pFirstAvailAsync->m_pNext; pAsyncClient->m_pNext = NULL; - delete pAsyncClient; + pAsyncClient->Release( FALSE); } if( F_FileHdl::m_hAsyncListMutex != F_MUTEX_NULL) diff --git a/ftk/src/ftknlm.cpp b/ftk/src/ftknlm.cpp index f7e9bf9..2a049a2 100644 --- a/ftk/src/ftknlm.cpp +++ b/ftk/src/ftknlm.cpp @@ -1048,7 +1048,7 @@ FSTATIC void DirectIONoWaitCallBack( } f_assert( pAsyncClient->getBytesToDo()); - pAsyncClient->signalComplete( rc, 0); + pAsyncClient->notifyComplete( rc, 0); } #endif @@ -1072,7 +1072,7 @@ FSTATIC void nssDioCallback( } f_assert( pAsyncClient->getBytesToDo()); - pAsyncClient->signalComplete( rc, 0); + pAsyncClient->notifyComplete( rc, 0); } #endif @@ -1631,7 +1631,7 @@ WARNING: Direct IO methods are calling this method. Make sure that all changes to this method work in direct IO mode. ****************************************************************************/ #if defined( FLM_RING_ZERO_NLM) -RCODE FLMAPI F_FileHdl::truncate( +RCODE FLMAPI F_FileHdl::truncateFile( FLMUINT64 ui64Size) { RCODE rc = NE_FLM_OK; @@ -3388,7 +3388,7 @@ RCODE F_FileHdl::lowLevelWrite( if( RC_BAD( rc = writeSectors( pvBuffer, pAsyncClient, lStartSector, lSectorCount))) { - pAsyncClient->notifyComplete( rc, 0, FALSE); + pAsyncClient->notifyComplete( rc, 0); goto Exit; } @@ -3466,6 +3466,49 @@ Exit: } #endif +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +RCODE F_FileHdl::extendFile( + FLMUINT64 ui64NewFileSize) +{ + RCODE rc = NE_FLM_OK; + FLMUINT64 ui64FileSize; + FLMUINT uiStartSector; + FLMUINT uiSectorCount; + + // Get the current file size + + if( RC_BAD( rc = size( &ui64FileSize))) + { + goto Exit; + } + + // File is already the requested size + + if( ui64FileSize >= ui64NewFileSize) + { + goto Exit; + } + + // Determine the number of sectors in the file + + uiStartSector = (FLMUINT)(ui64FileSize / FLM_NLM_SECTOR_SIZE); + uiSectorCount = (FLMUINT)(f_roundUp( ui64NewFileSize - ui64FileSize, + FLM_NLM_SECTOR_SIZE) / FLM_NLM_SECTOR_SIZE); + + if( RC_BAD( rc = expand( uiStartSector, uiSectorCount))) + { + goto Exit; + } + +Exit: + + return( rc); +} +#endif + /**************************************************************************** Desc: ****************************************************************************/ diff --git a/ftk/src/ftksem.cpp b/ftk/src/ftksem.cpp index 54875cc..b0d3fdb 100644 --- a/ftk/src/ftksem.cpp +++ b/ftk/src/ftksem.cpp @@ -48,6 +48,17 @@ typedef struct } sema_t; #endif +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_WIN) +typedef struct +{ + HANDLE hWinSem; + FLMATOMIC uiSignalCount; +} sema_t; +#endif + /**************************************************************************** Desc: ****************************************************************************/ @@ -496,9 +507,9 @@ FINLINE int _sema_timedwait( struct timeval now; struct timespec abstime; - // If timeout is F_SEM_WAITFOREVER, do sem_wait. + // If timeout is F_WAITFOREVER, do sem_wait. - if( msecs == F_SEM_WAITFOREVER) + if( msecs == F_WAITFOREVER) { iErr = _sema_wait( pSem); return( iErr); @@ -547,9 +558,9 @@ FINLINE int _sema_timedwait( { int iErr = 0; - // If timeout is F_SEM_WAITFOREVER, do sem_wait. + // If timeout is F_WAITFOREVER, do sem_wait. - if( msecs == F_SEM_WAITFOREVER) + if( msecs == F_WAITFOREVER) { iErr = _sema_wait( pSem); return( iErr); @@ -607,7 +618,7 @@ Desc: RCODE f_semCreate( F_SEM * phSem) { - RCODE rc = NE_FLM_OK; + RCODE rc = NE_FLM_OK; f_assert( phSem != NULL); @@ -664,13 +675,13 @@ RCODE f_semWait( f_assert( hSem != F_SEM_NULL); - // Catch the F_SEM_WAITFOREVER flag so we can directly call _sema_wait - // instead of passing F_SEM_WAITFOREVER through to _sema_timedwait. + // Catch the F_WAITFOREVER flag so we can directly call _sema_wait + // instead of passing F_WAITFOREVER through to _sema_timedwait. // Note that on AIX the datatype of the uiTimeout (in the timespec // struct) is surprisingly a signed int, which makes this catch // essential. - if( uiTimeout == F_SEM_WAITFOREVER) + if( uiTimeout == F_WAITFOREVER) { if( _sema_wait( (sema_t *)hSem)) { @@ -704,6 +715,17 @@ void FLMAPI f_semSignal( } #endif +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_UNIX) || defined( FLM_LIBC_NLM) +FLMUINT FLMAPI f_semGetSignalCount( + F_SEM hSem) +{ + return( (FLMUINT)((sema_t *)hSem)->count); +} +#endif + /************************************************************************* Desc: *************************************************************************/ @@ -745,7 +767,7 @@ RCODE FLMAPI f_semWait( { RCODE rc = NE_FLM_OK; - if( uiTimeout == F_SEM_WAITFOREVER) + if( uiTimeout == F_WAITFOREVER) { if( kSemaphoreWait( (SEMAPHORE)hSem) != 0) { @@ -775,6 +797,17 @@ void FLMAPI f_semSignal( } #endif +/**************************************************************************** +Desc: +****************************************************************************/ +#if defined( FLM_RING_ZERO_NLM) +FLMUINT FLMAPI f_semGetSignalCount( + F_SEM hSem) +{ + return( (FLMUINT)kSemaphoreExamineCount( (SEMAPHORE)hSem)); +} +#endif + /**************************************************************************** Desc: ****************************************************************************/ @@ -832,13 +865,39 @@ Desc: RCODE FLMAPI f_semCreate( F_SEM * phSem) { - if( (*phSem = CreateSemaphore( (LPSECURITY_ATTRIBUTES)NULL, - 0, 10000, NULL )) == NULL) + RCODE rc = NE_FLM_OK; + sema_t * pSem = NULL; + + f_assert( phSem != NULL); + f_assert( *phSem == F_SEM_NULL); + + if( RC_BAD( rc = f_calloc( sizeof( sema_t), &pSem))) { - return( RC_SET( NE_FLM_COULD_NOT_CREATE_SEMAPHORE)); + goto Exit; } - return NE_FLM_OK; + if( (pSem->hWinSem = CreateSemaphore( (LPSECURITY_ATTRIBUTES)NULL, + 0, 10000, NULL )) == NULL) + { + rc = RC_SET( NE_FLM_COULD_NOT_CREATE_SEMAPHORE); + } + + *phSem = pSem; + pSem = NULL; + +Exit: + + if( pSem) + { + if( pSem->hWinSem) + { + CloseHandle( pSem->hWinSem); + } + + f_free( &pSem); + } + + return( rc); } #endif @@ -849,11 +908,19 @@ Desc: void FLMAPI f_semDestroy( F_SEM * phSem) { - if (*phSem != F_SEM_NULL) + sema_t * pSem = (sema_t *)(*phSem); + + if( pSem) { - CloseHandle( *phSem); - *phSem = F_SEM_NULL; + if( pSem->hWinSem) + { + CloseHandle( pSem->hWinSem); + } + + f_free( &pSem); } + + *phSem = F_SEM_NULL; } #endif @@ -865,11 +932,27 @@ RCODE FLMAPI f_semWait( F_SEM hSem, FLMUINT uiTimeout) { - if( WaitForSingleObject( hSem, uiTimeout) == WAIT_OBJECT_0) + DWORD dwStatus; + + for( ;;) { - return( NE_FLM_OK); + dwStatus = WaitForSingleObjectEx( ((sema_t *)hSem)->hWinSem, + uiTimeout, true); + + if( dwStatus == WAIT_OBJECT_0) + { + f_atomicDec( &((sema_t *)hSem)->uiSignalCount); + return( NE_FLM_OK); + } + + if( dwStatus == WAIT_IO_COMPLETION) + { + continue; + } + + break; } - + return( RC_SET( NE_FLM_WAIT_TIMEOUT)); } #endif @@ -881,7 +964,19 @@ Desc: void FLMAPI f_semSignal( F_SEM hSem) { - (void)ReleaseSemaphore( hSem, 1, NULL); + f_atomicInc( &((sema_t *)hSem)->uiSignalCount); + (void)ReleaseSemaphore( ((sema_t *)hSem)->hWinSem, 1, NULL); +} +#endif + +/**************************************************************************** +Desc: +****************************************************************************/ +#ifdef FLM_WIN +FLMUINT FLMAPI f_semGetSignalCount( + F_SEM hSem) +{ + return( ((sema_t *)hSem)->uiSignalCount); } #endif @@ -1170,6 +1265,8 @@ RCODE FLMAPI f_notifyWait( F_NOTIFY_LIST_ITEM * pNotify = &stackNotify; f_assertMutexLocked( hMutex); + f_assert( pNotify != *ppNotifyList); + f_memset( &stackNotify, 0, sizeof( F_NOTIFY_LIST_ITEM)); pNotify->uiThreadId = f_threadId(); @@ -1197,7 +1294,7 @@ RCODE FLMAPI f_notifyWait( f_mutexUnlock( hMutex); - if( RC_BAD( tmpRc = f_semWait( pNotify->hSem, F_SEM_WAITFOREVER))) + if( RC_BAD( tmpRc = f_semWait( pNotify->hSem, F_WAITFOREVER))) { rc = tmpRc; } diff --git a/ftk/src/ftkstrm.cpp b/ftk/src/ftkstrm.cpp index c1d6250..9db61d2 100644 --- a/ftk/src/ftkstrm.cpp +++ b/ftk/src/ftkstrm.cpp @@ -104,6 +104,10 @@ class F_TCPStream : public IF_IStream, public IF_OStream { public: + #if defined( FLM_WIN) && _MSC_VER < 1300 + using IF_IStream::operator delete; + #endif + F_TCPStream( void); virtual ~F_TCPStream( void); diff --git a/ftk/src/ftksys.h b/ftk/src/ftksys.h index b4a3316..cc2413a 100644 --- a/ftk/src/ftksys.h +++ b/ftk/src/ftksys.h @@ -344,8 +344,19 @@ m_pAsyncClient->Release(); } } + + FLMINT FLMAPI AddRef( void) + { + return( f_atomicInc( &m_refCnt)); + } + + FLMINT Release( + FLMBOOL bMutexAlreadyLocked); - FLMINT FLMAPI Release( void); + FLMINT FLMAPI Release( void) + { + return( Release( FALSE)); + } RCODE setupBuffer( FLMUINT uiBufferSize, @@ -450,14 +461,9 @@ { RCODE rc = NE_FLM_OK; - f_assert( m_bPending); - if( m_pAsyncClient) { - IF_AsyncClient * pAsyncClient = m_pAsyncClient; - - m_pAsyncClient = NULL; - rc = pAsyncClient->waitToComplete( TRUE); + rc = m_pAsyncClient->waitToComplete(); } return( rc); @@ -521,20 +527,25 @@ m_uiBytesToDo = 0; m_uiBytesDone = 0; m_pNext = NULL; + #ifndef FLM_UNIX + m_hSem = F_SEM_NULL; + #endif #ifdef FLM_WIN m_Overlapped.hEvent = 0; #endif - #ifdef FLM_RING_ZERO_NLM - m_hSem = NULL; - #endif } ~F_FileAsyncClient(); - FLMINT FLMAPI Release(); + FLMINT FLMAPI AddRef( void) + { + return( f_atomicInc( &m_refCnt)); + } - RCODE FLMAPI waitToComplete( - FLMBOOL bRelease); + FLMINT FLMAPI Release( + FLMBOOL bOkToReuse = TRUE); + + RCODE FLMAPI waitToComplete( void); RCODE FLMAPI getCompletionCode( void); @@ -542,25 +553,18 @@ F_FileAsyncClient * m_pNext; - void signalComplete( - RCODE rc, - FLMUINT uiBytesDone); - FLMUINT getBytesToDo( void) { return( m_uiBytesToDo); } - private: - + void FLMAPI notifyComplete( + RCODE completionRc, + FLMUINT uiBytesDone); + 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; @@ -568,17 +572,15 @@ FLMUINT m_uiBytesDone; FLMUINT m_uiStartTime; FLMUINT m_uiEndTime; + #ifndef FLM_UNIX + F_SEM m_hSem; + #endif #if defined( FLM_WIN) OVERLAPPED m_Overlapped; #endif #if defined( FLM_UNIX) && defined( FLM_HAS_ASYNC_IO) struct aiocb m_aio; #endif - #ifdef FLM_RING_ZERO_NLM - SEMAPHORE m_hSem; - #endif - - friend class F_FileHdl; }; /*************************************************************************** @@ -592,6 +594,23 @@ virtual ~F_FileHdl(); + FLMINT FLMAPI AddRef( void) + { + return( f_atomicInc( &m_refCnt)); + } + + FLMINT FLMAPI Release( void) + { + FLMINT iRefCnt = f_atomicDec( &m_refCnt); + + if( !iRefCnt) + { + delete this; + } + + return( iRefCnt); + } + RCODE FLMAPI flush( void); RCODE FLMAPI read( @@ -1138,6 +1157,8 @@ FLMBOOL bReadOnly); FLMBOOL FLMAPI canDoAsync( void); + + FLMUINT FLMAPI getPendingAsyncCount( void); RCODE FLMAPI getFileId( const char * pszFileName, diff --git a/ftk/src/ftkunix.cpp b/ftk/src/ftkunix.cpp index a8944fb..f914301 100644 --- a/ftk/src/ftkunix.cpp +++ b/ftk/src/ftkunix.cpp @@ -614,13 +614,13 @@ RCODE F_FileHdl::lowLevelRead( rc = f_mapPlatformError( errno, NE_FLM_READING_FILE); } - pAsyncClient->notifyComplete( rc, uiBytesRead, FALSE); + pAsyncClient->notifyComplete( rc, uiBytesRead); goto Exit; } if( bWaitForRead) { - if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + if( RC_BAD( rc = pAsyncClient->waitToComplete())) { if( rc != NE_FLM_IO_END_OF_FILE) { @@ -839,13 +839,13 @@ RCODE F_FileHdl::lowLevelWrite( rc = f_mapPlatformError( errno, NE_FLM_WRITING_FILE); } - pAsyncClient->notifyComplete( rc, uiBytesWritten, FALSE); + pAsyncClient->notifyComplete( rc, uiBytesWritten); goto Exit; } if( bWaitForWrite) { - if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + if( RC_BAD( rc = pAsyncClient->waitToComplete())) { if( rc != NE_FLM_IO_DISK_FULL) { diff --git a/ftk/src/ftkwin.cpp b/ftk/src/ftkwin.cpp index 15749ea..3126b2d 100644 --- a/ftk/src/ftkwin.cpp +++ b/ftk/src/ftkwin.cpp @@ -29,6 +29,22 @@ extern FLMATOMIC gv_openFiles; +/**************************************************************************** +Desc: +****************************************************************************/ +FSTATIC VOID CALLBACK f_fileIOCompletionRoutine( + DWORD dwErrorCode, + DWORD dwNumberOfBytesTransfered, + LPOVERLAPPED lpOverlapped) +{ + F_FileAsyncClient * pAsyncClient; + + pAsyncClient = (F_FileAsyncClient *)(lpOverlapped->hEvent); + pAsyncClient->notifyComplete( + f_mapPlatformError( dwErrorCode, NE_FLM_ASYNC_FAILED), + (FLMUINT)dwNumberOfBytesTransfered); +} + /**************************************************************************** Desc: ****************************************************************************/ @@ -422,24 +438,37 @@ RCODE F_FileHdl::lowLevelRead( pOverlapped = &pAsyncClient->m_Overlapped; pOverlapped->Offset = (DWORD)(ui64ReadOffset & 0xFFFFFFFF); pOverlapped->OffsetHigh = (DWORD)(ui64ReadOffset >> 32); + pOverlapped->hEvent = (HANDLE)pAsyncClient; pIOBuffer = NULL; - if( !ReadFile( m_hFile, pvBuffer, uiBytesToRead, - &uiBytesRead, pOverlapped)) +RetryRead: + + if( !ReadFileEx( m_hFile, pvBuffer, uiBytesToRead, + pOverlapped, f_fileIOCompletionRoutine)) { DWORD udErrCode = GetLastError(); - if( udErrCode != ERROR_IO_PENDING) + if( rc == ERROR_NOT_ENOUGH_MEMORY || + rc == ERROR_INVALID_USER_BUFFER) + { + // The ReadFileEx function may fail, returning the messages + // ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY if there + // are too many outstanding asynchronous I/O requests + + f_sleep( 10); + goto RetryRead; + } + else if( udErrCode != ERROR_IO_PENDING) { rc = f_mapPlatformError( udErrCode, NE_FLM_READING_FILE); - pAsyncClient->notifyComplete( rc, uiBytesRead, FALSE); + pAsyncClient->notifyComplete( rc, 0); goto Exit; } } if( bWaitForRead) { - if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + if( RC_BAD( rc = pAsyncClient->waitToComplete())) { if( rc != NE_FLM_IO_END_OF_FILE) { @@ -611,24 +640,37 @@ RCODE F_FileHdl::lowLevelWrite( pOverlapped = &pAsyncClient->m_Overlapped; pOverlapped->Offset = (DWORD)(ui64WriteOffset & 0xFFFFFFFF); pOverlapped->OffsetHigh = (DWORD)(ui64WriteOffset >> 32); + pOverlapped->hEvent = (HANDLE)pAsyncClient; pIOBuffer = NULL; - if( !WriteFile( m_hFile, pvBuffer, - uiBytesToWrite, &uiBytesWritten, pOverlapped)) +RetryWrite: + + if( !WriteFileEx( m_hFile, pvBuffer, + uiBytesToWrite, pOverlapped, f_fileIOCompletionRoutine)) { DWORD udErrCode = GetLastError(); - - if( udErrCode != ERROR_IO_PENDING) + + if( rc == ERROR_NOT_ENOUGH_MEMORY || + rc == ERROR_INVALID_USER_BUFFER) + { + // The WriteFileEx function may fail, returning the messages + // ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY if there + // are too many outstanding asynchronous I/O requests + + f_sleep( 10); + goto RetryWrite; + } + else if( udErrCode != ERROR_IO_PENDING) { rc = f_mapPlatformError( udErrCode, NE_FLM_WRITING_FILE); - pAsyncClient->notifyComplete( rc, uiBytesWritten, FALSE); + pAsyncClient->notifyComplete( rc, 0); goto Exit; } } if( bWaitForWrite) { - if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + if( RC_BAD( rc = pAsyncClient->waitToComplete())) { if( rc != NE_FLM_IO_DISK_FULL) { @@ -870,21 +912,34 @@ RCODE F_FileHdl::extendFile( pOverlapped = &pAsyncClient->m_Overlapped; pOverlapped->Offset = (DWORD)(ui64FileSize & 0xFFFFFFFF); pOverlapped->OffsetHigh = (DWORD)(ui64FileSize >> 32); + pOverlapped->hEvent = (HANDLE)pAsyncClient; - if( !WriteFile( m_hFile, pucBuffer, - uiBytesToWrite, &uiBytesWritten, pOverlapped)) +RetryWrite: + + if( !WriteFileEx( m_hFile, pucBuffer, + uiBytesToWrite, pOverlapped, f_fileIOCompletionRoutine)) { DWORD udErrCode = GetLastError(); - if( udErrCode != ERROR_IO_PENDING) + if( rc == ERROR_NOT_ENOUGH_MEMORY || + rc == ERROR_INVALID_USER_BUFFER) + { + // The WriteFileEx function may fail, returning the messages + // ERROR_INVALID_USER_BUFFER or ERROR_NOT_ENOUGH_MEMORY if there + // are too many outstanding asynchronous I/O requests + + f_sleep( 10); + goto RetryWrite; + } + else if( udErrCode != ERROR_IO_PENDING) { rc = f_mapPlatformError( udErrCode, NE_FLM_WRITING_FILE); - pAsyncClient->notifyComplete( rc, uiBytesWritten, FALSE); + pAsyncClient->notifyComplete( rc, 0); goto Exit; } } - if( RC_BAD( rc = pAsyncClient->waitToComplete( FALSE))) + if( RC_BAD( rc = pAsyncClient->waitToComplete())) { goto Exit; } @@ -982,7 +1037,7 @@ Desc: ****************************************************************************/ void FLMAPI f_yieldCPU( void) { - Sleep( 0); + SleepEx( 0, true); } /********************************************************************** diff --git a/xflaim/src/flbackup.cpp b/xflaim/src/flbackup.cpp index d95512f..5fb36b4 100644 --- a/xflaim/src/flbackup.cpp +++ b/xflaim/src/flbackup.cpp @@ -2335,7 +2335,7 @@ RCODE F_BackerStream::flush( void) // Wait for the background thread to become idle. When it // does, we know that all writes have completed. - if( RC_BAD( rc = f_semWait( m_hIdleSem, F_SEM_WAITFOREVER))) + if( RC_BAD( rc = f_semWait( m_hIdleSem, F_WAITFOREVER))) { goto Exit; } @@ -2389,7 +2389,7 @@ RCODE F_BackerStream::signalThread( void) // Wait for the thread to become idle - if( RC_BAD( rc = f_semWait( m_hIdleSem, F_SEM_WAITFOREVER))) + if( RC_BAD( rc = f_semWait( m_hIdleSem, F_WAITFOREVER))) { goto Exit; } @@ -2454,7 +2454,7 @@ RCODE FLMAPI F_BackerStream::readThread( f_semSignal( pBackerStream->m_hIdleSem); if( RC_BAD( rc = f_semWait( pBackerStream->m_hDataSem, - F_SEM_WAITFOREVER))) + F_WAITFOREVER))) { goto Exit; } @@ -2493,7 +2493,7 @@ RCODE FLMAPI F_BackerStream::writeThread( f_semSignal( pBackerStream->m_hIdleSem); if( RC_BAD( rc = f_semWait( pBackerStream->m_hDataSem, - F_SEM_WAITFOREVER))) + F_WAITFOREVER))) { goto Exit; } diff --git a/xflaim/src/fqsort.cpp b/xflaim/src/fqsort.cpp index 7c52dd4..a970c51 100644 --- a/xflaim/src/fqsort.cpp +++ b/xflaim/src/fqsort.cpp @@ -1634,7 +1634,7 @@ RCODE F_Query::waitResultSetBuild( m_pSortResultSet->unlockMutex(); bMutexLocked = FALSE; - if (RC_BAD( TempRc = f_semWait( waiter.hESem, F_SEM_WAITFOREVER))) + if (RC_BAD( TempRc = f_semWait( waiter.hESem, F_WAITFOREVER))) { flmAssert( 0); rc = TempRc; diff --git a/xflaim/src/fslfileu.cpp b/xflaim/src/fslfileu.cpp index 566a959..15ae240 100644 --- a/xflaim/src/fslfileu.cpp +++ b/xflaim/src/fslfileu.cpp @@ -2780,7 +2780,7 @@ Retry: } pThread->setThreadStatus( FLM_THREAD_STATUS_SLEEPING); - f_semWait( pDatabase->m_hMaintSem, F_SEM_WAITFOREVER); + f_semWait( pDatabase->m_hMaintSem, F_WAITFOREVER); if( pThread->getShutdownFlag()) { diff --git a/xflaim/src/rfl.cpp b/xflaim/src/rfl.cpp index a4d091a..1508bee 100644 --- a/xflaim/src/rfl.cpp +++ b/xflaim/src/rfl.cpp @@ -733,7 +733,7 @@ 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_WAITFOREVER))) { RC_UNEXPECTED_ASSERT( TempRc); rc = TempRc;