mirror of https://gitee.com/bigwinds/arangodb
issue #662: ArangoDB on Windows hanging
This commit is contained in:
parent
87aed55acf
commit
af6da9a652
22
CHANGELOG
22
CHANGELOG
|
@ -67,6 +67,28 @@ v1.5.x (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
|
||||
|
||||
* issue #671: Method graph.measurement does not exist
|
||||
|
|
|
@ -213,8 +213,12 @@ static bool UnregisterCollection (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, collection->_name);
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsById, &collection->_cid);
|
||||
// only if we find the collection by its id, we can delete it by name
|
||||
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);
|
||||
|
||||
|
@ -237,9 +241,9 @@ static bool UnloadCollectionCallback (TRI_collection_t* col, void* data) {
|
|||
TRI_document_collection_t* document;
|
||||
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) {
|
||||
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) {
|
||||
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
|
||||
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsByName, name, collection, &found);
|
||||
|
||||
|
||||
if (found != NULL) {
|
||||
LOG_ERROR("duplicate entry for collection name '%s'", name);
|
||||
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
|
||||
assert(collection->_cid == cid);
|
||||
res = TRI_InsertKeyAssociativePointer2(&vocbase->_collectionsById, &cid, collection, &found);
|
||||
|
||||
|
||||
if (found != NULL) {
|
||||
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->_collectionsByName, name);
|
||||
TRI_Free(TRI_UNKNOWN_MEM_ZONE, collection);
|
||||
|
||||
TRI_set_errno(res);
|
||||
|
||||
return NULL;
|
||||
|
@ -720,8 +724,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
|
|||
void const* found;
|
||||
int res;
|
||||
|
||||
// lock collection because we are going to change the name
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// this must be done after the collection lock
|
||||
TRI_WRITE_LOCK_COLLECTIONS_VOCBASE(vocbase);
|
||||
|
@ -815,7 +818,7 @@ static int RenameCollection (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_RemoveKeyAssociativePointer(&vocbase->_collectionsByName, oldName);
|
||||
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
|
||||
found = TRI_InsertKeyAssociativePointer(&vocbase->_collectionsByName, newName, CONST_CAST(collection), false);
|
||||
assert(found == NULL);
|
||||
|
@ -1090,7 +1093,7 @@ static int LoadCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
// 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
|
||||
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);
|
||||
}
|
||||
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// cannot unload a corrupted collection
|
||||
if (collection->_status == TRI_VOC_COL_STATUS_CORRUPTED) {
|
||||
|
@ -2065,14 +2068,14 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
|
||||
TRI_ReadLockReadWriteLock(&vocbase->_inventoryLock);
|
||||
|
||||
// mark collection as deleted
|
||||
TRI_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
TRI_EVENTUAL_WRITE_LOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
||||
// .............................................................................
|
||||
// collection already deleted
|
||||
// .............................................................................
|
||||
|
||||
if (collection->_status == TRI_VOC_COL_STATUS_DELETED) {
|
||||
// mark collection as deleted
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
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
|
||||
tmpFile = TRI_Concatenate4String(collection->_path, TRI_DIR_SEPARATOR_STR, TRI_VOC_PARAMETER_FILE, ".tmp");
|
||||
|
||||
|
||||
if (tmpFile != NULL) {
|
||||
if (TRI_ExistsFile(tmpFile)) {
|
||||
TRI_UnlinkFile(tmpFile);
|
||||
|
@ -2125,7 +2128,6 @@ int TRI_DropCollectionVocBase (TRI_vocbase_t* vocbase,
|
|||
}
|
||||
|
||||
collection->_status = TRI_VOC_COL_STATUS_DELETED;
|
||||
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
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;
|
||||
|
||||
UnregisterCollection(vocbase, collection, generatingServer);
|
||||
|
||||
TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(collection);
|
||||
|
|
|
@ -114,6 +114,13 @@ struct TRI_vocbase_defaults_s;
|
|||
#define TRI_READ_UNLOCK_STATUS_VOCBASE_COL(a) \
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -128,6 +135,15 @@ struct TRI_vocbase_defaults_s;
|
|||
#define TRI_WRITE_UNLOCK_STATUS_VOCBASE_COL(a) \
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -208,43 +208,7 @@ void TRI_UnlockSpin (TRI_spin_t* spin) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_InitReadWriteLock (TRI_read_write_lock_t* 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);
|
||||
InitializeSRWLock(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -252,11 +216,6 @@ void TRI_InitReadWriteLock (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
|
||||
// -----------------------------------------------------------------------------
|
||||
|
@ -336,20 +245,7 @@ static void DecrementReaders (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
WaitForSingleObject(lock->_writerEvent, 10); // 10 millis timeout
|
||||
|
||||
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;
|
||||
return (TryAcquireSRWLockShared(&lock->_lock) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -357,43 +253,7 @@ bool TRI_TryReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* 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;
|
||||
}
|
||||
}
|
||||
AcquireSRWLockShared(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -401,98 +261,15 @@ void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_ReadUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
EnterCriticalSection(&lock->_lockReaders);
|
||||
|
||||
/* 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);
|
||||
ReleaseSRWLockShared(&lock->_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief tries to write lock a read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
||||
|
||||
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;
|
||||
return (TryAcquireSRWLockExclusive(&lock->_lock) != 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -500,99 +277,15 @@ bool TRI_TryWriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_WriteLockReadWriteLock (TRI_read_write_lock_t* 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);
|
||||
AcquireSRWLockExclusive(&lock->_lock);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief write unlocks read-write lock
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* 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);
|
||||
ReleaseSRWLockExclusive(&lock->_lock);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -715,7 +408,6 @@ void TRI_UnlockCondition (TRI_condition_t* cond) {
|
|||
LeaveCriticalSection(&cond->_lockWaiters);
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// COMPARE & SWAP operations below for windows
|
||||
// Note that for the MAC OS we use the 'barrier' functions which ensure that
|
||||
|
|
|
@ -65,13 +65,7 @@ TRI_mutex_t;
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef struct TRI_read_write_lock_s {
|
||||
HANDLE _writerEvent;
|
||||
HANDLE _readersEvent;
|
||||
|
||||
int _readers;
|
||||
|
||||
CRITICAL_SECTION _lockWriter;
|
||||
CRITICAL_SECTION _lockReaders;
|
||||
SRWLOCK _lock;
|
||||
}
|
||||
TRI_read_write_lock_t;
|
||||
|
||||
|
|
|
@ -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);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int getpagesize(void) {
|
||||
int getpagesize (void) {
|
||||
static int pageSize = 0; // only define it once
|
||||
|
||||
if (!pageSize) {
|
||||
if (! pageSize) {
|
||||
// first time, so call the system info function
|
||||
SYSTEM_INFO systemInfo;
|
||||
GetSystemInfo (&systemInfo);
|
||||
|
@ -76,22 +75,20 @@ int getpagesize(void) {
|
|||
return pageSize;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// 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;
|
||||
HANDLE hTimer = NULL; // stores the handle of the timer object
|
||||
LARGE_INTEGER wTime; // essentially a 64bit number
|
||||
|
@ -109,7 +106,7 @@ void TRI_usleep(unsigned long waitTime) {
|
|||
abort();
|
||||
}
|
||||
// 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
|
||||
CloseHandle(hTimer);
|
||||
return;
|
||||
|
@ -135,14 +132,13 @@ void TRI_usleep(unsigned long waitTime) {
|
|||
// for now is to ignore error and hope it goes away!
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void InvalidParameterHandler(const wchar_t* expression, // expression sent to function - NULL
|
||||
const wchar_t* function, // name of function - NULL
|
||||
const wchar_t* file, // file where code resides - NULL
|
||||
unsigned int line, // line within file - NULL
|
||||
uintptr_t pReserved) { // in case microsoft forget something
|
||||
static void InvalidParameterHandler (const wchar_t* expression, // expression sent to function - NULL
|
||||
const wchar_t* function, // name of function - NULL
|
||||
const wchar_t* file, // file where code resides - NULL
|
||||
unsigned int line, // line within file - NULL
|
||||
uintptr_t pReserved) { // in case microsoft forget something
|
||||
LOG_ERROR("Invalid handle parameter passed");
|
||||
|
||||
/* start oreste -debug */
|
||||
/*
|
||||
if (expression != 0) {
|
||||
wprintf(L"win-utils.c:InvalidParameterHandler:EXPRESSION = %s\n",expression);
|
||||
}
|
||||
|
@ -161,14 +157,12 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
|
|||
else {
|
||||
wprintf(L"win-utils.c:InvalidParameterHandler:FILE = NULL\n");
|
||||
}
|
||||
printf("oreste:win-utils.c:InvalidParameterHandler:LINE = %ud\n",line);
|
||||
/* end oreste -debug */
|
||||
*/
|
||||
//abort();
|
||||
// TODO: use the wcstombs_s function to convert wchar to char - since all the above
|
||||
// wchar never will contain 2 byte chars
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Called from the 'main' and performs any initialisation requirements which
|
||||
// are specific to windows.
|
||||
|
@ -178,8 +172,8 @@ static void InvalidParameterHandler(const wchar_t* expression, // expression sen
|
|||
// calling function should decide what to do.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) {
|
||||
int finaliseWindows (const TRI_win_finalise_e finaliseWhat,
|
||||
const char* data) {
|
||||
int result = 0;
|
||||
|
||||
// ............................................................................
|
||||
|
@ -209,10 +203,8 @@ int finaliseWindows(const TRI_win_finalise_e finaliseWhat, const char* data) {
|
|||
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
|
||||
|
@ -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) {
|
||||
HANDLE fileHandle;
|
||||
int fileDescriptor;
|
||||
|
@ -282,11 +273,10 @@ int TRI_createFile (const char* filename, int openFlags, int modeFlags) {
|
|||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
CREATE_NEW,
|
||||
(openFlags & O_APPEND) ? OPEN_ALWAYS : CREATE_NEW,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE) {
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -106,14 +106,14 @@ int TRI_openFile (const char* filename, int openFlags);
|
|||
// 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
|
||||
// .............................................................................
|
||||
|
||||
void TRI_usleep(unsigned long);
|
||||
void TRI_usleep (unsigned long);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @}
|
||||
|
|
Loading…
Reference in New Issue