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

Side by Side Diff: content/browser/service_worker/service_worker_database.cc

Issue 257593003: ServiceWorker: Clean up ServiceWorkerDatabase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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
« no previous file with comments | « content/browser/service_worker/service_worker_database.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "content/browser/service_worker/service_worker_database.h" 5 #include "content/browser/service_worker/service_worker_database.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/location.h"
10 #include "base/logging.h" 11 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
12 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 13 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
13 #include "third_party/leveldatabase/src/include/leveldb/db.h" 14 #include "third_party/leveldatabase/src/include/leveldb/db.h"
14 #include "third_party/leveldatabase/src/include/leveldb/env.h" 15 #include "third_party/leveldatabase/src/include/leveldb/env.h"
15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 16 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
16 17
17 // LevelDB database schema 18 // LevelDB database schema
18 // ======================= 19 // =======================
19 // 20 //
21 // NOTE
22 // - int64 value is serialized as a string by base::Int64ToString().
23 //
20 // Version 1 (in sorted order) 24 // Version 1 (in sorted order)
21 // key: "DB_VERSION" 25 // key: "DB_VERSION"
22 // value: <int64 serialized as a string> 26 // value: "1"
23 // 27 //
24 // key: "NEXT_REGISTRATION_ID" 28 // key: "NEXT_REGISTRATION_ID"
25 // value: <int64 serialized as a string> 29 // value: <int64 'next_available_registration_id'>
26 // 30 //
27 // key: "NEXT_RESOURCE_ID" 31 // key: "NEXT_RESOURCE_ID"
28 // value: <int64 serialized as a string> 32 // value: <int64 'next_available_resource_id'>
29 // 33 //
30 // key: "NEXT_VERSION_ID" 34 // key: "NEXT_VERSION_ID"
31 // value: <int64 serialized as a string> 35 // value: <int64 'next_available_version_id'>
32 36
33 namespace content { 37 namespace content {
34 38
35 namespace { 39 namespace {
36 40
37 const char kDatabaseVersionKey[] = "DB_VERSION"; 41 const char kDatabaseVersionKey[] = "DB_VERSION";
38 const char kNextRegIdKey[] = "NEXT_REGISTRATION_ID"; 42 const char kNextRegIdKey[] = "NEXT_REGISTRATION_ID";
39 const char kNextResIdKey[] = "NEXT_RESOURCE_ID"; 43 const char kNextResIdKey[] = "NEXT_RESOURCE_ID";
40 const char kNextVerIdKey[] = "NEXT_VERSION_ID"; 44 const char kNextVerIdKey[] = "NEXT_VERSION_ID";
41 45
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 DCHECK(next_avail_version_id); 77 DCHECK(next_avail_version_id);
74 DCHECK(next_avail_resource_id); 78 DCHECK(next_avail_resource_id);
75 79
76 if (!LazyOpen(false) || is_disabled_) 80 if (!LazyOpen(false) || is_disabled_)
77 return false; 81 return false;
78 82
79 int64 reg_id = -1; 83 int64 reg_id = -1;
80 int64 ver_id = -1; 84 int64 ver_id = -1;
81 int64 res_id = -1; 85 int64 res_id = -1;
82 86
83 if (!ReadInt64(kNextRegIdKey, &reg_id) || 87 if (!ReadNextAvailableId(kNextRegIdKey, &reg_id) ||
84 !ReadInt64(kNextVerIdKey, &ver_id) || 88 !ReadNextAvailableId(kNextVerIdKey, &ver_id) ||
85 !ReadInt64(kNextResIdKey, &res_id)) 89 !ReadNextAvailableId(kNextResIdKey, &res_id))
86 return false; 90 return false;
87 91
88 *next_avail_registration_id = reg_id; 92 *next_avail_registration_id = reg_id;
89 *next_avail_version_id = ver_id; 93 *next_avail_version_id = ver_id;
90 *next_avail_resource_id = res_id; 94 *next_avail_resource_id = res_id;
91 return true; 95 return true;
92 } 96 }
93 97
94 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) { 98 bool ServiceWorkerDatabase::LazyOpen(bool create_if_needed) {
95 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 99 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
(...skipping 22 matching lines...) Expand all
118 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default())); 122 env_.reset(leveldb::NewMemEnv(leveldb::Env::Default()));
119 options.env = env_.get(); 123 options.env = env_.get();
120 } 124 }
121 125
122 leveldb::DB* db = NULL; 126 leveldb::DB* db = NULL;
123 leveldb::Status status = 127 leveldb::Status status =
124 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db); 128 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db);
125 if (!status.ok()) { 129 if (!status.ok()) {
126 DCHECK(!db); 130 DCHECK(!db);
127 // TODO(nhiroki): Should we retry to open the database? 131 // TODO(nhiroki): Should we retry to open the database?
128 DLOG(ERROR) << "Failed to open LevelDB database: " << status.ToString(); 132 HandleError(FROM_HERE, status);
129 is_disabled_ = true;
130 return false; 133 return false;
131 } 134 }
132 db_.reset(db); 135 db_.reset(db);
133 136
134 if (IsEmpty() && !PopulateInitialData()) { 137 if (IsEmpty() && !PopulateInitialData()) {
135 DLOG(ERROR) << "Failed to populate the database."; 138 DLOG(ERROR) << "Failed to populate the database.";
136 is_disabled_ = true;
137 db_.reset(); 139 db_.reset();
138 return false; 140 return false;
139 } 141 }
140 return true; 142 return true;
141 } 143 }
142 144
143 bool ServiceWorkerDatabase::PopulateInitialData() { 145 bool ServiceWorkerDatabase::PopulateInitialData() {
144 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); 146 leveldb::WriteBatch batch;
145 batch->Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion)); 147 batch.Put(kDatabaseVersionKey, base::Int64ToString(kCurrentSchemaVersion));
146 batch->Put(kNextRegIdKey, "0"); 148 batch.Put(kNextRegIdKey, base::Int64ToString(0));
147 batch->Put(kNextResIdKey, "0"); 149 batch.Put(kNextResIdKey, base::Int64ToString(0));
148 batch->Put(kNextVerIdKey, "0"); 150 batch.Put(kNextVerIdKey, base::Int64ToString(0));
149 return WriteBatch(batch.Pass()); 151 return WriteBatch(&batch);
150 } 152 }
151 153
152 bool ServiceWorkerDatabase::ReadInt64( 154 bool ServiceWorkerDatabase::ReadNextAvailableId(
153 const leveldb::Slice& key, 155 const char* id_key, int64* next_avail_id) {
154 int64* value_out) { 156 DCHECK(id_key);
155 DCHECK(value_out); 157 DCHECK(next_avail_id);
156 158
157 std::string value; 159 std::string value;
158 leveldb::Status status = db_->Get(leveldb::ReadOptions(), key, &value); 160 leveldb::Status status = db_->Get(leveldb::ReadOptions(), id_key, &value);
159 if (!status.ok()) { 161 if (!status.ok()) {
160 DLOG(ERROR) << "Failed to read data keyed by " 162 HandleError(FROM_HERE, status);
161 << key.ToString() << ": " << status.ToString();
162 is_disabled_ = true;
163 if (status.IsCorruption())
164 was_corruption_detected_ = true;
165 return false; 163 return false;
166 } 164 }
167 165
168 int64 parsed = -1; 166 int64 parsed;
169 if (!base::StringToInt64(value, &parsed)) { 167 if (!base::StringToInt64(value, &parsed)) {
170 DLOG(ERROR) << "Database might be corrupted: " 168 HandleError(FROM_HERE, leveldb::Status::Corruption("failed to parse"));
171 << key.ToString() << ", " << value;
172 is_disabled_ = true;
173 was_corruption_detected_ = true;
174 return false; 169 return false;
175 } 170 }
176 171
177 *value_out = parsed; 172 *next_avail_id = parsed;
178 return true; 173 return true;
179 } 174 }
180 175
181 bool ServiceWorkerDatabase::WriteBatch(scoped_ptr<leveldb::WriteBatch> batch) { 176 bool ServiceWorkerDatabase::WriteBatch(leveldb::WriteBatch* batch) {
182 if (!batch) 177 DCHECK(batch);
183 return true; 178 DCHECK(!is_disabled_);
184 179 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch);
185 leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch.get()); 180 if (!status.ok()) {
186 if (status.ok()) 181 HandleError(FROM_HERE, status);
187 return true; 182 return false;
188 183 }
189 DLOG(ERROR) << "Failed to write the batch: " << status.ToString(); 184 return true;
190 is_disabled_ = true;
191 if (status.IsCorruption())
192 was_corruption_detected_ = true;
193 return false;
194 } 185 }
195 186
196 bool ServiceWorkerDatabase::IsOpen() { 187 bool ServiceWorkerDatabase::IsOpen() {
197 return db_.get() != NULL; 188 return db_.get() != NULL;
198 } 189 }
199 190
200 bool ServiceWorkerDatabase::IsEmpty() { 191 bool ServiceWorkerDatabase::IsEmpty() {
201 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 192 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
202 itr->SeekToFirst(); 193 itr->SeekToFirst();
194 // TODO(nhiroki): Handle an error.
195 DCHECK(itr->status().ok());
203 return !itr->Valid(); 196 return !itr->Valid();
204 } 197 }
205 198
199 void ServiceWorkerDatabase::HandleError(
200 const tracked_objects::Location& from_here,
201 const leveldb::Status& status) {
202 // TODO(nhiroki): Add an UMA histogram.
203 DLOG(ERROR) << "Failed at: " << from_here.ToString()
204 << " with error: " << status.ToString();
205 is_disabled_ = true;
206 if (status.IsCorruption())
207 was_corruption_detected_ = true;
208 db_.reset();
michaeln 2014/04/25 00:01:36 ok, db is closed when anything goes wrong
209 }
210
206 } // namespace content 211 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/service_worker/service_worker_database.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698