static int ApplyCap (TRI_cap_constraint_t* cap, TRI_document_collection_t* document, TRI_transaction_collection_t* trxCollection) { TRI_headers_t* headers = document->_headersPtr; // PROTECTED by trx in trxCollection size_t currentCount = headers->count(); int64_t currentSize = headers->size(); int res = TRI_ERROR_NO_ERROR; // delete while at least one of the constraints is still violated while ((cap->_count > 0 && currentCount > cap->_count) || (cap->_size > 0 && currentSize > cap->_size)) { TRI_doc_mptr_t* oldest = headers->front(); if (oldest != nullptr) { TRI_ASSERT(oldest->getDataPtr() != nullptr); // ONLY IN INDEX, PROTECTED by RUNTIME size_t oldSize = ((TRI_df_marker_t*) (oldest->getDataPtr()))->_size; // ONLY IN INDEX, PROTECTED by RUNTIME TRI_ASSERT(oldSize > 0); if (trxCollection != nullptr) { res = TRI_DeleteDocumentDocumentCollection(trxCollection, nullptr, oldest); if (res != TRI_ERROR_NO_ERROR) { LOG_WARNING("cannot cap collection: %s", TRI_errno_string(res)); break; } } else { headers->unlink(oldest); } currentCount--; currentSize -= (int64_t) oldSize; } else { // we should not get here LOG_WARNING("logic error in %s", __FUNCTION__); break; } } return res; }
TRI_doc_mptr_t* TRI_headers_t::request (size_t size) { TRI_doc_mptr_t* header; TRI_ASSERT(size > 0); if (_freelist == nullptr) { size_t blockSize = GetBlockSize(_blocks._length); TRI_ASSERT(blockSize > 0); TRI_doc_mptr_t* begin; try { begin = new TRI_doc_mptr_t[blockSize]; } catch (std::exception&) { begin = nullptr; } // out of memory if (begin == nullptr) { TRI_set_errno(TRI_ERROR_OUT_OF_MEMORY); return nullptr; } TRI_doc_mptr_t* ptr = begin + (blockSize - 1); header = nullptr; for (; begin <= ptr; ptr--) { ptr->setDataPtr(header); // ONLY IN HEADERS header = ptr; } _freelist = header; TRI_PushBackVectorPointer(&_blocks, begin); } TRI_ASSERT(_freelist != nullptr); TRI_doc_mptr_t* result = const_cast<TRI_doc_mptr_t*>(_freelist); TRI_ASSERT(result != nullptr); _freelist = static_cast<TRI_doc_mptr_t const*>(result->getDataPtr()); // ONLY IN HEADERS, PROTECTED by RUNTIME result->setDataPtr(nullptr); // ONLY IN HEADERS // put new header at the end of the list if (_begin == nullptr) { // list of headers is empty TRI_ASSERT(_nrLinked == 0); TRI_ASSERT(_totalSize == 0); _begin = result; _end = result; result->_prev = nullptr; result->_next = nullptr; } else { // list is not empty TRI_ASSERT(_nrLinked > 0); TRI_ASSERT(_totalSize > 0); TRI_ASSERT(_nrAllocated > 0); TRI_ASSERT(_begin != nullptr); TRI_ASSERT(_end != nullptr); _end->_next = result; result->_prev = _end; result->_next = nullptr; _end = result; } _nrAllocated++; _nrLinked++; _totalSize += (int64_t) TRI_DF_ALIGN_BLOCK(size); return result; }