aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinnokentii <innokentii@yandex-team.com>2022-09-16 17:12:05 +0300
committerinnokentii <innokentii@yandex-team.com>2022-09-16 17:12:05 +0300
commit2df8226558ba61b949a051ef03f59e2a60443cd4 (patch)
tree66c716bc8ce6f5ce13902a153581da32ffc7f792
parent0543d8ded75208f6c8de016998adb0d8b9b7530d (diff)
downloadydb-2df8226558ba61b949a051ef03f59e2a60443cd4.tar.gz
Add TContiguousData
extract TChunk as TContiguousData
-rw-r--r--library/cpp/actors/util/contiguous_data.h671
-rw-r--r--library/cpp/actors/util/contiguous_data_ut.cpp52
-rw-r--r--library/cpp/actors/util/rope.h556
-rw-r--r--library/cpp/actors/util/rope_cont_embedded_list.h2
-rw-r--r--library/cpp/actors/util/rope_ut.cpp63
-rw-r--r--library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp231
-rw-r--r--library/cpp/actors/util/shared_data_rope_backend.h10
-rw-r--r--library/cpp/actors/util/ut_helpers.h12
-rw-r--r--ydb/core/blobstorage/crypto/CMakeLists.txt1
-rw-r--r--ydb/core/blobstorage/crypto/ut/ut_helpers.h8
-rw-r--r--ydb/core/blobstorage/vdisk/hulldb/base/blobstorage_blob_ut.cpp2
-rw-r--r--ydb/core/blobstorage/vdisk/hulldb/base/hullds_arena.h10
-rw-r--r--ydb/core/blobstorage/vdisk/scrub/scrub_actor.cpp2
-rw-r--r--ydb/core/blobstorage/vdisk/scrub/scrub_actor_impl.h2
14 files changed, 1122 insertions, 500 deletions
diff --git a/library/cpp/actors/util/contiguous_data.h b/library/cpp/actors/util/contiguous_data.h
new file mode 100644
index 0000000000..ae4c913c20
--- /dev/null
+++ b/library/cpp/actors/util/contiguous_data.h
@@ -0,0 +1,671 @@
+#pragma once
+
+#include <util/generic/ptr.h>
+#include <util/generic/string.h>
+#include <util/generic/hash_set.h>
+#include <util/generic/scope.h>
+#include <util/stream/str.h>
+#include <util/system/sanitizers.h>
+#include <util/system/valgrind.h>
+#include <util/generic/array_ref.h>
+
+#include "shared_data.h"
+
+namespace NContiguousDataDetails {
+ template<typename TContainer>
+ struct TContainerTraits {
+ static char* UnsafeGetDataMut(const TContainer& backend) {
+ return const_cast<char*>(backend.data());
+ }
+ };
+} // NContiguousDataDetails
+
+class TContiguousSpan
+{
+private:
+ const char *Data = nullptr;
+ size_t Size = 0;
+
+public:
+ TContiguousSpan() = default;
+
+ TContiguousSpan(const char *data, size_t size)
+ : Data(data)
+ , Size(size)
+ {}
+
+ TContiguousSpan(const TString& str)
+ : Data(str.data())
+ , Size(str.size())
+ {}
+
+ TContiguousSpan(const TStringBuf& str)
+ : Data(str.data())
+ , Size(str.size())
+ {}
+
+ TContiguousSpan(const TArrayRef<char>& ref)
+ : Data(ref.data())
+ , Size(ref.size())
+ {}
+
+ TContiguousSpan(const TArrayRef<const char>& ref)
+ : Data(ref.data())
+ , Size(ref.size())
+ {}
+
+ TContiguousSpan(const NActors::TSharedData& data)
+ : Data(data.data())
+ , Size(data.size())
+ {}
+
+ const char *data() const noexcept {
+ return Data;
+ }
+
+ size_t size() const noexcept {
+ return Size;
+ }
+
+ const char *GetData() const noexcept {
+ return Data;
+ }
+
+ size_t GetSize() const noexcept {
+ return Size;
+ }
+
+ TContiguousSpan SubSpan(size_t pos, size_t n) const noexcept {
+ pos = Min(pos, size());
+ n = Min(n, size() - pos);
+ return TContiguousSpan(data() + pos, n);
+ }
+
+ friend bool operator==(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) == 0; }
+ friend bool operator!=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) != 0; }
+ friend bool operator< (const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) < 0; }
+ friend bool operator<=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) <= 0; }
+ friend bool operator> (const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) > 0; }
+ friend bool operator>=(const TContiguousSpan& x, const TContiguousSpan& y) { return Compare(x, y) >= 0; }
+
+private:
+ static int Compare(const TContiguousSpan& x, const TContiguousSpan& y) {
+ if(int res = std::memcmp(x.data(), y.data(), std::min(x.size(), y.size())); res) {
+ return res;
+ }
+ return x.size() - y.size();
+ }
+};
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator==(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) == TContiguousSpan(rhs);
+}
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator!=(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) != TContiguousSpan(rhs);
+}
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator<(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) < TContiguousSpan(rhs);
+}
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator<=(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) <= TContiguousSpan(rhs);
+}
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator>(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) > TContiguousSpan(rhs);
+}
+
+template <
+ class TLeft,
+ class TRight,
+ typename std::enable_if<std::is_convertible<TLeft,TContiguousSpan>::value>::type* = nullptr,
+ typename std::enable_if<std::is_convertible<TRight,TContiguousSpan>::value>::type* = nullptr
+ >
+bool operator>=(const TLeft& lhs, const TRight& rhs) {
+ return TContiguousSpan(lhs) >= TContiguousSpan(rhs);
+}
+
+
+class TMutableContiguousSpan
+{
+private:
+ char *Data = nullptr;
+ size_t Size = 0;
+
+public:
+ TMutableContiguousSpan() = default;
+
+ TMutableContiguousSpan(char *data, size_t size)
+ : Data(data)
+ , Size(size)
+ {}
+
+ char *data() noexcept {
+ return Data;
+ }
+
+ char *GetData() noexcept {
+ return Data;
+ }
+
+ TMutableContiguousSpan SubSpan(size_t pos, size_t n) noexcept {
+ pos = Min(pos, size());
+ n = Min(n, size() - pos);
+ return TMutableContiguousSpan(data() + pos, n);
+ }
+
+ const char *data() const noexcept {
+ return Data;
+ }
+
+ size_t size() const noexcept {
+ return Size;
+ }
+
+ const char *GetData() const noexcept {
+ return Data;
+ }
+
+ size_t GetSize() const noexcept {
+ return Size;
+ }
+
+ TContiguousSpan SubSpan(size_t pos, size_t n) const noexcept {
+ pos = Min(pos, size());
+ n = Min(n, size() - pos);
+ return TContiguousSpan(data() + pos, n);
+ }
+
+ operator TContiguousSpan() const noexcept {
+ return TContiguousSpan(Data, Size);
+ }
+};
+
+struct IContiguousChunk : TThrRefBase {
+ using TPtr = TIntrusivePtr<IContiguousChunk>;
+
+ virtual ~IContiguousChunk() = default;
+
+ /**
+ * Should give immutable access to data
+ */
+ virtual TContiguousSpan GetData() const = 0;
+
+ /**
+ * Should give mutable access to underlying data
+ * If data is shared - data should be copied
+ * E.g. for TString str.Detach() should be used
+ * Possibly invalidates previous *GetData*() calls
+ */
+ virtual TMutableContiguousSpan GetDataMut() = 0;
+
+ /**
+ * Should give mutable access to undelying data as fast as possible
+ * Even if data is shared this property should be ignored
+ * E.g. in TString const_cast<char *>(str.data()) should be used
+ * Possibly invalidates previous *GetData*() calls
+ */
+ virtual TMutableContiguousSpan UnsafeGetDataMut() {
+ return GetDataMut();
+ }
+
+ virtual size_t GetCapacity() const = 0;
+};
+
+class TRope;
+class TRopeArena;
+
+class TContiguousData {
+ friend class TRope;
+ friend class TRopeArena;
+ class TBackend {
+ enum class EType : uintptr_t {
+ STRING,
+ SHARED_DATA,
+ ROPE_CHUNK_BACKEND,
+ };
+
+ struct TBackendHolder {
+ uintptr_t Data[2];
+ operator bool() const noexcept {
+ return Data[0] || Data[1];
+ }
+ };
+
+ constexpr static TBackendHolder Empty = {0, 0};
+
+#ifndef TSTRING_IS_STD_STRING
+ static_assert(sizeof(TBackendHolder) >= sizeof(TString));
+#endif
+ static_assert(sizeof(TBackendHolder) >= sizeof(NActors::TSharedData));
+
+ TBackendHolder Owner = TBackend::Empty; // lower bits contain type of the owner
+
+ public:
+ TBackend() = default;
+
+ TBackend(const TBackend& other)
+ : Owner(Clone(other.Owner))
+ {}
+
+ TBackend(TBackend&& other)
+ : Owner(std::exchange(other.Owner, TBackend::Empty))
+ {}
+
+ TBackend(TString s)
+ : Owner(Construct<TString>(EType::STRING, std::move(s)))
+ {}
+
+ TBackend(NActors::TSharedData s)
+ : Owner(Construct<NActors::TSharedData>(EType::SHARED_DATA, std::move(s)))
+ {}
+
+ TBackend(IContiguousChunk::TPtr backend)
+ : Owner(Construct<IContiguousChunk::TPtr>(EType::ROPE_CHUNK_BACKEND, std::move(backend)))
+ {}
+
+ ~TBackend() {
+ if (Owner) {
+ Destroy(Owner);
+ }
+ }
+
+ TBackend& operator =(const TBackend& other) {
+ if (Y_UNLIKELY(this == &other)) {
+ return *this;
+ }
+
+ if (Owner) {
+ Destroy(Owner);
+ }
+ Owner = Clone(other.Owner);
+ return *this;
+ }
+
+ TBackend& operator =(TBackend&& other) {
+ if (Y_UNLIKELY(this == &other)) {
+ return *this;
+ }
+
+ if (Owner) {
+ Destroy(Owner);
+ }
+ Owner = std::exchange(other.Owner, TBackend::Empty);
+ return *this;
+ }
+
+ bool operator ==(const TBackend& other) const {
+ return Owner == other.Owner;
+ }
+
+ const void *UniqueId() const {
+ return reinterpret_cast<const void*>(Owner.Data[0]);
+ }
+
+ TContiguousSpan GetData() const {
+ return Visit(Owner, [](EType, auto& value) -> TContiguousSpan {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, TString>) {
+ return {value.data(), value.size()};
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ return {value.data(), value.size()};
+ } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
+ return value->GetData();
+ } else {
+ return {};
+ }
+ });
+ }
+
+ TMutableContiguousSpan GetDataMut() {
+ return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, TString>) {
+ return {value.Detach(), value.size()};
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ if(value.IsShared()) {
+ value = NActors::TSharedData::Copy(value.data(), value.size());
+ }
+ return {value.mutable_data(), value.size()};
+ } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
+ return value->GetDataMut();
+ } else {
+ return {};
+ }
+ });
+ }
+
+ TMutableContiguousSpan UnsafeGetDataMut() const {
+ return Visit(Owner, [](EType, auto& value) -> TMutableContiguousSpan {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, TString>) {
+ return {const_cast<char*>(value.data()), value.size()};
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ return {const_cast<char*>(value.data()), value.size()};
+ } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
+ return value->UnsafeGetDataMut();
+ } else {
+ return {};
+ }
+ });
+ }
+
+ size_t GetCapacity() const {
+ return Visit(Owner, [](EType, auto& value) {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, TString>) {
+ return value.capacity();
+ } else if constexpr (std::is_same_v<T, NActors::TSharedData>) {
+ return value.size(); // There is no capacity
+ } else if constexpr (std::is_same_v<T, IContiguousChunk::TPtr>) {
+ return value->GetCapacity();
+ } else {
+ Y_FAIL();
+ }
+ });
+ }
+
+ template <class TType>
+ bool ContainsNativeType() const {
+ return Visit(Owner, [](EType, auto& value) {
+ using T = std::decay_t<decltype(value)>;
+ return std::is_same_v<T, TType>;
+ });
+ }
+
+ template <class TResult>
+ TResult GetRaw() const {
+ return Visit(Owner, [](EType, auto& value) {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (std::is_same_v<T, TResult>) {
+ return value;
+ } else {
+ Y_FAIL();
+ return TResult{}; // unreachable
+ }
+ });
+ }
+
+ explicit operator bool() const {
+ return Owner;
+ }
+
+ private:
+ static constexpr uintptr_t TypeMask = (1 << 3) - 1;
+ static constexpr uintptr_t ValueMask = ~TypeMask;
+
+ template<typename T>
+ struct TObjectHolder {
+ struct TWrappedObject : TThrRefBase {
+ T Value;
+ TWrappedObject(T&& value)
+ : Value(std::move(value))
+ {}
+ };
+ TIntrusivePtr<TWrappedObject> Object;
+
+ TObjectHolder(T&& object)
+ : Object(MakeIntrusive<TWrappedObject>(std::move(object)))
+ {}
+ };
+
+ template<typename TObject>
+ static TBackendHolder Construct(EType type, TObject object) {
+ if constexpr (sizeof(TObject) <= sizeof(TBackendHolder)) {
+ TBackendHolder res = TBackend::Empty;
+ new(&res) TObject(std::move(object));
+ Y_VERIFY_DEBUG((res.Data[0] & ValueMask) == res.Data[0]);
+ res.Data[0] = res.Data[0] | static_cast<uintptr_t>(type);
+ return res;
+ } else {
+ return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::move(object)));
+ }
+ }
+
+ template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
+ static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> VisitRaw(TOwner& origValue, TCallback&& callback) {
+ Y_VERIFY_DEBUG(origValue);
+ const EType type = static_cast<EType>(origValue.Data[0] & TypeMask);
+ TBackendHolder value(origValue);
+ value.Data[0] = value.Data[0] & ValueMask;
+ // bring object type back
+ Y_SCOPE_EXIT(&value, &origValue, type){
+ if constexpr(!IsConst) {
+ value.Data[0] = value.Data[0] | static_cast<uintptr_t>(type);
+ origValue = value;
+ } else {
+ Y_UNUSED(value);
+ Y_UNUSED(origValue);
+ Y_UNUSED(type);
+ }
+ };
+ auto caller = [&](auto& value) { return std::invoke(std::forward<TCallback>(callback), type, value); };
+ auto wrapper = [&](auto& value) {
+ using T = std::decay_t<decltype(value)>;
+ if constexpr (sizeof(T) <= sizeof(TBackendHolder)) {
+ return caller(value);
+ } else {
+ return caller(reinterpret_cast<std::conditional_t<IsConst, const TObjectHolder<T>&, TObjectHolder<T>&>>(value));
+ }
+ };
+ switch (type) {
+ case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value));
+ case EType::SHARED_DATA: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const NActors::TSharedData&, NActors::TSharedData&>>(value));
+ case EType::ROPE_CHUNK_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IContiguousChunk::TPtr&, IContiguousChunk::TPtr&>>(value));
+ }
+ Y_FAIL("Unexpected type# %" PRIu64, static_cast<ui64>(type));
+ }
+
+ template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
+ static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> Visit(TOwner& value, TCallback&& callback) {
+ return VisitRaw(value, [&](EType type, auto& value) {
+ return std::invoke(std::forward<TCallback>(callback), type, Unwrap(value));
+ });
+ }
+
+ template<typename T> static T& Unwrap(T& object) { return object; }
+ template<typename T> static T& Unwrap(TObjectHolder<T>& holder) { return holder.Object->Value; }
+ template<typename T> static const T& Unwrap(const TObjectHolder<T>& holder) { return holder.Object->Value; }
+
+ template<typename TOwner>
+ static TBackendHolder Clone(TOwner& value) {
+ return VisitRaw(value, [](EType type, auto& value) { return Construct(type, value); });
+ }
+
+ template<typename TOwner>
+ static void Destroy(TOwner& value) {
+ VisitRaw(value, [](EType, auto& value) { CallDtor(value); });
+ }
+
+ template<typename T>
+ static void CallDtor(T& value) {
+ value.~T();
+ }
+ };
+
+ TBackend Backend; // who actually holds the data
+ const char *Begin; // data start
+ const char *End; // data end
+
+public:
+ static constexpr struct TSlice {} Slice{};
+
+ TContiguousData()
+ : Begin(nullptr)
+ , End(nullptr)
+ {}
+
+ template<typename T>
+ TContiguousData(T&& backend, const TContiguousSpan& data)
+ : Backend(std::forward<T>(backend))
+ , Begin(data.data())
+ , End(Begin + data.size())
+ {
+ Y_VERIFY_DEBUG(Begin != End);
+ }
+
+ explicit TContiguousData(TString s)
+ : Backend(std::move(s))
+ {
+ auto span = Backend.GetData();
+ Begin = span.data();
+ End = Begin + span.size();
+ }
+
+ explicit TContiguousData(NActors::TSharedData s)
+ : Backend(std::move(s))
+ {
+ auto span = Backend.GetData();
+ Begin = span.data();
+ End = Begin + span.size();
+ }
+
+ TContiguousData(IContiguousChunk::TPtr backend)
+ : TContiguousData(backend, backend->GetData())
+ {}
+
+ TContiguousData(TSlice, const char *data, size_t size, const TContiguousData& from)
+ : TContiguousData(from.Backend, {data, size})
+ {}
+
+ TContiguousData(TSlice, const char *begin, const char *end, const TContiguousData& from)
+ : TContiguousData(Slice, begin, end - begin, from)
+ {}
+
+ TContiguousData(const TContiguousData& other)
+ : Backend(other.Backend)
+ , Begin(other.Begin)
+ , End(other.End)
+ {}
+
+ TContiguousData(TContiguousData&& other)
+ : Backend(std::move(other.Backend))
+ , Begin(other.Begin)
+ , End(other.End)
+ {}
+
+ TContiguousData& operator =(const TContiguousData&) = default;
+ TContiguousData& operator =(TContiguousData&&) = default;
+
+ template <class TType>
+ bool ContainsNativeType() const {
+ return Backend.ContainsNativeType<TType>();
+ }
+
+ template <class TResult>
+ TResult GetRaw() const {
+ return Backend.GetRaw<TResult>();
+ }
+
+ bool ReferencesWholeContainer() const {
+ return Backend.GetData().size() == GetSize();
+ }
+
+ size_t GetSize() const {
+ return End - Begin;
+ }
+
+ size_t GetCapacity() const {
+ return Backend.GetCapacity();
+ }
+
+ const char* GetData() const {
+ return Begin;
+ }
+
+ char* GetDataMut() {
+ const char* oldBegin = Backend.GetData().data();
+ ptrdiff_t offset = Begin - oldBegin;
+ size_t size = GetSize();
+ char* newBegin = Backend.GetDataMut().data();
+ Begin = newBegin + offset;
+ End = Begin + size;
+ return newBegin + offset;
+ }
+
+ char* UnsafeGetDataMut() {
+ const char* oldBegin = Backend.GetData().data();
+ ptrdiff_t offset = Begin - oldBegin;
+ size_t size = GetSize();
+ char* newBegin = Backend.UnsafeGetDataMut().data();
+ Begin = newBegin + offset;
+ End = Begin + size;
+ return newBegin + offset;
+ }
+
+ template <class TResult>
+ TResult ExtractUnderlyingContainerOrCopy() const {
+ if (ContainsNativeType<TResult>() && ReferencesWholeContainer()) {
+ return GetRaw<TResult>();
+ }
+
+ TResult res = TResult::Uninitialized(GetSize());
+ char* data = NContiguousDataDetails::TContainerTraits<TResult>::UnsafeGetDataMut(res);
+ std::memcpy(data, Begin, End - Begin);
+ return res;
+ }
+
+ TContiguousSpan GetContiguousSpan() const {
+ return {GetData(), GetSize()};
+ }
+
+ TMutableContiguousSpan GetContiguousSpanMut() {
+ return {GetDataMut(), GetSize()};
+ }
+
+ TMutableContiguousSpan UnsafeGetContiguousSpanMut() {
+ return {UnsafeGetDataMut(), GetSize()};
+ }
+
+ size_t size() const {
+ return GetSize();
+ }
+
+ size_t capacity() const {
+ return GetCapacity();
+ }
+
+ const char* data() const {
+ return GetData();
+ }
+
+ operator TContiguousSpan() const noexcept {
+ return TContiguousSpan(GetData(), GetSize());
+ }
+
+ explicit operator TMutableContiguousSpan() noexcept {
+ return TMutableContiguousSpan(GetDataMut(), GetSize());
+ }
+};
diff --git a/library/cpp/actors/util/contiguous_data_ut.cpp b/library/cpp/actors/util/contiguous_data_ut.cpp
new file mode 100644
index 0000000000..b9361b3f39
--- /dev/null
+++ b/library/cpp/actors/util/contiguous_data_ut.cpp
@@ -0,0 +1,52 @@
+#include "contiguous_data.h"
+#include "ut_helpers.h"
+#include "rope.h"
+
+#include <library/cpp/testing/unittest/registar.h>
+#include <util/random/random.h>
+
+Y_UNIT_TEST_SUITE(TContiguousData) {
+ Y_UNIT_TEST(TypeSize) {
+ UNIT_ASSERT_EQUAL(sizeof(TContiguousData), 4 * sizeof(uintptr_t));
+ }
+
+ Y_UNIT_TEST(CrossCompare) {
+ TString str = "some very long string";
+ const TString constStr(str);
+ TStringBuf strbuf = str;
+ const TStringBuf constStrbuf = str;
+ TContiguousSpan span(str);
+ const TContiguousSpan constSpan(str);
+ TMutableContiguousSpan mutableSpan(const_cast<char*>(str.data()), str.size());
+ const TMutableContiguousSpan constMutableSpan(const_cast<char*>(str.data()), str.size());
+ TContiguousData data(str);
+ const TContiguousData constData(str);
+ TArrayRef<char> arrRef(const_cast<char*>(str.data()), str.size());
+ const TArrayRef<char> constArrRef(const_cast<char*>(str.data()), str.size());
+ TArrayRef<const char> arrConstRef(const_cast<char*>(str.data()), str.size());
+ const TArrayRef<const char> constArrConstRef(const_cast<char*>(str.data()), str.size());
+ NActors::TSharedData sharedData = NActors::TSharedData::Copy(str.data(), str.size());
+ const NActors::TSharedData constSharedData(sharedData);
+
+ Permutate(
+ [](auto& arg1, auto& arg2) {
+ UNIT_ASSERT(arg1 == arg2);
+ },
+ str,
+ constStr,
+ strbuf,
+ constStrbuf,
+ span,
+ constSpan,
+ mutableSpan,
+ constMutableSpan,
+ data,
+ constData,
+ arrRef,
+ constArrRef,
+ arrConstRef,
+ constArrConstRef,
+ sharedData,
+ constSharedData);
+ }
+}
diff --git a/library/cpp/actors/util/rope.h b/library/cpp/actors/util/rope.h
index 4e5336dc63..2a2e25f3a2 100644
--- a/library/cpp/actors/util/rope.h
+++ b/library/cpp/actors/util/rope.h
@@ -13,33 +13,9 @@
//#include "rope_cont_list.h"
//#include "rope_cont_deque.h"
-struct IRopeChunkBackend : TThrRefBase {
- using TData = std::tuple<const char*, size_t>;
- using TMutData = std::tuple<char*, size_t>;
- virtual ~IRopeChunkBackend() = default;
- /**
- * Should give immutable access to data
- */
- virtual TData GetData() const = 0;
- /**
- * Should give mutable access to underlying data
- * If data is shared - data should be copied
- * E.g. for TString str.Detach() should be used
- */
- virtual TMutData GetDataMut() = 0;
- /**
- * Should give mutable access to undelying data as fast as possible
- * Even if data is shared this property should be ignored
- * E.g. in TString const_cast<char *>(str.data()) should be used
- */
- virtual TMutData UnsafeGetDataMut() {
- return GetDataMut();
- }
- virtual size_t GetCapacity() const = 0;
- using TPtr = TIntrusivePtr<IRopeChunkBackend>;
-};
+#include "contiguous_data.h"
-class TRopeAlignedBuffer : public IRopeChunkBackend {
+class TRopeAlignedBuffer : public IContiguousChunk {
static constexpr size_t Alignment = 16;
static constexpr size_t MallocAlignment = sizeof(size_t);
@@ -78,11 +54,11 @@ public:
Y_UNUSED(ptr);
}
- TData GetData() const override {
+ TContiguousSpan GetData() const override {
return {Data + Offset, Size};
}
- TMutData GetDataMut() override {
+ TMutableContiguousSpan GetDataMut() override {
return {Data + Offset, Size};
}
@@ -117,12 +93,6 @@ namespace NRopeDetails {
using TListIterator = typename TList::iterator;
};
- template<typename TContainer>
- struct TContainerTraits {
- static char* UnsafeGetDataMut(const TContainer& backend) {
- return const_cast<char*>(backend.data());
- }
- };
} // NRopeDetails
class TRopeArena;
@@ -133,332 +103,7 @@ struct always_false : std::false_type {};
class TRope {
friend class TRopeArena;
- struct TChunk
- {
- class TBackend {
- enum class EType : uintptr_t {
- STRING,
- ROPE_CHUNK_BACKEND,
- };
-
- uintptr_t Owner = 0; // lower bits contain type of the owner
-
- public:
- TBackend() = default;
-
- TBackend(const TBackend& other)
- : Owner(Clone(other.Owner))
- {}
-
- TBackend(TBackend&& other)
- : Owner(std::exchange(other.Owner, 0))
- {}
-
- TBackend(TString s)
- : Owner(Construct<TString>(EType::STRING, std::move(s)))
- {}
-
- TBackend(IRopeChunkBackend::TPtr backend)
- : Owner(Construct<IRopeChunkBackend::TPtr>(EType::ROPE_CHUNK_BACKEND, std::move(backend)))
- {}
-
- ~TBackend() {
- if (Owner) {
- Destroy(Owner);
- }
- }
-
- TBackend& operator =(const TBackend& other) {
- if (Owner) {
- Destroy(Owner);
- }
- Owner = Clone(other.Owner);
- return *this;
- }
-
- TBackend& operator =(TBackend&& other) {
- if (Owner) {
- Destroy(Owner);
- }
- Owner = std::exchange(other.Owner, 0);
- return *this;
- }
-
- bool operator ==(const TBackend& other) const {
- return Owner == other.Owner;
- }
-
- const void *UniqueId() const {
- return reinterpret_cast<const void*>(Owner);
- }
-
- const IRopeChunkBackend::TData GetData() const {
- return Visit(Owner, [](EType, auto& value) -> IRopeChunkBackend::TData {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TString>) {
- return {value.data(), value.size()};
- } else if constexpr (std::is_same_v<T, IRopeChunkBackend::TPtr>) {
- return value->GetData();
- } else {
- return {};
- }
- });
- }
-
- const IRopeChunkBackend::TMutData GetDataMut() {
- return Visit(Owner, [](EType, auto& value) -> IRopeChunkBackend::TMutData {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TString>) {
- return {value.Detach(), value.size()};
- } else if constexpr (std::is_same_v<T, IRopeChunkBackend::TPtr>) {
- return value->GetDataMut();
- } else {
- return {};
- }
- });
- }
-
- const IRopeChunkBackend::TMutData UnsafeGetDataMut() const {
- return Visit(Owner, [](EType, auto& value) -> IRopeChunkBackend::TMutData {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TString>) {
- return {const_cast<char*>(value.data()), value.size()};
- } else if constexpr (std::is_same_v<T, IRopeChunkBackend::TPtr>) {
- return value->UnsafeGetDataMut();
- } else {
- return {};
- }
- });
- }
-
- size_t GetCapacity() const {
- return Visit(Owner, [](EType, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TString>) {
- return value.capacity();
- } else if constexpr (std::is_same_v<T, IRopeChunkBackend::TPtr>) {
- return value->GetCapacity();
- } else {
- Y_FAIL();
- }
- });
- }
-
- template <class TType>
- bool ContainsNativeType() const {
- return Visit(Owner, [](EType, auto& value) {
- using T = std::decay_t<decltype(value)>;
- return std::is_same_v<T, TType>;
- });
- }
-
- template <class TResult>
- TResult GetRaw() const {
- return Visit(Owner, [](EType, auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (std::is_same_v<T, TResult>) {
- return value;
- } else {
- Y_FAIL();
- return TResult{}; // unreachable
- }
- });
- }
-
- explicit operator bool() const {
- return Owner;
- }
-
- private:
- static constexpr uintptr_t TypeMask = (1 << 3) - 1;
- static constexpr uintptr_t ValueMask = ~TypeMask;
-
- template<typename T>
- struct TObjectHolder {
- struct TWrappedObject : TThrRefBase {
- T Value;
- TWrappedObject(T&& value)
- : Value(std::move(value))
- {}
- };
- TIntrusivePtr<TWrappedObject> Object;
-
- TObjectHolder(T&& object)
- : Object(MakeIntrusive<TWrappedObject>(std::move(object)))
- {}
- };
-
- template<typename TObject>
- static uintptr_t Construct(EType type, TObject object) {
- if constexpr (sizeof(TObject) <= sizeof(uintptr_t)) {
- uintptr_t res = 0;
- new(&res) TObject(std::move(object));
- Y_VERIFY_DEBUG((res & ValueMask) == res);
- return res | static_cast<uintptr_t>(type);
- } else {
- return Construct<TObjectHolder<TObject>>(type, TObjectHolder<TObject>(std::move(object)));
- }
- }
-
- template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
- static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> VisitRaw(TOwner& origValue, TCallback&& callback) {
- Y_VERIFY_DEBUG(origValue);
- const EType type = static_cast<EType>(origValue & TypeMask);
- uintptr_t value = origValue & ValueMask;
- // bring object type back
- Y_SCOPE_EXIT(&value, &origValue, type){
- if constexpr(!IsConst) {
- origValue = value | static_cast<uintptr_t>(type);
- } else {
- Y_UNUSED(value);
- Y_UNUSED(origValue);
- Y_UNUSED(type);
- }
- };
- auto caller = [&](auto& value) { return std::invoke(std::forward<TCallback>(callback), type, value); };
- auto wrapper = [&](auto& value) {
- using T = std::decay_t<decltype(value)>;
- if constexpr (sizeof(T) <= sizeof(uintptr_t)) {
- return caller(value);
- } else {
- return caller(reinterpret_cast<std::conditional_t<IsConst, const TObjectHolder<T>&, TObjectHolder<T>&>>(value));
- }
- };
- switch (type) {
- case EType::STRING: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const TString&, TString&>>(value));
- case EType::ROPE_CHUNK_BACKEND: return wrapper(reinterpret_cast<std::conditional_t<IsConst, const IRopeChunkBackend::TPtr&, IRopeChunkBackend::TPtr&>>(value));
- }
- Y_FAIL("Unexpected type# %" PRIu64, static_cast<ui64>(type));
- }
-
- template<typename TOwner, typename TCallback, bool IsConst = std::is_const_v<TOwner>>
- static std::invoke_result_t<TCallback, EType, std::conditional_t<IsConst, const TString&, TString&>> Visit(TOwner& value, TCallback&& callback) {
- return VisitRaw(value, [&](EType type, auto& value) {
- return std::invoke(std::forward<TCallback>(callback), type, Unwrap(value));
- });
- }
-
- template<typename T> static T& Unwrap(T& object) { return object; }
- template<typename T> static T& Unwrap(TObjectHolder<T>& holder) { return holder.Object->Value; }
- template<typename T> static const T& Unwrap(const TObjectHolder<T>& holder) { return holder.Object->Value; }
-
- template<typename TOwner>
- static uintptr_t Clone(TOwner& value) {
- return VisitRaw(value, [](EType type, auto& value) { return Construct(type, value); });
- }
-
- template<typename TOwner>
- static void Destroy(TOwner& value) {
- VisitRaw(value, [](EType, auto& value) { CallDtor(value); });
- }
-
- template<typename T>
- static void CallDtor(T& value) {
- value.~T();
- }
- };
-
- TBackend Backend; // who actually holds the data
- const char *Begin; // data start
- const char *End; // data end
-
- static constexpr struct TSlice {} Slice{};
-
- TChunk()
- : Begin(nullptr)
- , End(nullptr)
- {}
-
- template<typename T>
- TChunk(T&& backend, const IRopeChunkBackend::TData& data)
- : Backend(std::forward<T>(backend))
- , Begin(std::get<0>(data))
- , End(Begin + std::get<1>(data))
- {
- Y_VERIFY_DEBUG(Begin != End);
- }
-
- TChunk(TString s)
- : Backend(std::move(s))
- {
- size_t size;
- std::tie(Begin, size) = Backend.GetData();
- End = Begin + size;
- }
-
- TChunk(IRopeChunkBackend::TPtr backend)
- : TChunk(backend, backend->GetData())
- {}
-
- TChunk(TSlice, const char *data, size_t size, const TChunk& from)
- : TChunk(from.Backend, {data, size})
- {}
-
- TChunk(TSlice, const char *begin, const char *end, const TChunk& from)
- : TChunk(Slice, begin, end - begin, from)
- {}
-
- explicit TChunk(const TChunk& other)
- : Backend(other.Backend)
- , Begin(other.Begin)
- , End(other.End)
- {}
-
- TChunk(TChunk&& other)
- : Backend(std::move(other.Backend))
- , Begin(other.Begin)
- , End(other.End)
- {}
-
- TChunk& operator =(const TChunk&) = default;
- TChunk& operator =(TChunk&&) = default;
-
- template <class TType>
- bool ContainsNativeType() const {
- return Backend.ContainsNativeType<TType>();
- }
-
- template <class TResult>
- TResult GetRaw() const {
- return Backend.GetRaw<TResult>();
- }
-
- bool OwnsWholeContainer() const {
- auto [data, size] = Backend.GetData();
- return size == GetSize();
- }
-
- size_t GetSize() const {
- return End - Begin;
- }
-
- size_t GetCapacity() const {
- return Backend.GetCapacity();
- }
-
- char* GetDataMut() {
- const char* oldBegin = std::get<0>(Backend.GetData());
- ptrdiff_t offset = Begin - oldBegin;
- size_t size = GetSize();
- char* newBegin = std::get<0>(Backend.GetDataMut());
- Begin = newBegin + offset;
- End = Begin + size;
- return newBegin + offset;
- }
-
- char* UnsafeGetDataMut() {
- const char* oldBegin = std::get<0>(Backend.GetData());
- ptrdiff_t offset = Begin - oldBegin;
- size_t size = GetSize();
- char* newBegin = std::get<0>(Backend.UnsafeGetDataMut());
- Begin = newBegin + offset;
- End = Begin + size;
- return newBegin + offset;
- }
-
- };
-
- using TChunkList = NRopeDetails::TChunkList<TChunk>;
+ using TChunkList = NRopeDetails::TChunkList<TContiguousData>;
private:
// we use list here to store chain items as we have to keep valid iterators when erase/insert operations are invoked;
@@ -666,13 +311,13 @@ private:
return Iter;
}
- const TChunk& GetChunk() const {
+ const TContiguousData& GetChunk() const {
CheckValid();
return *Iter;
}
template<bool Mut = !IsConst, std::enable_if_t<Mut, bool> = true>
- TChunk& GetChunk() {
+ TContiguousData& GetChunk() {
CheckValid();
return *Iter;
}
@@ -710,6 +355,14 @@ public:
TRope() = default;
TRope(const TRope& rope) = default;
+ TRope(const TContiguousData& data) {
+ Chain.PutToEnd(data);
+ }
+
+ TRope(TContiguousData&& data) {
+ Chain.PutToEnd(std::move(data));
+ }
+
TRope(TRope&& rope)
: Chain(std::move(rope.Chain))
, Size(std::exchange(rope.Size, 0))
@@ -727,8 +380,13 @@ public:
}
}
- TRope(IRopeChunkBackend::TPtr item) {
- std::tie(std::ignore, Size) = item->GetData();
+ explicit TRope(NActors::TSharedData s) {
+ Size = s.size();
+ Chain.PutToEnd(std::move(s));
+ }
+
+ TRope(IContiguousChunk::TPtr item) {
+ Size = item->GetData().size();
Chain.PutToEnd(std::move(item));
}
@@ -742,13 +400,13 @@ public:
while (begin.Iter != end.Iter) {
const size_t size = begin.ContiguousSize();
- Chain.PutToEnd(TChunk::Slice, begin.ContiguousData(), size, begin.GetChunk());
+ Chain.PutToEnd(TContiguousData::Slice, begin.ContiguousData(), size, begin.GetChunk());
begin.AdvanceToNextContiguousBlock();
Size += size;
}
if (begin != end && end.PointsToChunkMiddle()) {
- Chain.PutToEnd(TChunk::Slice, begin.Ptr, end.Ptr, begin.GetChunk());
+ Chain.PutToEnd(TContiguousData::Slice, begin.Ptr, end.Ptr, begin.GetChunk());
Size += end.Ptr - begin.Ptr;
}
}
@@ -869,7 +527,7 @@ public:
return;
}
}
- dest->Chain.PutToEnd(TChunk::Slice, first->Begin, first->Begin + num, *first);
+ dest->Chain.PutToEnd(TContiguousData::Slice, first->Begin, first->Begin + num, *first);
first->Begin += num;
}
}
@@ -887,14 +545,14 @@ public:
// check if we have to split the block
if (pos.PointsToChunkMiddle()) {
- pos.Iter = Chain.InsertBefore(pos.Iter, TChunk::Slice, pos->Begin, pos.Ptr, pos.GetChunk());
+ pos.Iter = Chain.InsertBefore(pos.Iter, TContiguousData::Slice, pos->Begin, pos.Ptr, pos.GetChunk());
++pos.Iter;
pos->Begin = pos.Ptr;
}
// perform glueing if possible
- TChunk *ropeLeft = &rope.Chain.GetFirstChunk();
- TChunk *ropeRight = &rope.Chain.GetLastChunk();
+ TContiguousData *ropeLeft = &rope.Chain.GetFirstChunk();
+ TContiguousData *ropeRight = &rope.Chain.GetLastChunk();
bool gluedLeft = false, gluedRight = false;
if (pos.Iter != Chain.begin()) { // glue left part whenever possible
// obtain iterator to previous chunk
@@ -935,7 +593,7 @@ public:
while (len) {
Y_VERIFY_DEBUG(Chain);
- TChunk& item = Chain.GetFirstChunk();
+ TContiguousData& item = Chain.GetFirstChunk();
const size_t itemSize = item.GetSize();
if (len >= itemSize) {
Chain.EraseFront();
@@ -955,7 +613,7 @@ public:
while (len) {
Y_VERIFY_DEBUG(Chain);
- TChunk& item = Chain.GetLastChunk();
+ TContiguousData& item = Chain.GetLastChunk();
const size_t itemSize = item.GetSize();
if (len >= itemSize) {
Chain.EraseBack();
@@ -1012,7 +670,7 @@ public:
return xIter.Valid() - yIter.Valid();
}
- static int Compare(const TRope& x, const TString& y) {
+ static int Compare(const TRope& x, const TContiguousSpan& y) {
TConstIterator xIter = x.Begin();
const char* yData = y.data();
size_t yOffset = 0;
@@ -1027,7 +685,7 @@ public:
return xIter.Valid() - (yOffset != y.size());
}
- static int Compare(const TString& x, const TRope& y) {
+ static int Compare(const TContiguousSpan& x, const TRope& y) {
return -Compare(y, x);
}
@@ -1046,94 +704,15 @@ public:
TResult ExtractUnderlyingContainerOrCopy() const {
if (IsContiguous() && GetSize() != 0) {
const auto& chunk = Begin().GetChunk();
- if (chunk.ContainsNativeType<TResult>() && chunk.OwnsWholeContainer()) {
- return chunk.GetRaw<TResult>();
- }
+ return chunk.ExtractUnderlyingContainerOrCopy<TResult>();
}
TResult res = TResult::Uninitialized(GetSize());
- char* data = NRopeDetails::TContainerTraits<TResult>::UnsafeGetDataMut(res);
+ char* data = NContiguousDataDetails::TContainerTraits<TResult>::UnsafeGetDataMut(res);
Begin().ExtractPlainDataAndAdvance(data, res.size());
return res;
}
- class TContiguousSpan;
- class TMutableContiguousSpan {
- friend class TContiguousSpan;
- private:
- char *Data;
- size_t Size;
-
- public:
- TMutableContiguousSpan(char *data, size_t size)
- : Data(data)
- , Size(size)
- {}
-
- char *data() {
- return Data;
- }
-
- const char *data() const {
- return Data;
- }
-
- size_t size() const {
- return Size;
- }
-
- char *GetData() {
- return Data;
- }
-
- const char *GetData() const {
- return Data;
- }
-
- size_t GetSize() const {
- return Size;
- }
- };
-
- class TContiguousSpan {
- private:
- const char *Data;
- size_t Size;
-
- public:
- TContiguousSpan(const char *data, size_t size)
- : Data(data)
- , Size(size)
- {}
-
- TContiguousSpan(const TMutableContiguousSpan& other)
- : Data(other.Data)
- , Size(other.Size)
- {}
-
- TContiguousSpan& operator =(const TMutableContiguousSpan& other) {
- Data = other.Data;
- Size = other.Size;
- return *this;
- }
-
- const char *data() const {
- return Data;
- }
-
- size_t size() const {
- return Size;
- }
-
- const char *GetData() const {
- return Data;
- }
-
- size_t GetSize() const {
- return Size;
- }
- };
-
void clear() {
Erase(Begin(), End());
}
@@ -1170,7 +749,7 @@ public:
return {nullptr, 0};
}
Compact();
- return {Begin().ContiguousData(), Begin().ContiguousSize()};
+ return Begin()->GetContiguousSpan();
}
/**
@@ -1182,7 +761,7 @@ public:
return {nullptr, 0};
}
Compact();
- return {Begin().ContiguousDataMut(), Begin().ContiguousSize()};
+ return Begin()->GetContiguousSpanMut();
}
/**
@@ -1195,7 +774,7 @@ public:
return {nullptr, 0};
}
Compact();
- return {Begin().UnsafeContiguousDataMut(), Begin().ContiguousSize()};
+ return Begin()->UnsafeGetContiguousSpanMut();
}
TString DebugString() const {
@@ -1203,13 +782,18 @@ public:
s << "{Size# " << Size;
for (const auto& chunk : Chain) {
const char *data;
- std::tie(data, std::ignore) = chunk.Backend.GetData();
+ data = chunk.Backend.GetData().data();
s << " [" << chunk.Begin - data << ", " << chunk.End - data << ")@" << chunk.Backend.UniqueId();
}
s << "}";
return s.Str();
}
+ explicit operator TContiguousData() {
+ Compact();
+ return TContiguousData(Begin().GetChunk());
+ }
+
friend bool operator==(const TRope& x, const TRope& y) { return Compare(x, y) == 0; }
friend bool operator!=(const TRope& x, const TRope& y) { return Compare(x, y) != 0; }
friend bool operator< (const TRope& x, const TRope& y) { return Compare(x, y) < 0; }
@@ -1217,19 +801,35 @@ public:
friend bool operator> (const TRope& x, const TRope& y) { return Compare(x, y) > 0; }
friend bool operator>=(const TRope& x, const TRope& y) { return Compare(x, y) >= 0; }
- friend bool operator==(const TRope& x, const TString& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TRope& x, const TString& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TRope& x, const TString& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TRope& x, const TString& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TRope& x, const TString& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TRope& x, const TString& y) { return Compare(x, y) >= 0; }
+ friend bool operator==(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) == 0; }
+ friend bool operator!=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) != 0; }
+ friend bool operator< (const TRope& x, const TContiguousSpan& y) { return Compare(x, y) < 0; }
+ friend bool operator<=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) <= 0; }
+ friend bool operator> (const TRope& x, const TContiguousSpan& y) { return Compare(x, y) > 0; }
+ friend bool operator>=(const TRope& x, const TContiguousSpan& y) { return Compare(x, y) >= 0; }
+
+ friend bool operator==(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) == 0; }
+ friend bool operator!=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) != 0; }
+ friend bool operator< (const TContiguousSpan& x, const TRope& y) { return Compare(x, y) < 0; }
+ friend bool operator<=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) <= 0; }
+ friend bool operator> (const TContiguousSpan& x, const TRope& y) { return Compare(x, y) > 0; }
+ friend bool operator>=(const TContiguousSpan& x, const TRope& y) { return Compare(x, y) >= 0; }
+
+ // FIXME(innokentii) temporary hack
+ friend bool operator==(const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) == 0; }
+ friend bool operator!=(const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) != 0; }
+ friend bool operator< (const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) < 0; }
+ friend bool operator<=(const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) <= 0; }
+ friend bool operator> (const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) > 0; }
+ friend bool operator>=(const TRope& x, const TContiguousData& y) { return Compare(x, y.GetContiguousSpan()) >= 0; }
+
+ friend bool operator==(const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) == 0; }
+ friend bool operator!=(const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) != 0; }
+ friend bool operator< (const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) < 0; }
+ friend bool operator<=(const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) <= 0; }
+ friend bool operator> (const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) > 0; }
+ friend bool operator>=(const TContiguousData& x, const TRope& y) { return Compare(x.GetContiguousSpan(), y) >= 0; }
- friend bool operator==(const TString& x, const TRope& y) { return Compare(x, y) == 0; }
- friend bool operator!=(const TString& x, const TRope& y) { return Compare(x, y) != 0; }
- friend bool operator< (const TString& x, const TRope& y) { return Compare(x, y) < 0; }
- friend bool operator<=(const TString& x, const TRope& y) { return Compare(x, y) <= 0; }
- friend bool operator> (const TString& x, const TRope& y) { return Compare(x, y) > 0; }
- friend bool operator>=(const TString& x, const TRope& y) { return Compare(x, y) >= 0; }
private:
void Cut(TIterator begin, TIterator end, TRope *target) {
@@ -1242,9 +842,9 @@ private:
return;
}
- auto addBlock = [&](const TChunk& from, const char *begin, const char *end) {
+ auto addBlock = [&](const TContiguousData& from, const char *begin, const char *end) {
if (target) {
- target->Chain.PutToEnd(TChunk::Slice, begin, end, from);
+ target->Chain.PutToEnd(TContiguousData::Slice, begin, end, from);
target->Size += end - begin;
}
Size -= end - begin;
@@ -1257,7 +857,7 @@ private:
const char *firstChunkBegin = begin.PointsToChunkMiddle() ? begin->Begin : nullptr;
begin->Begin = end.Ptr; // this affects both begin and end iterator pointed values
if (firstChunkBegin) {
- Chain.InsertBefore(begin.Iter, TChunk::Slice, firstChunkBegin, begin.Ptr, begin.GetChunk());
+ Chain.InsertBefore(begin.Iter, TContiguousData::Slice, firstChunkBegin, begin.Ptr, begin.GetChunk());
}
} else {
// check the first iterator -- if it starts not from the begin of the block, we have to adjust end of the
@@ -1296,7 +896,7 @@ private:
};
class TRopeArena {
- using TAllocateCallback = std::function<TIntrusivePtr<IRopeChunkBackend>()>;
+ using TAllocateCallback = std::function<TIntrusivePtr<IContiguousChunk>()>;
TAllocateCallback Allocator;
TRope Arena;
@@ -1339,7 +939,7 @@ public:
return Size;
}
- void AccountChunk(const TRope::TChunk& chunk) {
+ void AccountChunk(const TContiguousData& chunk) {
if (AccountedBuffers.insert(chunk.Backend.UniqueId()).second) {
Size += chunk.GetCapacity();
}
@@ -1472,7 +1072,7 @@ public:
inline TRope TRope::CopySpaceOptimized(TRope&& origin, size_t worstRatioPer1k, TRopeArena& arena) {
TRope res;
- for (TChunk& chunk : origin.Chain) {
+ for (TContiguousData& chunk : origin.Chain) {
size_t ratio = chunk.GetSize() * 1024 / chunk.GetCapacity();
if (ratio < 1024 - worstRatioPer1k) {
res.Insert(res.End(), arena.CreateRope(chunk.Begin, chunk.GetSize()));
@@ -1482,7 +1082,7 @@ inline TRope TRope::CopySpaceOptimized(TRope&& origin, size_t worstRatioPer1k, T
}
res.Size = origin.Size;
origin = TRope();
- for (const TChunk& chunk : res.Chain) {
+ for (const TContiguousData& chunk : res.Chain) {
arena.AccountChunk(chunk);
}
return res;
diff --git a/library/cpp/actors/util/rope_cont_embedded_list.h b/library/cpp/actors/util/rope_cont_embedded_list.h
index 94d50d5236..80d5990310 100644
--- a/library/cpp/actors/util/rope_cont_embedded_list.h
+++ b/library/cpp/actors/util/rope_cont_embedded_list.h
@@ -48,7 +48,7 @@ class TChunkList {
template<typename... TArgs>
TItem *PrepareForUse(TArgs&&... args) {
Y_VERIFY_DEBUG(!IsInUse());
- static_cast<TChunk&>(*this) = {std::forward<TArgs>(args)...};
+ static_cast<TChunk&>(*this) = TChunk(std::forward<TArgs>(args)...);
Next = Prev = this;
Invalidate();
return this;
diff --git a/library/cpp/actors/util/rope_ut.cpp b/library/cpp/actors/util/rope_ut.cpp
index 1b2081eced..de7dd2c9ea 100644
--- a/library/cpp/actors/util/rope_ut.cpp
+++ b/library/cpp/actors/util/rope_ut.cpp
@@ -1,8 +1,9 @@
#include "rope.h"
#include <library/cpp/testing/unittest/registar.h>
#include <util/random/random.h>
+#include "ut_helpers.h"
-class TRopeStringBackend : public IRopeChunkBackend {
+class TRopeStringBackend : public IContiguousChunk {
TString Buffer;
public:
@@ -10,15 +11,15 @@ public:
: Buffer(std::move(buffer))
{}
- TData GetData() const override {
+ TContiguousSpan GetData() const override {
return {Buffer.data(), Buffer.size()};
}
- TMutData GetDataMut() override {
+ TMutableContiguousSpan GetDataMut() override {
return {Buffer.Detach(), Buffer.size()};
}
- TMutData UnsafeGetDataMut() override {
+ TMutableContiguousSpan UnsafeGetDataMut() override {
return {const_cast<char*>(Buffer.data()), Buffer.size()};
}
@@ -136,7 +137,61 @@ Y_UNIT_TEST_SUITE(TRope) {
UNIT_ASSERT_EQUAL(pf.UnsafeGetContiguousSpanMut().data(), string.data());
UNIT_ASSERT(!string.IsDetached());
}
+
+ Y_UNIT_TEST(ContiguousDataInterop) {
+ TString string = "Some long-long text needed for not sharing data and testing";
+ TContiguousData data(string);
+ TRope rope(data); // check operator TRope
+ UNIT_ASSERT_EQUAL(rope.UnsafeGetContiguousSpanMut().data(), string.data());
+ TContiguousData otherData(rope);
+ UNIT_ASSERT_EQUAL(otherData.UnsafeGetDataMut(), string.data());
+ TString extractedBack = otherData.ExtractUnderlyingContainerOrCopy<TString>();
+ UNIT_ASSERT_EQUAL(extractedBack.data(), string.data());
+ }
#endif
+ Y_UNIT_TEST(CrossCompare) {
+ TString str = "some very long string";
+ const TString constStr(str);
+ TStringBuf strbuf = str;
+ const TStringBuf constStrbuf = str;
+ TContiguousSpan span(str);
+ const TContiguousSpan constSpan(str);
+ TMutableContiguousSpan mutableSpan(const_cast<char*>(str.data()), str.size());
+ const TMutableContiguousSpan constMutableSpan(const_cast<char*>(str.data()), str.size());
+ TContiguousData data(str);
+ const TContiguousData constData(str);
+ TArrayRef<char> arrRef(const_cast<char*>(str.data()), str.size());
+ const TArrayRef<char> constArrRef(const_cast<char*>(str.data()), str.size());
+ TArrayRef<const char> arrConstRef(const_cast<char*>(str.data()), str.size());
+ const TArrayRef<const char> constArrConstRef(const_cast<char*>(str.data()), str.size());
+ NActors::TSharedData sharedData = NActors::TSharedData::Copy(str.data(), str.size());
+ const NActors::TSharedData constSharedData(sharedData);
+ TRope rope(str);
+ const TRope constRope(str);
+
+ Permutate(
+ [](auto& arg1, auto& arg2) {
+ UNIT_ASSERT(arg1 == arg2);
+ },
+ str,
+ constStr,
+ strbuf,
+ constStrbuf,
+ span,
+ constSpan,
+ mutableSpan,
+ constMutableSpan,
+ data,
+ constData,
+ arrRef,
+ constArrRef,
+ arrConstRef,
+ constArrConstRef,
+ sharedData,
+ constSharedData,
+ rope,
+ constRope);
+ }
Y_UNIT_TEST(BasicRange) {
TRope rope = CreateRope(Text, 10);
diff --git a/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp b/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
new file mode 100644
index 0000000000..443fc149da
--- /dev/null
+++ b/library/cpp/actors/util/shared_data_native_rope_backend_ut.cpp
@@ -0,0 +1,231 @@
+#include <library/cpp/actors/util/rope.h>
+#include <library/cpp/testing/unittest/registar.h>
+#include <util/random/random.h>
+
+#include "shared_data_rope_backend.h"
+
+namespace NActors {
+
+ namespace {
+
+ TRope CreateRope(TString s, size_t sliceSize) {
+ TRope res;
+ for (size_t i = 0; i < s.size(); ) {
+ size_t len = std::min(sliceSize, s.size() - i);
+ if (i % 2) {
+ auto str = s.substr(i, len);
+ res.Insert(res.End(), TRope(
+ TSharedData::Copy(str.data(), str.size())));
+ } else {
+ res.Insert(res.End(), TRope(s.substr(i, len)));
+ }
+ i += len;
+ }
+ return res;
+ }
+
+ TString RopeToString(const TRope& rope) {
+ TString res;
+ auto iter = rope.Begin();
+ while (iter != rope.End()) {
+ res.append(iter.ContiguousData(), iter.ContiguousSize());
+ iter.AdvanceToNextContiguousBlock();
+ }
+
+ UNIT_ASSERT_VALUES_EQUAL(rope.GetSize(), res.size());
+
+ TString temp = TString::Uninitialized(rope.GetSize());
+ rope.Begin().ExtractPlainDataAndAdvance(temp.Detach(), temp.size());
+ UNIT_ASSERT_VALUES_EQUAL(temp, res);
+
+ return res;
+ }
+
+ TString Text = "No elements are copied or moved, only the internal pointers of the list nodes are re-pointed.";
+
+ }
+
+ Y_UNIT_TEST_SUITE(TRopeSharedDataNativeBackend) {
+
+ // Same tests as in TRope but with new CreateRope using TSharedData backend
+
+ Y_UNIT_TEST(Leak) {
+ const size_t begin = 10, end = 20;
+ TRope rope = CreateRope(Text, 10);
+ rope.Erase(rope.Begin() + begin, rope.Begin() + end);
+ }
+
+ Y_UNIT_TEST(BasicRange) {
+ TRope rope = CreateRope(Text, 10);
+ for (size_t begin = 0; begin < Text.size(); ++begin) {
+ for (size_t end = begin; end <= Text.size(); ++end) {
+ TRope::TIterator rBegin = rope.Begin() + begin;
+ TRope::TIterator rEnd = rope.Begin() + end;
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(rBegin, rEnd)), Text.substr(begin, end - begin));
+ }
+ }
+ }
+
+ Y_UNIT_TEST(Erase) {
+ for (size_t begin = 0; begin < Text.size(); ++begin) {
+ for (size_t end = begin; end <= Text.size(); ++end) {
+ TRope rope = CreateRope(Text, 10);
+ rope.Erase(rope.Begin() + begin, rope.Begin() + end);
+ TString text = Text;
+ text.erase(text.begin() + begin, text.begin() + end);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
+ }
+ }
+ }
+
+ Y_UNIT_TEST(Insert) {
+ TRope rope = CreateRope(Text, 10);
+ for (size_t begin = 0; begin < Text.size(); ++begin) {
+ for (size_t end = begin; end <= Text.size(); ++end) {
+ TRope part = TRope(rope.Begin() + begin, rope.Begin() + end);
+ for (size_t where = 0; where <= Text.size(); ++where) {
+ TRope x(rope);
+ x.Insert(x.Begin() + where, TRope(part));
+ UNIT_ASSERT_VALUES_EQUAL(x.GetSize(), rope.GetSize() + part.GetSize());
+ TString text = Text;
+ text.insert(text.begin() + where, Text.begin() + begin, Text.begin() + end);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(x), text);
+ }
+ }
+ }
+ }
+
+ Y_UNIT_TEST(Extract) {
+ for (size_t begin = 0; begin < Text.size(); ++begin) {
+ for (size_t end = begin; end <= Text.size(); ++end) {
+ TRope rope = CreateRope(Text, 10);
+ TRope part = rope.Extract(rope.Begin() + begin, rope.Begin() + end);
+ TString text = Text;
+ text.erase(text.begin() + begin, text.begin() + end);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), text);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(part), Text.substr(begin, end - begin));
+ }
+ }
+ }
+
+ Y_UNIT_TEST(EraseFront) {
+ for (size_t pos = 0; pos <= Text.size(); ++pos) {
+ TRope rope = CreateRope(Text, 10);
+ rope.EraseFront(pos);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(pos));
+ }
+ }
+
+ Y_UNIT_TEST(EraseBack) {
+ for (size_t pos = 0; pos <= Text.size(); ++pos) {
+ TRope rope = CreateRope(Text, 10);
+ rope.EraseBack(pos);
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text.substr(0, Text.size() - pos));
+ }
+ }
+
+ Y_UNIT_TEST(ExtractFront) {
+ for (size_t step = 1; step <= Text.size(); ++step) {
+ TRope rope = CreateRope(Text, 10);
+ TRope out;
+ while (const size_t len = Min(step, rope.GetSize())) {
+ rope.ExtractFront(len, &out);
+ UNIT_ASSERT(rope.GetSize() + out.GetSize() == Text.size());
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(out), Text.substr(0, out.GetSize()));
+ }
+ }
+ }
+
+ Y_UNIT_TEST(ExtractFrontPlain) {
+ for (size_t step = 1; step <= Text.size(); ++step) {
+ TRope rope = CreateRope(Text, 10);
+ TString buffer = Text;
+ auto it = rope.Begin();
+ size_t remain = rope.GetSize();
+ while (const size_t len = Min(step, remain)) {
+ TString data = TString::Uninitialized(len);
+ it.ExtractPlainDataAndAdvance(data.Detach(), data.size());
+ UNIT_ASSERT_VALUES_EQUAL(data, buffer.substr(0, len));
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(TRope(it, rope.End())), buffer.substr(len));
+ buffer = buffer.substr(len);
+ remain -= len;
+ }
+ }
+ }
+
+ Y_UNIT_TEST(Glueing) {
+ TRope rope = CreateRope(Text, 10);
+ for (size_t begin = 0; begin <= Text.size(); ++begin) {
+ for (size_t end = begin; end <= Text.size(); ++end) {
+ TString repr = rope.DebugString();
+ TRope temp = rope.Extract(rope.Position(begin), rope.Position(end));
+ rope.Insert(rope.Position(begin), std::move(temp));
+ UNIT_ASSERT_VALUES_EQUAL(repr, rope.DebugString());
+ UNIT_ASSERT_VALUES_EQUAL(RopeToString(rope), Text);
+ }
+ }
+ }
+
+ Y_UNIT_TEST(IterWalk) {
+ TRope rope = CreateRope(Text, 10);
+ for (size_t step1 = 0; step1 <= rope.GetSize(); ++step1) {
+ for (size_t step2 = 0; step2 <= step1; ++step2) {
+ TRope::TConstIterator iter = rope.Begin();
+ iter += step1;
+ iter -= step2;
+ UNIT_ASSERT(iter == rope.Position(step1 - step2));
+ }
+ }
+ }
+
+ Y_UNIT_TEST(Compare) {
+ auto check = [](const TString& x, const TString& y) {
+ const TRope xRope = CreateRope(x, 7);
+ const TRope yRope = CreateRope(y, 11);
+ UNIT_ASSERT_VALUES_EQUAL(xRope == yRope, x == y);
+ UNIT_ASSERT_VALUES_EQUAL(xRope != yRope, x != y);
+ UNIT_ASSERT_VALUES_EQUAL(xRope < yRope, x < y);
+ UNIT_ASSERT_VALUES_EQUAL(xRope <= yRope, x <= y);
+ UNIT_ASSERT_VALUES_EQUAL(xRope > yRope, x > y);
+ UNIT_ASSERT_VALUES_EQUAL(xRope >= yRope, x >= y);
+ };
+
+ TVector<TString> pool;
+ for (size_t k = 0; k < 10; ++k) {
+ size_t len = RandomNumber<size_t>(100) + 100;
+ TString s = TString::Uninitialized(len);
+ char *p = s.Detach();
+ for (size_t j = 0; j < len; ++j) {
+ *p++ = RandomNumber<unsigned char>();
+ }
+ pool.push_back(std::move(s));
+ }
+
+ for (const TString& x : pool) {
+ for (const TString& y : pool) {
+ check(x, y);
+ }
+ }
+ }
+
+ // Specific TSharedDataRopeBackend tests
+
+ Y_UNIT_TEST(RopeOnlyBorrows) {
+ TSharedData data = TSharedData::Copy(Text.data(), Text.size());
+ {
+ TRope rope;
+ rope.Insert(rope.End(), TRope(data));
+ UNIT_ASSERT(data.IsShared());
+ TSharedData dataCopy = data;
+ UNIT_ASSERT(dataCopy.IsShared());
+ UNIT_ASSERT_EQUAL(dataCopy.data(), data.data());
+ rope.Insert(rope.End(), TRope(data));
+ rope.Insert(rope.End(), TRope(data));
+ dataCopy.Trim(10);
+ UNIT_ASSERT_EQUAL(rope.GetSize(), data.size() * 3);
+ }
+ UNIT_ASSERT(data.IsPrivate());
+ }
+ }
+
+} // namespace NActors
diff --git a/library/cpp/actors/util/shared_data_rope_backend.h b/library/cpp/actors/util/shared_data_rope_backend.h
index 3add6afd27..312dab9112 100644
--- a/library/cpp/actors/util/shared_data_rope_backend.h
+++ b/library/cpp/actors/util/shared_data_rope_backend.h
@@ -1,12 +1,12 @@
#pragma once
-#include <library/cpp/actors/util/rope.h>
+#include <library/cpp/actors/util/contiguous_data.h>
#include "shared_data.h"
namespace NActors {
-class TRopeSharedDataBackend : public IRopeChunkBackend {
+class TRopeSharedDataBackend : public IContiguousChunk {
TSharedData Buffer;
public:
@@ -14,18 +14,18 @@ public:
: Buffer(std::move(buffer))
{}
- TData GetData() const override {
+ TContiguousSpan GetData() const override {
return {Buffer.data(), Buffer.size()};
}
- TMutData GetDataMut() override {
+ TMutableContiguousSpan GetDataMut() override {
if(Buffer.IsShared()) {
Buffer = TSharedData::Copy(Buffer.data(), Buffer.size());
}
return {Buffer.mutable_data(), Buffer.size()};
}
- TMutData UnsafeGetDataMut() override {
+ TMutableContiguousSpan UnsafeGetDataMut() override {
return {const_cast<char *>(Buffer.data()), Buffer.size()};
}
diff --git a/library/cpp/actors/util/ut_helpers.h b/library/cpp/actors/util/ut_helpers.h
new file mode 100644
index 0000000000..d3fe873233
--- /dev/null
+++ b/library/cpp/actors/util/ut_helpers.h
@@ -0,0 +1,12 @@
+#pragma once
+
+// calls TCallback for all args permutations including (id, id)
+template <class TCallback, class... TArgs>
+void Permutate(TCallback&& fn, TArgs&&... args)
+{
+ auto forAll = [&](auto& arg){
+ (fn(std::forward<decltype(arg)>(arg), std::forward<decltype(args)>(args)), ...);
+ };
+
+ (forAll(std::forward<decltype(args)>(args)), ...);
+}
diff --git a/ydb/core/blobstorage/crypto/CMakeLists.txt b/ydb/core/blobstorage/crypto/CMakeLists.txt
index eed2c9cfcb..51e18b57d5 100644
--- a/ydb/core/blobstorage/crypto/CMakeLists.txt
+++ b/ydb/core/blobstorage/crypto/CMakeLists.txt
@@ -14,6 +14,7 @@ target_link_libraries(core-blobstorage-crypto PUBLIC
yutil
contrib-libs-t1ha
library-cpp-sse
+ cpp-actors-util
)
target_sources(core-blobstorage-crypto PRIVATE
${CMAKE_SOURCE_DIR}/ydb/core/blobstorage/crypto/chacha.cpp
diff --git a/ydb/core/blobstorage/crypto/ut/ut_helpers.h b/ydb/core/blobstorage/crypto/ut/ut_helpers.h
index faf1eaf009..628cf79bb3 100644
--- a/ydb/core/blobstorage/crypto/ut/ut_helpers.h
+++ b/ydb/core/blobstorage/crypto/ut/ut_helpers.h
@@ -57,7 +57,7 @@ public:
}
};
-class TRopeAlignedBufferBackend : public IRopeChunkBackend {
+class TRopeAlignedBufferBackend : public IContiguousChunk {
TAlignedBuf Buffer;
public:
@@ -65,15 +65,15 @@ public:
: Buffer(size, align)
{}
- TData GetData() const override {
+ TContiguousSpan GetData() const override {
return {reinterpret_cast<const char *>(Buffer.Data()), Buffer.Size()};
}
- TMutData GetDataMut() override {
+ TMutableContiguousSpan GetDataMut() override {
return {reinterpret_cast<char *>(Buffer.Data()), Buffer.Size()};
}
- TMutData UnsafeGetDataMut() override {
+ TMutableContiguousSpan UnsafeGetDataMut() override {
return {reinterpret_cast<char *>(Buffer.Data()), Buffer.Size()};
}
diff --git a/ydb/core/blobstorage/vdisk/hulldb/base/blobstorage_blob_ut.cpp b/ydb/core/blobstorage/vdisk/hulldb/base/blobstorage_blob_ut.cpp
index 5774a53a39..23251752b7 100644
--- a/ydb/core/blobstorage/vdisk/hulldb/base/blobstorage_blob_ut.cpp
+++ b/ydb/core/blobstorage/vdisk/hulldb/base/blobstorage_blob_ut.cpp
@@ -3,7 +3,7 @@
namespace NKikimr {
- TIntrusivePtr<IRopeChunkBackend> AllocateArena() {
+ TIntrusivePtr<IContiguousChunk> AllocateArena() {
return TRopeAlignedBuffer::Allocate(65536);
}
diff --git a/ydb/core/blobstorage/vdisk/hulldb/base/hullds_arena.h b/ydb/core/blobstorage/vdisk/hulldb/base/hullds_arena.h
index d2fedd6975..8e18a53248 100644
--- a/ydb/core/blobstorage/vdisk/hulldb/base/hullds_arena.h
+++ b/ydb/core/blobstorage/vdisk/hulldb/base/hullds_arena.h
@@ -9,12 +9,12 @@
namespace NKikimr {
- class TRopeArenaBackend : public IRopeChunkBackend {
- static constexpr size_t Capacity = 2 * 1024 * 1024 - 4096 /* lfalloc overhead */ - sizeof(IRopeChunkBackend);
+ class TRopeArenaBackend : public IContiguousChunk {
+ static constexpr size_t Capacity = 2 * 1024 * 1024 - 4096 /* lfalloc overhead */ - sizeof(IContiguousChunk);
char Data[Capacity];
public:
- TData GetData() const override {
+ TContiguousSpan GetData() const override {
return {Data, Capacity};
}
@@ -22,11 +22,11 @@ namespace NKikimr {
return Capacity;
}
- TMutData GetDataMut() override {
+ TMutableContiguousSpan GetDataMut() override {
return {Data, Capacity};
}
- static TIntrusivePtr<IRopeChunkBackend> Allocate() {
+ static TIntrusivePtr<IContiguousChunk> Allocate() {
return MakeIntrusive<TRopeArenaBackend>();
}
};
diff --git a/ydb/core/blobstorage/vdisk/scrub/scrub_actor.cpp b/ydb/core/blobstorage/vdisk/scrub/scrub_actor.cpp
index e71b15c833..618a4bf5ef 100644
--- a/ydb/core/blobstorage/vdisk/scrub/scrub_actor.cpp
+++ b/ydb/core/blobstorage/vdisk/scrub/scrub_actor.cpp
@@ -233,7 +233,7 @@ namespace NKikimr {
}
}
- TIntrusivePtr<IRopeChunkBackend> TScrubCoroImpl::AllocateRopeArenaChunk() {
+ TIntrusivePtr<IContiguousChunk> TScrubCoroImpl::AllocateRopeArenaChunk() {
return TRopeAlignedBuffer::Allocate(1 << 20); // 1 MB
}
diff --git a/ydb/core/blobstorage/vdisk/scrub/scrub_actor_impl.h b/ydb/core/blobstorage/vdisk/scrub/scrub_actor_impl.h
index 7f5e3ed298..3097197cc2 100644
--- a/ydb/core/blobstorage/vdisk/scrub/scrub_actor_impl.h
+++ b/ydb/core/blobstorage/vdisk/scrub/scrub_actor_impl.h
@@ -168,7 +168,7 @@ namespace NKikimr {
void HandleScrubAwait(TAutoPtr<IEventHandle> ev);
private:
- static TIntrusivePtr<IRopeChunkBackend> AllocateRopeArenaChunk();
+ static TIntrusivePtr<IContiguousChunk> AllocateRopeArenaChunk();
};
} // NKikimr