1
0
Fork 0

issue #662: ArangoDB on Windows hanging

This commit is contained in:
Jan Steemann 2013-11-19 16:27:26 +01:00
parent 87aed55acf
commit af6da9a652
7 changed files with 87 additions and 370 deletions

View File

@ -67,6 +67,28 @@ v1.5.x (XXXX-XX-XX)
v1.4.2 (XXXX-XX-XX) v1.4.2 (XXXX-XX-XX)
------------------- -------------------
* ported Windows version to use native Windows API SRWLocks (slim read-write locks)
and condition variables instead of homemade versions
MSDN states the following about the compatibility of SRWLocks and Condition Variables:
Minimum supported client:
Windows Server 2008 [desktop apps | Windows Store apps]
Minimum supported server:
Windows Vista [desktop apps | Windows Store apps]
* fixed issue #662: ArangoDB on Windows hanging
This fixes a deadlock issue that occurred on Windows when documents were written to
a collection at the same time when some other thread tried to drop the collection.
* fixed file-based logging in Windows
the logger complained on startup if the specified log file already existed
* fixed startup of server in daemon mode (`--daemon` startup option)
* fixed a segfault in the AQL optimiser * fixed a segfault in the AQL optimiser
* issue #671: Method graph.measurement does not exist * issue #671: Method graph.measurement does not exist

View File

@ -213,8 +213,12 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase,
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name); // only if we find the collection by its id, we can delete it by name
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &collection->_cid); if (TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &collection->_cid) != NULL) {
// this is because someone else might have created a new collection with the same name,
// but with a different id
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name);
}
TRI_ASSERT_MAINTAINER(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed); TRI_ASSERT_MAINTAINER(vocbase->_collectionsByName._nrUsed == vocbase->_collectionsById._nrUsed);
@ -237,9 +241,9 @@ static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
TRI_document_collection_t* document; TRI_document_collection_t* document;
int res; int res;
collection = data; collection = (TRI_vocbase_col_t*) data;
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection); TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
if (collection->_status != TRI_VOC_COL_STATUS_UNLOADING) { if (collection->_status != TRI_VOC_COL_STATUS_UNLOADING) {
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
@ -328,7 +332,7 @@ static bool DropCollectionCallback (TRI_collection_t* col,
} }
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection); TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
if (collection->_status != TRI_VOC_COL_STATUS_DELETED) { if (collection->_status != TRI_VOC_COL_STATUS_DELETED) {
LOG_ERROR("someone resurrected the collection '%s'", collection->_name); LOG_ERROR("someone resurrected the collection '%s'", collection->_name);
@ -559,7 +563,7 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
// check name // check name
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found); res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found);
if (found != NULL) { if (found != NULL) {
LOG_ERROR("duplicate entry for collection name '%s'", name); LOG_ERROR("duplicate entry for collection name '%s'", name);
LOG_ERROR("collection id %llu has same name as already added collection %llu", LOG_ERROR("collection id %llu has same name as already added collection %llu",
@ -582,8 +586,9 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
} }
// check collection identifier // check collection identifier
assert(collection->_cid == cid);
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found); res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found);
if (found != NULL) { if (found != NULL) {
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name); TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
@ -601,7 +606,6 @@ static TRI_vocbase_col_t* AddCollection (TRI_vocbase_t* vocbase,
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &cid); TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &cid);
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name); TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, name);
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection); TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
TRI_set_errno(res); TRI_set_errno(res);
return NULL; return NULL;
@ -720,8 +724,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
void const* found; void const* found;
int res; int res;
// lock collection because we are going to change the name TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
// this must be done after the collection lock // this must be done after the collection lock
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase); TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
@ -815,7 +818,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, oldName); TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, oldName);
TRI_CopyString(collection->_name, newName, sizeof(collection->_name) - 1); TRI_CopyString(collection->_name, newName, sizeof(collection->_name) - 1);
// this shouldn't fail, as we removed an element above so adding one should be ok // this shouldn't fail, as we removed an element above so adding one should be ok
found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, newName, CONST_CAST(collection), false); found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, newName, CONST_CAST(collection), false);
assert(found == NULL); assert(found == NULL);
@ -1090,7 +1093,7 @@ static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
// write lock // write lock
// ............................................................................. // .............................................................................
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection); TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
// someone else loaded the collection, release the WRITE lock and try again // someone else loaded the collection, release the WRITE lock and try again
if (collection->_status == TRI_VOC_COL_STATUS_LOADED) { if (collection->_status == TRI_VOC_COL_STATUS_LOADED) {
@ -1980,7 +1983,7 @@ int TRI_UnloadCollectionVocBase (TRI_vocbase_t* vocbase,
return TRI_set_errno(TRI_ERROR_FORBIDDEN); return TRI_set_errno(TRI_ERROR_FORBIDDEN);
} }
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection); TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
// cannot unload a corrupted collection // cannot unload a corrupted collection
if (collection->_status == TRI_VOC_COL_STATUS_CORRUPTED) { if (collection->_status == TRI_VOC_COL_STATUS_CORRUPTED) {
@ -2065,14 +2068,14 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock); TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
// mark collection as deleted TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
// ............................................................................. // .............................................................................
// collection already deleted // collection already deleted
// ............................................................................. // .............................................................................
if (collection->_status == TRI_VOC_COL_STATUS_DELETED) { if (collection->_status == TRI_VOC_COL_STATUS_DELETED) {
// mark collection as deleted
UnregisterCollection(vocbase, collection, generatingServer); UnregisterCollection(vocbase, collection, generatingServer);
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
@ -2101,7 +2104,7 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
// remove dangling .json.tmp file if it exists // remove dangling .json.tmp file if it exists
tmpFile = TRI_Concatenate4String(collection->_path, TRI_DIR_SEPARATOR_STR, TRI_VOC_PARAMETER_FILE, ".tmp"); tmpFile = TRI_Concatenate4String(collection->_path, TRI_DIR_SEPARATOR_STR, TRI_VOC_PARAMETER_FILE, ".tmp");
if (tmpFile != NULL) { if (tmpFile != NULL) {
if (TRI_ExistsFile(tmpFile)) { if (TRI_ExistsFile(tmpFile)) {
TRI_UnlinkFile(tmpFile); TRI_UnlinkFile(tmpFile);
@ -2125,7 +2128,6 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
} }
collection->_status = TRI_VOC_COL_STATUS_DELETED; collection->_status = TRI_VOC_COL_STATUS_DELETED;
UnregisterCollection(vocbase, collection, generatingServer); UnregisterCollection(vocbase, collection, generatingServer);
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
@ -2180,6 +2182,7 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
} }
collection->_status = TRI_VOC_COL_STATUS_DELETED; collection->_status = TRI_VOC_COL_STATUS_DELETED;
UnregisterCollection(vocbase, collection, generatingServer); UnregisterCollection(vocbase, collection, generatingServer);
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection); TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);

View File

@ -114,6 +114,13 @@ struct TRI_vocbase_defaults_s;
#define TRI_READ_UNLOCK_STATUS_VOCBASE_COL(a) \ #define TRI_READ_UNLOCK_STATUS_VOCBASE_COL(a) \
TRI_ReadUnlockReadWriteLock(&(a)->_lock) TRI_ReadUnlockReadWriteLock(&(a)->_lock)
////////////////////////////////////////////////////////////////////////////////
/// @brief tries to write lock the vocbase collection status
////////////////////////////////////////////////////////////////////////////////
#define TRI_TRY_WRITE_LOCK_STATUS_VOCBASE_COL(a) \
TRI_TryWriteLockReadWriteLock(&(a)->_lock)
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief write locks the vocbase collection status /// @brief write locks the vocbase collection status
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -128,6 +135,15 @@ struct TRI_vocbase_defaults_s;
#define TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(a) \ #define TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(a) \
TRI_WriteUnlockReadWriteLock(&(a)->_lock) TRI_WriteUnlockReadWriteLock(&(a)->_lock)
////////////////////////////////////////////////////////////////////////////////
/// @brief write locks the vocbase collection status using spinning
////////////////////////////////////////////////////////////////////////////////
#define TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(a) \
while (! TRI_TRY_WRITE_LOCK_STATUS_VOCBASE_COL(a)) { \
usleep(1000); \
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief locks the synchroniser waiters /// @brief locks the synchroniser waiters
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -208,43 +208,7 @@ void TRI_UnlockSpin (TRI_spin_t* spin) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock) {
InitializeSRWLock(&lock->_lock);
// ...........................................................................
// set the number of readers reading on the read_write lock to 0
// ...........................................................................
lock->_readers = 0;
// ...........................................................................
// Signaled: writer has no access
// Non-Signaled: writer has access, block readers
// Creates an event which allows a thread to wait on it (perhaps should use
// a mutux rather than an event here). The writer event is set to signalled
// when CreateEvent is called with these parameters.
// ...........................................................................
lock->_writerEvent = CreateEvent(0, TRUE, TRUE, 0);
// ...........................................................................
// Signaled: no readers
// Non-Signaled: some readers have access, block writer
// Same as the writer event above except this is the reader event
// ...........................................................................
lock->_readersEvent = CreateEvent(0, TRUE, TRUE, 0);
// ...........................................................................
// Creates critical sections for writer and readers.
// Waits for ownership of the specified critical section object.
// The function returns when the calling thread is granted ownership.
// ...........................................................................
InitializeCriticalSection(&lock->_lockWriter);
InitializeCriticalSection(&lock->_lockReaders);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -252,11 +216,6 @@ void TRI_InitReadWriteLock (TRI_read_write_lock_t* lock) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_DestroyReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_DestroyReadWriteLock (TRI_read_write_lock_t* lock) {
DeleteCriticalSection(&lock->_lockWriter);
DeleteCriticalSection(&lock->_lockReaders);
CloseHandle(lock->_writerEvent);
CloseHandle(lock->_readersEvent);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -272,56 +231,6 @@ void TRI_DestroyReadWriteLock (TRI_read_write_lock_t* lock) {
/// @{ /// @{
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/// @brief increments readers
////////////////////////////////////////////////////////////////////////////////
static void IncrementReaders (TRI_read_write_lock_t* lock) {
// ...........................................................................
// increment the number of readers we have on the read_write lock
// ...........................................................................
lock->_readers++;
// ...........................................................................
// Since the number of readers must be positive, set the readers event to
// non-signalled so that any write event will have to wait.
// ...........................................................................
ResetEvent(lock->_readersEvent);
}
////////////////////////////////////////////////////////////////////////////////
/// @brief decrements readers
////////////////////////////////////////////////////////////////////////////////
static void DecrementReaders (TRI_read_write_lock_t* lock) {
// ...........................................................................
// reduce the number of readers using the read_write lock by 1
// ...........................................................................
lock->_readers--;
// ...........................................................................
// When the number of readers is 0, set the event to signalled which allows
// a writer to use the read_write lock.
// ...........................................................................
if (lock->_readers == 0) {
SetEvent(lock->_readersEvent);
}
else if (lock->_readers < 0) {
LOG_FATAL_AND_EXIT("reader count is negative");
}
}
////////////////////////////////////////////////////////////////////////////////
/// @}
////////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// --SECTION-- public functions // --SECTION-- public functions
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
@ -336,20 +245,7 @@ static void DecrementReaders (TRI_read_write_lock_t* lock) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) { bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
WaitForSingleObject(lock->_writerEvent, 10); // 10 millis timeout return (TryAcquireSRWLockShared(&lock->_lock) != 0);
EnterCriticalSection(&lock->_lockReaders);
IncrementReaders(lock);
LeaveCriticalSection(&lock->_lockReaders);
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
EnterCriticalSection(&lock->_lockReaders);
DecrementReaders(lock);
LeaveCriticalSection(&lock->_lockReaders);
return false;
}
return true;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -357,43 +253,7 @@ bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
AcquireSRWLockShared(&lock->_lock);
while (true) {
// ........................................................................
// Waits for a writer to finish if there is one. This function only
// returns when the writer event is in a signalled state
// ........................................................................
WaitForSingleObject(lock->_writerEvent, INFINITE);
// .........................................................................
// This thread will wait here until this resource becomes excusively available
// .........................................................................
EnterCriticalSection(&lock->_lockReaders);
IncrementReaders(lock);
// .........................................................................
// allows some other thread to use this resource
// .........................................................................
LeaveCriticalSection(&lock->_lockReaders);
// it could have happened that the writer event is no longer in a signalled
// state. Between leaving the crtical section and here a writer sneaked in.
//
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
EnterCriticalSection(&lock->_lockReaders);
DecrementReaders(lock);
LeaveCriticalSection(&lock->_lockReaders);
}
else {
break;
}
}
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -401,98 +261,15 @@ void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_ReadUnlockReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_ReadUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
EnterCriticalSection(&lock->_lockReaders); ReleaseSRWLockShared(&lock->_lock);
/* this is wrong since it is possible for the write locker to block this event
// a write lock eists
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
LOG_FATAL_AND_EXIT("write lock, but trying to unlock read");
}
// at least one reader exists
else if (0 < lock->_readers) {
DecrementReaders(lock);
}
// ups, no writer and no reader
else {
LeaveCriticalSection(&lock->_lockReaders);
LOG_FATAL_AND_EXIT("no reader and no writer, but trying to unlock");
}
*/
if (0 < lock->_readers) {
DecrementReaders(lock);
}
// oops no reader
else {
LeaveCriticalSection(&lock->_lockReaders);
LOG_FATAL_AND_EXIT("no reader, but trying to unlock read lock");
}
LeaveCriticalSection(&lock->_lockReaders);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief tries to write lock a read-write lock /// @brief tries to write lock a read-write lock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) { bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
return (TryAcquireSRWLockExclusive(&lock->_lock) != 0);
BOOL result;
// ...........................................................................
// Here we use TryEnterCriticalSection instead of EnterCriticalSection
// There could already be a write lock - which will actuall block from this
// point on.
// ...........................................................................
result = TryEnterCriticalSection(&lock->_lockWriter);
if (result == 0) {
// appears some other writer is writing
return false;
}
// ...........................................................................
// Wait until the lock->_writerEvent is in a 'signalled' state
// This might fail because a reader is just about to read
// ...........................................................................
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
LeaveCriticalSection(&lock->_lockWriter);
return false;
}
// ...........................................................................
// Set _writeEvent as nonsignalled -- this will block other read/write
// lockers
// ...........................................................................
ResetEvent(lock->_writerEvent);
// ...........................................................................
// If there are ANY read locks outstanding, leave
// ...........................................................................
if (WaitForSingleObject(lock->_readersEvent, 0) != WAIT_OBJECT_0) {
LeaveCriticalSection(&lock->_lockWriter);
SetEvent(lock->_writerEvent);
return false;
}
// ...........................................................................
// Allow other threads to access this function
// ...........................................................................
LeaveCriticalSection(&lock->_lockWriter);
return true;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -500,99 +277,15 @@ bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_WriteLockReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_WriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
AcquireSRWLockExclusive(&lock->_lock);
// ...........................................................................
// Lock so no other thread can access this
// EnterCriticalSection(&lock->_lockWriter) will block this thread until
// it has been released by the other thread.
// ...........................................................................
EnterCriticalSection(&lock->_lockWriter);
// ...........................................................................
// Wait until the lock->_writerEvent is in a 'signalled' state
// ...........................................................................
WaitForSingleObject(lock->_writerEvent, INFINITE);
// ...........................................................................
// Set _writeEvent as nonsignalled -- this will block other read/write
// lockers
// ...........................................................................
ResetEvent(lock->_writerEvent);
// ...........................................................................
// If there are ANY read locks outstanding, then wait until these are cleared
// ...........................................................................
WaitForSingleObject(lock->_readersEvent, INFINITE);
// ...........................................................................
// Allow other threads to access this function
// ...........................................................................
LeaveCriticalSection(&lock->_lockWriter);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @brief write unlocks read-write lock /// @brief write unlocks read-write lock
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) { void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
ReleaseSRWLockExclusive(&lock->_lock);
// ...........................................................................
// Write lock this _lockReader so no other threads can access this
// This will block this thread until it is released by the other thread
// We do not need to lock the _lockWriter SINCE the TRI_WriteLockReadWriteLock
// function above will lock (due to the ResetEvent(lock->_writerEvent); )
// ...........................................................................
EnterCriticalSection(&lock->_lockReaders);
// ...........................................................................
// In the function TRI_WriteLockReadWriteLock we set the _writerEvent to
// 'nonsignalled'. So if a write lock exists clear it by setting it to
// 'signalled'
// ...........................................................................
if (WaitForSingleObject(lock->_writerEvent, 0) != WAIT_OBJECT_0) {
SetEvent(lock->_writerEvent);
}
// ...........................................................................
// Oops at least one reader exists - something terrible happened.
// ...........................................................................
else if (0 < lock->_readers) {
LeaveCriticalSection(&lock->_lockReaders);
LOG_FATAL_AND_EXIT("read lock, but trying to unlock write");
}
// ...........................................................................
// Oops we are trying to unlock a write lock, but there isn't one! Something
// terrible happend.
// ...........................................................................
else {
LeaveCriticalSection(&lock->_lockReaders);
LOG_FATAL_AND_EXIT("no reader and no writer, but trying to unlock");
}
// ...........................................................................
// Allow read locks to be applied now.
// ...........................................................................
LeaveCriticalSection(&lock->_lockReaders);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -715,7 +408,6 @@ void TRI_UnlockCondition (TRI_condition_t* cond) {
LeaveCriticalSection(&cond->_lockWaiters); LeaveCriticalSection(&cond->_lockWaiters);
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// COMPARE & SWAP operations below for windows // COMPARE & SWAP operations below for windows
// Note that for the MAC OS we use the 'barrier' functions which ensure that // Note that for the MAC OS we use the 'barrier' functions which ensure that

View File

@ -65,13 +65,7 @@ TRI_mutex_t;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_read_write_lock_s { typedef struct TRI_read_write_lock_s {
HANDLE _writerEvent; SRWLOCK _lock;
HANDLE _readersEvent;
int _readers;
CRITICAL_SECTION _lockWriter;
CRITICAL_SECTION _lockReaders;
} }
TRI_read_write_lock_t; TRI_read_write_lock_t;

View File

@ -57,16 +57,15 @@ _invalid_parameter_handler newInvalidHandleHandler;
/// @{ /// @{
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int ftruncate(int fd, long newSize) { int ftruncate (int fd, long newSize) {
int result = _chsize(fd, newSize); int result = _chsize(fd, newSize);
return result; return result;
} }
int getpagesize (void) {
int getpagesize(void) {
static int pageSize = 0; // only define it once static int pageSize = 0; // only define it once
if (!pageSize) { if (! pageSize) {
// first time, so call the system info function // first time, so call the system info function
SYSTEM_INFO systemInfo; SYSTEM_INFO systemInfo;
GetSystemInfo (&systemInfo); GetSystemInfo (&systemInfo);
@ -76,22 +75,20 @@ int getpagesize(void) {
return pageSize; return pageSize;
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Calls the windows Sleep function which always sleeps for milliseconds // Calls the windows Sleep function which always sleeps for milliseconds
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_sleep(unsigned long waitTime) { void TRI_sleep (unsigned long waitTime) {
Sleep(waitTime * 1000); Sleep(waitTime * 1000);
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Calls a timer which waits for a signal after the elapsed time. // Calls a timer which waits for a signal after the elapsed time.
// The timer is acurate to 100nanoseconds // The timer is accurate to 100nanoseconds
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void TRI_usleep(unsigned long waitTime) { void TRI_usleep (unsigned long waitTime) {
int result; int result;
HANDLE hTimer = NULL; // stores the handle of the timer object HANDLE hTimer = NULL; // stores the handle of the timer object
LARGE_INTEGER wTime; // essentially a 64bit number LARGE_INTEGER wTime; // essentially a 64bit number
@ -109,7 +106,7 @@ void TRI_usleep(unsigned long waitTime) {
abort(); abort();
} }
// Set timer to wait for indicated micro seconds. // Set timer to wait for indicated micro seconds.
if (!SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) { if (! SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) {
// not much we can do at this low level // not much we can do at this low level
CloseHandle(hTimer); CloseHandle(hTimer);
return; return;
@ -135,14 +132,13 @@ void TRI_usleep(unsigned long waitTime) {
// for now is to ignore error and hope it goes away! // for now is to ignore error and hope it goes away!
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
static void InvalidParameterHandler(const wchar_t* expression, // expression sent to function - NULL static void InvalidParameterHandler (const wchar_t* expression, // expression sent to function - NULL
const wchar_t* function, // name of function - NULL const wchar_t* function, // name of function - NULL
const wchar_t* file, // file where code resides - NULL const wchar_t* file, // file where code resides - NULL
unsigned int line, // line within file - NULL unsigned int line, // line within file - NULL
uintptr_t pReserved) { // in case microsoft forget something uintptr_t pReserved) { // in case microsoft forget something
LOG_ERROR("Invalid handle parameter passed"); LOG_ERROR("Invalid handle parameter passed");
/*
/* start oreste -debug */
if (expression != 0) { if (expression != 0) {
wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = %s\n",expression); wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = %s\n",expression);
} }
@ -161,14 +157,12 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
else { else {
wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n"); wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n");
} }
printf("oreste:win-utils.c:InvalidParameterHandler:LINE = %ud\n",line); */
/* end oreste -debug */
//abort(); //abort();
// TODO: use the wcstombs_s function to convert wchar to char - since all the above // TODO: use the wcstombs_s function to convert wchar to char - since all the above
// wchar never will contain 2 byte chars // wchar never will contain 2 byte chars
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Called from the 'main' and performs any initialisation requirements which // Called from the 'main' and performs any initialisation requirements which
// are specific to windows. // are specific to windows.
@ -178,8 +172,8 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
// calling function should decide what to do. // calling function should decide what to do.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
int finaliseWindows (const TRI_win_finalise_e finaliseWhat,
int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) { const char* data) {
int result = 0; int result = 0;
// ............................................................................ // ............................................................................
@ -209,10 +203,8 @@ int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) {
return -1; return -1;
} }
int initialiseWindows (const TRI_win_initialise_e initialiseWhat,
const char* data) {
int initialiseWindows(const TRI_win_initialise_e initialiseWhat, const char* data) {
// ............................................................................ // ............................................................................
// The data is used to transport information from the calling function to here // The data is used to transport information from the calling function to here
@ -273,7 +265,6 @@ int initialiseWindows(const TRI_win_initialise_e initialiseWhat, const char* dat
} }
int TRI_createFile (const char* filename, int openFlags, int modeFlags) { int TRI_createFile (const char* filename, int openFlags, int modeFlags) {
HANDLE fileHandle; HANDLE fileHandle;
int fileDescriptor; int fileDescriptor;
@ -282,11 +273,10 @@ int TRI_createFile (const char* filename, int openFlags, int modeFlags) {
GENERIC_READ | GENERIC_WRITE, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, NULL,
CREATE_NEW, (openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW,
0, 0,
NULL); NULL);
if (fileHandle == INVALID_HANDLE_VALUE) { if (fileHandle == INVALID_HANDLE_VALUE) {
return -1; return -1;
} }

View File

@ -106,14 +106,14 @@ int TRI_openFile (const char* filename, int openFlags);
// this provides a translation // this provides a translation
// ............................................................................. // .............................................................................
void TRI_sleep(unsigned long); void TRI_sleep (unsigned long);
// ............................................................................. // .............................................................................
// there is no usleep (micro sleep) in windows, so we create one here // there is no usleep (micro sleep) in windows, so we create one here
// ............................................................................. // .............................................................................
void TRI_usleep(unsigned long); void TRI_usleep (unsigned long);
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// @} /// @}