Beispiel #1
0
static bool CheckSyncCompactorDocumentCollection (TRI_document_collection_t* sim) {
  TRI_collection_t* base;
  TRI_datafile_t* journal;
  bool ok;
  bool worked;
  char const* synced;
  char* written;
  double ti;
  size_t i;
  size_t n;
  
  worked = false;
  base = &sim->base.base;

  // .............................................................................
  // the only thread MODIFYING the _compactors variable is this thread,
  // therefore no locking is required to access the _compactors
  // .............................................................................

  n = base->_compactors._length;

  for (i = 0;  i < n; ++i) {
    journal = base->_compactors._buffer[i];

    TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

    synced = journal->_synced;
    written = journal->_written;

    TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

    if (synced < written) {
      worked = true;
      ok = TRI_msync(journal->_fd, journal->_mmHandle, synced, written);
      ti = TRI_microtime();

      TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

      if (ok) {
        journal->_synced = written;
        journal->_lastSynced = ti;
      }
      else {
        journal->_state = TRI_DF_STATE_WRITE_ERROR;
      }

      TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(sim);
      TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

      if (ok) {
        LOG_TRACE("msync succeeded %p, size %lu", synced, (unsigned long)(written - synced));
      }
      else {
        LOG_ERROR("msync failed with: %s", TRI_last_error());
      }
    }
  }

  return worked;
}
Beispiel #2
0
static bool CheckCompactorDocumentCollection (TRI_document_collection_t* sim) {
  TRI_collection_t* base;
  TRI_datafile_t* compactor;
  bool worked;
  size_t i;
  size_t n;
  
  worked = false;
  base = &sim->base.base;

  // .............................................................................
  // the only thread MODIFYING the _compactor variable is this thread,
  // therefore no locking is required to access the _compactors
  // .............................................................................

  n = base->_compactors._length;

  for (i = 0;  i < n;) {
    compactor = base->_compactors._buffer[i];

    if (compactor->_full) {
      worked = true;

      LOG_DEBUG("closing full compactor '%s'", compactor->_filename);

      TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);
      TRI_CloseCompactorPrimaryCollection(&sim->base, i);
      TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

      n = base->_compactors._length;
      i = 0;
    }
    else {
      ++i;
    }
  }

  if (base->_compactors._length == 0) {
    TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);

    compactor = TRI_CreateCompactorPrimaryCollection(&sim->base);

    if (compactor != NULL) {
      worked = true;
      LOG_DEBUG("created new compactor '%s'", compactor->_filename);
    
      TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(sim);
    }
    else {
      // an error occurred when creating the compactor file
      LOG_ERROR("could not create compactor file");
    }

    TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(sim);
  }

  return worked;
}
Beispiel #3
0
static TRI_datafile_t* CreateCompactor (TRI_document_collection_t* document,
                                        TRI_voc_fid_t fid,
                                        TRI_voc_size_t maximalSize) {
  TRI_collection_t* collection;
  TRI_datafile_t* compactor;
  
  collection = &document->base.base;
  
  // reserve room for one additional entry
  if (TRI_ReserveVectorPointer(&collection->_compactors, 1) != TRI_ERROR_NO_ERROR) {
    // could not get memory, exit early
    return NULL;
  }
  
  TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);

  compactor = TRI_CreateCompactorPrimaryCollection(&document->base, fid, maximalSize);

  if (compactor != NULL) {
    int res = TRI_PushBackVectorPointer(&collection->_compactors, compactor);

    // we have reserved space before, so we can be sure the push succeeds
    assert(res == TRI_ERROR_NO_ERROR);
  }
    
  // we still must wake up the other thread from time to time, otherwise we'll deadlock
  TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(document);

  TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);

  return compactor;
}
Beispiel #4
0
int TRI_UpdateCollectionInfo (TRI_vocbase_t* vocbase,
                                       TRI_collection_t* collection,
                                       TRI_col_info_t const* parameter) {

  if (TRI_IS_DOCUMENT_COLLECTION(collection->_info._type)) {
    TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION((TRI_document_collection_t*) collection);
  }

  if (parameter != 0) {
    collection->_info._maximalSize = parameter->_maximalSize;
    collection->_info._waitForSync = parameter->_waitForSync;

    if (collection->_info._maximalSize < collection->_maximumMarkerSize + TRI_JOURNAL_OVERHEAD) {
      collection->_info._maximalSize = collection->_maximumMarkerSize + TRI_JOURNAL_OVERHEAD;
    }

    // the following collection properties are intentionally not updated as updating
    // them would be very complicated:
    // - _cid
    // - _name
    // - _type
    // - _isSystem
    // - _isVolatile
    // ... probably a few others missing here ...
  }

  if (TRI_IS_DOCUMENT_COLLECTION(collection->_info._type)) {
    TRI_document_collection_t* docCollection = (TRI_document_collection_t*) collection;

    if (docCollection->base._shaper != NULL) {
      TRI_shape_collection_t* shapeCollection = TRI_CollectionVocShaper(((TRI_document_collection_t*) collection)->base._shaper);

      if (shapeCollection != NULL) {
        // adjust wait for sync value of underlying shape collection
        shapeCollection->base._info._waitForSync = (vocbase->_forceSyncShapes || collection->_info._waitForSync);
      }
    }
    TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION((TRI_document_collection_t*) collection);
  }

  return TRI_SaveCollectionInfo(collection->_directory, &collection->_info);
}
Beispiel #5
0
static bool CheckSyncDocumentCollection (TRI_document_collection_t* doc) {
  TRI_collection_t* base;
  TRI_datafile_t* journal;
  bool ok;
  bool worked;
  char const* synced;
  char* written;
  size_t i;
  size_t n;

  worked = false;
  base = &doc->base.base;

  // .............................................................................
  // the only thread MODIFYING the _journals variable is this thread,
  // therefore no locking is required to access the _journals
  // .............................................................................

  n = base->_journals._length;

  for (i = 0;  i < n; ++i) {
    journal = base->_journals._buffer[i];

    // we only need to care about physical datafiles
    if (! journal->isPhysical(journal)) {
      // anonymous regions do not need to be synced
      continue;
    }

    TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

    synced = journal->_synced;

    written = journal->_written;

    TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

    if (synced < written) {
      worked = true;
      ok = journal->sync(journal, synced, written);

      TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

      if (ok) {
        journal->_synced = written;
      }
      else {
        journal->_state = TRI_DF_STATE_WRITE_ERROR;
      }

      TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
      TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

      if (ok) {
        LOG_TRACE("msync succeeded %p, size %lu", synced, (unsigned long)(written - synced));
      }
      else {
        LOG_ERROR("msync failed with: %s", TRI_last_error());
      }
    }
  }

  return worked;
}
Beispiel #6
0
static bool CheckJournalDocumentCollection (TRI_document_collection_t* doc) {
  TRI_collection_t* base;
  TRI_datafile_t* journal;
  bool worked;
  size_t i;
  size_t n;

  worked = false;
  base = &doc->base.base;

  if (base->_state != TRI_COL_STATE_WRITE) {
    return false;
  }

  // .............................................................................
  // the only thread MODIFYING the _journals variable is this thread,
  // therefore no locking is required to access the _journals
  // .............................................................................

  TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

  n = base->_journals._length;

  for (i = 0;  i < n;) {
    journal = base->_journals._buffer[i];

    if (journal->_full) {
      worked = true;

      LOG_DEBUG("closing full journal '%s'", journal->getName(journal));

      TRI_CloseJournalPrimaryCollection(&doc->base, i);

      n = base->_journals._length;
      i = 0;
    }
    else {
      ++i;
    }
  }

  if (base->_journals._length == 0) {
    journal = TRI_CreateJournalDocumentCollection(doc);

    if (journal != NULL) {
      worked = true;
      LOG_DEBUG("created new journal '%s'", journal->getName(journal));

      TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
    }
    else {
      // an error occurred when creating the journal file
      LOG_ERROR("could not create journal file");

      // we still must wake up the other thread from time to time, otherwise we'll deadlock
      TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(doc);
    }
  }

  TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(doc);

  return worked;
}
Beispiel #7
0
static bool CheckJournalDocumentCollection (TRI_document_collection_t* document) {
  TRI_collection_t* base;
  TRI_datafile_t* journal;
  bool worked;
  size_t i;
  size_t n;

  worked = false;
  base = &document->base.base;

  if (base->_state != TRI_COL_STATE_WRITE) {
    return false;
  }

  // .............................................................................
  // the only thread MODIFYING the _journals variable is this thread,
  // therefore no locking is required to access the _journals
  // .............................................................................

  TRI_LOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);
  n = base->_journals._length;

  for (i = 0;  i < n;) {
    journal = static_cast<TRI_datafile_t*>(base->_journals._buffer[i]);

    if (journal->_full) {
      worked = true;

      LOG_DEBUG("closing full journal '%s'", journal->getName(journal));

      TRI_CloseJournalPrimaryCollection(&document->base, i);

      n = base->_journals._length;
      i = 0;
    }
    else {
      ++i;
    }
  }

  // create a new journal if we do not have one, AND, if there was a request to create one
  // (sometimes we don't need a journal, e.g. directly after db._create(collection); when
  // the collection is still empty)
  if (base->_journals._length == 0 && 
      document->_requestedJournalSize > 0) {
    TRI_voc_size_t targetSize = document->base.base._info._maximalSize;

    if (document->_requestedJournalSize > 0 && 
        document->_requestedJournalSize > targetSize) {
      targetSize = document->_requestedJournalSize;
    }

    journal = TRI_CreateJournalDocumentCollection(document, targetSize);

    if (journal != NULL) {
      worked = true;
      document->_requestedJournalSize = 0;
      document->_rotateRequested      = false;

      LOG_DEBUG("created new journal '%s'", journal->getName(journal));
    }
    else {
      // an error occurred when creating the journal file
      LOG_ERROR("could not create journal file");
    }
  }
  else if (document->_rotateRequested) {
    // only a rotate was requested
    document->_rotateRequested = false;
  }
  
  // always broadcast, otherwise other threads waiting for the broadcast might deadlock!
  TRI_BROADCAST_JOURNAL_ENTRIES_DOC_COLLECTION(document);

  TRI_UNLOCK_JOURNAL_ENTRIES_DOC_COLLECTION(document);

  return worked;
}