Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(30)

Side by Side Diff: chrome/browser/chromeos/gdata/gdata_leveldb.cc

Issue 10168025: GDataDB support with leveldb. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: FindEntryByPath Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/gdata/gdata_leveldb.h"
6
7 #include <string.h>
8
9 #include <string>
10
11 #include "base/logging.h"
12 #include "chrome/browser/chromeos/gdata/gdata_files.h"
13 #include "leveldb/write_batch.h"
14
15 namespace gdata {
16 namespace {
17
18 // Helper class to convert |resource_id| and |path| to leveldb::Slice.
19 // We append prefixes id: and path: respectively to the keys.
20 class GDataSlice {
21 public:
22 // Methods to convert |resource_id| and |path| to leveldb::Slice, by
23 // appending id: and path: prefix. These slices point into slice_temp_.
24 leveldb::Slice ResourceIdToSlice(const std::string& resource_id);
25 leveldb::Slice PathToSlice(const FilePath& path);
26
27 private:
28 static const char kResourceIdPrefix[];
29 static const char kPathPrefix[];
30
31 // Backing storage for leveldb::Slice. The lifetime of GDataSlice must
32 // exceed that of the slice otherwise the slice will point to garbage.
33 std::string slice_temp_;
34 };
35
36 const char GDataSlice::kResourceIdPrefix[] = "id:";
37 const char GDataSlice::kPathPrefix[] = "path:";
38
39 leveldb::Slice GDataSlice::ResourceIdToSlice(const std::string& resource_id) {
40 slice_temp_ = kResourceIdPrefix + resource_id;
41 return leveldb::Slice(slice_temp_);
42 }
43
44 leveldb::Slice GDataSlice::PathToSlice(const FilePath& path) {
45 slice_temp_ = kPathPrefix + path.value();
46 return leveldb::Slice(slice_temp_);
47 }
48
49 } // namespace
50
51 GDataLevelDB::GDataLevelDB() {
52 }
53
54 GDataLevelDB::~GDataLevelDB() {
55 }
56
57 void GDataLevelDB::Init(const FilePath& db_path) {
58 leveldb::DB* level_db = NULL;
59 leveldb::Options options;
60 options.create_if_missing = true;
61 leveldb::Status status = leveldb::DB::Open(options,
62 db_path.Append("level_db").value(), &level_db);
63 DCHECK(level_db);
64 DCHECK(status.ok());
satorux1 2012/04/24 18:26:44 instead of DCHECK, shouldn't we return false?
achuithb 2012/04/24 19:43:58 I think we should handle the failure, ie, try to
65 level_db_.reset(level_db);
66 }
67
68 GDataDB::Status GDataLevelDB::Put(const GDataEntry& file) {
satorux1 2012/04/24 18:26:44 file -> entry
achuithb 2012/04/24 19:43:58 Done.
69 // Write the serialized proto.
70 std::string serialized_proto;
71 file.SerializeToString(&serialized_proto);
72
73 leveldb::WriteBatch batch;
74 GDataSlice gdata_slice;
75 batch.Put(gdata_slice.ResourceIdToSlice(file.resource_id()),
satorux1 2012/04/24 18:26:44 I found GDataSlice class to be rather complex. I g
achuithb 2012/04/24 19:43:58 Done.
76 leveldb::Slice(serialized_proto));
77 // Note we store the resource_id without prefix when it's the value.
78 batch.Put(gdata_slice.PathToSlice(file.GetFilePath()),
79 leveldb::Slice(file.resource_id()));
80 leveldb::Status status = level_db_->Write(
81 leveldb::WriteOptions(),
82 &batch);
83
84 DVLOG(1) << "GDataLevelDB::Put "
85 << gdata_slice.ResourceIdToSlice(file.resource_id()).ToString()
86 << ", " << gdata_slice.PathToSlice(file.GetFilePath()).ToString();
87 DCHECK(status.ok());
satorux1 2012/04/24 18:26:44 remove DCHECK? I guess it can fail if the disk is
achuithb 2012/04/24 19:43:58 Done.
88 return status.ok() ? DB_OK : DB_ERR;
89 }
90
91 GDataDB::Status GDataLevelDB::DeleteByResourceId(
92 const std::string& resource_id) {
93 scoped_ptr<GDataEntry> file;
94 Status status = GetByResourceId(resource_id, &file);
95 if (status == DB_ERR)
96 return DB_ERR;
97 else if (status == DB_NOT_FOUND)
98 return DB_OK;
satorux1 2012/04/24 18:26:44 is it OK? shouldn't we propagate that the resource
achuithb 2012/04/24 19:43:58 I believe not-found is handled as ok by the underl
99
100 leveldb::WriteBatch batch;
101 GDataSlice gdata_slice;
102 batch.Delete(gdata_slice.ResourceIdToSlice(resource_id));
103 batch.Delete(gdata_slice.PathToSlice(file->GetFilePath()));
104
105 leveldb::Status db_status = level_db_->Write(
106 leveldb::WriteOptions(), &batch);
107
108 return db_status.ok() ? DB_OK : DB_ERR;
109 }
110
111 GDataDB::Status GDataLevelDB::DeleteByPath(
112 const FilePath& path) {
113 std::string resource_id;
114 const Status status = ResourceIdForPath(path, &resource_id);
115 if (status != DB_OK)
116 return status;
117 return DeleteByResourceId(resource_id);
118 }
119
120 GDataDB::Status GDataLevelDB::GetByResourceId(const std::string& resource_id,
121 scoped_ptr<GDataEntry>* file) {
122 file->reset();
123 std::string serialized_proto;
124 const leveldb::Status status = level_db_->Get(leveldb::ReadOptions(),
125 GDataSlice().ResourceIdToSlice(resource_id), &serialized_proto);
126
127 if (status.IsNotFound())
128 return DB_NOT_FOUND;
129
130 if (status.ok()) {
131 DCHECK(!serialized_proto.empty());
132 *file = GDataEntry::FromProtoString(serialized_proto);
133 DCHECK(file->get());
134 return DB_OK;
135 }
136 return DB_ERR;
137 }
138
139 GDataDB::Status GDataLevelDB::GetByPath(const FilePath& path,
140 scoped_ptr<GDataEntry>* file) {
141 file->reset();
142 std::string resource_id;
143 const Status status = ResourceIdForPath(path, &resource_id);
144 if (status != DB_OK)
145 return status;
146 return GetByResourceId(resource_id, file);
147 }
148
149 GDataDB::Status GDataLevelDB::ResourceIdForPath(const FilePath& path,
150 std::string* resource_id) {
151 const leveldb::Status db_status = level_db_->Get(
152 leveldb::ReadOptions(), GDataSlice().PathToSlice(path), resource_id);
153
154 if (db_status.ok())
155 return DB_OK;
156 else if (db_status.IsNotFound())
157 return DB_NOT_FOUND;
158 else
159 return DB_ERR;
satorux1 2012/04/24 18:26:44 we might want to have a function that converts lev
achuithb 2012/04/24 19:43:58 Done.
160 }
161
162 scoped_ptr<GDataDBIter> GDataLevelDB::NewIterator(const FilePath& path) {
163 return scoped_ptr<GDataDBIter>(new GDataLevelDBIter(
164 scoped_ptr<leveldb::Iterator>(
165 level_db_->NewIterator(leveldb::ReadOptions())),
166 this,
167 path));
168 }
169
170 GDataLevelDBIter::GDataLevelDBIter(scoped_ptr<leveldb::Iterator> level_db_iter,
171 GDataDB* db,
172 const FilePath& path)
173 : level_db_iter_(level_db_iter.Pass()),
174 db_(db),
175 path_(path) {
176 level_db_iter_->Seek(GDataSlice().PathToSlice(path));
177 }
178
179 GDataLevelDBIter::~GDataLevelDBIter() {
180 }
181
182 scoped_ptr<GDataEntry> GDataLevelDBIter::GetNext() {
183 if (!level_db_iter_->Valid())
184 return scoped_ptr<GDataEntry>(NULL);
185
186 // Only consider keys under |path|.
187 if (!level_db_iter_->key().starts_with(GDataSlice().PathToSlice(path_)))
188 return scoped_ptr<GDataEntry>(NULL);
189
190 scoped_ptr<GDataEntry> entry;
191 GDataDB::Status status =
192 db_->GetByResourceId(level_db_iter_->value().ToString(), &entry);
193 DCHECK_EQ(GDataDB::DB_OK, status);
194 level_db_iter_->Next();
195 return entry.Pass();
196 }
197
198 } // namespace gdata
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698