diff options
Diffstat (limited to 'searchlib')
7 files changed, 225 insertions, 46 deletions
diff --git a/searchlib/src/vespa/searchlib/btree/btreenode.h b/searchlib/src/vespa/searchlib/btree/btreenode.h index fadb3acdee3..5a52cd7086b 100644 --- a/searchlib/src/vespa/searchlib/btree/btreenode.h +++ b/searchlib/src/vespa/searchlib/btree/btreenode.h @@ -12,8 +12,12 @@ namespace search { namespace datastore { +template <typename, typename> class Allocator; template <typename> class BufferType; -template <typename> class DataStoreT; + +namespace allocator { +template <typename, typename ...> class Assigner; +} } @@ -490,8 +494,10 @@ public: friend class BTreeNodeDataWrap; template <typename> friend class datastore::BufferType; - template <typename> - friend class datastore::DataStoreT; + template <typename, typename> + friend class datastore::Allocator; + template <typename, typename...> + friend class datastore::allocator::Assigner; typedef BTreeNode::Ref Ref; typedef std::pair<Ref, InternalNodeType *> RefPair; using ParentType::_keys; @@ -531,6 +537,7 @@ private: _validLeaves = rhs._validLeaves; return *this; } + public: BTreeNode::Ref getChild(uint32_t idx) const @@ -646,8 +653,10 @@ public: friend class BTreeNodeStore; template <typename> friend class datastore::BufferType; - template <typename> - friend class datastore::DataStoreT; + template <typename, typename> + friend class datastore::Allocator; + template <typename, typename...> + friend class datastore::allocator::Assigner; typedef BTreeNode::Ref Ref; typedef std::pair<Ref, LeafNodeType *> RefPair; using ParentType::validSlots; @@ -681,6 +690,7 @@ protected: ParentType::operator=(rhs); return *this; } + public: template <typename NodeAllocatorType> void diff --git a/searchlib/src/vespa/searchlib/datastore/allocator.h b/searchlib/src/vespa/searchlib/datastore/allocator.h new file mode 100644 index 00000000000..9534eb88157 --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/allocator.h @@ -0,0 +1,35 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "datastorebase.h" +#include "entryref.h" +#include "handle.h" + +namespace search { +namespace datastore { + +/** + * Allocator used to allocate entries of a specific type in an underlying data store. + */ +template <typename EntryT, typename RefT> +class Allocator +{ +public: + using ArrayRef = vespalib::ConstArrayRef<EntryT>; + using HandleType = Handle<EntryT>; + +protected: + DataStoreBase &_store; + uint32_t _typeId; + +public: + Allocator(DataStoreBase &store, uint32_t typeId); + + template <typename ... Args> + HandleType alloc(Args && ... args); + +}; + +} +} diff --git a/searchlib/src/vespa/searchlib/datastore/allocator.hpp b/searchlib/src/vespa/searchlib/datastore/allocator.hpp new file mode 100644 index 00000000000..e4b30e40c01 --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/allocator.hpp @@ -0,0 +1,35 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "allocator.h" +#include "bufferstate.h" + +namespace search { +namespace datastore { + +template <typename EntryT, typename RefT> +Allocator<EntryT, RefT>::Allocator(DataStoreBase &store, uint32_t typeId) + : _store(store), + _typeId(typeId) +{ +} + +template <typename EntryT, typename RefT> +template <typename ... Args> +typename Allocator<EntryT, RefT>::HandleType +Allocator<EntryT, RefT>::alloc(Args && ... args) +{ + _store.ensureBufferCapacity(_typeId, 1); + uint32_t activeBufferId = _store.getActiveBufferId(_typeId); + BufferState &state = _store.getBufferState(activeBufferId); + assert(state.isActive()); + size_t oldSize = state.size(); + EntryT *entry = _store.getBufferEntry<EntryT>(activeBufferId, oldSize); + new (static_cast<void *>(entry)) EntryT(std::forward<Args>(args)...); + state.pushed_back(1); + return HandleType(RefT(oldSize, activeBufferId), entry); +} + +} +} diff --git a/searchlib/src/vespa/searchlib/datastore/datastore.hpp b/searchlib/src/vespa/searchlib/datastore/datastore.hpp index 658acac0ad9..23c1a30f2a7 100644 --- a/searchlib/src/vespa/searchlib/datastore/datastore.hpp +++ b/searchlib/src/vespa/searchlib/datastore/datastore.hpp @@ -3,6 +3,8 @@ #pragma once #include "datastore.h" +#include "allocator.hpp" +#include "free_list_allocator.hpp" namespace search { namespace datastore { @@ -109,15 +111,9 @@ template <typename EntryType> std::pair<RefT, EntryType *> DataStoreT<RefT>::allocNewEntry(uint32_t typeId) { - ensureBufferCapacity(typeId, 1); - uint32_t activeBufferId = getActiveBufferId(typeId); - BufferState &state = getBufferState(activeBufferId); - assert(state.isActive()); - size_t oldSize = state.size(); - EntryType *entry = getBufferEntry<EntryType>(activeBufferId, oldSize); - new (static_cast<void *>(entry)) EntryType(); - state.pushed_back(1); - return std::make_pair(RefType(oldSize, activeBufferId), entry); + Allocator<EntryType, RefT> allocator(*this, typeId); + auto handle = allocator.alloc(); + return std::make_pair(handle.ref, handle.data); } @@ -126,17 +122,9 @@ template <typename EntryType, typename Reclaimer> std::pair<RefT, EntryType *> DataStoreT<RefT>::allocEntry(uint32_t typeId) { - BufferState::FreeListList &freeListList = getFreeList(typeId); - if (freeListList._head == NULL) { - return allocNewEntry<EntryType>(typeId); - } - BufferState &state = *freeListList._head; - assert(state.isActive()); - RefType ref(state.popFreeList()); - EntryType *entry = - getBufferEntry<EntryType>(ref.bufferId(), ref.offset()); - Reclaimer::reclaim(entry); - return std::make_pair(ref, entry); + FreeListAllocator<EntryType, RefT, Reclaimer> allocator(*this, typeId); + auto handle = allocator.alloc(); + return std::make_pair(handle.ref, handle.data); } @@ -145,15 +133,9 @@ template <typename EntryType> std::pair<RefT, EntryType *> DataStoreT<RefT>::allocNewEntryCopy(uint32_t typeId, const EntryType &rhs) { - ensureBufferCapacity(typeId, 1); - uint32_t activeBufferId = getActiveBufferId(typeId); - BufferState &state = getBufferState(activeBufferId); - assert(state.isActive()); - size_t oldSize = state.size(); - EntryType *entry = getBufferEntry<EntryType>(activeBufferId, oldSize); - new (static_cast<void *>(entry)) EntryType(rhs); - state.pushed_back(1); - return std::make_pair(RefType(oldSize, activeBufferId), entry); + Allocator<EntryType, RefT> allocator(*this, typeId); + auto handle = allocator.alloc(rhs); + return std::make_pair(handle.ref, handle.data); } @@ -162,18 +144,9 @@ template <typename EntryType, typename Reclaimer> std::pair<RefT, EntryType *> DataStoreT<RefT>::allocEntryCopy(uint32_t typeId, const EntryType &rhs) { - BufferState::FreeListList &freeListList = getFreeList(typeId); - if (freeListList._head == NULL) { - return allocNewEntryCopy<EntryType>(typeId, rhs); - } - BufferState &state = *freeListList._head; - assert(state.isActive()); - RefType ref(state.popFreeList()); - EntryType *entry = - getBufferEntry<EntryType>(ref.bufferId(), ref.offset()); - Reclaimer::reclaim(entry); - *entry = rhs; - return std::make_pair(ref, entry); + FreeListAllocator<EntryType, RefT, Reclaimer> allocator(*this, typeId); + auto handle = allocator.alloc(rhs); + return std::make_pair(handle.ref, handle.data); } diff --git a/searchlib/src/vespa/searchlib/datastore/free_list_allocator.h b/searchlib/src/vespa/searchlib/datastore/free_list_allocator.h new file mode 100644 index 00000000000..2b77479b589 --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/free_list_allocator.h @@ -0,0 +1,34 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "allocator.h" + +namespace search { +namespace datastore { + +/** + * Allocator used to allocate entries of a specific type in an underlying data store + * and uses free lists if available. + */ +template <typename EntryT, typename RefT, typename ReclaimerT> +class FreeListAllocator : public Allocator<EntryT, RefT> +{ +public: + using ParentType = Allocator<EntryT, RefT>; + using HandleType = typename ParentType::HandleType; + +private: + using ParentType::_store; + using ParentType::_typeId; + +public: + FreeListAllocator(DataStoreBase &store, uint32_t typeId); + + template <typename ... Args> + HandleType alloc(Args && ... args); + +}; + +} +} diff --git a/searchlib/src/vespa/searchlib/datastore/free_list_allocator.hpp b/searchlib/src/vespa/searchlib/datastore/free_list_allocator.hpp new file mode 100644 index 00000000000..8d741aee529 --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/free_list_allocator.hpp @@ -0,0 +1,70 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "free_list_allocator.h" +#include "bufferstate.h" + +namespace search { +namespace datastore { + +template <typename EntryT, typename RefT, typename ReclaimerT> +FreeListAllocator<EntryT, RefT, ReclaimerT>::FreeListAllocator(DataStoreBase &store, uint32_t typeId) + : ParentType(store, typeId) +{ +} + +namespace allocator { + +template <typename EntryT, typename ... Args> +struct Assigner { + static void assign(EntryT &entry, Args && ... args) { + entry = EntryT(std::forward<Args>(args)...); + } +}; + +template <typename EntryT> +struct Assigner<EntryT> { + static void assign(EntryT &entry) { + (void) entry; + } +}; + +// Assignment operator +template <typename EntryT> +struct Assigner<EntryT, const EntryT &> { + static void assign(EntryT &entry, const EntryT &rhs) { + entry = rhs; + } +}; + +// Move assignment +template <typename EntryT> +struct Assigner<EntryT, EntryT &&> { + static void assign(EntryT &entry, EntryT &&rhs) { + entry = std::move(rhs); + } +}; + +} + +template <typename EntryT, typename RefT, typename ReclaimerT> +template <typename ... Args> +typename Allocator<EntryT, RefT>::HandleType +FreeListAllocator<EntryT, RefT, ReclaimerT>::alloc(Args && ... args) +{ + BufferState::FreeListList &freeListList = _store.getFreeList(_typeId); + if (freeListList._head == NULL) { + return ParentType::alloc(std::forward<Args>(args)...); + } + BufferState &state = *freeListList._head; + assert(state.isActive()); + RefT ref = state.popFreeList(); + EntryT *entry = _store.template getBufferEntry<EntryT>(ref.bufferId(), ref.offset()); + ReclaimerT::reclaim(entry); + allocator::Assigner<EntryT, Args...>::assign(*entry, std::forward<Args>(args)...); + return HandleType(ref, entry); +} + +} +} diff --git a/searchlib/src/vespa/searchlib/datastore/handle.h b/searchlib/src/vespa/searchlib/datastore/handle.h new file mode 100644 index 00000000000..b5489d4ecf8 --- /dev/null +++ b/searchlib/src/vespa/searchlib/datastore/handle.h @@ -0,0 +1,22 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +#pragma once + +#include "entryref.h" + +namespace search { +namespace datastore { + +/** + * Handle to data allocated in a data store and a EntryRef used for read-only access to data later. + */ +template <typename EntryT> +struct Handle +{ + EntryRef ref; + EntryT *data; + Handle(EntryRef ref_, EntryT *data_) : ref(ref_), data(data_) {} +}; + +} +} |