aboutsummaryrefslogtreecommitdiffstats
path: root/searchlib
diff options
context:
space:
mode:
authorGeir Storli <geirst@yahoo-inc.com>2016-11-22 17:42:54 +0100
committerGeir Storli <geirst@yahoo-inc.com>2016-11-28 10:49:02 +0100
commit41d1c0dbd5ea84c7f448598d53a2437ab8111691 (patch)
tree056ab7504399f58cc9f11e37dcabb13af8640bc2 /searchlib
parent1c31200e6f6b40344c6ab90743149e66ea3de67d (diff)
Add allocator helper classes used to allocate entries in a data store.
Diffstat (limited to 'searchlib')
-rw-r--r--searchlib/src/vespa/searchlib/btree/btreenode.h20
-rw-r--r--searchlib/src/vespa/searchlib/datastore/allocator.h35
-rw-r--r--searchlib/src/vespa/searchlib/datastore/allocator.hpp35
-rw-r--r--searchlib/src/vespa/searchlib/datastore/datastore.hpp55
-rw-r--r--searchlib/src/vespa/searchlib/datastore/free_list_allocator.h34
-rw-r--r--searchlib/src/vespa/searchlib/datastore/free_list_allocator.hpp70
-rw-r--r--searchlib/src/vespa/searchlib/datastore/handle.h22
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_) {}
+};
+
+}
+}