diff options
author | Derek Mauro <dmauro@google.com> | 2022-12-11 16:43:28 -0800 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2022-12-11 16:44:18 -0800 |
commit | ff5644bb34333d2ad7f1abf421d57bda155398e7 (patch) | |
tree | e2fc6335996cb5d96d871e67c0411c8c104233d4 /absl/strings | |
parent | 0b8e676c1b83b157786b4766362fd647b5c59e0d (diff) |
Allow Cord to store chunked checksums
PiperOrigin-RevId: 494587777
Change-Id: I41504edca6fcf750d52602fa84a33bc7fe5fbb48
Diffstat (limited to 'absl/strings')
-rw-r--r-- | absl/strings/BUILD.bazel | 4 | ||||
-rw-r--r-- | absl/strings/CMakeLists.txt | 4 | ||||
-rw-r--r-- | absl/strings/cord.cc | 29 | ||||
-rw-r--r-- | absl/strings/cord.h | 5 | ||||
-rw-r--r-- | absl/strings/internal/cord_rep_crc.cc | 7 | ||||
-rw-r--r-- | absl/strings/internal/cord_rep_crc.h | 7 | ||||
-rw-r--r-- | absl/strings/internal/cord_rep_crc_test.cc | 34 | ||||
-rw-r--r-- | absl/strings/internal/cordz_info_statistics_test.cc | 4 |
8 files changed, 68 insertions, 26 deletions
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel index 3c852989..d86f59f0 100644 --- a/absl/strings/BUILD.bazel +++ b/absl/strings/BUILD.bazel @@ -324,6 +324,7 @@ cc_library( "//absl/container:compressed_tuple", "//absl/container:inlined_vector", "//absl/container:layout", + "//absl/crc:crc_cord_state", "//absl/functional:function_ref", "//absl/meta:type_traits", "//absl/types:span", @@ -405,6 +406,7 @@ cc_test( ":cord_internal", ":cord_rep_test_util", "//absl/base:config", + "//absl/crc:crc_cord_state", "@com_google_googletest//:gtest_main", ], ) @@ -463,6 +465,7 @@ cc_library( "//absl/base:raw_logging_internal", "//absl/container:fixed_array", "//absl/container:inlined_vector", + "//absl/crc:crc_cord_state", "//absl/functional:function_ref", "//absl/meta:type_traits", "//absl/numeric:bits", @@ -659,6 +662,7 @@ cc_test( ":cordz_update_scope", ":cordz_update_tracker", "//absl/base:config", + "//absl/crc:crc_cord_state", "//absl/synchronization", "//absl/synchronization:thread_pool", "@com_google_googletest//:gtest_main", diff --git a/absl/strings/CMakeLists.txt b/absl/strings/CMakeLists.txt index 33e4ff1b..a23b34a1 100644 --- a/absl/strings/CMakeLists.txt +++ b/absl/strings/CMakeLists.txt @@ -605,6 +605,7 @@ absl_cc_library( absl::compressed_tuple absl::config absl::core_headers + absl::crc_cord_state absl::endian absl::inlined_vector absl::layout @@ -783,6 +784,7 @@ absl_cc_test( absl::cordz_statistics absl::cordz_update_scope absl::cordz_update_tracker + absl::crc_cord_state absl::thread_pool GTest::gmock_main ) @@ -882,6 +884,7 @@ absl_cc_library( absl::cordz_update_scope absl::cordz_update_tracker absl::core_headers + absl::crc_cord_state absl::endian absl::fixed_array absl::function_ref @@ -1054,6 +1057,7 @@ absl_cc_test( absl::config absl::cord_internal absl::cord_rep_test_util + absl::crc_cord_state GTest::gmock_main ) diff --git a/absl/strings/cord.cc b/absl/strings/cord.cc index 92822c05..0bac4164 100644 --- a/absl/strings/cord.cc +++ b/absl/strings/cord.cc @@ -35,6 +35,7 @@ #include "absl/base/port.h" #include "absl/container/fixed_array.h" #include "absl/container/inlined_vector.h" +#include "absl/crc/internal/crc_cord_state.h" #include "absl/strings/cord_buffer.h" #include "absl/strings/escaping.h" #include "absl/strings/internal/cord_data_edge.h" @@ -854,28 +855,44 @@ inline absl::string_view Cord::InlineRep::FindFlatStartPiece() const { return absl::string_view(node->external()->base + offset, length); } -void Cord::SetExpectedChecksum(uint32_t crc) { +void Cord::SetCrcCordState(crc_internal::CrcCordState state) { auto constexpr method = CordzUpdateTracker::kSetExpectedChecksum; if (empty()) { contents_.MaybeRemoveEmptyCrcNode(); - CordRep* rep = CordRepCrc::New(nullptr, crc); + CordRep* rep = CordRepCrc::New(nullptr, std::move(state)); contents_.EmplaceTree(rep, method); } else if (!contents_.is_tree()) { CordRep* rep = contents_.MakeFlatWithExtraCapacity(0); - rep = CordRepCrc::New(rep, crc); + rep = CordRepCrc::New(rep, std::move(state)); contents_.EmplaceTree(rep, method); } else { const CordzUpdateScope scope(contents_.data_.cordz_info(), method); - CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), crc); + CordRep* rep = CordRepCrc::New(contents_.data_.as_tree(), std::move(state)); contents_.SetTree(rep, scope); } } +void Cord::SetExpectedChecksum(uint32_t crc) { + // Construct a CrcCordState with a single chunk. + crc_internal::CrcCordState state; + state.mutable_rep()->prefix_crc.push_back( + crc_internal::CrcCordState::PrefixCrc(size(), absl::crc32c_t{crc})); + SetCrcCordState(std::move(state)); +} + +const crc_internal::CrcCordState* Cord::MaybeGetCrcCordState() const { + if (!contents_.is_tree() || !contents_.tree()->IsCrc()) { + return nullptr; + } + return &contents_.tree()->crc()->crc_cord_state; +} + absl::optional<uint32_t> Cord::ExpectedChecksum() const { if (!contents_.is_tree() || !contents_.tree()->IsCrc()) { return absl::nullopt; } - return contents_.tree()->crc()->crc; + return static_cast<uint32_t>( + contents_.tree()->crc()->crc_cord_state.Checksum()); } inline int Cord::CompareSlowPath(absl::string_view rhs, size_t compared_size, @@ -1255,7 +1272,7 @@ static void DumpNode(CordRep* rep, bool include_data, std::ostream* os, *os << "NULL\n"; leaf = true; } else if (rep->IsCrc()) { - *os << "CRC crc=" << rep->crc()->crc << "\n"; + *os << "CRC crc=" << rep->crc()->crc_cord_state.Checksum() << "\n"; indent += kIndentStep; rep = rep->crc()->child; } else if (rep->IsSubstring()) { diff --git a/absl/strings/cord.h b/absl/strings/cord.h index 6e3da89e..1349b115 100644 --- a/absl/strings/cord.h +++ b/absl/strings/cord.h @@ -76,6 +76,7 @@ #include "absl/base/macros.h" #include "absl/base/port.h" #include "absl/container/inlined_vector.h" +#include "absl/crc/internal/crc_cord_state.h" #include "absl/functional/function_ref.h" #include "absl/meta/type_traits.h" #include "absl/strings/cord_analysis.h" @@ -1002,6 +1003,10 @@ class Cord { }); return H::combine(combiner.finalize(std::move(hash_state)), size()); } + + friend class CrcCord; + void SetCrcCordState(crc_internal::CrcCordState state); + const crc_internal::CrcCordState* MaybeGetCrcCordState() const; }; ABSL_NAMESPACE_END diff --git a/absl/strings/internal/cord_rep_crc.cc b/absl/strings/internal/cord_rep_crc.cc index 7d7273ef..dbe54cc4 100644 --- a/absl/strings/internal/cord_rep_crc.cc +++ b/absl/strings/internal/cord_rep_crc.cc @@ -16,6 +16,7 @@ #include <cassert> #include <cstdint> +#include <utility> #include "absl/base/config.h" #include "absl/strings/internal/cord_internal.h" @@ -24,10 +25,10 @@ namespace absl { ABSL_NAMESPACE_BEGIN namespace cord_internal { -CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { +CordRepCrc* CordRepCrc::New(CordRep* child, crc_internal::CrcCordState state) { if (child != nullptr && child->IsCrc()) { if (child->refcount.IsOne()) { - child->crc()->crc = crc; + child->crc()->crc_cord_state = std::move(state); return child->crc(); } CordRep* old = child; @@ -39,7 +40,7 @@ CordRepCrc* CordRepCrc::New(CordRep* child, uint32_t crc) { new_cordrep->length = child != nullptr ? child->length : 0; new_cordrep->tag = cord_internal::CRC; new_cordrep->child = child; - new_cordrep->crc = crc; + new_cordrep->crc_cord_state = std::move(state); return new_cordrep; } diff --git a/absl/strings/internal/cord_rep_crc.h b/absl/strings/internal/cord_rep_crc.h index 455a1127..379d7a60 100644 --- a/absl/strings/internal/cord_rep_crc.h +++ b/absl/strings/internal/cord_rep_crc.h @@ -20,6 +20,7 @@ #include "absl/base/config.h" #include "absl/base/optimization.h" +#include "absl/crc/internal/crc_cord_state.h" #include "absl/strings/internal/cord_internal.h" namespace absl { @@ -34,14 +35,14 @@ namespace cord_internal { // the contained checksum is the user's responsibility. struct CordRepCrc : public CordRep { CordRep* child; - uint32_t crc; + absl::crc_internal::CrcCordState crc_cord_state; // Consumes `child` and returns a CordRepCrc prefixed tree containing `child`. // If the specified `child` is itself a CordRepCrc node, then this method - // either replaces the existing node, or directly updates the crc value in it + // either replaces the existing node, or directly updates the crc state in it // depending on the node being shared or not, i.e.: refcount.IsOne(). // `child` must only be null if the Cord is empty. Never returns null. - static CordRepCrc* New(CordRep* child, uint32_t crc); + static CordRepCrc* New(CordRep* child, crc_internal::CrcCordState state); // Destroys (deletes) the provided node. `node` must not be null. static void Destroy(CordRepCrc* node); diff --git a/absl/strings/internal/cord_rep_crc_test.cc b/absl/strings/internal/cord_rep_crc_test.cc index 42a9110b..3d27c33c 100644 --- a/absl/strings/internal/cord_rep_crc_test.cc +++ b/absl/strings/internal/cord_rep_crc_test.cc @@ -17,6 +17,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" +#include "absl/crc/internal/crc_cord_state.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_rep_test_util.h" @@ -38,33 +39,40 @@ TEST(CordRepCrc, RemoveCrcWithNullptr) { #endif // !NDEBUG && GTEST_HAS_DEATH_TEST +absl::crc_internal::CrcCordState MakeCrcCordState(uint32_t crc) { + crc_internal::CrcCordState state; + state.mutable_rep()->prefix_crc.push_back( + crc_internal::CrcCordState::PrefixCrc(42, crc32c_t{crc})); + return state; +} + TEST(CordRepCrc, NewDestroy) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); - CordRepCrc* crc = CordRepCrc::New(rep, 12345); + CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345)); EXPECT_TRUE(crc->refcount.IsOne()); EXPECT_THAT(crc->child, Eq(rep)); - EXPECT_THAT(crc->crc, Eq(12345u)); + EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u})); EXPECT_TRUE(rep->refcount.IsOne()); CordRepCrc::Destroy(crc); } TEST(CordRepCrc, NewExistingCrcNotShared) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); - CordRepCrc* crc = CordRepCrc::New(rep, 12345); - CordRepCrc* new_crc = CordRepCrc::New(crc, 54321); + CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345)); + CordRepCrc* new_crc = CordRepCrc::New(crc, MakeCrcCordState(54321)); EXPECT_THAT(new_crc, Eq(crc)); EXPECT_TRUE(new_crc->refcount.IsOne()); EXPECT_THAT(new_crc->child, Eq(rep)); - EXPECT_THAT(new_crc->crc, Eq(54321u)); + EXPECT_THAT(new_crc->crc_cord_state.Checksum(), Eq(crc32c_t{54321u})); EXPECT_TRUE(rep->refcount.IsOne()); CordRepCrc::Destroy(new_crc); } TEST(CordRepCrc, NewExistingCrcShared) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); - CordRepCrc* crc = CordRepCrc::New(rep, 12345); + CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345)); CordRep::Ref(crc); - CordRepCrc* new_crc = CordRepCrc::New(crc, 54321); + CordRepCrc* new_crc = CordRepCrc::New(crc, MakeCrcCordState(54321)); EXPECT_THAT(new_crc, Ne(crc)); EXPECT_TRUE(new_crc->refcount.IsOne()); @@ -72,19 +80,19 @@ TEST(CordRepCrc, NewExistingCrcShared) { EXPECT_FALSE(rep->refcount.IsOne()); EXPECT_THAT(crc->child, Eq(rep)); EXPECT_THAT(new_crc->child, Eq(rep)); - EXPECT_THAT(crc->crc, Eq(12345u)); - EXPECT_THAT(new_crc->crc, Eq(54321u)); + EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u})); + EXPECT_THAT(new_crc->crc_cord_state.Checksum(), Eq(crc32c_t{54321u})); CordRep::Unref(crc); CordRep::Unref(new_crc); } TEST(CordRepCrc, NewEmpty) { - CordRepCrc* crc = CordRepCrc::New(nullptr, 12345); + CordRepCrc* crc = CordRepCrc::New(nullptr, MakeCrcCordState(12345)); EXPECT_TRUE(crc->refcount.IsOne()); EXPECT_THAT(crc->child, IsNull()); EXPECT_THAT(crc->length, Eq(0u)); - EXPECT_THAT(crc->crc, Eq(12345u)); + EXPECT_THAT(crc->crc_cord_state.Checksum(), Eq(crc32c_t{12345u})); EXPECT_TRUE(crc->refcount.IsOne()); CordRepCrc::Destroy(crc); } @@ -98,7 +106,7 @@ TEST(CordRepCrc, RemoveCrcNotCrc) { TEST(CordRepCrc, RemoveCrcNotShared) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); - CordRepCrc* crc = CordRepCrc::New(rep, 12345); + CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345)); CordRep* nocrc = RemoveCrcNode(crc); EXPECT_THAT(nocrc, Eq(rep)); EXPECT_TRUE(rep->refcount.IsOne()); @@ -107,7 +115,7 @@ TEST(CordRepCrc, RemoveCrcNotShared) { TEST(CordRepCrc, RemoveCrcShared) { CordRep* rep = cordrep_testing::MakeFlat("Hello world"); - CordRepCrc* crc = CordRepCrc::New(rep, 12345); + CordRepCrc* crc = CordRepCrc::New(rep, MakeCrcCordState(12345)); CordRep::Ref(crc); CordRep* nocrc = RemoveCrcNode(crc); EXPECT_THAT(nocrc, Eq(rep)); diff --git a/absl/strings/internal/cordz_info_statistics_test.cc b/absl/strings/internal/cordz_info_statistics_test.cc index 6d6feb52..53d2f2ea 100644 --- a/absl/strings/internal/cordz_info_statistics_test.cc +++ b/absl/strings/internal/cordz_info_statistics_test.cc @@ -19,6 +19,7 @@ #include "gmock/gmock.h" #include "gtest/gtest.h" #include "absl/base/config.h" +#include "absl/crc/internal/crc_cord_state.h" #include "absl/strings/cord.h" #include "absl/strings/internal/cord_internal.h" #include "absl/strings/internal/cord_rep_btree.h" @@ -451,7 +452,8 @@ TEST(CordzInfoStatisticsTest, BtreeNodeShared) { TEST(CordzInfoStatisticsTest, Crc) { RefHelper ref; auto* left = Flat(1000); - auto* crc = ref.NeedsUnref(CordRepCrc::New(left, 12345)); + auto* crc = + ref.NeedsUnref(CordRepCrc::New(left, crc_internal::CrcCordState())); CordzStatistics expected; expected.size = left->length; |