Changeset 30104

Show
Ignore:
Timestamp:
02/08/08 20:15:27 (10 months ago)
Author:
timothy@apple.com
Message:

Reviewed by Brady Eidson.

<rdar://problem/5640896> Removing database then trying
to recreate it causes trouble

Added open Database support to DatabaseTracker. So any Database that
is deleted will be marked as deleted and will fail to open any transaction
or execute any new SQL queries.

  • storage/Database.cpp: (WebCore::Database::Database): Call DatabaseTracker::addOpenDatabase. (WebCore::Database::~Database): Call DatabaseTracker::removeOpenDatabase. (WebCore::Database::markAsDeleted): Set the m_deleted flag. (WebCore::Database::version): Return a null String if m_deleted is true.
  • storage/Database.h: (WebCore::Database::deleted): Return m_deleted.
  • storage/DatabaseTracker.cpp: (WebCore::DatabaseTracker::addOpenDatabase): Add the Database to a map of origins and names. (WebCore::DatabaseTracker::removeOpenDatabase): Remove the Database from the map. (WebCore::DatabaseTracker::deleteDatabaseFile): Call markAsDeleted on all the open Databases matching the origin/name.
  • storage/DatabaseTracker.h:
  • storage/SQLStatement.cpp: (WebCore::SQLStatement::setDatabaseDeletedError): Set the error about the user deleting the database.
  • storage/SQLStatement.h:
  • storage/SQLTransaction.cpp: (WebCore::SQLTransaction::executeSQL): If the Database is deleted, call setDatabaseDeletedError. (WebCore::SQLTransaction::openTransactionAndPreflight): Set the error about the user deleting the database if the Database was marked as deleted.
Location:
trunk/WebCore
Files:
8 modified

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r30102 r30104  
     12008-02-08  Timothy Hatcher  <timothy@apple.com> 
     2 
     3        Reviewed by Brady Eidson. 
     4 
     5        <rdar://problem/5640896> Removing database then trying 
     6        to recreate it causes trouble 
     7 
     8        Added open Database support to DatabaseTracker. So any Database that  
     9        is deleted will be marked as deleted and will fail to open any transaction 
     10        or execute any new SQL queries. 
     11 
     12        * storage/Database.cpp: 
     13        (WebCore::Database::Database): Call DatabaseTracker::addOpenDatabase. 
     14        (WebCore::Database::~Database): Call DatabaseTracker::removeOpenDatabase. 
     15        (WebCore::Database::markAsDeleted): Set the m_deleted flag. 
     16        (WebCore::Database::version): Return a null String if m_deleted is true. 
     17        * storage/Database.h: 
     18        (WebCore::Database::deleted): Return m_deleted. 
     19        * storage/DatabaseTracker.cpp: 
     20        (WebCore::DatabaseTracker::addOpenDatabase): Add the Database to a map of origins and names. 
     21        (WebCore::DatabaseTracker::removeOpenDatabase): Remove the Database from the map. 
     22        (WebCore::DatabaseTracker::deleteDatabaseFile): Call markAsDeleted on all the open Databases 
     23          matching the origin/name. 
     24        * storage/DatabaseTracker.h: 
     25        * storage/SQLStatement.cpp: 
     26        (WebCore::SQLStatement::setDatabaseDeletedError): Set the error about the user deleting the database. 
     27        * storage/SQLStatement.h: 
     28        * storage/SQLTransaction.cpp: 
     29        (WebCore::SQLTransaction::executeSQL): If the Database is deleted, call setDatabaseDeletedError. 
     30        (WebCore::SQLTransaction::openTransactionAndPreflight): Set the error about the user deleting the database 
     31          if the Database was marked as deleted. 
     32 
    1332008-02-08  Darin Adler  <darin@apple.com> 
    234 
  • trunk/WebCore/storage/Database.cpp

    r30076 r30104  
    146146    , m_guid(0) 
    147147    , m_expectedVersion(expectedVersion) 
     148    , m_deleted(0) 
    148149    , m_databaseThread(0) 
    149150#ifndef NDEBUG 
     
    177178 
    178179    m_filename = DatabaseTracker::tracker().fullPathForDatabase(m_securityOrigin.get(), m_name); 
     180 
     181    DatabaseTracker::tracker().addOpenDatabase(this); 
    179182} 
    180183 
     
    192195        guidToVersionMap().remove(m_guid); 
    193196    } 
     197 
     198    DatabaseTracker::tracker().removeOpenDatabase(this); 
    194199} 
    195200 
     
    292297     
    293298    return true; 
     299} 
     300 
     301void Database::markAsDeleted() 
     302{ 
     303    if (m_deleted) 
     304        return; 
     305    LOG(StorageAPI, "Marking %s (%p) as deleted", stringIdentifier().ascii().data(), this); 
     306    m_deleted = true; 
    294307} 
    295308 
     
    557570String Database::version() const 
    558571{ 
     572    if (m_deleted) 
     573        return String(); 
    559574    MutexLocker locker(guidMutex()); 
    560575    return guidToVersionMap().get(m_guid).copy(); 
  • trunk/WebCore/storage/Database.h

    r29983 r30104  
    9090    void setExpectedVersion(const String&); 
    9191    bool versionMatchesExpected() const; 
    92      
     92 
     93    void markAsDeleted(); 
     94    bool deleted() const { return m_deleted; } 
     95 
    9396    unsigned long long databaseSize() const; 
    9497    unsigned long long maximumSize() const; 
     
    127130    String m_filename; 
    128131 
     132    bool m_deleted; 
     133 
    129134    SQLiteDatabase m_sqliteDatabase; 
    130135    RefPtr<DatabaseAuthorizer> m_databaseAuthorizer; 
  • trunk/WebCore/storage/DatabaseTracker.cpp

    r30076 r30104  
    3535#include "Document.h" 
    3636#include "FileSystem.h" 
     37#include "Logging.h" 
    3738#include "OriginQuotaManager.h" 
    3839#include "Page.h" 
     
    421422} 
    422423 
     424void DatabaseTracker::addOpenDatabase(Database* database) 
     425{ 
     426    if (!database) 
     427        return; 
     428 
     429    MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); 
     430 
     431    if (!m_openDatabaseMap) 
     432        m_openDatabaseMap.set(new DatabaseOriginMap); 
     433 
     434    RefPtr<SecurityOrigin> origin(database->securityOriginCopy()); 
     435    String name(database->stringIdentifier()); 
     436 
     437    DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); 
     438    if (!nameMap) { 
     439        nameMap = new DatabaseNameMap; 
     440        m_openDatabaseMap->set(origin, nameMap); 
     441    } 
     442 
     443    DatabaseSet* databaseSet = nameMap->get(name); 
     444    if (!databaseSet) { 
     445        databaseSet = new DatabaseSet; 
     446        nameMap->set(name, databaseSet); 
     447    } 
     448 
     449    databaseSet->add(database); 
     450 
     451    LOG(StorageAPI, "Added open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database); 
     452} 
     453 
     454void DatabaseTracker::removeOpenDatabase(Database* database) 
     455{ 
     456    if (!database) 
     457        return; 
     458 
     459    MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); 
     460 
     461    if (!m_openDatabaseMap) { 
     462        ASSERT_NOT_REACHED(); 
     463        return; 
     464    } 
     465 
     466    RefPtr<SecurityOrigin> origin(database->securityOriginCopy()); 
     467    String name(database->stringIdentifier()); 
     468 
     469    DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); 
     470    if (!nameMap) { 
     471        ASSERT_NOT_REACHED(); 
     472        return; 
     473    } 
     474 
     475    DatabaseSet* databaseSet = nameMap->get(name); 
     476    if (!databaseSet) { 
     477        ASSERT_NOT_REACHED(); 
     478        return; 
     479    } 
     480 
     481    databaseSet->remove(database); 
     482 
     483    LOG(StorageAPI, "Removed open Database %s (%p)\n", database->stringIdentifier().ascii().data(), database); 
     484 
     485    if (!databaseSet->isEmpty()) 
     486        return; 
     487 
     488    nameMap->remove(name); 
     489    delete databaseSet; 
     490 
     491    if (!nameMap->isEmpty()) 
     492        return; 
     493 
     494    m_openDatabaseMap->remove(origin); 
     495    delete nameMap; 
     496} 
     497 
    423498unsigned long long DatabaseTracker::usageForOrigin(SecurityOrigin* origin) 
    424499{ 
     
    650725    if (fullPath.isEmpty()) 
    651726        return true; 
    652          
     727 
     728    { 
     729        MutexLocker openDatabaseMapLock(m_openDatabaseMapGuard); 
     730        if (m_openDatabaseMap) { 
     731            // There are some open databases, lets check if they are for this origin. 
     732            DatabaseNameMap* nameMap = m_openDatabaseMap->get(origin); 
     733            if (nameMap && nameMap->size()) { 
     734                // There are some open databases for this origin, lets check 
     735                // if they are this database by name. 
     736                DatabaseSet* databaseSet = nameMap->get(name); 
     737                if (databaseSet && databaseSet->size()) { 
     738                    // We have some database open with this name. Mark them as deleted. 
     739                    DatabaseSet::const_iterator end = databaseSet->end(); 
     740                    for (DatabaseSet::const_iterator it = databaseSet->begin(); it != end; ++it) 
     741                        (*it)->markAsDeleted(); 
     742                } 
     743            } 
     744        } 
     745    } 
     746 
    653747    return deleteFile(fullPath); 
    654748} 
  • trunk/WebCore/storage/DatabaseTracker.h

    r29983 r30104  
    3939namespace WebCore { 
    4040 
     41class Database; 
    4142class DatabaseTrackerClient; 
    4243class Document; 
     
    6061 
    6162    DatabaseDetails detailsForNameAndOrigin(const String&, SecurityOrigin*); 
    62      
     63 
     64    void addOpenDatabase(Database*); 
     65    void removeOpenDatabase(Database*); 
     66 
    6367    unsigned long long usageForDatabase(const String&, SecurityOrigin*); 
    6468    unsigned long long usageForOrigin(SecurityOrigin*); 
     
    100104    Mutex m_quotaMapGuard; 
    101105    mutable OwnPtr<QuotaMap> m_quotaMap; 
    102      
     106 
     107    typedef HashSet<Database*> DatabaseSet; 
     108    typedef HashMap<String, DatabaseSet*> DatabaseNameMap; 
     109    typedef HashMap<RefPtr<SecurityOrigin>, DatabaseNameMap*, SecurityOriginHash, SecurityOriginTraits> DatabaseOriginMap; 
     110 
     111    Mutex m_openDatabaseMapGuard; 
     112    mutable OwnPtr<DatabaseOriginMap> m_openDatabaseMap; 
     113 
    103114    OwnPtr<OriginQuotaManager> m_quotaManager; 
    104115 
  • trunk/WebCore/storage/SQLStatement.cpp

    r30087 r30104  
    140140} 
    141141 
     142void SQLStatement::setDatabaseDeletedError() 
     143{ 
     144    ASSERT(!m_error && !m_resultSet); 
     145    m_error = new SQLError(0, "unable to execute statement, because the user deleted the database"); 
     146} 
     147 
    142148void SQLStatement::setVersionMismatchedError() 
    143149{ 
  • trunk/WebCore/storage/SQLStatement.h

    r29663 r30104  
    5757    bool hasStatementCallback() const { return m_statementCallback; } 
    5858    bool hasStatementErrorCallback() const { return m_statementErrorCallback; } 
     59 
     60    void setDatabaseDeletedError(); 
    5961    void setVersionMismatchedError(); 
    6062 
  • trunk/WebCore/storage/SQLTransaction.cpp

    r29983 r30104  
    7979     
    8080    RefPtr<SQLStatement> statement = new SQLStatement(sqlStatement.copy(), arguments, callback, callbackError); 
    81      
     81 
     82    if (m_database->deleted()) 
     83        statement->setDatabaseDeletedError(); 
     84 
    8285    if (!m_database->versionMatchesExpected()) 
    8386        statement->setVersionMismatchedError(); 
     
    120123 
    121124    LOG(StorageAPI, "Opening and preflighting transaction %p", this); 
    122      
     125 
     126    // If the database was deleted, jump to the error callback 
     127    if (m_database->deleted()) { 
     128        m_transactionError = new SQLError(0, "unable to open a transaction, because the user deleted the database"); 
     129        handleTransactionError(false); 
     130        return; 
     131    } 
     132 
    123133    // Set the maximum usage for this transaction 
    124134    m_database->m_sqliteDatabase.setMaximumSize(m_database->maximumSize());