⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 icondatabase.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
    return m_threadTerminationRequested || m_removeIconsRequested;}void* IconDatabase::iconDatabaseSyncThreadStart(void* vIconDatabase){        IconDatabase* iconDB = static_cast<IconDatabase*>(vIconDatabase);        return iconDB->iconDatabaseSyncThread();}void* IconDatabase::iconDatabaseSyncThread(){    // The call to create this thread might not complete before the thread actually starts, so we might fail this ASSERT_ICON_SYNC_THREAD() because the pointer     // to our thread structure hasn't been filled in yet.    // To fix this, the main thread acquires this lock before creating us, then releases the lock after creation is complete.  A quick lock/unlock cycle here will     // prevent us from running before that call completes    m_syncLock.lock();    m_syncLock.unlock();    ASSERT_ICON_SYNC_THREAD();        LOG(IconDatabase, "(THREAD) IconDatabase sync thread started");#ifndef NDEBUG    double startTime = currentTime();#endif    // Need to create the database path if it doesn't already exist    makeAllDirectories(m_databaseDirectory);    // Existence of a journal file is evidence of a previous crash/force quit and automatically qualifies    // us to do an integrity check    String journalFilename = m_completeDatabasePath + "-journal";    if (!checkIntegrityOnOpen) {        AutodrainedPool pool;        checkIntegrityOnOpen = fileExists(journalFilename);    }        {        MutexLocker locker(m_syncLock);        if (!m_syncDB.open(m_completeDatabasePath)) {            LOG_ERROR("Unable to open icon database at path %s - %s", m_completeDatabasePath.ascii().data(), m_syncDB.lastErrorMsg());            return 0;        }    }        if (shouldStopThreadActivity())        return syncThreadMainLoop();        #ifndef NDEBUG    double timeStamp = currentTime();    LOG(IconDatabase, "(THREAD) Open took %.4f seconds", timeStamp - startTime);#endif        performOpenInitialization();    if (shouldStopThreadActivity())        return syncThreadMainLoop();        #ifndef NDEBUG    double newStamp = currentTime();    LOG(IconDatabase, "(THREAD) performOpenInitialization() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);    timeStamp = newStamp;#endif     if (!imported()) {        LOG(IconDatabase, "(THREAD) Performing Safari2 import procedure");        SQLiteTransaction importTransaction(m_syncDB);        importTransaction.begin();                // Commit the transaction only if the import completes (the import should be atomic)        if (m_client->performImport()) {            setImported(true);            importTransaction.commit();        } else {            LOG(IconDatabase, "(THREAD) Safari 2 import was cancelled");            importTransaction.rollback();        }                if (shouldStopThreadActivity())            return syncThreadMainLoop();            #ifndef NDEBUG        newStamp = currentTime();        LOG(IconDatabase, "(THREAD) performImport() took %.4f seconds, now %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);        timeStamp = newStamp;#endif     }            // Uncomment the following line to simulate a long lasting URL import (*HUGE* icon databases, or network home directories)    // while (currentTime() - timeStamp < 10);    // Read in URL mappings from the database              LOG(IconDatabase, "(THREAD) Starting iconURL import");    performURLImport();        if (shouldStopThreadActivity())        return syncThreadMainLoop();#ifndef NDEBUG    newStamp = currentTime();    LOG(IconDatabase, "(THREAD) performURLImport() took %.4f seconds.  Entering main loop %.4f seconds from thread start", newStamp - timeStamp, newStamp - startTime);#endif     LOG(IconDatabase, "(THREAD) Beginning sync");    return syncThreadMainLoop();}static int databaseVersionNumber(SQLiteDatabase& db){    return SQLiteStatement(db, "SELECT value FROM IconDatabaseInfo WHERE key = 'Version';").getColumnInt(0);}static bool isValidDatabase(SQLiteDatabase& db){    // These four tables should always exist in a valid db    if (!db.tableExists("IconInfo") || !db.tableExists("IconData") || !db.tableExists("PageURL") || !db.tableExists("IconDatabaseInfo"))        return false;        if (databaseVersionNumber(db) < currentDatabaseVersion) {        LOG(IconDatabase, "DB version is not found or below expected valid version");        return false;    }        return true;}static void createDatabaseTables(SQLiteDatabase& db){    if (!db.executeCommand("CREATE TABLE PageURL (url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,iconID INTEGER NOT NULL ON CONFLICT FAIL);")) {        LOG_ERROR("Could not create PageURL table in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE INDEX PageURLIndex ON PageURL (url);")) {        LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE TABLE IconInfo (iconID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE ON CONFLICT REPLACE, url TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT FAIL, stamp INTEGER);")) {        LOG_ERROR("Could not create IconInfo table in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE INDEX IconInfoIndex ON IconInfo (url, iconID);")) {        LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE TABLE IconData (iconID INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE ON CONFLICT REPLACE, data BLOB);")) {        LOG_ERROR("Could not create IconData table in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE INDEX IconDataIndex ON IconData (iconID);")) {        LOG_ERROR("Could not create PageURL index in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand("CREATE TABLE IconDatabaseInfo (key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,value TEXT NOT NULL ON CONFLICT FAIL);")) {        LOG_ERROR("Could not create IconDatabaseInfo table in database (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }    if (!db.executeCommand(String("INSERT INTO IconDatabaseInfo VALUES ('Version', ") + String::number(currentDatabaseVersion) + ");")) {        LOG_ERROR("Could not insert icon database version into IconDatabaseInfo table (%i) - %s", db.lastError(), db.lastErrorMsg());        db.close();        return;    }}    void IconDatabase::performOpenInitialization(){    ASSERT_ICON_SYNC_THREAD();        if (!isOpen())        return;        if (checkIntegrityOnOpen) {        checkIntegrityOnOpen = false;        if (!checkIntegrity()) {            LOG(IconDatabase, "Integrity check was bad - dumping IconDatabase");            m_syncDB.close();                        {                MutexLocker locker(m_syncLock);                // Should've been consumed by SQLite, delete just to make sure we don't see it again in the future;                deleteFile(m_completeDatabasePath + "-journal");                deleteFile(m_completeDatabasePath);            }                        // Reopen the write database, creating it from scratch            if (!m_syncDB.open(m_completeDatabasePath)) {                LOG_ERROR("Unable to open icon database at path %s - %s", m_completeDatabasePath.ascii().data(), m_syncDB.lastErrorMsg());                return;            }                  }    }        int version = databaseVersionNumber(m_syncDB);        if (version > currentDatabaseVersion) {        LOG(IconDatabase, "Database version number %i is greater than our current version number %i - closing the database to prevent overwriting newer versions", version, currentDatabaseVersion);        m_syncDB.close();        m_threadTerminationRequested = true;        return;    }        if (!isValidDatabase(m_syncDB)) {        LOG(IconDatabase, "%s is missing or in an invalid state - reconstructing", m_completeDatabasePath.ascii().data());        m_syncDB.clearAllTables();        createDatabaseTables(m_syncDB);    }    // Reduce sqlite RAM cache size from default 2000 pages (~1.5kB per page). 3MB of cache for icon database is overkill    if (!SQLiteStatement(m_syncDB, "PRAGMA cache_size = 200;").executeCommand())                 LOG_ERROR("SQLite database could not set cache_size");}bool IconDatabase::checkIntegrity(){    ASSERT_ICON_SYNC_THREAD();        SQLiteStatement integrity(m_syncDB, "PRAGMA integrity_check;");    if (integrity.prepare() != SQLResultOk) {        LOG_ERROR("checkIntegrity failed to execute");        return false;    }        int resultCode = integrity.step();    if (resultCode == SQLResultOk)        return true;            if (resultCode != SQLResultRow)        return false;    int columns = integrity.columnCount();    if (columns != 1) {        LOG_ERROR("Received %i columns performing integrity check, should be 1", columns);        return false;    }            String resultText = integrity.getColumnText(0);            // A successful, no-error integrity check will be "ok" - all other strings imply failure    if (resultText == "ok")        return true;        LOG_ERROR("Icon database integrity check failed - \n%s", resultText.ascii().data());    return false;}void IconDatabase::performURLImport(){    ASSERT_ICON_SYNC_THREAD();    SQLiteStatement query(m_syncDB, "SELECT PageURL.url, IconInfo.url, IconInfo.stamp FROM PageURL INNER JOIN IconInfo ON PageURL.iconID=IconInfo.iconID;");        if (query.prepare() != SQLResultOk) {        LOG_ERROR("Unable to prepare icon url import query");        return;    }        // Informal testing shows that draining the autorelease pool every 25 iterations is about as low as we can go    // before performance starts to drop off, but we don't want to increase this number because then accumulated memory usage will go up    AutodrainedPool pool(25);            int result = query.step();    while (result == SQLResultRow) {        String pageURL = query.getColumnText(0);        String iconURL = query.getColumnText(1);        {            MutexLocker locker(m_urlAndIconLock);                        PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURL);                        // If the pageRecord doesn't exist in this map, then no one has retained this pageURL            // If the s_databaseCleanupCounter count is non-zero, then we're not supposed to be pruning the database in any manner,            // so go ahead and actually create a pageURLRecord for this url even though it's not retained.            // If database cleanup *is* allowed, we don't want to bother pulling in a page url from disk that noone is actually interested            // in - we'll prune it later instead!            if (!pageRecord && databaseCleanupCounter && !pageURL.isEmpty()) {                pageRecord = new PageURLRecord(pageURL);                m_pageURLToRecordMap.set(pageURL, pageRecord);            }                        if (pageRecord) {                IconRecord* currentIcon = pageRecord->iconRecord();                if (!currentIcon || currentIcon->iconURL() != iconURL) {                    pageRecord->setIconRecord(getOrCreateIconRecord(iconURL));                    currentIcon = pageRecord->iconRecord();                }                            // Regardless, the time stamp from disk still takes precedence.  Until we read this icon from disk, we didn't think we'd seen it before                // so we marked the timestamp as "now", but it's really much older                currentIcon->setTimestamp(query.getColumnInt(2));            }                    }                // FIXME: Currently the WebKit API supports 1 type of notification that is sent whenever we get an Icon URL for a Page URL.  We might want to re-purpose it to work for         // getting the actually icon itself also (so each pageurl would get this notification twice) or we might want to add a second type of notification -        // one for the URL and one for the Image itself        // Note that WebIconDatabase is not neccessarily API so we might be able to make this change        {            MutexLocker locker(m_pendingReadingLock);            if (m_pageURLsPendingImport.contains(pageURL)) {                m_client->dispatchDidAddIconForPageURL(pageURL);                m_pageURLsPendingImport.remove(pageURL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -