mirror of https://gitee.com/bigwinds/arangodb
175 lines
5.6 KiB
C++
175 lines
5.6 KiB
C++
////////////////////////////////////////////////////////////////////////////////
|
|
/// DISCLAIMER
|
|
///
|
|
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
|
|
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
|
|
///
|
|
/// Licensed under the Apache License, Version 2.0 (the "License");
|
|
/// you may not use this file except in compliance with the License.
|
|
/// You may obtain a copy of the License at
|
|
///
|
|
/// http://www.apache.org/licenses/LICENSE-2.0
|
|
///
|
|
/// Unless required by applicable law or agreed to in writing, software
|
|
/// distributed under the License is distributed on an "AS IS" BASIS,
|
|
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
/// See the License for the specific language governing permissions and
|
|
/// limitations under the License.
|
|
///
|
|
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
|
|
///
|
|
/// @author Jan Steemann
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "MMFilesRevisionsCache.h"
|
|
#include "Basics/ReadLocker.h"
|
|
#include "Basics/WriteLocker.h"
|
|
#include "Basics/xxhash.h"
|
|
#include "Logger/Logger.h"
|
|
#include "MMFiles/MMFilesDatafileHelper.h"
|
|
|
|
using namespace arangodb;
|
|
|
|
namespace {
|
|
static inline uint64_t HashKey(void*, TRI_voc_rid_t const* key) {
|
|
return std::hash<TRI_voc_rid_t>()(*key);
|
|
// return XXH64(key, sizeof(TRI_voc_rid_t), 0x12345678);
|
|
}
|
|
|
|
static inline uint64_t HashElement(void*, MMFilesDocumentPosition const& element) {
|
|
return std::hash<TRI_voc_rid_t>()(element.revisionId());
|
|
// TRI_voc_rid_t revisionId = element.revisionId();
|
|
// return HashKey(nullptr, &revisionId);
|
|
}
|
|
|
|
static bool IsEqualKeyElement(void*, TRI_voc_rid_t const* key,
|
|
uint64_t hash, MMFilesDocumentPosition const& element) {
|
|
return *key == element.revisionId();
|
|
}
|
|
|
|
static bool IsEqualElementElement(void*, MMFilesDocumentPosition const& left,
|
|
MMFilesDocumentPosition const& right) {
|
|
return left.revisionId() == right.revisionId();
|
|
}
|
|
|
|
} // namespace
|
|
|
|
MMFilesRevisionsCache::MMFilesRevisionsCache()
|
|
: _positions(HashKey, HashElement, IsEqualKeyElement, IsEqualElementElement, IsEqualElementElement, 8, []() -> std::string { return "mmfiles revisions"; }) {}
|
|
|
|
MMFilesRevisionsCache::~MMFilesRevisionsCache() {}
|
|
|
|
MMFilesDocumentPosition MMFilesRevisionsCache::lookup(TRI_voc_rid_t revisionId) const {
|
|
TRI_ASSERT(revisionId != 0);
|
|
READ_LOCKER(locker, _lock);
|
|
|
|
return _positions.findByKey(nullptr, &revisionId);
|
|
}
|
|
|
|
void MMFilesRevisionsCache::sizeHint(int64_t hint) {
|
|
WRITE_LOCKER(locker, _lock);
|
|
if (hint > 256) {
|
|
_positions.resize(nullptr, static_cast<size_t>(hint));
|
|
}
|
|
}
|
|
|
|
size_t MMFilesRevisionsCache::size() {
|
|
READ_LOCKER(locker, _lock);
|
|
return _positions.size();
|
|
}
|
|
|
|
size_t MMFilesRevisionsCache::capacity() {
|
|
READ_LOCKER(locker, _lock);
|
|
return _positions.capacity();
|
|
}
|
|
|
|
size_t MMFilesRevisionsCache::memoryUsage() {
|
|
READ_LOCKER(locker, _lock);
|
|
return _positions.memoryUsage();
|
|
}
|
|
|
|
void MMFilesRevisionsCache::clear() {
|
|
WRITE_LOCKER(locker, _lock);
|
|
_positions.truncate([](MMFilesDocumentPosition&) { return true; });
|
|
}
|
|
|
|
MMFilesDocumentPosition MMFilesRevisionsCache::insert(TRI_voc_rid_t revisionId, uint8_t const* dataptr, TRI_voc_fid_t fid, bool isInWal, bool shouldLock) {
|
|
TRI_ASSERT(revisionId != 0);
|
|
TRI_ASSERT(dataptr != nullptr);
|
|
|
|
CONDITIONAL_WRITE_LOCKER(locker, _lock, shouldLock);
|
|
int res = _positions.insert(nullptr, MMFilesDocumentPosition(revisionId, dataptr, fid, isInWal));
|
|
|
|
if (res != TRI_ERROR_NO_ERROR) {
|
|
MMFilesDocumentPosition old = _positions.removeByKey(nullptr, &revisionId);
|
|
_positions.insert(nullptr, MMFilesDocumentPosition(revisionId, dataptr, fid, isInWal));
|
|
return old;
|
|
}
|
|
|
|
return MMFilesDocumentPosition();
|
|
}
|
|
|
|
void MMFilesRevisionsCache::insert(MMFilesDocumentPosition const& position, bool shouldLock) {
|
|
CONDITIONAL_WRITE_LOCKER(locker, _lock, shouldLock);
|
|
_positions.insert(nullptr, position);
|
|
}
|
|
|
|
void MMFilesRevisionsCache::update(TRI_voc_rid_t revisionId, uint8_t const* dataptr, TRI_voc_fid_t fid, bool isInWal) {
|
|
TRI_ASSERT(revisionId != 0);
|
|
TRI_ASSERT(dataptr != nullptr);
|
|
|
|
WRITE_LOCKER(locker, _lock);
|
|
|
|
MMFilesDocumentPosition* old = _positions.findByKeyRef(nullptr, &revisionId);
|
|
if (old == nullptr) {
|
|
return;
|
|
}
|
|
|
|
// update the element in place
|
|
old->dataptr(dataptr);
|
|
old->fid(fid, isInWal);
|
|
}
|
|
|
|
bool MMFilesRevisionsCache::updateConditional(TRI_voc_rid_t revisionId, TRI_df_marker_t const* oldPosition, TRI_df_marker_t const* newPosition, TRI_voc_fid_t newFid, bool isInWal) {
|
|
WRITE_LOCKER(locker, _lock);
|
|
|
|
MMFilesDocumentPosition old = _positions.findByKey(nullptr, &revisionId);
|
|
if (!old) {
|
|
return false;
|
|
}
|
|
|
|
uint8_t const* vpack = static_cast<uint8_t const*>(old.dataptr());
|
|
TRI_ASSERT(vpack != nullptr);
|
|
|
|
TRI_df_marker_t const* markerPtr = reinterpret_cast<TRI_df_marker_t const*>(vpack - MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT));
|
|
|
|
if (markerPtr != oldPosition) {
|
|
// element already outdated
|
|
return false;
|
|
}
|
|
|
|
_positions.removeByKey(nullptr, &revisionId);
|
|
|
|
old.dataptr(reinterpret_cast<char const*>(newPosition) + MMFilesDatafileHelper::VPackOffset(TRI_DF_MARKER_VPACK_DOCUMENT));
|
|
old.fid(newFid, isInWal);
|
|
|
|
_positions.insert(nullptr, old);
|
|
|
|
return true;
|
|
}
|
|
|
|
void MMFilesRevisionsCache::remove(TRI_voc_rid_t revisionId) {
|
|
TRI_ASSERT(revisionId != 0);
|
|
|
|
WRITE_LOCKER(locker, _lock);
|
|
_positions.removeByKey(nullptr, &revisionId);
|
|
}
|
|
|
|
MMFilesDocumentPosition MMFilesRevisionsCache::fetchAndRemove(TRI_voc_rid_t revisionId) {
|
|
TRI_ASSERT(revisionId != 0);
|
|
|
|
WRITE_LOCKER(locker, _lock);
|
|
return _positions.removeByKey(nullptr, &revisionId);
|
|
}
|
|
|