Skip to content
This repository has been archived by the owner on Mar 22, 2023. It is now read-only.

radix: adjust implementation to work with basic_dram_inline_string #1021

Merged
merged 2 commits into from
Jul 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 14 additions & 60 deletions src/engines-experimental/radix.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,6 @@ void transaction::abort()
} /* namespace radix */
} /* namespace internal */

static constexpr size_t align_up(size_t size, size_t align)
{
return ((size) + (align)-1) & ~((align)-1);
}

radix::radix(std::unique_ptr<internal::config> cfg)
: pmemobj_engine_base(cfg, "pmemkv_radix"), config(std::move(cfg))
{
Expand Down Expand Up @@ -463,51 +458,6 @@ const heterogeneous_radix::uvalue_type *heterogeneous_radix::tombstone_persisten
return reinterpret_cast<const heterogeneous_radix::uvalue_type *>(2ULL);
}

heterogeneous_radix::queue_entry::queue_entry(cache_type::value_type *dram_entry,
string_view key_, string_view value_)
: dram_entry(dram_entry)
{
auto key_size = pmem::obj::experimental::total_sizeof<uvalue_type>::value(key_);
auto key_dst = reinterpret_cast<uvalue_type *>(this + 1);
auto padding = align_up(key_size, alignof(uvalue_type)) - key_size;
auto val_dst = reinterpret_cast<uvalue_type *>(reinterpret_cast<char *>(key_dst) +
key_size + padding);

new (key_dst) uvalue_type(key_);

if (value_.data() == nullptr) {
new (val_dst) uvalue_type(string_view(""));
remove = true;
} else {
new (val_dst) uvalue_type(value_);
remove = false;
}
}

const heterogeneous_radix::uvalue_type &heterogeneous_radix::queue_entry::key() const
{
auto key = reinterpret_cast<const uvalue_type *>(this + 1);
return *key;
}

const heterogeneous_radix::uvalue_type &heterogeneous_radix::queue_entry::value() const
{
auto key_size = pmem::obj::experimental::total_sizeof<uvalue_type>::value(
string_view(key()));
auto key_dst = reinterpret_cast<const char *>(this + 1);
auto padding = align_up(key_size, alignof(uvalue_type)) - key_size;
auto val_dst =
reinterpret_cast<const uvalue_type *>(key_dst + key_size + padding);

return *reinterpret_cast<const uvalue_type *>(val_dst);
}

heterogeneous_radix::uvalue_type &heterogeneous_radix::queue_entry::value()
{
auto val = &const_cast<const queue_entry *>(this)->value();
return *const_cast<heterogeneous_radix::uvalue_type *>(val);
}

heterogeneous_radix::heterogeneous_radix(std::unique_ptr<internal::config> cfg)
: pmemobj_engine_base(cfg, "pmemkv_radix"), config(std::move(cfg))
{
Expand Down Expand Up @@ -629,14 +579,18 @@ status heterogeneous_radix::put(string_view key, string_view value)
auto padding = align_up(uvalue_key_size, alignof(uvalue_type)) - uvalue_key_size;
auto req_size = uvalue_key_size +
pmem::obj::experimental::total_sizeof<uvalue_type>::value(value) +
sizeof(queue_entry) + padding;
sizeof(queue_entry<dram_uvalue_type>) + padding;

using alloc_type = typename std::aligned_storage<sizeof(queue_entry),
alignof(queue_entry)>::type;
auto alloc_size = (req_size + sizeof(queue_entry) - 1) / sizeof(queue_entry);
using alloc_type = typename std::aligned_storage<
sizeof(queue_entry<dram_uvalue_type>),
alignof(queue_entry<dram_uvalue_type>)>::type;
auto alloc_size = (req_size + sizeof(queue_entry<dram_uvalue_type>) - 1) /
sizeof(queue_entry<dram_uvalue_type>);
auto data = std::unique_ptr<alloc_type[]>(new alloc_type[alloc_size]);

assert(reinterpret_cast<uintptr_t>(data.get()) % alignof(queue_entry) == 0);
assert(reinterpret_cast<uintptr_t>(data.get()) %
alignof(queue_entry<dram_uvalue_type>) ==
0);

/* XXX: implement blocking cache_put_with_evict */
cache_type::value_type *cache_val = nullptr;
Expand All @@ -645,15 +599,15 @@ status heterogeneous_radix::put(string_view key, string_view value)
handle_oom_from_bg();
}

new (data.get()) queue_entry(cache_val, key, value);
new (data.get()) queue_entry<dram_uvalue_type>(cache_val, key, value);

while (true) {
auto produced = queue_worker->try_produce(
pmem::obj::string_view(reinterpret_cast<const char *>(data.get()),
req_size),
[&](pmem::obj::string_view target) {
auto pmem_entry = reinterpret_cast<const queue_entry *>(
target.data());
auto pmem_entry = reinterpret_cast<
const queue_entry<uvalue_type> *>(target.data());
assert(pmem_entry->key() == key);

const uvalue_type *val =
Expand Down Expand Up @@ -1102,8 +1056,8 @@ void heterogeneous_radix::consume_queue_entry(pmem::obj::string_view entry,
* This allows us to keep processed elements in cache without additional
* value copies.
*/
auto e = reinterpret_cast<const queue_entry *>(entry.data());
auto dram_entry = const_cast<queue_entry *>(e)->dram_entry;
auto e = reinterpret_cast<const queue_entry<uvalue_type> *>(entry.data());
auto dram_entry = const_cast<queue_entry<uvalue_type> *>(e)->dram_entry;
const uvalue_type *expected = e->remove ? tombstone_volatile() : &e->value();
const uvalue_type *desired;

Expand Down
67 changes: 63 additions & 4 deletions src/engines-experimental/radix.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,27 +315,29 @@ class heterogeneous_radix
using container_type = internal::radix::map_mt_type;
using pmem_type = internal::radix::pmem_type<container_type>;
using uvalue_type = pmem::obj::experimental::inline_string;
using dram_uvalue_type = pmem::obj::experimental::dram_inline_string;
using cache_type = internal::radix::ordered_cache<uvalue_type>;
using pmem_log_type = internal::radix::log_type;
using unique_ptr_type = std::unique_ptr<const char[], void (*)(const char *)>;
using dram_iterator = typename cache_type::iterator;
using pmem_iterator = typename container_type::iterator;

template <typename KeyValueType>
struct queue_entry {
queue_entry(cache_type::value_type *dram_entry, string_view key_,
string_view value_);

const uvalue_type &key() const;
const KeyValueType &key() const;

const uvalue_type &value() const;
uvalue_type &value();
const KeyValueType &value() const;
KeyValueType &value();

cache_type::value_type *dram_entry;
bool remove;
char padding[7];
};

static_assert(sizeof(queue_entry) == 16);
static_assert(sizeof(queue_entry<uvalue_type>) == 16, "queue_entry too big");

using pmem_queue_type = pmem::obj::experimental::mpsc_queue;

Expand Down Expand Up @@ -415,6 +417,63 @@ class heterogeneous_radix
std::unique_ptr<pmem_queue_type::worker> queue_worker;
};

static inline constexpr size_t align_up(size_t size, size_t align)
{
return ((size) + (align)-1) & ~((align)-1);
}

template <typename KeyValueType>
heterogeneous_radix::queue_entry<KeyValueType>::queue_entry(
heterogeneous_radix::cache_type::value_type *dram_entry, string_view key_,
string_view value_)
: dram_entry(dram_entry)
{
auto key_size = pmem::obj::experimental::total_sizeof<KeyValueType>::value(key_);
auto key_dst = reinterpret_cast<KeyValueType *>(this + 1);
auto padding = align_up(key_size, alignof(KeyValueType)) - key_size;
auto val_dst = reinterpret_cast<KeyValueType *>(
reinterpret_cast<char *>(key_dst) + key_size + padding);

new (key_dst) KeyValueType(key_);

if (value_.data() == nullptr) {
new (val_dst) KeyValueType(string_view(""));
remove = true;
} else {
new (val_dst) KeyValueType(value_);
remove = false;
}
}

/* Returns reference to the key which is held right after queue_entry struct. */
template <typename KeyValueType>
const KeyValueType &heterogeneous_radix::queue_entry<KeyValueType>::key() const
{
auto key = reinterpret_cast<const KeyValueType *>(this + 1);
return *key;
}

/* Returns reference to the value which is held after the key (and optional padding). */
template <typename KeyValueType>
const KeyValueType &heterogeneous_radix::queue_entry<KeyValueType>::value() const
{
auto key_size = pmem::obj::experimental::total_sizeof<KeyValueType>::value(
string_view(key()));
auto key_dst = reinterpret_cast<const char *>(this + 1);
auto padding = align_up(key_size, alignof(KeyValueType)) - key_size;
auto val_dst =
reinterpret_cast<const KeyValueType *>(key_dst + key_size + padding);

return *reinterpret_cast<const KeyValueType *>(val_dst);
}

template <typename KeyValueType>
KeyValueType &heterogeneous_radix::queue_entry<KeyValueType>::value()
{
auto val = &const_cast<const queue_entry<KeyValueType> *>(this)->value();
return *const_cast<KeyValueType *>(val);
}

template <>
class radix::radix_iterator<true> : public internal::iterator_base {
using container_type = radix::container_type;
Expand Down
5 changes: 2 additions & 3 deletions utils/docker/images/install-libpmemobj-cpp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ PREFIX="/usr"
PACKAGE_TYPE=${1^^} #To uppercase
echo "PACKAGE_TYPE: ${PACKAGE_TYPE}"

# Merge pull request #1151 from igchor/more_radix_fixes
# More radix fixes
LIBPMEMOBJ_CPP_VERSION="36bfcee24b652f5dba702d35adf4989f3e9baa7a"
# 1.13.0-rc1 release
LIBPMEMOBJ_CPP_VERSION="5629c29a2a998ce0c1b45db5885358c35435a7a3"
echo "LIBPMEMOBJ_CPP_VERSION: ${LIBPMEMOBJ_CPP_VERSION}"

build_dir=$(mktemp -d -t libpmemobj-cpp-XXX)
Expand Down