OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/gdata/gdata_leveldb.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_leveldb.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/threading/thread_restrictions.h" |
10 #include "chrome/browser/chromeos/gdata/gdata_files.h" | 11 #include "chrome/browser/chromeos/gdata/gdata_files.h" |
11 #include "leveldb/write_batch.h" | 12 #include "leveldb/write_batch.h" |
12 | 13 |
13 namespace gdata { | 14 namespace gdata { |
14 namespace { | 15 namespace { |
15 | 16 |
16 const char kResourceIdPrefix[] = "r:"; | 17 const char kResourceIdPrefix[] = "r:"; |
17 const char kPathPrefix[] = "p:"; | 18 const char kPathPrefix[] = "p:"; |
18 | 19 |
19 // Append prefix id: to |resource_id|. | 20 // Append prefix id: to |resource_id|. |
(...skipping 25 matching lines...) Expand all Loading... |
45 | 46 |
46 } // namespace | 47 } // namespace |
47 | 48 |
48 GDataLevelDB::GDataLevelDB() { | 49 GDataLevelDB::GDataLevelDB() { |
49 } | 50 } |
50 | 51 |
51 GDataLevelDB::~GDataLevelDB() { | 52 GDataLevelDB::~GDataLevelDB() { |
52 } | 53 } |
53 | 54 |
54 void GDataLevelDB::Init(const FilePath& db_path) { | 55 void GDataLevelDB::Init(const FilePath& db_path) { |
| 56 base::ThreadRestrictions::AssertIOAllowed(); |
| 57 |
55 leveldb::DB* level_db = NULL; | 58 leveldb::DB* level_db = NULL; |
56 leveldb::Options options; | 59 leveldb::Options options; |
57 options.create_if_missing = true; | 60 options.create_if_missing = true; |
58 leveldb::Status db_status = leveldb::DB::Open(options, | 61 leveldb::Status db_status = leveldb::DB::Open(options, |
59 db_path.Append("level_db").value(), &level_db); | 62 db_path.Append("level_db").value(), &level_db); |
60 DCHECK(level_db); | 63 DCHECK(level_db); |
61 // TODO(achuith): If db cannot be opened, we should try to recover it. | 64 // TODO(achuith): If db cannot be opened, we should try to recover it. |
62 // If that fails, we should just delete it and create a new file. | 65 // If that fails, we should just delete it and create a new file. |
63 DCHECK(db_status.ok()); | 66 DCHECK(db_status.ok()); |
64 level_db_.reset(level_db); | 67 level_db_.reset(level_db); |
65 } | 68 } |
66 | 69 |
67 GDataDB::Status GDataLevelDB::Put(const GDataEntry& entry) { | 70 GDataDB::Status GDataLevelDB::Put(const GDataEntry& entry) { |
| 71 base::ThreadRestrictions::AssertIOAllowed(); |
| 72 |
68 // Write the serialized proto. | 73 // Write the serialized proto. |
69 std::string serialized_proto; | 74 std::string serialized_proto; |
70 entry.SerializeToString(&serialized_proto); | 75 entry.SerializeToString(&serialized_proto); |
71 | 76 |
72 leveldb::WriteBatch batch; | 77 leveldb::WriteBatch batch; |
73 const std::string resource_id_key = | 78 const std::string resource_id_key = |
74 ResourceIdToKey(entry.resource_id()); | 79 ResourceIdToKey(entry.resource_id()); |
75 const std::string path_key = PathToKey(entry.GetFilePath()); | 80 const std::string path_key = PathToKey(entry.GetFilePath()); |
76 batch.Put(leveldb::Slice(resource_id_key), leveldb::Slice(serialized_proto)); | 81 batch.Put(leveldb::Slice(resource_id_key), leveldb::Slice(serialized_proto)); |
77 // Note we store the resource_id without prefix when it's the value. | 82 // Note we store the resource_id without prefix when it's the value. |
78 batch.Put(leveldb::Slice(path_key), leveldb::Slice(entry.resource_id())); | 83 batch.Put(leveldb::Slice(path_key), leveldb::Slice(entry.resource_id())); |
79 leveldb::Status db_status = level_db_->Write( | 84 leveldb::Status db_status = level_db_->Write( |
80 leveldb::WriteOptions(), | 85 leveldb::WriteOptions(), |
81 &batch); | 86 &batch); |
82 | 87 |
83 DVLOG(1) << "GDataLevelDB::Put resource_id key = " << resource_id_key | 88 DVLOG(1) << "GDataLevelDB::Put resource_id key = " << resource_id_key |
84 << ", path key = " << path_key; | 89 << ", path key = " << path_key; |
85 return GetStatus(db_status); | 90 return GetStatus(db_status); |
86 } | 91 } |
87 | 92 |
88 GDataDB::Status GDataLevelDB::DeleteByResourceId( | 93 GDataDB::Status GDataLevelDB::DeleteByResourceId( |
89 const std::string& resource_id) { | 94 const std::string& resource_id) { |
| 95 base::ThreadRestrictions::AssertIOAllowed(); |
| 96 |
90 scoped_ptr<GDataEntry> entry; | 97 scoped_ptr<GDataEntry> entry; |
91 Status status = GetByResourceId(resource_id, &entry); | 98 Status status = GetByResourceId(resource_id, &entry); |
92 if (status == DB_KEY_NOT_FOUND) | 99 if (status == DB_KEY_NOT_FOUND) |
93 return DB_OK; | 100 return DB_OK; |
94 else if (status != DB_OK) | 101 else if (status != DB_OK) |
95 return status; | 102 return status; |
96 | 103 |
97 leveldb::WriteBatch batch; | 104 leveldb::WriteBatch batch; |
98 const std::string resource_id_key = ResourceIdToKey(resource_id); | 105 const std::string resource_id_key = ResourceIdToKey(resource_id); |
99 const std::string path_key = PathToKey(entry->GetFilePath()); | 106 const std::string path_key = PathToKey(entry->GetFilePath()); |
100 batch.Delete(leveldb::Slice(resource_id_key)); | 107 batch.Delete(leveldb::Slice(resource_id_key)); |
101 batch.Delete(leveldb::Slice(path_key)); | 108 batch.Delete(leveldb::Slice(path_key)); |
102 | 109 |
103 leveldb::Status db_status = level_db_->Write(leveldb::WriteOptions(), | 110 leveldb::Status db_status = level_db_->Write(leveldb::WriteOptions(), |
104 &batch); | 111 &batch); |
105 return GetStatus(db_status); | 112 return GetStatus(db_status); |
106 } | 113 } |
107 | 114 |
108 GDataDB::Status GDataLevelDB::DeleteByPath( | 115 GDataDB::Status GDataLevelDB::DeleteByPath( |
109 const FilePath& path) { | 116 const FilePath& path) { |
| 117 base::ThreadRestrictions::AssertIOAllowed(); |
| 118 |
110 std::string resource_id; | 119 std::string resource_id; |
111 const Status status = ResourceIdForPath(path, &resource_id); | 120 const Status status = ResourceIdForPath(path, &resource_id); |
112 if (status != DB_OK) | 121 if (status != DB_OK) |
113 return status; | 122 return status; |
114 return DeleteByResourceId(resource_id); | 123 return DeleteByResourceId(resource_id); |
115 } | 124 } |
116 | 125 |
117 GDataDB::Status GDataLevelDB::GetByResourceId(const std::string& resource_id, | 126 GDataDB::Status GDataLevelDB::GetByResourceId(const std::string& resource_id, |
118 scoped_ptr<GDataEntry>* entry) { | 127 scoped_ptr<GDataEntry>* entry) { |
| 128 base::ThreadRestrictions::AssertIOAllowed(); |
| 129 |
119 entry->reset(); | 130 entry->reset(); |
120 std::string serialized_proto; | 131 std::string serialized_proto; |
121 const std::string resource_id_key = ResourceIdToKey(resource_id); | 132 const std::string resource_id_key = ResourceIdToKey(resource_id); |
122 const leveldb::Status db_status = level_db_->Get(leveldb::ReadOptions(), | 133 const leveldb::Status db_status = level_db_->Get(leveldb::ReadOptions(), |
123 leveldb::Slice(resource_id_key), &serialized_proto); | 134 leveldb::Slice(resource_id_key), &serialized_proto); |
124 | 135 |
125 if (db_status.IsNotFound()) | 136 if (db_status.IsNotFound()) |
126 return DB_KEY_NOT_FOUND; | 137 return DB_KEY_NOT_FOUND; |
127 | 138 |
128 if (db_status.ok()) { | 139 if (db_status.ok()) { |
129 DCHECK(!serialized_proto.empty()); | 140 DCHECK(!serialized_proto.empty()); |
130 *entry = GDataEntry::FromProtoString(serialized_proto); | 141 *entry = GDataEntry::FromProtoString(serialized_proto); |
131 DCHECK(entry->get()); | 142 DCHECK(entry->get()); |
132 return DB_OK; | 143 return DB_OK; |
133 } | 144 } |
134 return GetStatus(db_status); | 145 return GetStatus(db_status); |
135 } | 146 } |
136 | 147 |
137 GDataDB::Status GDataLevelDB::GetByPath(const FilePath& path, | 148 GDataDB::Status GDataLevelDB::GetByPath(const FilePath& path, |
138 scoped_ptr<GDataEntry>* entry) { | 149 scoped_ptr<GDataEntry>* entry) { |
| 150 base::ThreadRestrictions::AssertIOAllowed(); |
| 151 |
139 entry->reset(); | 152 entry->reset(); |
140 std::string resource_id; | 153 std::string resource_id; |
141 const Status status = ResourceIdForPath(path, &resource_id); | 154 const Status status = ResourceIdForPath(path, &resource_id); |
142 if (status != DB_OK) | 155 if (status != DB_OK) |
143 return status; | 156 return status; |
144 return GetByResourceId(resource_id, entry); | 157 return GetByResourceId(resource_id, entry); |
145 } | 158 } |
146 | 159 |
147 GDataDB::Status GDataLevelDB::ResourceIdForPath(const FilePath& path, | 160 GDataDB::Status GDataLevelDB::ResourceIdForPath(const FilePath& path, |
148 std::string* resource_id) { | 161 std::string* resource_id) { |
| 162 base::ThreadRestrictions::AssertIOAllowed(); |
| 163 |
149 const std::string path_key = PathToKey(path); | 164 const std::string path_key = PathToKey(path); |
150 const leveldb::Status db_status = level_db_->Get( | 165 const leveldb::Status db_status = level_db_->Get( |
151 leveldb::ReadOptions(), path_key, resource_id); | 166 leveldb::ReadOptions(), path_key, resource_id); |
152 | 167 |
153 return GetStatus(db_status); | 168 return GetStatus(db_status); |
154 } | 169 } |
155 | 170 |
156 scoped_ptr<GDataDBIter> GDataLevelDB::CreateIterator(const FilePath& path) { | 171 scoped_ptr<GDataDBIter> GDataLevelDB::CreateIterator(const FilePath& path) { |
157 return scoped_ptr<GDataDBIter>(new GDataLevelDBIter( | 172 return scoped_ptr<GDataDBIter>(new GDataLevelDBIter( |
158 scoped_ptr<leveldb::Iterator>( | 173 scoped_ptr<leveldb::Iterator>( |
159 level_db_->NewIterator(leveldb::ReadOptions())), | 174 level_db_->NewIterator(leveldb::ReadOptions())), |
160 this, | 175 this, |
161 path)); | 176 path)); |
162 } | 177 } |
163 | 178 |
164 GDataLevelDBIter::GDataLevelDBIter(scoped_ptr<leveldb::Iterator> level_db_iter, | 179 GDataLevelDBIter::GDataLevelDBIter(scoped_ptr<leveldb::Iterator> level_db_iter, |
165 GDataDB* db, | 180 GDataDB* db, |
166 const FilePath& path) | 181 const FilePath& path) |
167 : level_db_iter_(level_db_iter.Pass()), | 182 : level_db_iter_(level_db_iter.Pass()), |
168 db_(db), | 183 db_(db), |
169 path_(path) { | 184 path_(path) { |
| 185 base::ThreadRestrictions::AssertIOAllowed(); |
| 186 |
170 const std::string path_key = PathToKey(path); | 187 const std::string path_key = PathToKey(path); |
171 level_db_iter_->Seek(leveldb::Slice(path_key)); | 188 level_db_iter_->Seek(leveldb::Slice(path_key)); |
172 } | 189 } |
173 | 190 |
174 GDataLevelDBIter::~GDataLevelDBIter() { | 191 GDataLevelDBIter::~GDataLevelDBIter() { |
175 } | 192 } |
176 | 193 |
177 bool GDataLevelDBIter::GetNext(std::string* path, | 194 bool GDataLevelDBIter::GetNext(std::string* path, |
178 scoped_ptr<GDataEntry>* entry) { | 195 scoped_ptr<GDataEntry>* entry) { |
| 196 base::ThreadRestrictions::AssertIOAllowed(); |
| 197 |
179 DCHECK(path); | 198 DCHECK(path); |
180 DCHECK(entry); | 199 DCHECK(entry); |
181 path->clear(); | 200 path->clear(); |
182 entry->reset(); | 201 entry->reset(); |
183 | 202 |
184 if (!level_db_iter_->Valid()) | 203 if (!level_db_iter_->Valid()) |
185 return false; | 204 return false; |
186 | 205 |
187 // Only consider keys under |path|. | 206 // Only consider keys under |path|. |
188 const std::string path_key = PathToKey(path_); | 207 const std::string path_key = PathToKey(path_); |
189 leveldb::Slice key_slice(level_db_iter_->key()); | 208 leveldb::Slice key_slice(level_db_iter_->key()); |
190 if (!key_slice.starts_with(path_key)) | 209 if (!key_slice.starts_with(path_key)) |
191 return false; | 210 return false; |
192 | 211 |
193 GDataDB::Status status = | 212 GDataDB::Status status = |
194 db_->GetByResourceId(level_db_iter_->value().ToString(), entry); | 213 db_->GetByResourceId(level_db_iter_->value().ToString(), entry); |
195 DCHECK_EQ(GDataDB::DB_OK, status); | 214 DCHECK_EQ(GDataDB::DB_OK, status); |
196 | 215 |
197 key_slice.remove_prefix(sizeof(kPathPrefix) - 1); | 216 key_slice.remove_prefix(sizeof(kPathPrefix) - 1); |
198 path->assign(key_slice.ToString()); | 217 path->assign(key_slice.ToString()); |
199 | 218 |
200 level_db_iter_->Next(); | 219 level_db_iter_->Next(); |
201 return true; | 220 return true; |
202 } | 221 } |
203 | 222 |
204 } // namespace gdata | 223 } // namespace gdata |
OLD | NEW |