Changeset 29983 in webkit
- Timestamp:
- Feb 4, 2008, 4:55:47 PM (17 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 4 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r29982 r29983 1 2008-02-04 Brady Eidson <beidson@apple.com> 2 3 Reviewed by Darin 4 5 Fix for <rdar://problem/5628468> - Quotas need to be implemented per-origin, and not per-database 6 7 To accomplish this, we need to track the sizes of all databases in an origin to constantly keep an up to date 8 count of the origin's total disk usage. I've introduced the OriginQuotaManager and OriginUsageRecord classes 9 to accomplish this. 10 11 Whenever a transaction is known to mutate the size of a database (tracked by the DatabaseAuthorizer), it marks 12 that database as unknown in the OriginQuotaManager. When a transaction later comes along to ask the 13 OriginQuotaManager the usage for that origin, it stat's all of the unknown databases in the origin and returns 14 the result. 15 16 Since the OriginQuotaManager is interesting from both the main thread and a DatabaseThread, all accessors it 17 provides require it to be locked first. ASSERTs help guarantee this is always the case. 18 19 Layout test will involve adding functionality to DRT on multiple platforms and will be coming up shortly 20 21 * WebCore.xcodeproj/project.pbxproj: 22 23 * platform/SecurityOrigin.h: Changed to be ThreadSafeShared instead of RefCounted 24 25 * storage/Database.cpp: 26 (WebCore::Database::databaseSize): Return the current filesize of this database on disk 27 (WebCore::Database::maximumSize): Added - calculates maximum size of this database based on quota and usage 28 * storage/Database.h: Add databaseSize() accessor, and get rid of unused declared methods that *were* going 29 to be the solution for this bug. 30 31 * storage/DatabaseTracker.cpp: 32 (WebCore::DatabaseTracker::originQuotaManager): Accessor to the OriginQuotaManager which is lazily created 33 (WebCore::DatabaseTracker::canEstablishDatabase): Fetch the usage for this database slightly earlier, which 34 will ensure that the OriginQuotaManager is primed to track this origin 35 (WebCore::DatabaseTracker::fullPathForDatabase): Ditto 36 (WebCore::DatabaseTracker::populateOrigins): Create the OriginQuotaManager here. 37 (WebCore::DatabaseTracker::usageForOrigin): Use the OriginQuotaManager instead of looping through each database 38 in the origin 39 (WebCore::DatabaseTracker::deleteOrigin): Remove this origin from the OriginQuotaManager as it is no longer 40 interesting 41 (WebCore::DatabaseTracker::deleteDatabase): Remove this database from the OriginQuotaManager as it is no longer 42 interesting 43 * storage/DatabaseTracker.h: 44 45 * storage/OriginQuotaManager.cpp: Added. 46 (WebCore::OriginQuotaManager::OriginQuotaManager): 47 (WebCore::OriginQuotaManager::lock): 48 (WebCore::OriginQuotaManager::unlock): 49 (WebCore::OriginQuotaManager::trackOrigin): Add an origin to be tracked. Useful for when the very first database 50 in a new origin is still in the process of being created 51 (WebCore::OriginQuotaManager::tracksOrigin): 52 (WebCore::OriginQuotaManager::addDatabase): 53 (WebCore::OriginQuotaManager::removeDatabase): 54 (WebCore::OriginQuotaManager::removeOrigin): Removes all records in a certain origin from being tracked 55 (WebCore::OriginQuotaManager::markDatabase): Mark a specific database as having an unknown size - called when the 56 DatabaseAuthorizer in a SQLTransaction knows the file size might change. 57 (WebCore::OriginQuotaManager::diskUsage): Returns the disk usage for the given origin 58 * storage/OriginQuotaManager.h: Added. 59 60 * storage/OriginUsageRecord.cpp: Added. 61 (WebCore::OriginUsageRecord::OriginUsageRecord): 62 (WebCore::OriginUsageRecord::addDatabase): Adds an entry for the database in this origin's record 63 (WebCore::OriginUsageRecord::removeDatabase): Removes that entry 64 (WebCore::OriginUsageRecord::markDatabase): Marks the database as of unknown size 65 (WebCore::OriginUsageRecord::diskUsage): Returns the cached disk usage value, or recalculates it if any databases 66 are marked 67 * storage/OriginUsageRecord.h: Added. 68 69 * storage/SQLTransaction.cpp: 70 (WebCore::SQLTransaction::openTransactionAndPreflight): Use Database::maximumSize() instead of attributing the 71 entire quota to each database. 72 (WebCore::SQLTransaction::runStatements): Use Database::maximumSize() instead of attributing the entire quota 73 to each database. 74 (WebCore::SQLTransaction::runCurrentStatement): Mark this databases's size as unknown in the 75 OriginQuotaManager if this statement will change the size of the database 76 * storage/SQLTransaction.h: 77 1 78 2008-02-04 David Harrison <harrison@apple.com> 2 79 -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r29929 r29983 418 418 51A45B560CAD7FD7000D2BE9 /* DatabaseAuthorizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */; }; 419 419 51A45B570CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */; }; 420 51A9267C0D53F0570063ECC2 /* OriginQuotaManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A926780D53F0570063ECC2 /* OriginQuotaManager.cpp */; }; 421 51A9267D0D53F0570063ECC2 /* OriginQuotaManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A926790D53F0570063ECC2 /* OriginQuotaManager.h */; }; 422 51A9267E0D53F0570063ECC2 /* OriginUsageRecord.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51A9267A0D53F0570063ECC2 /* OriginUsageRecord.cpp */; }; 423 51A9267F0D53F0570063ECC2 /* OriginUsageRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 51A9267B0D53F0570063ECC2 /* OriginUsageRecord.h */; }; 420 424 51AA3F6F0BD5AA9E00892971 /* ResourceLoaderMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */; }; 421 425 51C81B890C4422F70019ECE3 /* FTPDirectoryParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */; }; … … 4674 4678 51A45B540CAD7FD7000D2BE9 /* DatabaseAuthorizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DatabaseAuthorizer.h; sourceTree = "<group>"; }; 4675 4679 51A45B550CAD7FD7000D2BE9 /* DatabaseAuthorizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DatabaseAuthorizer.cpp; sourceTree = "<group>"; }; 4680 51A926780D53F0570063ECC2 /* OriginQuotaManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OriginQuotaManager.cpp; sourceTree = "<group>"; }; 4681 51A926790D53F0570063ECC2 /* OriginQuotaManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OriginQuotaManager.h; sourceTree = "<group>"; }; 4682 51A9267A0D53F0570063ECC2 /* OriginUsageRecord.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OriginUsageRecord.cpp; sourceTree = "<group>"; }; 4683 51A9267B0D53F0570063ECC2 /* OriginUsageRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OriginUsageRecord.h; sourceTree = "<group>"; }; 4676 4684 51AA3F6E0BD5AA9E00892971 /* ResourceLoaderMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ResourceLoaderMac.mm; sourceTree = "<group>"; }; 4677 4685 51C81B870C4422F70019ECE3 /* FTPDirectoryParser.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FTPDirectoryParser.cpp; sourceTree = "<group>"; }; … … 8090 8098 1AD51A120CB59CD300953D11 /* DatabaseTracker.h */, 8091 8099 51FAFE330CECBF2D00BB3F24 /* DatabaseTrackerClient.h */, 8100 51A926780D53F0570063ECC2 /* OriginQuotaManager.cpp */, 8101 51A926790D53F0570063ECC2 /* OriginQuotaManager.h */, 8102 51A9267A0D53F0570063ECC2 /* OriginUsageRecord.cpp */, 8103 51A9267B0D53F0570063ECC2 /* OriginUsageRecord.h */, 8092 8104 51EC92570CE90DB400F90308 /* SQLError.h */, 8093 8105 51EC92580CE90DB400F90308 /* SQLError.idl */, … … 14206 14218 515378030D52D0630063A78B /* Locker.h in Headers */, 14207 14219 514075C60D53ECFE00BC2D85 /* SecurityOriginHash.h in Headers */, 14220 51A9267D0D53F0570063ECC2 /* OriginQuotaManager.h in Headers */, 14221 51A9267F0D53F0570063ECC2 /* OriginUsageRecord.h in Headers */, 14208 14222 ); 14209 14223 runOnlyForDeploymentPostprocessing = 0; … … 15797 15811 E4EEFFC80D34550C00469A58 /* JSAudioConstructor.cpp in Sources */, 15798 15812 BCE7B1930D4E86960075A539 /* JSHistoryCustom.cpp in Sources */, 15813 51A9267C0D53F0570063ECC2 /* OriginQuotaManager.cpp in Sources */, 15814 51A9267E0D53F0570063ECC2 /* OriginUsageRecord.cpp in Sources */, 15799 15815 ); 15800 15816 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/platform/SecurityOrigin.h
r29663 r29983 34 34 35 35 #include "PlatformString.h" 36 #include "Threading.h" 36 37 37 38 namespace WebCore { … … 40 41 class KURL; 41 42 42 class SecurityOrigin : public RefCounted<SecurityOrigin> {43 class SecurityOrigin : public ThreadSafeShared<SecurityOrigin> { 43 44 public: 44 45 static PassRefPtr<SecurityOrigin> createForFrame(Frame*); -
trunk/WebCore/storage/Database.cpp
r29964 r29983 44 44 #include "NotImplemented.h" 45 45 #include "Page.h" 46 #include "OriginQuotaManager.h" 46 47 #include "SQLiteDatabase.h" 47 48 #include "SQLiteStatement.h" … … 291 292 292 293 return true; 294 } 295 296 unsigned long long Database::databaseSize() const 297 { 298 long long size; 299 if (!fileSize(m_filename, size)) 300 size = 0; 301 return size; 302 } 303 304 unsigned long long Database::maximumSize() const 305 { 306 // The maximum size for this database is the full quota for this origin, minus the current usage within this origin, 307 // except for the current usage of this database 308 309 OriginQuotaManager& manager(DatabaseTracker::tracker().originQuotaManager()); 310 Locker<OriginQuotaManager> locker(manager); 311 312 return DatabaseTracker::tracker().quotaForOrigin(m_securityOrigin.get()) - manager.diskUsage(m_securityOrigin.get()) + databaseSize(); 293 313 } 294 314 -
trunk/WebCore/storage/Database.h
r29922 r29983 91 91 bool versionMatchesExpected() const; 92 92 93 unsigned long long databaseSize() const; 94 unsigned long long maximumSize() const; 95 93 96 // Called from DatabaseThread, must be prepared to work on the background thread 94 97 void resetAuthorizer(); … … 113 116 Deque<RefPtr<SQLTransaction> > m_transactionQueue; 114 117 RefPtr<SQLTransaction> m_currentTransaction; 115 116 static void scheduleFileSizeTimerOnMainThread(Database*);117 static void performScheduleFileSizeTimers();118 void scheduleFileSizeTimer();119 void sizeTimerFired(Timer<Database>*);120 OwnPtr<Timer<Database> > m_sizeTimer;121 118 122 119 static void deliverAllPendingCallbacks(void*); -
trunk/WebCore/storage/DatabaseTracker.cpp
r29929 r29983 35 35 #include "Document.h" 36 36 #include "FileSystem.h" 37 #include "OriginQuotaManager.h" 37 38 #include "Page.h" 38 39 #include "SecurityOrigin.h" … … 43 44 44 45 namespace WebCore { 46 47 OriginQuotaManager& DatabaseTracker::originQuotaManager() 48 { 49 populateOrigins(); 50 ASSERT(m_quotaManager); 51 return *m_quotaManager; 52 } 45 53 46 54 DatabaseTracker& DatabaseTracker::tracker() … … 119 127 populateOrigins(); 120 128 129 SecurityOrigin* origin = document->securityOrigin(); 130 131 // Since we're imminently opening a database within this Document's origin, make sure this origin is being tracked by the QuotaTracker 132 // by fetching it's current usage now 133 unsigned long long usage = usageForOrigin(origin); 134 121 135 // If a database already exists, ignore the passed-in estimated size and say it's OK. 122 SecurityOrigin* origin = document->securityOrigin();123 136 if (hasEntryForDatabase(origin, name)) 124 137 return true; 125 138 126 139 // If the database will fit, allow its creation. 127 unsigned long long usage = usageForOrigin(origin);128 140 unsigned long long requirement = usage + max(1UL, estimatedSize); 129 141 if (requirement < usage) … … 242 254 return String(); 243 255 256 // If this origin's quota is being tracked (open handle to a database in this origin), add this new database 257 // to the quota manager now 258 { 259 Locker<OriginQuotaManager> locker(originQuotaManager()); 260 if (originQuotaManager().tracksOrigin(origin)) 261 originQuotaManager().addDatabase(origin, name, filename); 262 } 263 244 264 return filename; 245 265 } … … 253 273 254 274 m_quotaMap.set(new QuotaMap); 275 m_quotaManager.set(new OriginQuotaManager); 255 276 256 277 openTrackerDatabase(false); … … 403 424 { 404 425 ASSERT(currentThread() == m_thread); 426 Locker<OriginQuotaManager> locker(originQuotaManager()); 427 428 // Use the OriginQuotaManager mechanism to calculate the usage 429 if (originQuotaManager().tracksOrigin(origin)) 430 return originQuotaManager().diskUsage(origin); 431 432 // If the OriginQuotaManager doesn't track this origin already, prime it to do so 433 originQuotaManager().trackOrigin(origin); 434 405 435 Vector<String> names; 406 436 databaseNamesForOrigin(origin, names); 407 408 unsigned long long result = 0; 437 409 438 for (unsigned i = 0; i < names.size(); ++i) 410 result += usageForDatabase(names[i], origin); 411 412 return result; 439 originQuotaManager().addDatabase(origin, names[i], fullPathForDatabase(origin, names[i], false)); 440 441 if (!originQuotaManager().tracksOrigin(origin)) 442 return 0; 443 return originQuotaManager().diskUsage(origin); 413 444 } 414 445 … … 557 588 MutexLocker lockQuotaMap(m_quotaMapGuard); 558 589 m_quotaMap->remove(origin); 590 Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); 591 originQuotaManager().removeOrigin(origin); 559 592 } 560 593 … … 600 633 } 601 634 635 { 636 Locker<OriginQuotaManager> quotaManagerLocker(originQuotaManager()); 637 originQuotaManager().removeDatabase(origin, name); 638 } 639 602 640 if (m_client) { 603 641 m_client->dispatchDidModifyOrigin(origin); -
trunk/WebCore/storage/DatabaseTracker.h
r29922 r29983 41 41 class DatabaseTrackerClient; 42 42 class Document; 43 class OriginQuotaManager; 43 44 class SecurityOrigin; 44 45 … … 74 75 void scheduleNotifyDatabaseChanged(SecurityOrigin*, const String& name); 75 76 77 OriginQuotaManager& originQuotaManager(); 78 76 79 static DatabaseTracker& tracker(); 77 80 … … 97 100 Mutex m_quotaMapGuard; 98 101 mutable OwnPtr<QuotaMap> m_quotaMap; 102 103 OwnPtr<OriginQuotaManager> m_quotaManager; 99 104 100 105 String m_databaseDirectoryPath; -
trunk/WebCore/storage/SQLTransaction.cpp
r29964 r29983 38 38 #include "ExceptionCode.h" 39 39 #include "Logging.h" 40 #include "OriginQuotaManager.h" 40 41 #include "Page.h" 41 42 #include "PlatformString.h" … … 120 121 LOG(StorageAPI, "Opening and preflighting transaction %p", this); 121 122 122 // FIXME: This is a glaring bug that gives each database in an origin the full quota of that origin 123 // An efficient way to track the size of individual databases in an origin will need to be developed 124 // before we can know 125 // <rdar://problem/5628468> tracks this task 126 m_database->m_sqliteDatabase.setMaximumSize(DatabaseTracker::tracker().quotaForOrigin(m_database->securityOriginCopy().get())); 123 // Set the maximum usage for this transaction 124 m_database->m_sqliteDatabase.setMaximumSize(m_database->maximumSize()); 127 125 128 126 ASSERT(!m_sqliteTransaction); … … 196 194 197 195 // Reset the maximum size here, as it was increased to allow us to retry this statement 198 m_database->m_sqliteDatabase.setMaximumSize( DatabaseTracker::tracker().quotaForOrigin(m_database->securityOriginCopy().get()));196 m_database->m_sqliteDatabase.setMaximumSize(m_database->maximumSize()); 199 197 } else { 200 198 // If the current statement has already been run, failed due to quota constraints, and we're not retrying it, … … 236 234 237 235 if (m_currentStatement->execute(m_database)) { 238 // Flag this transaction as having changed the database for later delegate notification239 if (m_database->m_databaseAuthorizer->lastActionChangedDatabase())236 if (m_database->m_databaseAuthorizer->lastActionChangedDatabase()) { 237 // Flag this transaction as having changed the database for later delegate notification 240 238 m_modifiedDatabase = true; 239 // Also dirty the size of this database file for calculating quota usage 240 OriginQuotaManager& manager(DatabaseTracker::tracker().originQuotaManager()); 241 Locker<OriginQuotaManager> locker(manager); 242 243 manager.markDatabase(m_database); 244 } 241 245 242 246 if (m_currentStatement->hasStatementCallback()) {
Note:
See TracChangeset
for help on using the changeset viewer.