OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * Copyright (C) 2013 Apple Inc. All rights reserved. | 3 * Copyright (C) 2013 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * | 8 * |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 errorMessage = formatErrorMessage("unable to open database", m_sqliteDat abase.lastError(), m_sqliteDatabase.lastErrorMsg()); | 322 errorMessage = formatErrorMessage("unable to open database", m_sqliteDat abase.lastError(), m_sqliteDatabase.lastErrorMsg()); |
323 return false; | 323 return false; |
324 } | 324 } |
325 if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum()) | 325 if (!m_sqliteDatabase.turnOnIncrementalAutoVacuum()) |
326 WTF_LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sql iteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); | 326 WTF_LOG_ERROR("Unable to turn on incremental auto-vacuum (%d %s)", m_sql iteDatabase.lastError(), m_sqliteDatabase.lastErrorMsg()); |
327 | 327 |
328 m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); | 328 m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); |
329 | 329 |
330 String currentVersion; | 330 String currentVersion; |
331 { | 331 { |
332 MutexLocker locker(guidMutex()); | 332 GuidVersionMap::iterator entry; |
Vyacheslav Egorov (Google)
2014/06/13 12:49:39
An alternative less intrusive approach would be to
| |
333 | 333 GuidVersionMap::iterator end; |
334 GuidVersionMap::iterator entry = guidToVersionMap().find(m_guid); | 334 { |
335 if (entry != guidToVersionMap().end()) { | 335 MutexLocker locker(guidMutex()); |
336 entry = guidToVersionMap().find(m_guid); | |
337 end = guidToVersionMap().end(); | |
338 } | |
339 if (entry != end) { | |
336 // Map null string to empty string (see updateGuidVersionMap()). | 340 // Map null string to empty string (see updateGuidVersionMap()). |
337 currentVersion = entry->value.isNull() ? emptyString() : entry->valu e.isolatedCopy(); | 341 currentVersion = entry->value.isNull() ? emptyString() : entry->valu e.isolatedCopy(); |
338 WTF_LOG(StorageAPI, "Current cached version for guid %i is %s", m_gu id, currentVersion.ascii().data()); | 342 WTF_LOG(StorageAPI, "Current cached version for guid %i is %s", m_gu id, currentVersion.ascii().data()); |
339 | 343 |
340 // Note: In multi-process browsers the cached value may be inaccurat e, but | 344 // Note: In multi-process browsers the cached value may be inaccurat e, but |
341 // we cannot read the actual version from the database without poten tially | 345 // we cannot read the actual version from the database without poten tially |
342 // inducing a form of deadlock, a busytimeout error when trying to | 346 // inducing a form of deadlock, a busytimeout error when trying to |
343 // access the database. So we'll use the cached value if we're unabl e to read | 347 // access the database. So we'll use the cached value if we're unabl e to read |
344 // the value from the database file without waiting. | 348 // the value from the database file without waiting. |
345 // FIXME: Add an async openDatabase method to the DatabaseAPI. | 349 // FIXME: Add an async openDatabase method to the DatabaseAPI. |
346 const int noSqliteBusyWaitTime = 0; | 350 const int noSqliteBusyWaitTime = 0; |
347 m_sqliteDatabase.setBusyTimeout(noSqliteBusyWaitTime); | 351 m_sqliteDatabase.setBusyTimeout(noSqliteBusyWaitTime); |
348 String versionFromDatabase; | 352 String versionFromDatabase; |
349 if (getVersionFromDatabase(versionFromDatabase, false)) { | 353 if (getVersionFromDatabase(versionFromDatabase, false)) { |
350 currentVersion = versionFromDatabase; | 354 currentVersion = versionFromDatabase; |
355 MutexLocker locker(guidMutex()); | |
351 updateGuidVersionMap(m_guid, currentVersion); | 356 updateGuidVersionMap(m_guid, currentVersion); |
352 } | 357 } |
353 m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); | 358 m_sqliteDatabase.setBusyTimeout(maxSqliteBusyWaitTime); |
354 } else { | 359 } else { |
355 WTF_LOG(StorageAPI, "No cached version for guid %i", m_guid); | 360 WTF_LOG(StorageAPI, "No cached version for guid %i", m_guid); |
356 | 361 |
357 SQLiteTransaction transaction(m_sqliteDatabase); | 362 SQLiteTransaction transaction(m_sqliteDatabase); |
358 transaction.begin(); | 363 transaction.begin(); |
359 if (!transaction.inProgress()) { | 364 if (!transaction.inProgress()) { |
360 reportOpenDatabaseResult(2, InvalidStateError, m_sqliteDatabase. lastError()); | 365 reportOpenDatabaseResult(2, InvalidStateError, m_sqliteDatabase. lastError()); |
(...skipping 27 matching lines...) Expand all Loading... | |
388 WTF_LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().dat a()); | 393 WTF_LOG(StorageAPI, "Setting version %s in database %s that was just created", m_expectedVersion.ascii().data(), databaseDebugName().ascii().dat a()); |
389 if (!setVersionInDatabase(m_expectedVersion, false)) { | 394 if (!setVersionInDatabase(m_expectedVersion, false)) { |
390 reportOpenDatabaseResult(5, InvalidStateError, m_sqliteDatab ase.lastError()); | 395 reportOpenDatabaseResult(5, InvalidStateError, m_sqliteDatab ase.lastError()); |
391 errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase .lastErrorMsg()); | 396 errorMessage = formatErrorMessage("unable to open database, failed to write current version", m_sqliteDatabase.lastError(), m_sqliteDatabase .lastErrorMsg()); |
392 transaction.rollback(); | 397 transaction.rollback(); |
393 m_sqliteDatabase.close(); | 398 m_sqliteDatabase.close(); |
394 return false; | 399 return false; |
395 } | 400 } |
396 currentVersion = m_expectedVersion; | 401 currentVersion = m_expectedVersion; |
397 } | 402 } |
398 updateGuidVersionMap(m_guid, currentVersion); | 403 |
399 transaction.commit(); | 404 { |
405 MutexLocker locker(guidMutex()); | |
406 entry = guidToVersionMap().find(m_guid); | |
407 end = guidToVersionMap().end(); | |
408 // We always update the map with the version when at this point. | |
409 updateGuidVersionMap(m_guid, currentVersion); | |
410 } | |
411 | |
412 // Only commit the transaction if no other thread has already create d the table, etc. | |
413 // We use the presence of an entry in the guidToVersionMap to determ ine if this thread | |
414 // is first. | |
415 if (entry != end) { | |
416 transaction.commit(); | |
417 } else { | |
418 // Some other thread has already created table, set the version, etc. | |
419 transaction.rollback(); | |
420 } | |
400 } | 421 } |
401 } | 422 } |
402 | 423 |
403 if (currentVersion.isNull()) { | 424 if (currentVersion.isNull()) { |
404 WTF_LOG(StorageAPI, "Database %s does not have its version set", databas eDebugName().ascii().data()); | 425 WTF_LOG(StorageAPI, "Database %s does not have its version set", databas eDebugName().ascii().data()); |
405 currentVersion = ""; | 426 currentVersion = ""; |
406 } | 427 } |
407 | 428 |
408 // If the expected version isn't the empty string, ensure that the current d atabase version we have matches that version. Otherwise, set an exception. | 429 // If the expected version isn't the empty string, ensure that the current d atabase version we have matches that version. Otherwise, set an exception. |
409 // If the expected version is the empty string, then we always return with w hatever version of the database we have. | 430 // If the expected version is the empty string, then we always return with w hatever version of the database we have. |
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
666 { | 687 { |
667 executionContext()->addConsoleMessage(StorageMessageSource, ErrorMessageLeve l, message); | 688 executionContext()->addConsoleMessage(StorageMessageSource, ErrorMessageLeve l, message); |
668 } | 689 } |
669 | 690 |
670 ExecutionContext* DatabaseBackendBase::executionContext() const | 691 ExecutionContext* DatabaseBackendBase::executionContext() const |
671 { | 692 { |
672 return databaseContext()->executionContext(); | 693 return databaseContext()->executionContext(); |
673 } | 694 } |
674 | 695 |
675 } // namespace WebCore | 696 } // namespace WebCore |
OLD | NEW |