Reviewed by Maciej
authorbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Jul 2006 09:57:23 +0000 (09:57 +0000)
committerbeidson <beidson@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 10 Jul 2006 09:57:23 +0000 (09:57 +0000)
        SQLite Icon DB now fully replicates functionality of the old DB, including pruning to keep unused
        information out to keep down disk usage.  For now, it is still off by default, as the critical
        feature of importing old icons into the new DB is still unrealized.
        If you'd like to test, add #define ICONDEBUG to your WebKitPrefix.h

        * icon/IconDatabase.cpp:
        (WebCore::IconDatabase::IconDatabase):
        (WebCore::IconDatabase::open):
          -Sets up a timer for initial pruning
        (WebCore::IconDatabase::iconForPageURL):
          -Switched away from "dirty blob hack" as the problem is provisionally solved
        (WebCore::IconDatabase::retainIconForURL):
        (WebCore::IconDatabase::releaseIconForURL):
          -Same as found in WebKit
        (WebCore::IconDatabase::totalRetainCountForIconURL):
          -Adds up all retainers of icon
        (WebCore::IconDatabase::forgetIconForIconURLFromDatabase):
          -Wipes an Icon table entry out
        (WebCore::IconDatabase::establishTemporaryIconIDForIconURL):
        (WebCore::IconDatabase::establishTemporaryIconIDForEscapedIconURL):
        (WebCore::IconDatabase::establishIconIDForIconURL):
        (WebCore::IconDatabase::establishIconIDForEscapedIconURL):
          -Added ability to get an iconID without creating a new one if a lookup is all
           that is genuinely wanted
        (WebCore::IconDatabase::pruneUnreferencedIcons):
        (WebCore::IconDatabase::pruneUnretainedIcons):
          -Called on a timer on DB startup to clean it out
        * icon/IconDatabase.h:
        * icon/SiteIcon.cpp:
        (SiteIcon::SiteIcon):
        (SiteIcon::~SiteIcon):
          -Deletes the image on deletion
        (SiteIcon::getImage):
          -Cut down on no-longer-necessary debug info

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15297 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/icon/IconDatabase.cpp
WebCore/icon/IconDatabase.h
WebCore/icon/SiteIcon.cpp

index 2943927a005468cc8853e50797ebe198f9f07882..b94a0f97a8dafa8cf5e7dd1b59532c033e56092e 100644 (file)
@@ -1,3 +1,42 @@
+2006-07-10  Brady Eidson  <beidson@apple.com>
+
+        Reviewed by Maciej
+
+        SQLite Icon DB now fully replicates functionality of the old DB, including pruning to keep unused
+        information out to keep down disk usage.  For now, it is still off by default, as the critical
+        feature of importing old icons into the new DB is still unrealized.
+        If you'd like to test, add #define ICONDEBUG to your WebKitPrefix.h
+
+        * icon/IconDatabase.cpp:
+        (WebCore::IconDatabase::IconDatabase):
+        (WebCore::IconDatabase::open):
+          -Sets up a timer for initial pruning
+        (WebCore::IconDatabase::iconForPageURL):
+          -Switched away from "dirty blob hack" as the problem is provisionally solved
+        (WebCore::IconDatabase::retainIconForURL):
+        (WebCore::IconDatabase::releaseIconForURL):
+          -Same as found in WebKit
+        (WebCore::IconDatabase::totalRetainCountForIconURL):
+          -Adds up all retainers of icon
+        (WebCore::IconDatabase::forgetIconForIconURLFromDatabase):
+          -Wipes an Icon table entry out
+        (WebCore::IconDatabase::establishTemporaryIconIDForIconURL):
+        (WebCore::IconDatabase::establishTemporaryIconIDForEscapedIconURL):
+        (WebCore::IconDatabase::establishIconIDForIconURL):
+        (WebCore::IconDatabase::establishIconIDForEscapedIconURL):
+          -Added ability to get an iconID without creating a new one if a lookup is all
+           that is genuinely wanted
+        (WebCore::IconDatabase::pruneUnreferencedIcons):
+        (WebCore::IconDatabase::pruneUnretainedIcons):
+          -Called on a timer on DB startup to clean it out
+        * icon/IconDatabase.h:
+        * icon/SiteIcon.cpp:
+        (SiteIcon::SiteIcon):
+        (SiteIcon::~SiteIcon):
+          -Deletes the image on deletion
+        (SiteIcon::getImage):
+          -Cut down on no-longer-necessary debug info
+
 2006-07-10  Anders Carlsson  <acarlsson@apple.com>
 
         Reviewed by Adele.
index 912c03694ac044c30fa5025e833dbd7f7cd3b7d8..75e0d1b2af7d6f506871c0561da2e0b7baa4a373 100644 (file)
@@ -56,6 +56,7 @@ IconDatabase* IconDatabase::sharedIconDatabase()
 
 IconDatabase::IconDatabase()
     : m_privateBrowsingEnabled(false)
+    , m_startupTimer(this, &IconDatabase::pruneUnretainedIcons)
 {
     close();
 }
@@ -75,10 +76,20 @@ bool IconDatabase::open(const String& databasePath)
         recreateDatabase();
     }
 
+    // We're going to track an icon's retain count in a temp table in memory so we can cross reference it to to the on disk tables
+    bool result;
+    result = m_db.executeCommand("CREATE TEMP TABLE PageRetain (url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,count INTEGER NOT NULL ON CONFLICT FAIL);");
+    // Creating an in-memory temp table should never, ever, ever fail
+    ASSERT(result);
+    
     // These are actually two different SQLite config options - not my fault they are named confusingly  ;)
     m_db.setSynchronous(SQLDatabase::SyncOff);    
     m_db.setFullsync(false);
     
+    // Only if we successfully remained open will we setup our "initial purge timer"
+    if (isOpen())
+        m_startupTimer.startOneShot(0);
+    
     return isOpen();
 }
 
@@ -357,8 +368,12 @@ Image* IconDatabase::iconForPageURL(const String& url, const IntSize& size, bool
         return 0;
     
     // If we do, maybe we have an image for this IconURL
-    if (m_iconURLToSiteIcons.contains(iconURL))
-        return m_iconURLToSiteIcons.get(iconURL)->getImage(size);
+    if (m_iconURLToSiteIcons.contains(iconURL)) {
+        SiteIcon* icon = m_iconURLToSiteIcons.get(iconURL);
+        // Assign this SiteIcon to this PageURL for faster lookup in the future
+        m_pageURLToSiteIcons.set(url, icon);
+        return icon->getImage(size);
+    }
         
     // If we don't have either, we have to create the SiteIcon
     SiteIcon* icon = new SiteIcon(iconURL);
@@ -390,13 +405,148 @@ Image* IconDatabase::defaultIcon(const IntSize& size)
     return 0;
 }
 
-void IconDatabase::retainIconForURL(const String& url)
+void IconDatabase::retainIconForURL(const String& _url)
 {
+    if (_url.isEmpty())
+        return;
+        
+    String url = _url;
+    url.replace('\'', "''");
+    
+    int retainCount = SQLStatement(m_db, "SELECT count FROM PageRetain WHERE url = '" + url + "';").getColumnInt(0);
+    ASSERT(retainCount > -1);
+    
+    if (!m_db.executeCommand("INSERT INTO PageRetain VALUES ('" + url + "', " + String::number(retainCount + 1) + ");"))
+        LOG_ERROR("Failed to increment retain count for url %s", _url.ascii().data());
+        
+    LOG(IconDatabase, "URL %s now has a retain count of %i", _url.ascii().data(), retainCount + 1);
+}
 
+void IconDatabase::releaseIconForURL(const String& _url)
+{
+    if (_url.isEmpty())
+        return;
+        
+    String url = _url;
+    url.replace('\'', "''");
+    
+    SQLStatement sql(m_db, "SELECT count FROM PageRetain WHERE url = '" + url + "';");
+    switch (sql.prepareAndStep()) {
+        case SQLITE_ROW:
+            break;
+        case SQLITE_DONE:
+            LOG_ERROR("Released icon for url %s that had not been retained", _url.ascii().data());
+            return;
+        default:
+            LOG_ERROR("Error retrieving retain count for url %s", _url.ascii().data());
+            return;
+    }
+    
+    int retainCount = sql.getColumnInt(0);
+    sql.finalize();
+    
+    // If the retain count SOMEHOW gets to zero or less, we need to bail right here   
+    if (retainCount < 1) {
+        LOG_ERROR("Attempting to release icon for URL %s - already fully released", _url.ascii().data());
+        return;
+    }
+    
+    --retainCount;
+    if (!m_db.executeCommand("INSERT INTO PageRetain VALUES ('" + url + "', " + String::number(retainCount) + ");"))
+        LOG_ERROR("Failed to decrement retain count for url %s", _url.ascii().data());
+    
+    LOG(IconDatabase, "URL %s now has a retain count of %i", _url.ascii().data(), retainCount);
+    
+    // If we still have a positve retain count, we're done - lets bail
+    if (retainCount)
+        return;
+    
+    // Grab the iconURL for later use...
+    String iconURL = iconURLForPageURL(_url);
+    
+    // The retain count is zilch so we can wipe this PageURL
+    if (!m_db.executeCommand("DELETE FROM PageRetain WHERE url = '" + url + "';"))
+        LOG_ERROR("Failed to delete retain record for url %s", _url.ascii().data());
+    if (m_privateBrowsingEnabled)
+        if (!m_db.executeCommand("DELETE FROM TempPageURL WHERE url = '" + url + "';"))
+            LOG_ERROR("Failed to delete record of PageURL %s from private browsing tables", _url.ascii().data());
+    if (!m_db.executeCommand("DELETE FROM PageURL WHERE url = '" + url + "';"))
+        LOG_ERROR("Failed to delete record of PageURL %s from on-disk tables", _url.ascii().data());            
+            
+    // And now see if we can wipe the icon itself
+    if (iconURL.isEmpty())
+        return;
+    retainCount = totalRetainCountForIconURL(iconURL);
+    
+    // If the icon has other retainers, we're all done - bail
+    if (retainCount)
+        return;
+        
+    LOG(IconDatabase, "No retainers for Icon URL %s - forgetting icon altogether", iconURL.ascii().data());
+
+    // Wipe it from the database...
+    forgetIconForIconURLFromDatabase(iconURL);
+
+    // And then from the SiteIcons
+    SiteIcon* icon1;
+    SiteIcon* icon2;
+    if ((icon1 = m_pageURLToSiteIcons.get(_url)))
+        m_pageURLToSiteIcons.remove(_url);
+    if ((icon2 = m_iconURLToSiteIcons.get(iconURL)))
+        m_iconURLToSiteIcons.remove(iconURL);
+    
+    if (icon1 && icon2) {
+        ASSERT(icon1 == icon2);
+        delete icon1;
+        icon1 = icon2 = 0;
+    } 
+    if (icon1)
+        delete icon1;
+    else if (icon2)
+        delete icon2;
 }
 
-void IconDatabase::releaseIconForURL(const String& url)
+int IconDatabase::totalRetainCountForIconURL(const String& _iconURL)
 {
+    if (_iconURL.isEmpty())
+        return 0;
+        
+    String iconURL = _iconURL;
+    iconURL.replace('\'', "''");
+    
+    int retainCount = SQLStatement(m_db, "SELECT sum(count) FROM PageRetain WHERE url IN(SELECT PageURL.url FROM PageURL, Icon WHERE PageURL.iconID = Icon.iconID AND Icon.url = '" + iconURL + "');").getColumnInt(0);
+    LOG(IconDatabase, "The total retain count for URL %s is %i", _iconURL.ascii().data(), retainCount);
+    return retainCount;
+}
+
+void IconDatabase::forgetIconForIconURLFromDatabase(const String& _iconURL)
+{
+    if (_iconURL.isEmpty())
+        return;
+        
+    String iconURL = _iconURL;
+    iconURL.replace('\'', "''");
+    
+    // Lets start with the icon from the temporary private tables...
+    int64_t iconID;
+    if (m_privateBrowsingEnabled) {
+        iconID = establishTemporaryIconIDForIconURL(iconURL, false);
+        if (iconID) {
+            if (!m_db.executeCommand(String::sprintf("DELETE FROM TempIcon WHERE iconID = %lli", iconID)))
+                LOG_ERROR("Unable to drop Icon at URL %s from table TemporaryIcon", iconURL.ascii().data()); 
+            if (!m_db.executeCommand(String::sprintf("DELETE FROM TempPageURL WHERE iconID = %lli", iconID)))
+                LOG_ERROR("Unable to drop temporary PageURLs pointing at Icon URL %s", iconURL.ascii().data());
+        }
+    }
+    
+    // And then from the on-disk tables
+    iconID = establishIconIDForIconURL(iconURL, false);
+    if (iconID) {
+        if (!m_db.executeCommand(String::sprintf("DELETE FROM Icon WHERE iconID = %lli", iconID)))
+            LOG_ERROR("Unable to drop Icon at URL %s from table Icon", iconURL.ascii().data()); 
+        if (!m_db.executeCommand(String::sprintf("DELETE FROM PageURL WHERE iconID = %lli", iconID)))
+            LOG_ERROR("Unable to drop PageURLs pointing at Icon URL %s", iconURL.ascii().data());
+    }
 
 }
 
@@ -463,7 +613,16 @@ void IconDatabase::performSetIconDataForIconID(int64_t iconID, const String& res
     return;
 }
 
-int IconDatabase::establishTemporaryIconIDForEscapedIconURL(const String& iconURL)
+int64_t IconDatabase::establishTemporaryIconIDForIconURL(const String& _iconURL, bool create)
+{
+    if (_iconURL.isEmpty())
+        return 0;
+    String iconURL = _iconURL;
+    iconURL.replace('\'', "''");
+    return establishTemporaryIconIDForEscapedIconURL(iconURL, create);
+}
+
+int64_t IconDatabase::establishTemporaryIconIDForEscapedIconURL(const String& iconURL, bool create)
 {
     // We either lookup the iconURL and return its ID, or we create a new one for it
     int64_t iconID = 0;
@@ -473,13 +632,23 @@ int IconDatabase::establishTemporaryIconIDForEscapedIconURL(const String& iconUR
         iconID = sql.getColumnInt64(0);
     } else {
         sql.finalize();
-        if (m_db.executeCommand("INSERT INTO TempIcon (url) VALUES ('" + iconURL + "');"))
-            iconID = m_db.lastInsertRowID();
+        if (create)
+            if (m_db.executeCommand("INSERT INTO TempIcon (url) VALUES ('" + iconURL + "');"))
+                iconID = m_db.lastInsertRowID();
     }
     return iconID;
 }
 
-int IconDatabase::establishIconIDForEscapedIconURL(const String& iconURL)
+int64_t IconDatabase::establishIconIDForIconURL(const String& _iconURL, bool create)
+{
+    if (_iconURL.isEmpty())
+        return 0;
+    String iconURL = _iconURL;
+    iconURL.replace('\'', "''");
+    return establishIconIDForEscapedIconURL(iconURL, create);
+}
+
+int64_t IconDatabase::establishIconIDForEscapedIconURL(const String& iconURL, bool create)
 {
     // We either lookup the iconURL and return its ID, or we create a new one for it
     int64_t iconID = 0;
@@ -489,8 +658,9 @@ int IconDatabase::establishIconIDForEscapedIconURL(const String& iconURL)
         iconID = sql.getColumnInt64(0);
     } else {
         sql.finalize();
-        if (m_db.executeCommand("INSERT INTO Icon (url) VALUES ('" + iconURL + "');"))
-            iconID = m_db.lastInsertRowID();
+        if (create)
+            if (m_db.executeCommand("INSERT INTO Icon (url) VALUES ('" + iconURL + "');"))
+                iconID = m_db.lastInsertRowID();
     }
     return iconID;
 }
@@ -538,13 +708,32 @@ void IconDatabase::pruneUnreferencedIcons(int numberToPrune)
 {
     if (!numberToPrune)
         return;
-        
-    if (numberToPrune > 0)
-        if (!m_db.executeCommand(String::sprintf("DELETE FROM Icon WHERE iconID IN (SELECT Icon.iconID FROM Icon WHERE Icon.iconID NOT IN(SELECT PageURL.iconID FROM PageURL) LIMIT %i;", numberToPrune)))
-            LOG_ERROR("Failed to prune %i unreferenced icons from the DB", numberToPrune);
-    else
-        if (!m_db.executeCommand(String("DELETE FROM Icon WHERE iconID IN (SELECT Icon.iconID FROM Icon WHERE Icon.iconID NOT IN(SELECT PageURL.iconID FROM PageURL);")))
-            LOG_ERROR("Failed to prune all unreferenced icons from the DB");
+    
+    if (numberToPrune > 0) {
+        if (!m_db.executeCommand(String::sprintf("DELETE FROM Icon WHERE Icon.iconID IN (SELECT Icon.iconID FROM Icon WHERE Icon.iconID NOT IN(SELECT PageURL.iconID FROM PageURL) LIMIT %i);", numberToPrune)))
+            LOG_ERROR("Failed to prune %i unreferenced icons from the DB - %s", numberToPrune, m_db.lastErrorMsg());
+    } else {
+        if (!m_db.executeCommand("DELETE FROM Icon WHERE Icon.iconID IN (SELECT Icon.iconID FROM Icon WHERE Icon.iconID NOT IN(SELECT PageURL.iconID FROM PageURL));"))
+            LOG_ERROR("Failed to prune all unreferenced icons from the DB - %s", m_db.lastErrorMsg());
+    }
+}
+
+void IconDatabase::pruneUnretainedIcons(Timer<IconDatabase>* timer)
+{
+
+// FIXME - The PageURL delete and the pruneunreferenced icons need to be in an atomic transaction
+#ifndef NDEBUG
+    double start = CFAbsoluteTimeGetCurrent();
+#endif
+    if (!m_db.executeCommand("DELETE FROM PageURL WHERE PageURL.url NOT IN(SELECT url FROM PageRetain WHERE count > 0);"))
+        LOG_ERROR("Failed to delete unretained PageURLs from DB - %s", m_db.lastErrorMsg());
+    pruneUnreferencedIcons(-1);
+#ifndef NDEBUG
+    double duration = CFAbsoluteTimeGetCurrent() - start;
+    LOG(IconDatabase, "Pruning unretained icons took %d seconds", duration);
+    if (duration > 1.0) 
+        LOG_ERROR("Pruning unretained icons took %d seconds - this is much too long!", duration);
+#endif
 }
 
 
index b0d66ae42e5ab220aef1c8808659b7c5fc41b459..d1339911cfe7690c9921eed3d557e729d6d8682a 100644 (file)
@@ -32,6 +32,7 @@
 #include "PlatformString.h"
 #include "SQLDatabase.h"
 #include "StringHash.h"
+#include "Timer.h"
 
 #include <wtf/HashMap.h>
 
@@ -57,18 +58,11 @@ public:
     void resetExpiration(time_t newExpiration = 0);
     time_t getExpiration();
         
-    //getImage() inherently touch()es the icon
-    Image* getImage(const IntSize&);
-    
-    //incase a user wants to manually touch() the icon
-    void touch();
-    time_t getTouch() { return m_touch; }
-    
+    Image* getImage(const IntSize&);    
     String getIconURL() { return m_iconURL; }
-        
+
 private:
     String m_iconURL;
-    time_t m_touch;
     time_t m_expire;
     Image* m_image;
     
@@ -111,29 +105,50 @@ public:
     void setHaveNoIconForIconURL(const String&);
     void setIconURLForPageURL(const String& iconURL, const String& pageURL);
 
-    // Removes icons from the db that no longer have any PageURLs pointing to them
-    // If numberToPrune is negative, ALL dangling icons will be pruned
-    void pruneUnreferencedIcons(int numberToPrune);
-
     static const int currentDatabaseVersion;    
 private:
     IconDatabase();
     ~IconDatabase();
     
+    // Remove the Icon and IconResource entry for this icon, as well as the SiteIcon object in memory
+    void forgetIconForIconURLFromDatabase(const String&);
+    
+    // Wipe all icons from the DB
     void removeAllIcons();
+    
+    // Removes icons from the db that no longer have any PageURLs pointing to them
+    // If numberToPrune is negative, ALL dangling icons will be pruned
+    void pruneUnreferencedIcons(int numberToPrune);
+    
+    // Removes ALL icons that are unretained
+    // Meant to be called just once on startup, after initial retains are complete
+    // via a timer fire
+    void pruneUnretainedIcons(Timer<IconDatabase>*);
+    
+    // Add up the retain count for an iconURL
+    int totalRetainCountForIconURL(const String&);
+    
     bool isEnabled();
     
+    // Do a quick check to make sure the database tables are in place and the db version is current
     bool isValidDatabase();
+    
+    // Delete all tables from the database
     void clearDatabase();
+    
+    // Create the tables and triggers for the on-disk database
     void recreateDatabase();
 
+    // Create/Delete the temporary, in-memory tables used for private browsing
     void createPrivateTables();
     void deletePrivateTables();
     
-    // The following two methods will either find the iconID for a given iconURL or, if the iconURL
-    // isn't in the table yet, will create an entry and return the resulting iconID
-    int establishIconIDForEscapedIconURL(const String&);
-    int establishTemporaryIconIDForEscapedIconURL(const String&);
+    // The following four methods will either find the iconID for a given iconURL or, if the iconURL
+    // isn't in the table yet and you don't pass a false flag, will create an entry and return the resulting iconID
+    int64_t establishIconIDForIconURL(const String&, bool create = true);
+    int64_t establishIconIDForEscapedIconURL(const String&, bool create = true);
+    int64_t establishTemporaryIconIDForIconURL(const String&, bool create = true);
+    int64_t establishTemporaryIconIDForEscapedIconURL(const String&, bool create = true);
     
     // Since we store data in both the ondisk tables and temporary tables, these methods will do the work 
     // for either case
@@ -153,6 +168,8 @@ private:
     SQLDatabase m_db;
     bool m_privateBrowsingEnabled;
     
+    Timer<IconDatabase> m_startupTimer;
+    
     typedef HashMap<String, SiteIcon*> SiteIconMap;
     SiteIconMap m_pageURLToSiteIcons;
     SiteIconMap m_iconURLToSiteIcons;
index 722061ff0b0e21f4d64f4fed390e816ec4fa7893..8ee835a221964aade5c2f19ec6c73b07065709fa 100644 (file)
@@ -22,7 +22,6 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
-
 #include "IconDatabase.h"
 
 #include "Logging.h"
@@ -33,7 +32,6 @@ using namespace WebCore;
 
 SiteIcon::SiteIcon(const String& url)
     : m_iconURL(url)
-    , m_touch(0)
     , m_image(0)
 {
 
@@ -41,7 +39,8 @@ SiteIcon::SiteIcon(const String& url)
 
 SiteIcon::~SiteIcon()
 {
-
+    // Upon destruction of a SiteIcon, its image should no longer be in use anywhere
+    delete m_image;
 }
 
 Image* SiteIcon::getImage(const IntSize& size)
@@ -58,13 +57,12 @@ Image* SiteIcon::getImage(const IntSize& size)
         if (!imageData.size())
             return 0;
 
-        String hexdata;
         int checksum = 0;
-        for (unsigned int i=0; i<imageData.size(); ++i) {
+#ifndef NDEBUG
+        for (unsigned int i=0; i<imageData.size(); ++i) 
             checksum += imageData[i];
-            hexdata.append(String::sprintf("%.2hhX", imageData[i]));
-        }
-            
+#endif
+
         NativeBytePtr nativeData = 0;
         // FIXME - Any other platform will need their own method to create NativeBytePtr from the void*
 #ifdef __APPLE__
@@ -72,13 +70,11 @@ Image* SiteIcon::getImage(const IntSize& size)
 #endif
         m_image = new Image();
         
-
-        LOG(IconDatabase,"DUMP-\n%s", hexdata.ascii().data());
         if (m_image->setNativeData(nativeData, true)) {
             LOG(IconDatabase, "%s\nImage Creation SUCCESSFUL - %i bytes of data with a checksum of %i", m_iconURL.ascii().data(), imageData.size(), checksum);
             return m_image;
         }
-        LOG(IconDatabase,     "%s\nImage Creation FAILURE    - %i bytes of data with a checksum of %i", m_iconURL.ascii().data(), imageData.size(), checksum);
+        LOG(IconDatabase, "%s\nImage Creation FAILURE - %i bytes of data with a checksum of %i", m_iconURL.ascii().data(), imageData.size(), checksum);
         delete m_image;
         return m_image = 0;
     }
@@ -96,5 +92,4 @@ time_t SiteIcon::getExpiration()
     return INT_MAX;
 }
     
-//void touch();