Esempio n. 1
0
void TRI_LockMutex (TRI_mutex_t* mutex) {
  // as of VS2013, exclusive SRWLocks tend to be faster than native mutexes
#if TRI_WINDOWS_VISTA_LOCKS
  DWORD result = WaitForSingleObject(mutex->_mutex, INFINITE);

  switch (result) {
    case WAIT_ABANDONED: {
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_ABANDONED");
    }

    case WAIT_OBJECT_0: {
      // everything ok
      break;
    }

    case WAIT_TIMEOUT: {
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_TIMEOUT");
    }

    case WAIT_FAILED: {
      result = GetLastError();
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_FAILED - reason -->%d",result);
    }
  }
#else
  AcquireSRWLockExclusive(&mutex->_mutex);
#endif
}
Esempio n. 2
0
bool TRI_TimedWaitCondition (TRI_condition_t* cond, uint64_t delay) {
  int rc;
  struct timespec ts;
  struct timeval tp;
  uint64_t x, y;

  rc = gettimeofday(&tp, NULL);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not get time of day for the condition: %s", strerror(rc));
  }

  // Convert from timeval to timespec
  ts.tv_sec = tp.tv_sec;
  x = (tp.tv_usec * 1000) + (delay * 1000);
  y = (x % 1000000000);
  ts.tv_nsec = y;
  ts.tv_sec  = ts.tv_sec + ((x - y) / 1000000000);

  // and wait
  rc = pthread_cond_timedwait(&cond->_cond, cond->_mutex, &ts);

  if (rc != 0) {
    if (rc == ETIMEDOUT) {
      return false;
    }

    LOG_FATAL_AND_EXIT("could not wait for the condition: %s", strerror(rc));
  }

  return true;
}
Esempio n. 3
0
void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
#if TRI_WINDOWS_VISTA_LOCKS
  // ...........................................................................
  // 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);
#else
  ReleaseSRWLockExclusive(&lock->_lock);
#endif
}
Esempio n. 4
0
void TRI_UnlockMutex (TRI_mutex_t* mutex) {
  BOOL ok = ReleaseMutex(mutex->_mutex);

  if (! ok) {
    LOG_FATAL_AND_EXIT("could not unlock the mutex");
  }
}
Esempio n. 5
0
void TRI_ReadLockReadWriteLock (TRI_read_write_lock_t* lock) {
  int rc;
  bool complained = false;

again:
  rc = pthread_rwlock_rdlock(lock);

  if (rc != 0) {
    if (rc == EAGAIN) {
      // use busy waiting if we cannot acquire the read-lock in case of too many
      // concurrent read locks ("resource temporarily unavailable").
      // in this case we'll wait in a busy loop until we can acquire the lock
      if (! complained) {
        LOG_WARNING("too many read-locks on read-write lock");
        complained = true;
      }
      usleep(BUSY_LOCK_DELAY);
#ifdef TRI_HAVE_SCHED_H
      // let other threads do things
      sched_yield();
#endif

      // ideal use case for goto :-)
      goto again;
    }

    if (rc == EDEADLK) {
      LOG_ERROR("rw-lock deadlock detected");
    }

    LOG_FATAL_AND_EXIT("could not read-lock the read-write lock: %s", strerror(rc));
  }
}
Esempio n. 6
0
void TRI_UnlockCondition (TRI_condition_t* cond) {
  int rc;

  rc = pthread_mutex_unlock(cond->_mutex);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not unlock the condition: %s", strerror(rc));
  }
}
Esempio n. 7
0
int TRI_InitMutex (TRI_mutex_t* mutex) {
  mutex->_mutex = CreateMutex(NULL, FALSE, NULL);

  if (mutex->_mutex == NULL) {
    LOG_FATAL_AND_EXIT("cannot create the mutex");
  }

  return TRI_ERROR_NO_ERROR;
}
Esempio n. 8
0
void TRI_WaitCondition (TRI_condition_t* cond) {
  int rc;

  rc = pthread_cond_wait(&cond->_cond, cond->_mutex);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not wait for the condition: %s", strerror(rc));
  }
}
Esempio n. 9
0
void TRI_BroadcastCondition (TRI_condition_t* cond) {
  int rc;

  rc = pthread_cond_broadcast(&cond->_cond);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not croadcast the condition: %s", strerror(rc));
  }
}
Esempio n. 10
0
void TRI_SignalCondition (TRI_condition_t* cond) {
  int rc;

  rc = pthread_cond_signal(&cond->_cond);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not signal the condition: %s", strerror(rc));
  }
}
Esempio n. 11
0
int TRI_DestroyMutex (TRI_mutex_t* mutex) {
  if (CloseHandle(mutex->_mutex) == 0) {
    DWORD result = GetLastError();
      
    LOG_FATAL_AND_EXIT("locks-win32.c:TRI_DestroyMutex:could not destroy the mutex -->%d",result);
  }
  
  return TRI_ERROR_NO_ERROR;
}
Esempio n. 12
0
void TRI_WriteUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
  int rc;

  rc  = pthread_rwlock_unlock(lock);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not read-unlock the read-write lock: %s", strerror(rc));
  }
}
Esempio n. 13
0
void TRI_UnlockMutex (TRI_mutex_t* mutex) {
  int rc;

  rc = pthread_mutex_unlock(mutex);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not release the mutex: %s", strerror(rc));
  }
}
Esempio n. 14
0
void TRI_UnlockSpin (TRI_spin_t* spinLock) {
  int rc;

  rc = pthread_spin_unlock(spinLock);

  if (rc != 0) {
    LOG_FATAL_AND_EXIT("could not release the spin-lock: %s", strerror(rc));
  }
}
Esempio n. 15
0
      void fillBuffer () {
        DWORD n = sizeof(buffer);
        BYTE* ptr = reinterpret_cast<BYTE*>(&buffer);

        // fill the buffer with random characters
        int result = CryptGenRandom(cryptoHandle, n, ptr);
        if (result == 0) {
          LOG_FATAL_AND_EXIT("read on random device failed: nothing read");
        }
        pos = 0;
      }
Esempio n. 16
0
      void fillBuffer () {
        size_t n = sizeof(buffer);

        char* ptr = reinterpret_cast<char*>(&buffer);

        while (0 < n) {
          ssize_t r = TRI_READ(fd, ptr, (TRI_read_t) n);

          if (r == 0) {
            LOG_FATAL_AND_EXIT("read on random device failed: nothing read");
          }
          else if (r < 0) {
            LOG_FATAL_AND_EXIT("read on random device failed: %s", strerror(errno));
          }

          ptr += r;
          n -= r;
        }

        pos = 0;
      }
Esempio n. 17
0
void TRI_InitCondition (TRI_condition_t* cond) {
  pthread_cond_init(&cond->_cond, 0);

  cond->_ownMutex = true;
  cond->_mutex = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(pthread_mutex_t), false);

  if (cond->_mutex == NULL) {
    LOG_FATAL_AND_EXIT("could not allocate memory for condition variable mutex");
  }

  pthread_mutex_init(cond->_mutex, 0);
}
Esempio n. 18
0
int TRI_DestroyMutex (TRI_mutex_t* mutex) {
  // as of VS2013, exclusive SRWLocks tend to be faster than native mutexes
#if TRI_WINDOWS_VISTA_LOCKS
  if (CloseHandle(mutex->_mutex) == 0) {
    DWORD result = GetLastError();

    LOG_FATAL_AND_EXIT("locks-win32.c:TRI_DestroyMutex:could not destroy the mutex -->%d",result);
  }
#else
#endif
  return TRI_ERROR_NO_ERROR;
}
Esempio n. 19
0
void TRI_UnlockMutex (TRI_mutex_t* mutex) {
  // as of VS2013, exclusive SRWLocks tend to be faster than native mutexes
#if TRI_WINDOWS_VISTA_LOCKS
  BOOL ok = ReleaseMutex(mutex->_mutex);

  if (! ok) {
    LOG_FATAL_AND_EXIT("could not unlock the mutex");
  }
#else
  ReleaseSRWLockExclusive(&mutex->_mutex);
#endif
}
Esempio n. 20
0
void TRI_WriteLockReadWriteLock (TRI_read_write_lock_t* lock) {
  int rc;

  rc = pthread_rwlock_wrlock(lock);

  if (rc != 0) {
    if (rc == EDEADLK) {
      LOG_ERROR("rw-lock deadlock detected");
    }

    LOG_FATAL_AND_EXIT("could not write-lock the read-write lock: %s", strerror(rc));
  }
}
Esempio n. 21
0
void TRI_LockSpin (TRI_spin_t* spinLock) {
  int rc;

  rc = pthread_spin_lock(spinLock);

 if (rc != 0) {
    if (rc == EDEADLK) {
      LOG_ERROR("spinlock deadlock detected");
    }

    LOG_FATAL_AND_EXIT("could not lock the spin-lock: %s", strerror(rc));
  }
}
Esempio n. 22
0
int TRI_InitMutex (TRI_mutex_t* mutex) {
  // as of VS2013, exclusive SRWLocks tend to be faster than native mutexes
#if TRI_WINDOWS_VISTA_LOCKS
  mutex->_mutex = CreateMutex(nullptr, FALSE, nullptr);

  if (mutex->_mutex == nullptr) {
    LOG_FATAL_AND_EXIT("cannot create the mutex");
  }
#else
  InitializeSRWLock(&mutex->_mutex);
#endif
  return TRI_ERROR_NO_ERROR;
}
Esempio n. 23
0
      void fillBuffer () {
        size_t n = sizeof(buffer);
        char* ptr = reinterpret_cast<char*>(&buffer);

        while (0 < n) {
          ssize_t r = TRI_READ(fd, ptr, (TRI_read_t) n);

          if (r == 0) {
            LOG_FATAL_AND_EXIT("read on random device failed: nothing read");
          }
          else if (errno == EWOULDBLOCK) {
            LOG_INFO("not enough entropy (got %d), switching to pseudo-random", (int) (sizeof(buffer) - n));
            break;
          }
          else if (r < 0) {
            LOG_FATAL_AND_EXIT("read on random device failed: %s", strerror(errno));
          }

          ptr += r;
          n -= r;

          rseed = buffer[0];

          LOG_TRACE("using seed %lu", (long unsigned int) rseed);
        }

        if (0 < n) {
          std::mt19937 engine;
          unsigned long seed = RandomDevice::getSeed();
          engine.seed((uint32_t) (rseed ^ (uint32_t) seed));

          while (0 < n) {
            *ptr++ = engine();
            --n;
          }
        }

        pos = 0;
      }
Esempio n. 24
0
void TRI_LockMutex (TRI_mutex_t* mutex) {
  int rc;

  rc = pthread_mutex_lock(mutex);

  if (rc != 0) {
    if (rc == EDEADLK) {
      LOG_ERROR("mutex deadlock detected");
    }

    LOG_FATAL_AND_EXIT("could not lock the mutex: %s", strerror(rc));
  }
}
Esempio n. 25
0
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
  wTime.QuadPart = waitTime * 10; // *10 to change to microseconds
  wTime.QuadPart = -wTime.QuadPart;  // negative indicates relative time elapsed,

  // Create an unnamed waitable timer.
  hTimer = CreateWaitableTimer(NULL, 1, NULL);

  if (hTimer == NULL) {
    // not much we can do at this low level
    return;
  }

  if (GetLastError() == ERROR_ALREADY_EXISTS) {
    LOG_FATAL_AND_EXIT("internal error in TRI_usleep()");
  }

  // Set timer to wait for indicated micro seconds.
  if (! SetWaitableTimer(hTimer, &wTime, 0, NULL, NULL, 0)) {
    // not much we can do at this low level
    CloseHandle(hTimer);
    return;
  }

  // Wait for the timer
  result = WaitForSingleObject(hTimer, INFINITE);

  if (result != WAIT_OBJECT_0) {
    CloseHandle(hTimer);
    LOG_FATAL_AND_EXIT("couldn't wait for timer in TRI_usleep()");
  }

  CloseHandle(hTimer);
  // todo: go through what the result is e.g. WAIT_OBJECT_0
  return;
}
Esempio n. 26
0
void TRI_LockMutex (TRI_mutex_t* mutex) {
  DWORD result = WaitForSingleObject(mutex->_mutex, INFINITE);

  switch (result) {
    case WAIT_ABANDONED: {
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_ABANDONED");
    }

    case WAIT_OBJECT_0: {
      // everything ok
      break;
    }

    case WAIT_TIMEOUT: {
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_TIMEOUT");
    }

    case WAIT_FAILED: {
      result = GetLastError();
      LOG_FATAL_AND_EXIT("locks-win32.c:TRI_LockMutex:could not lock the condition --> WAIT_FAILED - reason -->%d",result);
    }
  }

}
Esempio n. 27
0
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");
  }
}
Esempio n. 28
0
void TRI_ReadUnlockReadWriteLock (TRI_read_write_lock_t* lock) {
#if TRI_WINDOWS_VISTA_LOCKS
  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);
#else
  ReleaseSRWLockShared(&lock->_lock);
#endif
}
Esempio n. 29
0
static bool Compactifier (TRI_df_marker_t const* marker, 
                          void* data, 
                          TRI_datafile_t* datafile, 
                          bool journal) {
  TRI_df_marker_t* result;
  TRI_doc_mptr_t const* found;
  TRI_document_collection_t* document;
  TRI_primary_collection_t* primary;
  compaction_context_t* context;
  int res;

  context  = data;
  document = context->_document;
  primary  = &document->base;

  // new or updated document
  if (marker->_type == TRI_DOC_MARKER_KEY_DOCUMENT ||
      marker->_type == TRI_DOC_MARKER_KEY_EDGE) {

    TRI_doc_document_key_marker_t const* d;
    TRI_doc_mptr_t* found2;
    TRI_voc_key_t key;
    bool deleted;

    d = (TRI_doc_document_key_marker_t const*) marker;
    key = (char*) d + d->_offsetKey;

    // check if the document is still active
    TRI_READ_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);

    found = TRI_LookupByKeyAssociativePointer(&primary->_primaryIndex, key);
    deleted = (found == NULL || found->_rid > d->_rid);

    TRI_READ_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);

    if (deleted) {
      LOG_TRACE("found a stale document: %s", key);
      return true;
    }
    
    context->_keepDeletions = true;

    // write to compactor files
    res = CopyMarker(document, context->_compactor, marker, &result);

    if (res != TRI_ERROR_NO_ERROR) {
      LOG_FATAL_AND_EXIT("cannot write compactor file: %s", TRI_last_error());
    }

    // check if the document is still active
    TRI_WRITE_LOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);

    found = TRI_LookupByKeyAssociativePointer(&primary->_primaryIndex, key);
    deleted = found == NULL;

    if (deleted) {
      context->_dfi._numberDead += 1;
      context->_dfi._sizeDead += (int64_t) marker->_size;
      
      TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);

      LOG_DEBUG("found a stale document after copying: %s", key);

      return true;
    }

    found2 = CONST_CAST(found);
    assert(found2->_data != NULL);
    assert(((TRI_df_marker_t*) found2->_data)->_size > 0);

    // the fid might change
    if (found->_fid != context->_compactor->_fid) {
      // update old datafile's info
      TRI_doc_datafile_info_t* dfi = TRI_FindDatafileInfoPrimaryCollection(primary, found->_fid, false);

      if (dfi != NULL) {
        dfi->_numberDead += 1;
        dfi->_sizeDead += (int64_t) marker->_size;
      }

      found2->_fid = context->_compactor->_fid;
    }

    // let marker point to the new position
    found2->_data = result;

    // let _key point to the new key position
    found2->_key = ((char*) result) + (((TRI_doc_document_key_marker_t*) result)->_offsetKey);

    // update datafile info
    context->_dfi._numberAlive += 1;
    context->_dfi._sizeAlive += (int64_t) marker->_size;

    TRI_WRITE_UNLOCK_DOCUMENTS_INDEXES_PRIMARY_COLLECTION(primary);
  }

  // deletion
  else if (marker->_type == TRI_DOC_MARKER_KEY_DELETION && 
           context->_keepDeletions) {
    // write to compactor files
    res = CopyMarker(document, context->_compactor, marker, &result);

    if (res != TRI_ERROR_NO_ERROR) {
      LOG_FATAL_AND_EXIT("cannot write compactor file: %s", TRI_last_error());
    }

    // update datafile info
    context->_dfi._numberDeletion++;
  }
  else if (marker->_type == TRI_DOC_MARKER_BEGIN_TRANSACTION ||
           marker->_type == TRI_DOC_MARKER_COMMIT_TRANSACTION ||
           marker->_type == TRI_DOC_MARKER_ABORT_TRANSACTION ||
           marker->_type == TRI_DOC_MARKER_PREPARE_TRANSACTION) {
    // write to compactor files
    res = CopyMarker(document, context->_compactor, marker, &result);

    if (res != TRI_ERROR_NO_ERROR) {
      LOG_FATAL_AND_EXIT("cannot write compactor file: %s", TRI_last_error());
    }
    
    context->_dfi._numberTransaction++;
    context->_dfi._sizeTransaction += (int64_t) marker->_size;
  }

  return true;
}
Esempio n. 30
0
bool TRI_LoadAuthInfo (TRI_vocbase_t* vocbase) {
  TRI_vocbase_col_t* collection;
  TRI_primary_collection_t* primary;
  void** beg;
  void** end;
  void** ptr;

  LOG_DEBUG("starting to load authentication and authorisation information");

  collection = TRI_LookupCollectionByNameVocBase(vocbase, "_users");

  if (collection == NULL) {
    LOG_INFO("collection '_users' does not exist, no authentication available");
    return false;
  }

  TRI_UseCollectionVocBase(vocbase, collection);

  primary = collection->_collection;

  if (primary == NULL) {
    LOG_FATAL_AND_EXIT("collection '_users' cannot be loaded");
  }

  if (! TRI_IS_DOCUMENT_COLLECTION(primary->base._info._type)) {
    TRI_ReleaseCollectionVocBase(vocbase, collection);
    LOG_FATAL_AND_EXIT("collection '_users' has an unknown collection type");
  }

  TRI_WriteLockReadWriteLock(&vocbase->_authInfoLock);

  // .............................................................................
  // inside a write transaction
  // .............................................................................

  collection->_collection->beginWrite(collection->_collection);

  beg = primary->_primaryIndex._table;
  end = beg + primary->_primaryIndex._nrAlloc;
  ptr = beg;

  for (;  ptr < end;  ++ptr) {
    if (*ptr) {
      TRI_doc_mptr_t const* d;
      TRI_shaped_json_t shapedJson;

      d = (TRI_doc_mptr_t const*) *ptr;

      if (d->_validTo == 0) {
        TRI_vocbase_auth_t* auth;

        TRI_EXTRACT_SHAPED_JSON_MARKER(shapedJson, d->_data);

        auth = ConvertAuthInfo(vocbase, primary, &shapedJson);

        if (auth != NULL) {
          TRI_vocbase_auth_t* old;

          old = TRI_InsertKeyAssociativePointer(&vocbase->_authInfo, auth->_username, auth, true);

          if (old != NULL) {
            FreeAuthInfo(old);
          }
        }
      }
    }
  }

  collection->_collection->endWrite(collection->_collection);

  // .............................................................................
  // outside a write transaction
  // .............................................................................

  vocbase->_authInfoFlush = true;
  TRI_WriteUnlockReadWriteLock(&vocbase->_authInfoLock);

  TRI_ReleaseCollectionVocBase(vocbase, collection);

  return true;
}