Improve robustness of WebSQL quota management.
https://bugs.webkit.org/show_bug.cgi?id=110600.

Reviewed by Geoffrey Garen.

Source/WebCore: 

1. Introduced the OriginLock for synchronizing write access to the
   database origin directory. This allows us to more accurately
   compute the disk usage.

   The OriginLock uses a mutex to provide mutual exclusion between
   threads and a file lock for mutual exclusion between processes.
   The file lock part is conditional on USE(FILE_LOCK).

   The mutex mutual exclusion also serves to ensure that only 1 thread
   can write to a sqlite database at one time.

2. Change the SQLTransactionCoordinator to only allow one write
   transaction to an origin instead of one write transaction per
   database. This is needed in order to accurately compute the
   disk usage. It is also necessary so that the OriginLock does not
   deadlock itself (as would be the case if concurrent write transactions
   to different databases in the same origin are allowed).

3. Fix DatabaseTracker::getMaxSizeForDatabase() to check for when
   disk usage may exceed the quota, and ensure that we will return
   an appropriate max database size.

   Disk usage can exceed the usage if it is already near the quota limit
   but have not exceeded it yet. If a new database is opened in that
   origin, it may bump the usage above the quota, but should not
   continually repeat this. Subsequent attempts to open a database
   will find that the quota is already exhausted and fail.

   There is still a race condition pertaining to the tracker database
   getting out of sync that may still enable runaway growth in the
   database sizes. That issue only manifest in a multi-process
   environment, and will be fixed in another changeset.

4. Fixed a bug in SQLStatement to check if the errorCallback exists
   before invoking it.

No new layout tests. A quota-test.html was attached to bugzilla for manual
testing of multi-tab concurrent consumption of storage resource, and also
to test handling situations when the user deletes the database files while
the script is still using the database.

* CMakeLists.txt:
* GNUmakefile.list.am:
* Modules/webdatabase/DatabaseTracker.cpp:
(WebCore::DatabaseTracker::getMaxSizeForDatabase):
(WebCore::DatabaseTracker::originLockFor):
(WebCore::DatabaseTracker::deleteOriginLockFor):
(WebCore::DatabaseTracker::deleteOrigin):
* Modules/webdatabase/DatabaseTracker.h:
* Modules/webdatabase/OriginLock.cpp: Added.
(WebCore::OriginLock::lockFileNameForPath):
(WebCore::OriginLock::OriginLock):
(WebCore::OriginLock::~OriginLock):
(WebCore::OriginLock::lock):
(WebCore::OriginLock::unlock):
* Modules/webdatabase/OriginLock.h: Added.
* Modules/webdatabase/SQLStatement.cpp:
(WebCore::SQLStatement::performCallback):
* Modules/webdatabase/SQLTransactionBackend.cpp:
(WebCore::SQLTransactionBackend::doCleanup):
(WebCore::SQLTransactionBackend::computeNextStateAndCleanupIfNeeded):
(WebCore::SQLTransactionBackend::openTransactionAndPreflight):
(WebCore::SQLTransactionBackend::postflightAndCommit):
(WebCore::SQLTransactionBackend::cleanupAfterTransactionErrorCallback):
(WebCore::SQLTransactionBackend::acquireOriginLock):
(WebCore::SQLTransactionBackend::releaseOriginLockIfNeeded):
* Modules/webdatabase/SQLTransactionBackend.h:
(SQLTransactionBackend):
* Modules/webdatabase/SQLTransactionCoordinator.cpp:
(WebCore::getDatabaseIdentifier):
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.vcxproj/WebCore.vcxproj:
* WebCore.vcxproj/WebCore.vcxproj.filters:
* WebCore.xcodeproj/project.pbxproj:
* config.h:
* platform/FileSystem.h:
* platform/posix/FileSystemPOSIX.cpp:
(WebCore::lockFile):
(WebCore::unlockFile):

LayoutTests: 

* storage/websql/multiple-databases-garbage-collection.js:
- This test runs 2 transactions on 2 databases (1 each). The 2 databases
  are named "persistent" and "forgotten". The test executes the
  transaction on "persistent" first, but expects the transaction on
  "forgotten" to finish first. This is because "forgotten"'s transaction
  is a smaller one. The new changes to SQLTransactionCoordinator now
  ensures that a write transaction must completes before another is
  started for databases in the same origin. Hence, the previously expected
  result will no longer be true.

  Regardless, the purpose of the test is not to test the order of
  completion but that resources are reclaimed. So, I'm changing the test
  to start the "forgotten" transaction first followed by the "persistent"
  transaction. This ensures that the test will yield consistent results
  even when run on ports that may allow more than one write transaction
  to run at the same time.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@144760 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h b/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h
index ce5459f..00c2280 100644
--- a/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h
+++ b/Source/WebCore/Modules/webdatabase/SQLTransactionBackend.h
@@ -42,6 +42,7 @@
 
 class AbstractSQLTransaction;
 class DatabaseBackend;
+class OriginLock;
 class SQLError;
 class SQLiteTransaction;
 class SQLStatementBackend;
@@ -108,6 +109,9 @@
 
     void getNextStatement();
 
+    void acquireOriginLock();
+    void releaseOriginLockIfNeeded();
+
     RefPtr<AbstractSQLTransaction> m_frontend; // Has a reference cycle, and will break in doCleanup().
     RefPtr<SQLStatementBackend> m_currentStatementBackend;
 
@@ -128,6 +132,9 @@
     Deque<RefPtr<SQLStatementBackend> > m_statementQueue;
 
     OwnPtr<SQLiteTransaction> m_sqliteTransaction;
+#if !PLATFORM(CHROMIUM)
+    RefPtr<OriginLock> m_originLock;
+#endif
 };
 
 } // namespace WebCore