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; }
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; }
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; }
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); }
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; }
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; }
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; }