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

Commit

Permalink
Merge pull request #1021 from igchor/dram_inline_string
Browse files Browse the repository at this point in the history
radix: adjust implementation to work with basic_dram_inline_string
  • Loading branch information
igchor committed Jul 23, 2021
2 parents d13eeb9 + 5ced45d commit 15190c5
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 67 deletions.
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

0 comments on commit 15190c5

Please sign in to comment.