OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/sync/syncable/directory_backing_store.h" | 5 #include "chrome/browser/sync/syncable/directory_backing_store.h" |
6 | 6 |
7 #include "build/build_config.h" | 7 #include "build/build_config.h" |
8 | 8 |
9 #include <limits> | 9 #include <limits> |
10 | 10 |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 } | 184 } |
185 if (NULL != save_dbhandle_) { | 185 if (NULL != save_dbhandle_) { |
186 sqlite3_close(save_dbhandle_); | 186 sqlite3_close(save_dbhandle_); |
187 save_dbhandle_ = NULL; | 187 save_dbhandle_ = NULL; |
188 } | 188 } |
189 } | 189 } |
190 | 190 |
191 bool DirectoryBackingStore::OpenAndConfigureHandleHelper( | 191 bool DirectoryBackingStore::OpenAndConfigureHandleHelper( |
192 sqlite3** handle) const { | 192 sqlite3** handle) const { |
193 if (SQLITE_OK == sqlite_utils::OpenSqliteDb(backing_filepath_, handle)) { | 193 if (SQLITE_OK == sqlite_utils::OpenSqliteDb(backing_filepath_, handle)) { |
194 sqlite_utils::scoped_sqlite_db_ptr scoped_handle(*handle); | 194 sqlite3_busy_timeout(*handle, std::numeric_limits<int>::max()); |
195 sqlite3_busy_timeout(scoped_handle.get(), std::numeric_limits<int>::max()); | |
196 { | 195 { |
197 string integrity_error; | 196 string integrity_error; |
198 bool is_ok = CheckIntegrity(scoped_handle.get(), &integrity_error); | 197 bool is_ok = CheckIntegrity(*handle, &integrity_error); |
199 if (!is_ok) { | 198 if (!is_ok) { |
200 LOG(ERROR) << "Integrity check failed: " << integrity_error; | 199 LOG(ERROR) << "Integrity check failed: " << integrity_error; |
| 200 sqlite3_close(*handle); |
| 201 *handle = NULL; |
201 return false; | 202 return false; |
202 } | 203 } |
203 } | 204 } |
204 { | 205 { |
205 sqlite_utils::SQLStatement statement; | 206 sqlite_utils::SQLStatement statement; |
206 statement.prepare(scoped_handle.get(), "PRAGMA fullfsync = 1"); | 207 statement.prepare(*handle, "PRAGMA fullfsync = 1"); |
207 if (SQLITE_DONE != statement.step()) { | 208 if (SQLITE_DONE != statement.step()) { |
208 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); | 209 LOG(ERROR) << sqlite3_errmsg(*handle); |
| 210 sqlite3_close(*handle); |
| 211 *handle = NULL; |
209 return false; | 212 return false; |
210 } | 213 } |
211 } | 214 } |
212 { | 215 { |
213 sqlite_utils::SQLStatement statement; | 216 sqlite_utils::SQLStatement statement; |
214 statement.prepare(scoped_handle.get(), "PRAGMA synchronous = 2"); | 217 statement.prepare(*handle, "PRAGMA synchronous = 2"); |
215 if (SQLITE_DONE != statement.step()) { | 218 if (SQLITE_DONE != statement.step()) { |
216 LOG(ERROR) << sqlite3_errmsg(scoped_handle.get()); | 219 LOG(ERROR) << sqlite3_errmsg(*handle); |
| 220 sqlite3_close(*handle); |
| 221 *handle = NULL; |
217 return false; | 222 return false; |
218 } | 223 } |
219 } | 224 } |
220 sqlite3_busy_timeout(scoped_handle.release(), | 225 sqlite3_busy_timeout(*handle, kDirectoryBackingStoreBusyTimeoutMs); |
221 kDirectoryBackingStoreBusyTimeoutMs); | |
222 #if defined(OS_WIN) | 226 #if defined(OS_WIN) |
223 // Do not index this file. Scanning can occur every time we close the file, | 227 // Do not index this file. Scanning can occur every time we close the file, |
224 // which causes long delays in SQLite's file locking. | 228 // which causes long delays in SQLite's file locking. |
225 const DWORD attrs = GetFileAttributes(backing_filepath_.value().c_str()); | 229 const DWORD attrs = GetFileAttributes(backing_filepath_.value().c_str()); |
226 const BOOL attrs_set = | 230 const BOOL attrs_set = |
227 SetFileAttributes(backing_filepath_.value().c_str(), | 231 SetFileAttributes(backing_filepath_.value().c_str(), |
228 attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); | 232 attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); |
229 #endif | 233 #endif |
230 | 234 |
231 return true; | 235 return true; |
| 236 } else { |
| 237 // The sqlite3 API docs indicate a handle is usually returned even |
| 238 // in the case of error. We clean it up here. |
| 239 if (*handle != NULL) { |
| 240 sqlite3_close(*handle); |
| 241 *handle = NULL; |
| 242 } |
| 243 return false; |
232 } | 244 } |
233 return false; | |
234 } | 245 } |
235 | 246 |
236 bool DirectoryBackingStore::CheckIntegrity(sqlite3* handle, string* error) | 247 bool DirectoryBackingStore::CheckIntegrity(sqlite3* handle, string* error) |
237 const { | 248 const { |
238 sqlite_utils::SQLStatement statement; | 249 sqlite_utils::SQLStatement statement; |
239 statement.prepare(handle, "PRAGMA integrity_check(1)"); | 250 if (SQLITE_OK != |
| 251 statement.prepare(handle, "PRAGMA integrity_check(1)")) { |
| 252 *error = sqlite3_errmsg(handle); |
| 253 return false; |
| 254 } |
240 if (SQLITE_ROW != statement.step()) { | 255 if (SQLITE_ROW != statement.step()) { |
241 *error = sqlite3_errmsg(handle); | 256 *error = sqlite3_errmsg(handle); |
242 return false; | 257 return false; |
243 } | 258 } |
244 string integrity_result = statement.column_text(0); | 259 string integrity_result = statement.column_text(0); |
245 if (integrity_result != "ok") { | 260 if (integrity_result != "ok") { |
246 *error = integrity_result; | 261 *error = integrity_result; |
247 return false; | 262 return false; |
248 } | 263 } |
249 return true; | 264 return true; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 STLDeleteElements(entry_bucket); | 297 STLDeleteElements(entry_bucket); |
283 | 298 |
284 // Close database handle. | 299 // Close database handle. |
285 EndLoad(); | 300 EndLoad(); |
286 | 301 |
287 return result; | 302 return result; |
288 } | 303 } |
289 | 304 |
290 bool DirectoryBackingStore::BeginLoad() { | 305 bool DirectoryBackingStore::BeginLoad() { |
291 DCHECK(load_dbhandle_ == NULL); | 306 DCHECK(load_dbhandle_ == NULL); |
292 bool ret = OpenAndConfigureHandleHelper(&load_dbhandle_); | 307 return OpenAndConfigureHandleHelper(&load_dbhandle_); |
293 if (ret) | |
294 return true; | |
295 // Something's gone wrong. Nuke the database and try again. | |
296 using ::operator<<; // For string16. | |
297 LOG(ERROR) << "Sync database " << backing_filepath_.value() | |
298 << " corrupt. Deleting and recreating."; | |
299 file_util::Delete(backing_filepath_, false); | |
300 bool failed_again = !OpenAndConfigureHandleHelper(&load_dbhandle_); | |
301 | |
302 // Using failed_again here lets us distinguish from cases where corruption | |
303 // occurred even when re-opening a fresh directory (they'll go in a separate | |
304 // double weight histogram bucket). Failing twice in a row means we disable | |
305 // sync, so it's useful to see this number separately. | |
306 int bucket = failed_again ? 2 : 1; | |
307 #if defined(OS_WIN) | |
308 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedWin", bucket); | |
309 #elif defined(OS_MACOSX) | |
310 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedMac", bucket); | |
311 #else | |
312 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedNotWinMac", bucket); | |
313 | |
314 #if defined(OS_CHROMEOS) | |
315 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedCros", bucket); | |
316 #elif defined(OS_LINUX) | |
317 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedLinux", bucket); | |
318 #else | |
319 UMA_HISTOGRAM_COUNTS_100("Sync.DirectoryOpenFailedOther", bucket); | |
320 #endif // OS_LINUX && !OS_CHROMEOS | |
321 #endif // OS_WIN | |
322 return !failed_again; | |
323 } | 308 } |
324 | 309 |
325 void DirectoryBackingStore::EndLoad() { | 310 void DirectoryBackingStore::EndLoad() { |
326 sqlite3_close(load_dbhandle_); | 311 sqlite3_close(load_dbhandle_); |
327 load_dbhandle_ = NULL; // No longer used. | 312 load_dbhandle_ = NULL; // No longer used. |
328 } | 313 } |
329 | 314 |
330 void DirectoryBackingStore::EndSave() { | 315 void DirectoryBackingStore::EndSave() { |
331 sqlite3_close(save_dbhandle_); | 316 sqlite3_close(save_dbhandle_); |
332 save_dbhandle_ = NULL; | 317 save_dbhandle_ = NULL; |
(...skipping 937 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1270 "id TEXT primary key, " | 1255 "id TEXT primary key, " |
1271 "name TEXT, " | 1256 "name TEXT, " |
1272 "store_birthday TEXT, " | 1257 "store_birthday TEXT, " |
1273 "db_create_version TEXT, " | 1258 "db_create_version TEXT, " |
1274 "db_create_time INT, " | 1259 "db_create_time INT, " |
1275 "next_id INT default -2, " | 1260 "next_id INT default -2, " |
1276 "cache_guid TEXT )"); | 1261 "cache_guid TEXT )"); |
1277 return ExecQuery(load_dbhandle_, query.c_str()); | 1262 return ExecQuery(load_dbhandle_, query.c_str()); |
1278 } | 1263 } |
1279 } // namespace syncable | 1264 } // namespace syncable |
OLD | NEW |