Index: chrome/browser/chromeos/gdata/gdata_files.cc |
=================================================================== |
--- chrome/browser/chromeos/gdata/gdata_files.cc (revision 148059) |
+++ chrome/browser/chromeos/gdata/gdata_files.cc (working copy) |
@@ -9,12 +9,16 @@ |
#include "base/platform_file.h" |
#include "base/string_util.h" |
#include "base/stringprintf.h" |
+#include "base/sequenced_task_runner.h" |
#include "base/utf_string_conversions.h" |
#include "chrome/browser/chromeos/gdata/gdata.pb.h" |
#include "chrome/browser/chromeos/gdata/gdata_util.h" |
#include "chrome/browser/chromeos/gdata/gdata_wapi_parser.h" |
+#include "content/public/browser/browser_thread.h" |
#include "net/base/escape.h" |
+using content::BrowserThread; |
+ |
namespace gdata { |
namespace { |
@@ -437,7 +441,8 @@ |
// GDataDirectoryService class implementation. |
GDataDirectoryService::GDataDirectoryService() |
- : serialized_size_(0), |
+ : blocking_task_runner_(NULL), |
+ serialized_size_(0), |
largest_changestamp_(0), |
origin_(UNINITIALIZED) { |
root_.reset(new GDataDirectory(NULL, this)); |
@@ -536,6 +541,129 @@ |
base::Bind(&RefreshFileInternal, base::Passed(&fresh_file))); |
} |
+void GDataDirectoryService::InitFromDB( |
+ const FilePath& db_path, |
+ base::SequencedTaskRunner* blocking_task_runner) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(!db_path.empty()); |
+ DCHECK(blocking_task_runner); |
+ |
+ db_path_ = db_path; |
+ blocking_task_runner_ = blocking_task_runner; |
+ |
+ SerializedMap* serialized_resources(new SerializedMap); |
+ blocking_task_runner_->PostTaskAndReply( |
+ FROM_HERE, |
+ base::Bind(&GDataDirectoryService::ReadFromDBOnBlockingThread, |
+ base::Unretained(this), |
+ db_path, |
+ serialized_resources), |
+ base::Bind(&GDataDirectoryService::InitResourceMapOnUIThread, |
+ base::Unretained(this), |
hashimoto
2012/07/24 08:41:51
Is this Unretained safe?
satorux1
2012/07/24 16:30:34
should use WeakPtr here.
|
+ base::Owned(serialized_resources))); |
satorux1
2012/07/24 16:30:34
Seems to me that initialization from the DB is sig
|
+} |
+ |
+void GDataDirectoryService::ReadFromDBOnBlockingThread( |
+ const FilePath& db_path, |
+ SerializedMap* serialized_resources) { |
+ DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ InitDBOnBlockingThread(db_path); |
+ |
+ if (serialized_resources) { |
+ scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( |
+ leveldb::ReadOptions())); |
+ for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { |
+ serialized_resources->insert(std::make_pair(iter->key().ToString(), |
+ iter->value().ToString())); |
+ } |
+ } |
+} |
+ |
+void GDataDirectoryService::InitDBOnBlockingThread(const FilePath& db_path) { |
+ DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ DCHECK(!db_path.empty()); |
+ |
+ db_path_ = db_path; |
+ leveldb::DB* level_db = NULL; |
+ leveldb::Options options; |
+ options.create_if_missing = true; |
+ leveldb::Status db_status = leveldb::DB::Open(options, db_path.value(), |
+ &level_db); |
+ DCHECK(level_db); |
+ DCHECK(db_status.ok()); |
+ level_db_.reset(level_db); |
+} |
+ |
+void GDataDirectoryService::InitResourceMapOnUIThread( |
+ SerializedMap* serialized_resources) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(resource_map_.empty()); |
+ |
+ ResourceMap resource_map; |
+ for (SerializedMap::const_iterator iter = serialized_resources->begin(); |
+ iter != serialized_resources->end(); ++iter) { |
+ scoped_ptr<GDataEntry> entry = GDataEntry::FromProtoString(iter->second); |
+ resource_map.insert(std::make_pair(iter->first, entry.release())); |
+ } |
+ |
+ // Fix up parent-child relations. |
+ for (ResourceMap::iterator iter = resource_map.begin(); |
+ iter != resource_map.end(); ++iter) { |
+ GDataEntry* entry = iter->second; |
+ ResourceMap::iterator parent_it = |
+ resource_map.find(entry->parent_resource_id()); |
+ if (parent_it != resource_map.end()) { |
+ GDataDirectory* parent = parent_it->second->AsGDataDirectory(); |
+ if (parent) { |
+ parent->AddEntry(entry); |
+ } else { |
+ NOTREACHED() << "Parent is not a directory " << parent->resource_id(); |
+ } |
+ } else { |
+ NOTREACHED() << "Missing parent id " << entry->parent_resource_id(); |
+ } |
+ } |
+} |
+ |
+void GDataDirectoryService::SaveResourceMapToDB() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ SerializedMap serialized_resources; |
+ for (ResourceMap::const_iterator iter = resource_map_.begin(); |
+ iter != resource_map_.end(); ++iter) { |
+ GDataEntryProto proto; |
+ iter->second->ToProtoFull(&proto); |
+ std::string serialized_string; |
+ const bool ok = proto.SerializeToString(&serialized_string); |
+ DCHECK(ok); |
+ if (ok) { |
+ serialized_resources.insert( |
+ std::make_pair(iter->first, serialized_string)); |
+ } |
+ } |
+ blocking_task_runner_->PostTask( |
+ FROM_HERE, |
+ base::Bind(&GDataDirectoryService::SaveSerializedToDBOnBlockingThread, |
+ base::Unretained(this), |
+ serialized_resources)); |
+} |
+ |
+void GDataDirectoryService::SaveSerializedToDBOnBlockingThread( |
+ const SerializedMap& serialized_resources) { |
+ DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); |
+ |
+ // Truncate the DB. |
+ level_db_.reset(); |
+ leveldb::DestroyDB(db_path_.value(), leveldb::Options()); |
+ InitDBOnBlockingThread(db_path_); |
+ |
+ for (SerializedMap::const_iterator iter = serialized_resources.begin(); |
+ iter != serialized_resources.end(); ++iter) { |
+ level_db_->Put(leveldb::WriteOptions(), |
+ leveldb::Slice(iter->first), |
+ leveldb::Slice(iter->second)); |
+ } |
+} |
+ |
// Convert to/from proto. |
// static |