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

📄 icondatabase.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 5 页
字号:
                            pool.cycle();            }        }                // Stop the import at any time of the thread has been asked to shutdown        if (shouldStopThreadActivity()) {            LOG(IconDatabase, "IconDatabase asked to terminate during performURLImport()");            return;        }                result = query.step();    }        if (result != SQLResultDone)        LOG(IconDatabase, "Error reading page->icon url mappings from database");    // Clear the m_pageURLsPendingImport set - either the page URLs ended up with an iconURL (that we'll notify about) or not,     // but after m_iconURLImportComplete is set to true, we don't care about this set anymore    Vector<String> urls;    {        MutexLocker locker(m_pendingReadingLock);        urls.appendRange(m_pageURLsPendingImport.begin(), m_pageURLsPendingImport.end());        m_pageURLsPendingImport.clear();                m_iconURLImportComplete = true;    }        Vector<String> urlsToNotify;        // Loop through the urls pending import    // Remove unretained ones if database cleanup is allowed    // Keep a set of ones that are retained and pending notification        {        MutexLocker locker(m_urlAndIconLock);                for (unsigned i = 0; i < urls.size(); ++i) {            if (!m_retainedPageURLs.contains(urls[i])) {                PageURLRecord* record = m_pageURLToRecordMap.get(urls[i]);                if (record && !databaseCleanupCounter) {                    m_pageURLToRecordMap.remove(urls[i]);                    IconRecord* iconRecord = record->iconRecord();                                        // If this page is the only remaining retainer of its icon, mark that icon for deletion and don't bother                    // reading anything related to it                     if (iconRecord && iconRecord->hasOneRef()) {                        m_iconURLToRecordMap.remove(iconRecord->iconURL());                                                {                            MutexLocker locker(m_pendingReadingLock);                            m_pageURLsInterestedInIcons.remove(urls[i]);                            m_iconsPendingReading.remove(iconRecord);                        }                        {                            MutexLocker locker(m_pendingSyncLock);                            m_iconsPendingSync.set(iconRecord->iconURL(), iconRecord->snapshot(true));                                            }                    }                                        delete record;                }            } else {                urlsToNotify.append(urls[i]);            }        }    }    LOG(IconDatabase, "Notifying %zu interested page URLs that their icon URL is known due to the import", urlsToNotify.size());    // Now that we don't hold any locks, perform the actual notifications    for (unsigned i = 0; i < urlsToNotify.size(); ++i) {        LOG(IconDatabase, "Notifying icon info known for pageURL %s", urlsToNotify[i].ascii().data());        m_client->dispatchDidAddIconForPageURL(urlsToNotify[i]);        if (shouldStopThreadActivity())            return;        pool.cycle();    }        // Notify all DocumentLoaders that were waiting for an icon load decision on the main thread    callOnMainThread(notifyPendingLoadDecisionsOnMainThread, this);}void* IconDatabase::syncThreadMainLoop(){    ASSERT_ICON_SYNC_THREAD();    static bool prunedUnretainedIcons = false;    m_syncLock.lock();    // It's possible thread termination is requested before the main loop even starts - in that case, just skip straight to cleanup    while (!m_threadTerminationRequested) {        m_syncLock.unlock();#ifndef NDEBUG        double timeStamp = currentTime();#endif        LOG(IconDatabase, "(THREAD) Main work loop starting");        // If we should remove all icons, do it now.  This is an uninteruptible procedure that we will always do before quitting if it is requested        if (m_removeIconsRequested) {            removeAllIconsOnThread();            m_removeIconsRequested = false;        }                // Then, if the thread should be quitting, quit now!        if (m_threadTerminationRequested)            break;                bool didAnyWork = true;        while (didAnyWork) {            bool didWrite = writeToDatabase();            if (shouldStopThreadActivity())                break;                            didAnyWork = readFromDatabase();            if (shouldStopThreadActivity())                break;                            // Prune unretained icons after the first time we sync anything out to the database            // This way, pruning won't be the only operation we perform to the database by itself            // We also don't want to bother doing this if the thread should be terminating (the user is quitting)            // or if private browsing is enabled            // We also don't want to prune if the m_databaseCleanupCounter count is non-zero - that means someone            // has asked to delay pruning            if (didWrite && !m_privateBrowsingEnabled && !prunedUnretainedIcons && !databaseCleanupCounter) {#ifndef NDEBUG                double time = currentTime();#endif                LOG(IconDatabase, "(THREAD) Starting pruneUnretainedIcons()");                                pruneUnretainedIcons();                                LOG(IconDatabase, "(THREAD) pruneUnretainedIcons() took %.4f seconds", currentTime() - time);                                // If pruneUnretainedIcons() returned early due to requested thread termination, its still okay                // to mark prunedUnretainedIcons true because we're about to terminate anyway                prunedUnretainedIcons = true;            }                        didAnyWork = didAnyWork || didWrite;            if (shouldStopThreadActivity())                break;        }        #ifndef NDEBUG        double newstamp = currentTime();        LOG(IconDatabase, "(THREAD) Main work loop ran for %.4f seconds, %s requested to terminate", newstamp - timeStamp, shouldStopThreadActivity() ? "was" : "was not");#endif                            m_syncLock.lock();                // There is some condition that is asking us to stop what we're doing now and handle a special case        // This is either removing all icons, or shutting down the thread to quit the app        // We handle those at the top of this main loop so continue to jump back up there        if (shouldStopThreadActivity())            continue;                    m_syncCondition.wait(m_syncLock);     }    m_syncLock.unlock();        // Thread is terminating at this point    return cleanupSyncThread();}bool IconDatabase::readFromDatabase(){    ASSERT_ICON_SYNC_THREAD();    #ifndef NDEBUG    double timeStamp = currentTime();#endif    bool didAnyWork = false;    // We'll make a copy of the sets of things that need to be read.  Then we'll verify at the time of updating the record that it still wants to be updated    // This way we won't hold the lock for a long period of time    Vector<IconRecord*> icons;    {        MutexLocker locker(m_pendingReadingLock);        icons.appendRange(m_iconsPendingReading.begin(), m_iconsPendingReading.end());    }        // Keep track of icons we actually read to notify them of the new icon        HashSet<String> urlsToNotify;        for (unsigned i = 0; i < icons.size(); ++i) {        didAnyWork = true;        RefPtr<SharedBuffer> imageData = getImageDataForIconURLFromSQLDatabase(icons[i]->iconURL());        // Verify this icon still wants to be read from disk        {            MutexLocker urlLocker(m_urlAndIconLock);            {                MutexLocker readLocker(m_pendingReadingLock);                                if (m_iconsPendingReading.contains(icons[i])) {                    // Set the new data                    icons[i]->setImageData(imageData.get());                                        // Remove this icon from the set that needs to be read                    m_iconsPendingReading.remove(icons[i]);                                        // We have a set of all Page URLs that retain this icon as well as all PageURLs waiting for an icon                    // We want to find the intersection of these two sets to notify them                    // Check the sizes of these two sets to minimize the number of iterations                    const HashSet<String>* outerHash;                    const HashSet<String>* innerHash;                                        if (icons[i]->retainingPageURLs().size() > m_pageURLsInterestedInIcons.size()) {                        outerHash = &m_pageURLsInterestedInIcons;                        innerHash = &(icons[i]->retainingPageURLs());                    } else {                        innerHash = &m_pageURLsInterestedInIcons;                        outerHash = &(icons[i]->retainingPageURLs());                    }                                        HashSet<String>::const_iterator iter = outerHash->begin();                    HashSet<String>::const_iterator end = outerHash->end();                    for (; iter != end; ++iter) {                        if (innerHash->contains(*iter)) {                            LOG(IconDatabase, "%s is interesting in the icon we just read.  Adding it to the list and removing it from the interested set", urlForLogging(*iter).ascii().data());                            urlsToNotify.add(*iter);                        }                                                // If we ever get to the point were we've seen every url interested in this icon, break early                        if (urlsToNotify.size() == m_pageURLsInterestedInIcons.size())                            break;                    }                                        // We don't need to notify a PageURL twice, so all the ones we're about to notify can be removed from the interested set                    if (urlsToNotify.size() == m_pageURLsInterestedInIcons.size())                        m_pageURLsInterestedInIcons.clear();                    else {                        iter = urlsToNotify.begin();                        end = urlsToNotify.end();                        for (; iter != end; ++iter)                            m_pageURLsInterestedInIcons.remove(*iter);                    }                }            }        }            if (shouldStopThreadActivity())            return didAnyWork;                // 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);        // Now that we don't hold any locks, perform the actual notifications        HashSet<String>::iterator iter = urlsToNotify.begin();        HashSet<String>::iterator end = urlsToNotify.end();        for (unsigned iteration = 0; iter != end; ++iter, ++iteration) {            LOG(IconDatabase, "Notifying icon received for pageURL %s", urlForLogging(*iter).ascii().data());            m_client->dispatchDidAddIconForPageURL(*iter);            if (shouldStopThreadActivity())                return didAnyWork;                        pool.cycle();        }        LOG(IconDatabase, "Done notifying %i pageURLs who just received their icons", urlsToNotify.size());        urlsToNotify.clear();                if (shouldStopThreadActivity())            return didAnyWork;    }    LOG(IconDatabase, "Reading from database took %.4f seconds", currentTime() - timeStamp);    return didAnyWork;}bool IconDatabase::writeToDatabase(){    ASSERT_ICON_SYNC_THREAD();#ifndef NDEBUG    double timeStamp = currentTime();#endif    bool didAnyWork = false;        // We can copy the current work queue then clear it out - If any new work comes in while we're writing out,    // we'll pick it up on the next pass.  This greatly simplifies the locking strategy for this method and remains cohesive with changes    // asked for by the database on the main thread    Vector<IconSnapshot> iconSnapshots;    Vector<PageURLSnapshot> pageSnapshots;    {        MutexLocker locker(m_pendingSyncLock);                iconSnapshots.appendRange(m_iconsPendingSync.begin().values(), m_iconsPendingSync.end().values());        m_iconsPendingSync.clear();                pageSnapshots.appendRange(m_pageURLsPendingSync.begin().values(), m_pageURLsPendingSync.end().values());        m_pageURLsPendingSync.clear();    }        if (iconSnapshots.size() || pageSnapshots.size())        didAnyWork = true;            SQLiteTransaction syncTransaction(m_syncDB);    syncTransaction.begin();        for (unsigned i = 0; i < iconSnapshots.size(); ++i) {        writeIconSnapshotToSQLDatabase(iconSnapshots[i]);        LOG(IconDatabase, "Wrote IconRecord for IconURL %s with timeStamp of %i to the DB", urlForLogging(iconSnapshots[i].iconURL).ascii().data(), iconSnapshots[i].

⌨️ 快捷键说明

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