summaryrefslogtreecommitdiffstats
path: root/components/dom_distiller
diff options
context:
space:
mode:
authorjyasskin@chromium.org <jyasskin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-22 05:54:08 +0000
committerjyasskin@chromium.org <jyasskin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-22 05:54:08 +0000
commite6f27a38b986daf96d9ba601f52b8a3380c69691 (patch)
tree97dd5457ea374e057fd00e3526def873565e2c62 /components/dom_distiller
parent5a65fde3eed81247f89429e963d7393fb8dc7341 (diff)
downloadchromium_src-e6f27a38b986daf96d9ba601f52b8a3380c69691.zip
chromium_src-e6f27a38b986daf96d9ba601f52b8a3380c69691.tar.gz
chromium_src-e6f27a38b986daf96d9ba601f52b8a3380c69691.tar.bz2
Revert 230025 "Extract the in-memory model from DomDistillerStore"
It caused "Use of uninitialised values" in the Linux valgrind bot: http://build.chromium.org/p/chromium.memory.fyi/builders/Linux%20Tests%20%28valgrind%29%282%29/builds/31483 > Extract the in-memory model from DomDistillerStore > > This moves interaction with the in-memory model from the store to its > own class: DomDistillerModel. This also adds two ways to lookup entries > to both the store and the model, GetEntryById and GetEntryByUrl. > > BUG=288015 > TBR=joi@chromium.org > > Review URL: https://codereview.chromium.org/26574002 TBR=cjhopman@chromium.org Review URL: https://codereview.chromium.org/34363003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@230057 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/dom_distiller')
-rw-r--r--components/dom_distiller/core/article_entry.cc21
-rw-r--r--components/dom_distiller/core/article_entry.h10
-rw-r--r--components/dom_distiller/core/dom_distiller_model.cc206
-rw-r--r--components/dom_distiller/core/dom_distiller_model.h94
-rw-r--r--components/dom_distiller/core/dom_distiller_model_unittest.cc131
-rw-r--r--components/dom_distiller/core/dom_distiller_store.cc177
-rw-r--r--components/dom_distiller/core/dom_distiller_store.h36
-rw-r--r--components/dom_distiller/core/dom_distiller_store_unittest.cc17
8 files changed, 142 insertions, 550 deletions
diff --git a/components/dom_distiller/core/article_entry.cc b/components/dom_distiller/core/article_entry.cc
index 1550caf..2e370a4 100644
--- a/components/dom_distiller/core/article_entry.cc
+++ b/components/dom_distiller/core/article_entry.cc
@@ -5,7 +5,6 @@
#include "components/dom_distiller/core/article_entry.h"
#include "base/logging.h"
-#include "sync/api/sync_change.h"
using sync_pb::EntitySpecifics;
using sync_pb::ArticlePage;
@@ -46,24 +45,4 @@ EntitySpecifics SpecificsFromEntry(const ArticleEntry& entry) {
return specifics;
}
-ArticleEntry GetEntryFromChange(const syncer::SyncChange& change) {
- DCHECK(change.IsValid());
- DCHECK(change.sync_data().IsValid());
- return EntryFromSpecifics(change.sync_data().GetSpecifics());
-}
-
-std::string GetEntryIdFromSyncData(const syncer::SyncData& data) {
- const EntitySpecifics& entity = data.GetSpecifics();
- DCHECK(entity.has_article());
- const ArticleSpecifics& specifics = entity.article();
- DCHECK(specifics.has_entry_id());
- return specifics.entry_id();
-}
-
-syncer::SyncData CreateLocalData(const ArticleEntry& entry) {
- EntitySpecifics specifics = SpecificsFromEntry(entry);
- const std::string& entry_id = entry.entry_id();
- return syncer::SyncData::CreateLocalData(entry_id, entry_id, specifics);
-}
-
} // namespace dom_distiller
diff --git a/components/dom_distiller/core/article_entry.h b/components/dom_distiller/core/article_entry.h
index 388dc51..3811612 100644
--- a/components/dom_distiller/core/article_entry.h
+++ b/components/dom_distiller/core/article_entry.h
@@ -5,14 +5,9 @@
#ifndef COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ENTRY_H_
#define COMPONENTS_DOM_DISTILLER_CORE_ARTICLE_ENTRY_H_
-#include "sync/api/sync_data.h"
#include "sync/protocol/article_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
-namespace syncer {
-class SyncChange;
-}
-
namespace dom_distiller {
typedef sync_pb::ArticleSpecifics ArticleEntry;
@@ -25,11 +20,6 @@ bool AreEntriesEqual(const ArticleEntry& left, const ArticleEntry& right);
sync_pb::EntitySpecifics SpecificsFromEntry(const ArticleEntry& entry);
ArticleEntry EntryFromSpecifics(const sync_pb::EntitySpecifics& specifics);
-ArticleEntry GetEntryFromChange(const syncer::SyncChange& change);
-std::string GetEntryIdFromSyncData(const syncer::SyncData& data);
-syncer::SyncData CreateLocalData(const ArticleEntry& entry);
-
-
} // namespace dom_distiller
#endif
diff --git a/components/dom_distiller/core/dom_distiller_model.cc b/components/dom_distiller/core/dom_distiller_model.cc
deleted file mode 100644
index 9468487..0000000
--- a/components/dom_distiller/core/dom_distiller_model.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright 2013 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 "components/dom_distiller/core/dom_distiller_model.h"
-
-using syncer::SyncChange;
-using syncer::SyncChangeList;
-using syncer::SyncData;
-using syncer::SyncDataList;
-
-namespace dom_distiller {
-
-DomDistillerModel::DomDistillerModel() {}
-
-DomDistillerModel::DomDistillerModel(
- const std::vector<ArticleEntry>& initial_data) {
- for (size_t i = 0; i < initial_data.size(); ++i) {
- AddEntry(initial_data[i]);
- }
-}
-
-DomDistillerModel::~DomDistillerModel() {}
-
-bool DomDistillerModel::GetEntryById(const std::string& entry_id,
- ArticleEntry* entry) const {
- KeyType key;
- if (!GetKeyById(entry_id, &key)) {
- return false;
- }
- GetEntryByKey(key, entry);
- return true;
-}
-
-bool DomDistillerModel::GetEntryByUrl(const GURL& url,
- ArticleEntry* entry) const {
- KeyType key;
- if (!GetKeyByUrl(url, &key)) {
- return false;
- }
- GetEntryByKey(key, entry);
- return true;
-}
-
-bool DomDistillerModel::GetKeyById(const std::string& entry_id,
- KeyType* key) const {
- StringToKeyMap::const_iterator it = entry_id_to_key_map_.find(entry_id);
- if (it == entry_id_to_key_map_.end()) {
- return false;
- }
- if (key != NULL) {
- *key = it->second;
- }
- return true;
-}
-
-bool DomDistillerModel::GetKeyByUrl(const GURL& url, KeyType* key) const {
- StringToKeyMap::const_iterator it = url_to_key_map_.find(url.spec());
- if (it == url_to_key_map_.end()) {
- return false;
- }
- if (key != NULL) {
- *key = it->second;
- }
- return true;
-}
-
-void DomDistillerModel::GetEntryByKey(KeyType key, ArticleEntry* entry) const {
- if (entry != NULL) {
- EntryMap::const_iterator it = entries_.find(key);
- DCHECK(it != entries_.end());
- *entry = it->second;
- }
-}
-
-size_t DomDistillerModel::GetNumEntries() const {
- return entries_.size();
-}
-
-std::vector<ArticleEntry> DomDistillerModel::GetEntries() const {
- std::vector<ArticleEntry> entries_list;
- for (EntryMap::const_iterator it = entries_.begin(); it != entries_.end();
- ++it) {
- entries_list.push_back(it->second);
- }
- return entries_list;
-}
-
-SyncDataList DomDistillerModel::GetAllSyncData() const {
- SyncDataList data;
- for (EntryMap::const_iterator it = entries_.begin(); it != entries_.end();
- ++it) {
- data.push_back(CreateLocalData(it->second));
- }
- return data;
-}
-
-void DomDistillerModel::CalculateChangesForMerge(
- const SyncDataList& data,
- SyncChangeList* changes_to_apply,
- SyncChangeList* changes_missing) {
- typedef base::hash_set<std::string> StringSet;
- StringSet entries_to_change;
- for (SyncDataList::const_iterator it = data.begin(); it != data.end(); ++it) {
- std::string entry_id = GetEntryIdFromSyncData(*it);
- std::pair<StringSet::iterator, bool> insert_result =
- entries_to_change.insert(entry_id);
-
- DCHECK(insert_result.second);
-
- SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD;
- if (GetEntryById(entry_id, NULL)) {
- change_type = SyncChange::ACTION_UPDATE;
- }
- changes_to_apply->push_back(SyncChange(FROM_HERE, change_type, *it));
- }
-
- for (EntryMap::const_iterator it = entries_.begin(); it != entries_.end();
- ++it) {
- if (entries_to_change.find(it->second.entry_id()) ==
- entries_to_change.end()) {
- changes_missing->push_back(SyncChange(
- FROM_HERE, SyncChange::ACTION_ADD, CreateLocalData(it->second)));
- }
- }
-}
-
-DomDistillerModel::ChangeResult DomDistillerModel::ApplyChangesToModel(
- const SyncChangeList& changes,
- SyncChangeList* changes_applied,
- SyncChangeList* changes_missing) {
- DCHECK(changes_applied);
- DCHECK(changes_missing);
-
- ChangeResult result = SUCCESS;
-
- for (SyncChangeList::const_iterator it = changes.begin(); it != changes.end();
- ++it) {
- result = ApplyChangeToModel(*it, changes_applied, changes_missing);
- if (result != SUCCESS) {
- break;
- }
- }
- return result;
-}
-
-void DomDistillerModel::AddEntry(const ArticleEntry& entry) {
- const std::string& entry_id = entry.entry_id();
- KeyType key = next_key_++;
- DCHECK(!GetKeyById(entry_id, NULL));
- entries_.insert(std::make_pair(key, entry));
- entry_id_to_key_map_.insert(std::make_pair(entry_id, key));
- for (int i = 0; i < entry.pages_size(); ++i) {
- url_to_key_map_.insert(std::make_pair(entry.pages(i).url(), key));
- }
-}
-
-void DomDistillerModel::RemoveEntry(const ArticleEntry& entry) {
- const std::string& entry_id = entry.entry_id();
- KeyType key;
- bool success = GetKeyById(entry_id, &key);
- DCHECK(success);
-
- entries_.erase(key);
- entry_id_to_key_map_.erase(entry_id);
- for (int i = 0; i < entry.pages_size(); ++i) {
- url_to_key_map_.erase(entry.pages(i).url());
- }
-}
-
-DomDistillerModel::ChangeResult DomDistillerModel::ApplyChangeToModel(
- const SyncChange& change,
- SyncChangeList* changes_applied,
- SyncChangeList* changes_missing) {
- DCHECK(change.IsValid());
- DCHECK(changes_applied);
- DCHECK(changes_missing);
-
- const std::string& entry_id = GetEntryIdFromSyncData(change.sync_data());
-
- if (change.change_type() == SyncChange::ACTION_DELETE) {
- // TODO(cjhopman): Support delete.
- NOTIMPLEMENTED();
- return DELETE_NOT_SUPPORTED;
- }
-
- ArticleEntry entry = GetEntryFromChange(change);
- ArticleEntry current_entry;
- if (!GetEntryById(entry_id, &current_entry)) {
- AddEntry(entry);
- changes_applied->push_back(SyncChange(
- change.location(), SyncChange::ACTION_ADD, change.sync_data()));
- } else {
- if (!AreEntriesEqual(current_entry, entry)) {
- // Currently, conflicts are simply resolved by accepting the last one to
- // arrive.
- RemoveEntry(current_entry);
- AddEntry(entry);
- changes_applied->push_back(SyncChange(
- change.location(), SyncChange::ACTION_UPDATE, change.sync_data()));
- }
- }
- return SUCCESS;
-}
-
-} // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_model.h b/components/dom_distiller/core/dom_distiller_model.h
deleted file mode 100644
index 1bc2ec2..0000000
--- a/components/dom_distiller/core/dom_distiller_model.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2013 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 COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_MODEL_H_
-#define COMPONENTS_DOM_DISTILLER_CORE_DOM_DISTILLER_MODEL_H_
-
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/id_map.h"
-#include "components/dom_distiller/core/article_entry.h"
-#include "sync/api/sync_change.h"
-#include "sync/api/sync_change_processor.h" // syncer::SyncChangeList
-#include "sync/api/sync_data.h"
-#include "url/gurl.h"
-
-namespace dom_distiller {
-
-// This stores the in-memory model of the DOM distiller list. Entries can be
-// looked up by URL or by entry_id.
-// The model assumes that an URL corresponds to at most a single entry. If this
-// assumption is broken, lookup by URL may return unexpected results.
-class DomDistillerModel {
- public:
- enum ChangeResult {
- SUCCESS = 0,
- DELETE_NOT_SUPPORTED,
- };
-
- DomDistillerModel();
- explicit DomDistillerModel(const std::vector<ArticleEntry>& initial_data);
-
- ~DomDistillerModel();
-
- // Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry
- // was found. On success, if |entry| is not null, it will contain the entry.
- bool GetEntryById(const std::string& entry_id, ArticleEntry* entry) const;
- bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) const;
-
- std::vector<ArticleEntry> GetEntries() const;
- size_t GetNumEntries() const;
-
- syncer::SyncDataList GetAllSyncData() const;
-
- // Convert a SyncDataList to a SyncChangeList of add or update changes based
- // on the state of the model. Also calculate the entries missing from the
- // SyncDataList.
- void CalculateChangesForMerge(const syncer::SyncDataList& data,
- syncer::SyncChangeList* changes_to_apply,
- syncer::SyncChangeList* changes_missing);
-
- // Applies the change list to the model, appending the actual changes made to
- // the model to |changes_applied|. If conflict resolution does not apply the
- // requested change, then adds the "diff" between what was requested and what
- // was actually applied to |changes_missing|.
- // Note: Currently conflicts are resolved by just applying the requested
- // change. This means nothing will be added to |changes_missing|.
- ChangeResult ApplyChangesToModel(const syncer::SyncChangeList& change_list,
- syncer::SyncChangeList* changes_applied,
- syncer::SyncChangeList* changes_missing);
-
- private:
- typedef int32 KeyType;
- typedef base::hash_map<KeyType, ArticleEntry> EntryMap;
- typedef base::hash_map<std::string, KeyType> StringToKeyMap;
-
- void AddEntry(const ArticleEntry& entry);
- void RemoveEntry(const ArticleEntry& entry);
-
- // Lookup an entry's key by ID or URL. Returns whether a corresponding key was
- // found. On success, if |key| is not null, it will contain the entry.
- bool GetKeyById(const std::string& entry_id, KeyType* key) const;
- bool GetKeyByUrl(const GURL& url, KeyType* key) const;
-
- // If |entry| is not null, assigns the entry for |key| to it. |key| must map
- // to an entry in |entries_|.
- void GetEntryByKey(KeyType key, ArticleEntry* entry) const;
-
- ChangeResult ApplyChangeToModel(const syncer::SyncChange& change,
- syncer::SyncChangeList* changes_applied,
- syncer::SyncChangeList* changes_missing);
-
- KeyType next_key_;
- EntryMap entries_;
- StringToKeyMap url_to_key_map_;
- StringToKeyMap entry_id_to_key_map_;
-
- DISALLOW_COPY_AND_ASSIGN(DomDistillerModel);
-};
-
-} // namespace dom_distiller
-
-#endif
diff --git a/components/dom_distiller/core/dom_distiller_model_unittest.cc b/components/dom_distiller/core/dom_distiller_model_unittest.cc
deleted file mode 100644
index 0220439..0000000
--- a/components/dom_distiller/core/dom_distiller_model_unittest.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2013 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 "components/dom_distiller/core/dom_distiller_model.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace dom_distiller {
-
-TEST(DomDistillerModelTest, TestGetByEntryId) {
- ArticleEntry entry1;
- entry1.set_entry_id("id1");
- entry1.set_title("title1");
- ArticleEntry entry2;
- entry2.set_entry_id("id2");
- entry2.set_title("title1");
-
- std::vector<ArticleEntry> initial_model;
- initial_model.push_back(entry1);
- initial_model.push_back(entry2);
-
- DomDistillerModel model(initial_model);
-
- ArticleEntry found_entry;
- EXPECT_TRUE(model.GetEntryById(entry1.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry1, found_entry));
-
- EXPECT_TRUE(model.GetEntryById(entry2.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry2, found_entry));
-
- EXPECT_FALSE(model.GetEntryById("some_other_id", NULL));
-}
-
-TEST(DomDistillerModelTest, TestGetByUrl) {
- ArticleEntry entry1;
- entry1.set_entry_id("id1");
- entry1.set_title("title1");
- ArticleEntryPage* page1 = entry1.add_pages();
- page1->set_url("http://example.com/1");
- ArticleEntryPage* page2 = entry1.add_pages();
- page2->set_url("http://example.com/2");
-
- ArticleEntry entry2;
- entry2.set_entry_id("id2");
- entry2.set_title("title1");
- ArticleEntryPage* page3 = entry2.add_pages();
- page3->set_url("http://example.com/a1");
-
- std::vector<ArticleEntry> initial_model;
- initial_model.push_back(entry1);
- initial_model.push_back(entry2);
-
- DomDistillerModel model(initial_model);
-
- ArticleEntry found_entry;
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page1->url()), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry1, found_entry));
-
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page2->url()), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry1, found_entry));
-
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page3->url()), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry2, found_entry));
-
- EXPECT_FALSE(model.GetEntryByUrl(GURL("http://example.com/foo"), NULL));
-}
-
-// This test ensures that the model handles the case where an URL maps to
-// multiple entries. In that case, the model is allowed to have an inconsistent
-// url-to-entry mapping, but it should not fail in other ways (i.e. id-to-entry
-// should be correct, shouldn't crash).
-TEST(DomDistillerModelTest, TestUrlToMultipleEntries) {
- ArticleEntry entry1;
- entry1.set_entry_id("id1");
- entry1.set_title("title1");
- ArticleEntryPage* page1 = entry1.add_pages();
- page1->set_url("http://example.com/1");
- ArticleEntryPage* page2 = entry1.add_pages();
- page2->set_url("http://example.com/2");
-
- ArticleEntry entry2;
- entry2.set_entry_id("id2");
- entry2.set_title("title1");
- ArticleEntryPage* page3 = entry2.add_pages();
- page3->set_url("http://example.com/1");
-
- std::vector<ArticleEntry> initial_model;
- initial_model.push_back(entry1);
- initial_model.push_back(entry2);
-
- DomDistillerModel model(initial_model);
-
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page1->url()), NULL));
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page2->url()), NULL));
- EXPECT_TRUE(model.GetEntryByUrl(GURL(page3->url()), NULL));
-
- ArticleEntry found_entry;
- EXPECT_TRUE(model.GetEntryById(entry1.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry1, found_entry));
-
- EXPECT_TRUE(model.GetEntryById(entry2.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry2, found_entry));
-
- syncer::SyncChangeList changes_to_apply;
- syncer::SyncChangeList changes_applied;
- syncer::SyncChangeList changes_missing;
-
- entry2.mutable_pages(0)->set_url("http://example.com/foo1");
- changes_to_apply.push_back(syncer::SyncChange(
- FROM_HERE, syncer::SyncChange::ACTION_UPDATE, CreateLocalData(entry2)));
- model.ApplyChangesToModel(
- changes_to_apply, &changes_applied, &changes_missing);
-
- EXPECT_TRUE(model.GetEntryById(entry1.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry1, found_entry));
-
- EXPECT_TRUE(model.GetEntryById(entry2.entry_id(), &found_entry));
- ASSERT_TRUE(IsEntryValid(found_entry));
- EXPECT_TRUE(AreEntriesEqual(entry2, found_entry));
-}
-
-} // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_store.cc b/components/dom_distiller/core/dom_distiller_store.cc
index 8be2cb6..f5a7a70 100644
--- a/components/dom_distiller/core/dom_distiller_store.cc
+++ b/components/dom_distiller/core/dom_distiller_store.cc
@@ -23,6 +23,24 @@ using syncer::SyncMergeResult;
namespace dom_distiller {
+namespace {
+
+std::string GetEntryIdFromSyncData(const SyncData& data) {
+ const EntitySpecifics& entity = data.GetSpecifics();
+ DCHECK(entity.has_article());
+ const ArticleSpecifics& specifics = entity.article();
+ DCHECK(specifics.has_entry_id());
+ return specifics.entry_id();
+}
+
+SyncData CreateLocalData(const ArticleEntry& entry) {
+ EntitySpecifics specifics = SpecificsFromEntry(entry);
+ const std::string& entry_id = entry.entry_id();
+ return SyncData::CreateLocalData(entry_id, entry_id, specifics);
+}
+
+} // namespace
+
DomDistillerStore::DomDistillerStore(
scoped_ptr<DomDistillerDatabaseInterface> database,
const base::FilePath& database_dir)
@@ -36,11 +54,11 @@ DomDistillerStore::DomDistillerStore(
DomDistillerStore::DomDistillerStore(
scoped_ptr<DomDistillerDatabaseInterface> database,
- const std::vector<ArticleEntry>& initial_data,
+ const EntryMap& initial_model,
const base::FilePath& database_dir)
: database_(database.Pass()),
database_loaded_(false),
- model_(initial_data),
+ model_(initial_model),
weak_ptr_factory_(this) {
database_->Init(database_dir,
base::Bind(&DomDistillerStore::OnDatabaseInit,
@@ -54,23 +72,11 @@ syncer::SyncableService* DomDistillerStore::GetSyncableService() {
return this;
}
-bool DomDistillerStore::GetEntryById(const std::string& entry_id,
- ArticleEntry* entry) {
- return model_.GetEntryById(entry_id, entry);
-}
-
-bool DomDistillerStore::GetEntryByUrl(const GURL& url,
- ArticleEntry* entry) {
- return model_.GetEntryByUrl(url, entry);
-}
-
-
bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
if (!database_loaded_) {
return false;
}
-
- if (model_.GetEntryById(entry.entry_id(), NULL)) {
+ if (model_.find(entry.entry_id()) != model_.end()) {
return false;
}
@@ -80,11 +86,7 @@ bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
SyncChangeList changes_applied;
SyncChangeList changes_missing;
-
- if (!ApplyChangesToModel(
- changes_to_apply, &changes_applied, &changes_missing)) {
- return false;
- }
+ ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
DCHECK_EQ(size_t(0), changes_missing.size());
DCHECK_EQ(size_t(1), changes_applied.size());
@@ -96,7 +98,11 @@ bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
}
std::vector<ArticleEntry> DomDistillerStore::GetEntries() const {
- return model_.GetEntries();
+ std::vector<ArticleEntry> entries;
+ for (EntryMap::const_iterator it = model_.begin(); it != model_.end(); ++it) {
+ entries.push_back(it->second);
+ }
+ return entries;
}
// syncer::SyncableService implementation.
@@ -127,7 +133,11 @@ void DomDistillerStore::StopSyncing(ModelType type) {
}
SyncDataList DomDistillerStore::GetAllSyncData(ModelType type) const {
- return model_.GetAllSyncData();
+ SyncDataList data;
+ for (EntryMap::const_iterator it = model_.begin(); it != model_.end(); ++it) {
+ data.push_back(CreateLocalData(it->second));
+ }
+ return data;
}
SyncError DomDistillerStore::ProcessSyncChanges(
@@ -136,34 +146,17 @@ SyncError DomDistillerStore::ProcessSyncChanges(
DCHECK(database_loaded_);
SyncChangeList database_changes;
SyncChangeList sync_changes;
- if (!ApplyChangesToModel(change_list, &database_changes, &sync_changes)) {
- return SyncError(FROM_HERE,
- SyncError::DATATYPE_ERROR,
- "Applying changes to the DOM distiller model failed",
- syncer::ARTICLES);
- }
+ SyncError error =
+ ApplyChangesToModel(change_list, &database_changes, &sync_changes);
ApplyChangesToDatabase(database_changes);
DCHECK_EQ(size_t(0), sync_changes.size());
- return SyncError();
+ return error;
}
-bool DomDistillerStore::ApplyChangesToModel(
- const SyncChangeList& changes,
- SyncChangeList* changes_applied,
- SyncChangeList* changes_missing) {
- DomDistillerModel::ChangeResult change_result =
- model_.ApplyChangesToModel(changes, changes_applied, changes_missing);
- if (change_result == DomDistillerModel::SUCCESS) {
- return true;
- }
-
- LOG(WARNING) << "Applying changes to DOM distiller model failed with error "
- << change_result;
-
- database_.reset();
- database_loaded_ = false;
- StopSyncing(syncer::ARTICLES);
- return false;
+ArticleEntry DomDistillerStore::GetEntryFromChange(const SyncChange& change) {
+ DCHECK(change.IsValid());
+ DCHECK(change.sync_data().IsValid());
+ return EntryFromSpecifics(change.sync_data().GetSpecifics());
}
void DomDistillerStore::OnDatabaseInit(bool success) {
@@ -245,6 +238,35 @@ bool DomDistillerStore::ApplyChangesToDatabase(
return true;
}
+void DomDistillerStore::CalculateChangesForMerge(
+ const SyncDataList& data,
+ SyncChangeList* changes_to_apply,
+ SyncChangeList* changes_missing) {
+ typedef base::hash_set<std::string> StringSet;
+ StringSet entries_to_change;
+ for (SyncDataList::const_iterator it = data.begin(); it != data.end(); ++it) {
+ std::string entry_id = GetEntryIdFromSyncData(*it);
+ std::pair<StringSet::iterator, bool> insert_result =
+ entries_to_change.insert(entry_id);
+
+ DCHECK(insert_result.second);
+
+ SyncChange::SyncChangeType change_type = SyncChange::ACTION_ADD;
+ EntryMap::const_iterator current = model_.find(entry_id);
+ if (current != model_.end()) {
+ change_type = SyncChange::ACTION_UPDATE;
+ }
+ changes_to_apply->push_back(SyncChange(FROM_HERE, change_type, *it));
+ }
+
+ for (EntryMap::const_iterator it = model_.begin(); it != model_.end(); ++it) {
+ if (entries_to_change.find(it->first) == entries_to_change.end()) {
+ changes_missing->push_back(SyncChange(
+ FROM_HERE, SyncChange::ACTION_ADD, CreateLocalData(it->second)));
+ }
+ }
+}
+
SyncMergeResult DomDistillerStore::MergeDataWithModel(
const SyncDataList& data,
SyncChangeList* changes_applied,
@@ -253,18 +275,12 @@ SyncMergeResult DomDistillerStore::MergeDataWithModel(
DCHECK(changes_missing);
SyncMergeResult result(syncer::ARTICLES);
- result.set_num_items_before_association(model_.GetNumEntries());
+ result.set_num_items_before_association(model_.size());
SyncChangeList changes_to_apply;
- model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing);
- SyncError error;
- if (!ApplyChangesToModel(
- changes_to_apply, changes_applied, changes_missing)) {
- error = SyncError(FROM_HERE,
- SyncError::DATATYPE_ERROR,
- "Applying changes to the DOM distiller model failed",
- syncer::ARTICLES);
- }
+ CalculateChangesForMerge(data, &changes_to_apply, changes_missing);
+ SyncError error =
+ ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing);
int num_added = 0;
int num_modified = 0;
@@ -288,10 +304,57 @@ SyncMergeResult DomDistillerStore::MergeDataWithModel(
result.set_num_items_deleted(0);
result.set_pre_association_version(0);
- result.set_num_items_after_association(model_.GetNumEntries());
+ result.set_num_items_after_association(model_.size());
result.set_error(error);
return result;
}
+SyncError DomDistillerStore::ApplyChangesToModel(
+ const SyncChangeList& changes,
+ SyncChangeList* changes_applied,
+ SyncChangeList* changes_missing) {
+ DCHECK(changes_applied);
+ DCHECK(changes_missing);
+
+ for (SyncChangeList::const_iterator it = changes.begin(); it != changes.end();
+ ++it) {
+ ApplyChangeToModel(*it, changes_applied, changes_missing);
+ }
+ return SyncError();
+}
+
+void DomDistillerStore::ApplyChangeToModel(const SyncChange& change,
+ SyncChangeList* changes_applied,
+ SyncChangeList* changes_missing) {
+ DCHECK(changes_applied);
+ DCHECK(changes_missing);
+ DCHECK(change.IsValid());
+
+ const std::string& entry_id = GetEntryIdFromSyncData(change.sync_data());
+ EntryMap::iterator entry_it = model_.find(entry_id);
+
+ if (change.change_type() == SyncChange::ACTION_DELETE) {
+ // TODO(cjhopman): Support delete.
+ NOTIMPLEMENTED();
+ StopSyncing(syncer::ARTICLES);
+ return;
+ }
+
+ ArticleEntry entry = GetEntryFromChange(change);
+ if (entry_it == model_.end()) {
+ model_.insert(std::make_pair(entry.entry_id(), entry));
+ changes_applied->push_back(SyncChange(
+ change.location(), SyncChange::ACTION_ADD, change.sync_data()));
+ } else {
+ if (!AreEntriesEqual(entry_it->second, entry)) {
+ // Currently, conflicts are simply resolved by accepting the last one to
+ // arrive.
+ entry_it->second = entry;
+ changes_applied->push_back(SyncChange(
+ change.location(), SyncChange::ACTION_UPDATE, change.sync_data()));
+ }
+ }
+}
+
} // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_store.h b/components/dom_distiller/core/dom_distiller_store.h
index 18641b7..fdc1851 100644
--- a/components/dom_distiller/core/dom_distiller_store.h
+++ b/components/dom_distiller/core/dom_distiller_store.h
@@ -11,14 +11,12 @@
#include "base/memory/weak_ptr.h"
#include "components/dom_distiller/core/article_entry.h"
#include "components/dom_distiller/core/dom_distiller_database.h"
-#include "components/dom_distiller/core/dom_distiller_model.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_data.h"
#include "sync/api/sync_error.h"
#include "sync/api/sync_error_factory.h"
#include "sync/api/sync_merge_result.h"
#include "sync/api/syncable_service.h"
-#include "url/gurl.h"
namespace base {
class FilePath;
@@ -36,12 +34,6 @@ class DomDistillerStoreInterface {
virtual bool AddEntry(const ArticleEntry& entry) = 0;
- // Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry
- // was found. On success, if |entry| is not null, it will contain the entry.
- virtual bool GetEntryById(const std::string& entry_id,
- ArticleEntry* entry) = 0;
- virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) = 0;
-
// Gets a copy of all the current entries.
virtual std::vector<ArticleEntry> GetEntries() const = 0;
@@ -67,6 +59,8 @@ class DomDistillerStoreInterface {
class DomDistillerStore : public syncer::SyncableService,
DomDistillerStoreInterface {
public:
+ typedef base::hash_map<std::string, ArticleEntry> EntryMap;
+
// Creates storage using the given database for local storage. Initializes the
// database with |database_dir|.
DomDistillerStore(scoped_ptr<DomDistillerDatabaseInterface> database,
@@ -76,7 +70,7 @@ class DomDistillerStore : public syncer::SyncableService,
// database with |database_dir|. Also initializes the internal model to
// |initial_model|.
DomDistillerStore(scoped_ptr<DomDistillerDatabaseInterface> database,
- const std::vector<ArticleEntry>& initial_data,
+ const EntryMap& initial_model,
const base::FilePath& database_dir);
virtual ~DomDistillerStore();
@@ -84,9 +78,6 @@ class DomDistillerStore : public syncer::SyncableService,
// DomDistillerStoreInterface implementation.
virtual syncer::SyncableService* GetSyncableService() OVERRIDE;
virtual bool AddEntry(const ArticleEntry& entry) OVERRIDE;
- virtual bool GetEntryById(const std::string& entry_id,
- ArticleEntry* entry) OVERRIDE;
- virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) OVERRIDE;
virtual std::vector<ArticleEntry> GetEntries() const OVERRIDE;
// syncer::SyncableService implementation.
@@ -101,6 +92,9 @@ class DomDistillerStore : public syncer::SyncableService,
virtual syncer::SyncError ProcessSyncChanges(
const tracked_objects::Location& from_here,
const syncer::SyncChangeList& change_list) OVERRIDE;
+
+ static ArticleEntry GetEntryFromChange(const syncer::SyncChange& change);
+
private:
void OnDatabaseInit(bool success);
void OnDatabaseLoad(bool success, scoped_ptr<EntryVector> entries);
@@ -122,18 +116,24 @@ class DomDistillerStore : public syncer::SyncableService,
const syncer::SyncChangeList& change_list);
bool ApplyChangesToDatabase(const syncer::SyncChangeList& change_list);
- // Applies the changes to |model_|. If the model returns an error, disables
- // syncing and database changes and returns false.
- bool ApplyChangesToModel(const syncer::SyncChangeList& change_list,
- syncer::SyncChangeList* changes_applied,
- syncer::SyncChangeList* changes_missing);
+ // Applies the change list to the in-memory model, appending the actual
+ // changes made to the model to changes_applied. If conflict resolution does
+ // not apply the requested change, then adds the "diff" to changes_missing.
+ syncer::SyncError ApplyChangesToModel(
+ const syncer::SyncChangeList& change_list,
+ syncer::SyncChangeList* changes_applied,
+ syncer::SyncChangeList* changes_missing);
+
+ void ApplyChangeToModel(const syncer::SyncChange& change,
+ syncer::SyncChangeList* changes_applied,
+ syncer::SyncChangeList* changes_missing);
scoped_ptr<syncer::SyncChangeProcessor> sync_processor_;
scoped_ptr<syncer::SyncErrorFactory> error_factory_;
scoped_ptr<DomDistillerDatabaseInterface> database_;
bool database_loaded_;
- DomDistillerModel model_;
+ EntryMap model_;
base::WeakPtrFactory<DomDistillerStore> weak_ptr_factory_;
diff --git a/components/dom_distiller/core/dom_distiller_store_unittest.cc b/components/dom_distiller/core/dom_distiller_store_unittest.cc
index 9e4cf35..333d72d 100644
--- a/components/dom_distiller/core/dom_distiller_store_unittest.cc
+++ b/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -34,21 +34,12 @@ namespace {
const ModelType kDomDistillerModelType = syncer::ARTICLES;
-typedef base::hash_map<std::string, ArticleEntry> EntryMap;
+typedef DomDistillerStore::EntryMap EntryMap;
void AddEntry(const ArticleEntry& e, EntryMap* map) {
(*map)[e.entry_id()] = e;
}
-std::vector<ArticleEntry> EntryMapToList(const EntryMap& entries) {
- std::vector<ArticleEntry> entry_list;
- for (EntryMap::const_iterator it = entries.begin(); it != entries.end();
- ++it) {
- entry_list.push_back(it->second);
- }
- return entry_list;
-}
-
class FakeDB : public DomDistillerDatabaseInterface {
typedef base::Callback<void(bool)> Callback;
@@ -143,7 +134,7 @@ class FakeSyncChangeProcessor : public syncer::SyncChangeProcessor {
for (SyncChangeList::const_iterator it = changes.begin();
it != changes.end();
++it) {
- AddEntry(GetEntryFromChange(*it), model_);
+ AddEntry(DomDistillerStore::GetEntryFromChange(*it), model_);
}
return SyncError();
}
@@ -212,7 +203,7 @@ class DomDistillerStoreTest : public testing::Test {
fake_db_ = new FakeDB(&db_model_);
store_.reset(new DomDistillerStore(
scoped_ptr<DomDistillerDatabaseInterface>(fake_db_),
- EntryMapToList(store_model_),
+ store_model_,
db_dir_));
}
@@ -457,7 +448,7 @@ TEST_F(DomDistillerStoreTest, TestSyncMergeWithSecondDomDistillerStore) {
FakeDB* other_fake_db = new FakeDB(&other_db_model);
scoped_ptr<DomDistillerStore> owned_other_store(new DomDistillerStore(
scoped_ptr<DomDistillerDatabaseInterface>(other_fake_db),
- std::vector<ArticleEntry>(),
+ EntryMap(),
base::FilePath(FILE_PATH_LITERAL("/fake/other/path"))));
DomDistillerStore* other_store = owned_other_store.get();
other_fake_db->InitCallback(true);