diff options
author | maxbogue <maxbogue@chromium.org> | 2015-10-29 11:39:19 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-10-29 18:40:28 +0000 |
commit | 95e33335f64bff190d67d8958a3ffac701f6da6f (patch) | |
tree | 3e50077e0b59ee1bbe4b79e380308c29708023a4 /sync/syncable | |
parent | 68cfb908f4a01b95b64eac573825325dd7bdf55d (diff) | |
download | chromium_src-95e33335f64bff190d67d8958a3ffac701f6da6f.zip chromium_src-95e33335f64bff190d67d8958a3ffac701f6da6f.tar.gz chromium_src-95e33335f64bff190d67d8958a3ffac701f6da6f.tar.bz2 |
[Sync] Introduce EntityData and EntityMetadata.
BUG=536895
Review URL: https://codereview.chromium.org/1421663004
Cr-Commit-Position: refs/heads/master@{#356899}
Diffstat (limited to 'sync/syncable')
-rw-r--r-- | sync/syncable/entry_kernel.h | 2 | ||||
-rw-r--r-- | sync/syncable/proto_value_ptr.h | 110 | ||||
-rw-r--r-- | sync/syncable/proto_value_ptr_unittest.cc | 208 |
3 files changed, 1 insertions, 319 deletions
diff --git a/sync/syncable/entry_kernel.h b/sync/syncable/entry_kernel.h index c1fc5e5..4e901ce 100644 --- a/sync/syncable/entry_kernel.h +++ b/sync/syncable/entry_kernel.h @@ -13,8 +13,8 @@ #include "sync/internal_api/public/base/model_type.h" #include "sync/internal_api/public/base/unique_position.h" #include "sync/internal_api/public/util/immutable.h" +#include "sync/internal_api/public/util/proto_value_ptr.h" #include "sync/syncable/metahandle_set.h" -#include "sync/syncable/proto_value_ptr.h" #include "sync/syncable/syncable_id.h" #include "sync/util/time.h" diff --git a/sync/syncable/proto_value_ptr.h b/sync/syncable/proto_value_ptr.h deleted file mode 100644 index dea3a68..0000000 --- a/sync/syncable/proto_value_ptr.h +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_ -#define SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_ - -#include "base/gtest_prod_util.h" -#include "base/memory/ref_counted.h" -#include "sync/protocol/attachments.pb.h" -#include "sync/protocol/sync.pb.h" - -namespace syncer { -namespace syncable { - -// Default traits struct for ProtoValuePtr - adapts a -// ::google::protobuf::MessageLite derived type to be used with ProtoValuePtr. -template <typename T> -struct DefaultProtoValuePtrTraits { - // Deep copy the value from |src| to |dest|. - static void CopyValue(T* dest, const T& src) { dest->CopyFrom(src); } - // Parse the value from BLOB. - static void ParseFromBlob(T* dest, const void* blob, int length) { - dest->ParseFromArray(blob, length); - } - // True if the |value| is a non-default value. - static bool HasValue(const T& value) { return value.ByteSize() > 0; } - // Default value for the type. - static const T& DefaultValue() { return T::default_instance(); } -}; - -// This is a smart pointer to a ::google::protobuf::MessageLite derived type -// that implements immutable, shareable, copy-on-write semantics. -// -// Additionally this class helps to avoid storing multiple copies of default -// instances of the wrapped type. -// -// Copying ProtoValuePtr results in ref-counted sharing of the -// underlying wrapper and the value contained in the wrapper. -// -// The public interface includes only immutable access to the wrapped value. -// The only way to assign a value to ProtoValuePtr is through a -// private SetValue function which is called from EntryKernel. That results -// in stopping sharing the previous value and creating a wrapper to the new -// value. -template <typename T, typename Traits = DefaultProtoValuePtrTraits<T>> -class ProtoValuePtr { - private: - // Immutable shareable ref-counted wrapper that embeds the value. - class Wrapper : public base::RefCountedThreadSafe<Wrapper> { - public: - Wrapper(const T& value) { Traits::CopyValue(&value_, value); } - const T& value() const { return value_; } - // Create wrapper by deserializing a BLOB. - static Wrapper* ParseFromBlob(const void* blob, int length) { - Wrapper* wrapper = new Wrapper; - Traits::ParseFromBlob(&wrapper->value_, blob, length); - return wrapper; - } - - private: - friend class base::RefCountedThreadSafe<Wrapper>; - Wrapper() {} - ~Wrapper() {} - - T value_; - }; - - ProtoValuePtr() {} - ~ProtoValuePtr() {} - - public: - const T& value() const { - return wrapper_ ? wrapper_->value() : Traits::DefaultValue(); - } - - const T* operator->() const { - const T& wrapped_instance = value(); - return &wrapped_instance; - } - - private: - friend struct EntryKernel; - FRIEND_TEST_ALL_PREFIXES(ProtoValuePtrTest, BasicTest); - FRIEND_TEST_ALL_PREFIXES(ProtoValuePtrTest, SharingTest); - FRIEND_TEST_ALL_PREFIXES(ProtoValuePtrTest, ParsingTest); - - void set_value(const T& new_value) { - if (Traits::HasValue(new_value)) { - wrapper_ = new Wrapper(new_value); - } else { - // Don't store default value. - wrapper_ = nullptr; - } - } - - void load(const void* blob, int length) { - wrapper_ = Wrapper::ParseFromBlob(blob, length); - } - - scoped_refptr<Wrapper> wrapper_; -}; - -typedef ProtoValuePtr<sync_pb::EntitySpecifics> EntitySpecificsPtr; -typedef ProtoValuePtr<sync_pb::AttachmentMetadata> AttachmentMetadataPtr; - -} // namespace syncable -} // namespace syncer - -#endif // SYNC_SYNCABLE_ENTRY_PROTO_FIELD_PTR_H_ diff --git a/sync/syncable/proto_value_ptr_unittest.cc b/sync/syncable/proto_value_ptr_unittest.cc deleted file mode 100644 index 4686286c6..0000000 --- a/sync/syncable/proto_value_ptr_unittest.cc +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright (c) 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "sync/syncable/proto_value_ptr.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace syncer { -namespace syncable { - -namespace { - -// TestValue class is used as a template argument with ProtoValuePtr<T> -class TestValue { - public: - TestValue() : value_(0), is_initialized_(false), is_default_(false) {} - explicit TestValue(int value) - : value_(value), is_initialized_(true), is_default_(false) {} - - ~TestValue() { g_delete_count++; } - - static void ResetCounters() { - g_copy_count = 0; - g_parse_count = 0; - g_delete_count = 0; - } - - static int copy_count() { return g_copy_count; } - static int parse_count() { return g_parse_count; } - static int delete_count() { return g_delete_count; } - - int value() const { return value_; } - bool is_initialized() const { return is_initialized_; } - bool is_default() const { return is_default_; } - - // TestValue uses the default traits struct with ProtoValuePtr<TestValue>. - // The following 4 functions are expected by the traits struct to exist - // in this class. - void CopyFrom(const TestValue& from) { - // Expected to always copy from an initialized instance - // to an uninitialized one. - // Not expected either value to be default. - ASSERT_FALSE(is_initialized()); - ASSERT_FALSE(is_default()); - ASSERT_TRUE(from.is_initialized()); - ASSERT_FALSE(from.is_default()); - value_ = from.value(); - is_initialized_ = true; - g_copy_count++; - } - - void ParseFromArray(const void* blob, int length) { - // Similarly to CopyFrom this is expected to be called on - // an uninitialized instance. - ASSERT_FALSE(is_initialized()); - ASSERT_FALSE(is_default()); - // The blob is an address of an integer - ASSERT_EQ(static_cast<int>(sizeof(int)), length); - value_ = *static_cast<const int*>(blob); - is_initialized_ = true; - g_parse_count++; - } - - int ByteSize() const { return is_initialized() ? sizeof(int) : 0; } - - static const TestValue& default_instance() { - static TestValue default_instance; - default_instance.is_default_ = true; - return default_instance; - } - - private: - static int g_copy_count; - static int g_parse_count; - static int g_delete_count; - - int value_; - bool is_initialized_; - bool is_default_; - - DISALLOW_COPY_AND_ASSIGN(TestValue); -}; - -// Static initializers. -int TestValue::g_copy_count = 0; -int TestValue::g_parse_count = 0; -int TestValue::g_delete_count = 0; - -} // namespace - -typedef ProtoValuePtr<TestValue> TestPtr; - -class ProtoValuePtrTest : public testing::Test { - public: - void SetUp() override { TestValue::ResetCounters(); } - - static bool WrappedValuesAreShared(const TestPtr& ptr1, const TestPtr& ptr2) { - const TestValue& wrapped_value_1 = ptr1.value(); - const TestValue& wrapped_value_2 = ptr2.value(); - // Compare addresses. - return &wrapped_value_1 == &wrapped_value_2; - } -}; - -TEST_F(ProtoValuePtrTest, BasicTest) { - // Basic assignment and default value. - TestValue t1(1); - { - TestPtr ptr1; - EXPECT_TRUE(ptr1->is_default()); - - ptr1.set_value(t1); - EXPECT_FALSE(ptr1->is_default()); - EXPECT_EQ(1, ptr1->value()); - } - - EXPECT_EQ(1, TestValue::copy_count()); - EXPECT_EQ(1, TestValue::delete_count()); -} - -TEST_F(ProtoValuePtrTest, SharingTest) { - // Sharing between two pointers. - TestValue empty; - TestValue t2(2); - TestValue t3(3); - { - TestPtr ptr2; - TestPtr ptr3; - - EXPECT_TRUE(ptr2->is_default()); - EXPECT_TRUE(ptr3->is_default()); - EXPECT_EQ(0, TestValue::copy_count()); - EXPECT_EQ(0, TestValue::delete_count()); - - ptr2.set_value(t2); - EXPECT_EQ(1, TestValue::copy_count()); - EXPECT_EQ(0, TestValue::delete_count()); - - ptr3 = ptr2; - // Both |ptr2| and |ptr3| now share the same value "2". - // No additional copies expected. - EXPECT_EQ(1, TestValue::copy_count()); - EXPECT_EQ(0, TestValue::delete_count()); - EXPECT_FALSE(ptr3->is_default()); - EXPECT_EQ(2, ptr3->value()); - EXPECT_TRUE(WrappedValuesAreShared(ptr2, ptr3)); - - // Stop sharing - |ptr2| is "3" and |ptr3| is still "2". - ptr2.set_value(t3); - EXPECT_FALSE(WrappedValuesAreShared(ptr2, ptr3)); - EXPECT_EQ(3, ptr2->value()); - EXPECT_EQ(2, ptr3->value()); - // No extra copies or deletions expected. - EXPECT_EQ(2, TestValue::copy_count()); - EXPECT_EQ(0, TestValue::delete_count()); - - // |ptr3| still has the old value. - EXPECT_EQ(2, ptr3->value()); - - // Share again. Both values are "3". - ptr3 = ptr2; - EXPECT_EQ(3, ptr3->value()); - // This should have resulted in deleting the wrapper for the value "2". - EXPECT_EQ(1, TestValue::delete_count()); - // No extra copies expected. - EXPECT_EQ(2, TestValue::copy_count()); - - // Set default value to one of the pointers. - ptr2.set_value(empty); - EXPECT_TRUE(ptr2->is_default()); - // The other one is still intact. - EXPECT_FALSE(ptr3->is_default()); - EXPECT_EQ(3, ptr3->value()); - // No extra copies or deletions expected. - EXPECT_EQ(1, TestValue::delete_count()); - EXPECT_EQ(2, TestValue::copy_count()); - - // Copy the default value between the pointers. - ptr3 = ptr2; - EXPECT_TRUE(ptr3->is_default()); - // The wrapper for "3" is now deleted. - EXPECT_EQ(2, TestValue::delete_count()); - } - - // No extra deletions expected upon leaving the scope. - EXPECT_EQ(2, TestValue::delete_count()); -} - -TEST_F(ProtoValuePtrTest, ParsingTest) { - int v1 = 21; - - { - TestPtr ptr1; - - ptr1.load(&v1, sizeof(int)); - - EXPECT_EQ(1, TestValue::parse_count()); - EXPECT_EQ(0, TestValue::copy_count()); - - EXPECT_EQ(v1, ptr1->value()); - } - - EXPECT_EQ(1, TestValue::delete_count()); -} - -} // namespace syncable -} // namespace syncer |