Пример #1
0
CFDictionaryRef WebBackForwardList::createCFDictionaryRepresentation(WebPageProxy::WebPageProxySessionStateFilterCallback filter, void* context) const
{
    ASSERT(m_current == NoCurrentItemIndex || m_current < m_entries.size());

    RetainPtr<CFMutableArrayRef> entries(AdoptCF, CFArrayCreateMutable(0, m_entries.size(), &kCFTypeArrayCallBacks));

    // We may need to update the current index to account for entries that are filtered by the callback.
    int currentIndex = m_current;

    for (size_t i = 0; i < m_entries.size(); ++i) {
        RefPtr<WebURL> webURL = WebURL::create(m_entries[i]->url());
        if (filter && !filter(toAPI(m_page), WKPageGetSessionHistoryURLValueType(), toURLRef(m_entries[i]->originalURL().impl()), context)) {
            if (i <= static_cast<size_t>(m_current))
                currentIndex--;
            continue;
        }
        
        RetainPtr<CFStringRef> url(AdoptCF, m_entries[i]->url().createCFString());
        RetainPtr<CFStringRef> title(AdoptCF, m_entries[i]->title().createCFString());
        RetainPtr<CFStringRef> originalURL(AdoptCF, m_entries[i]->originalURL().createCFString());
        RetainPtr<CFDataRef> entryData(AdoptCF, CFDataCreate(kCFAllocatorDefault, m_entries[i]->backForwardData().data(), m_entries[i]->backForwardData().size()));
        
        const void* keys[4] = { SessionHistoryEntryURLKey(), SessionHistoryEntryTitleKey(), SessionHistoryEntryOriginalURLKey(), SessionHistoryEntryDataKey() };
        const void* values[4] = { url.get(), title.get(), originalURL.get(), entryData.get() };

        RetainPtr<CFDictionaryRef> entryDictionary(AdoptCF, CFDictionaryCreate(0, keys, values, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
        CFArrayAppendValue(entries.get(), entryDictionary.get());
    }

    ASSERT(currentIndex < CFArrayGetCount(entries.get()));
    RetainPtr<CFNumberRef> currentIndexNumber(AdoptCF, CFNumberCreate(0, kCFNumberIntType, &currentIndex));

    const void* keys[2] = { SessionHistoryCurrentIndexKey(), SessionHistoryEntriesKey() };
    const void* values[2] = { currentIndexNumber.get(), entries.get() };

    return CFDictionaryCreate(0, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
}
void ColumnMapScanProcessor::processMainPage(const ColumnMapMainPage* page, uint64_t startIdx, uint64_t endIdx) {
    mKeyData.resize(page->count, 0u);
    mValidFromData.resize(page->count, 0u);
    mValidToData.resize(page->count, 0u);
    auto resultSize = mNumConjuncts * page->count;
    if (mResult.size() < resultSize) {
        mResult.resize(resultSize, 0u);
    }

    auto entries = page->entryData();
    auto sizeData = page->sizeData();

    auto i = startIdx;
    while (i < endIdx) {
        auto key = entries[i].key;
        auto newest = entries[i].newest.load();
        auto validTo = std::numeric_limits<uint64_t>::max();
        if (newest != 0u) {
            if ((newest & crossbow::to_underlying(NewestPointerTag::INVALID)) != 0x0u) {
                // Skip to element with next key
                auto j = i;
                for (++i; i < endIdx && entries[i].key == key; ++i);
                if (startIdx == j) {
                    startIdx = i;
                }
                continue;
            }
            if (auto relocated = reinterpret_cast<const ColumnMapMainEntry*>(newestMainRecord(newest))) {
                if (i > startIdx) {
                    evaluateMainQueries(page, startIdx, i);
                }

                auto relocatedPage = mContext.pageFromEntry(relocated);
                auto relocatedStartIdx = ColumnMapContext::pageIndex(relocatedPage, relocated);
                auto relocatedEndIdx = relocatedStartIdx;

                while (true) {
                    for (++i; i < endIdx && entries[i].key == key; ++i);
                    if (i >= endIdx) {
                        break;
                    }

                    key = entries[i].key;
                    newest = entries[i].newest.load();

                    relocated = reinterpret_cast<const ColumnMapMainEntry*>(newestMainRecord(newest));
                    if (relocated) {
                        if (mContext.pageFromEntry(relocated) != relocatedPage) {
                            break;
                        }
                        relocatedEndIdx = ColumnMapContext::pageIndex(relocatedPage, relocated);
                    } else if ((newest & crossbow::to_underlying(NewestPointerTag::INVALID)) != 0x0u) {
                        continue;
                    } else {
                        break;
                    }
                }

                auto relocatedEntries = relocatedPage->entryData();
                key = relocatedEntries[relocatedEndIdx].key;
                for (++relocatedEndIdx; relocatedEndIdx < relocatedPage->count && relocatedEntries[relocatedEndIdx].key == key; ++relocatedEndIdx);

                processMainPage(relocatedPage, relocatedStartIdx, relocatedEndIdx);

                if (i >= endIdx) {
                    return;
                }

                mKeyData.resize(page->count, 0u);
                mValidFromData.resize(page->count, 0u);
                mValidToData.resize(page->count, 0u);

                startIdx = i;
                continue;
            }

            auto lowestVersion = processUpdateRecord(reinterpret_cast<const UpdateLogEntry*>(newest),
                    entries[i].version, validTo);

            // Skip elements with version above lowest version and set the valid-to version to 0 to exclude them from
            // the query processing
            auto j = i;
            for (; i < endIdx && entries[i].key == key && entries[i].version >= lowestVersion; ++i);
            if (startIdx == j) {
                startIdx = i;
            }
        }

        // Set valid-to version for every element of the same key to the valid-from version of the previous
        // If the element marks a deletion set the valid-to version to 0 to exclude them from the query processing.
        for (; i < endIdx && entries[i].key == key; ++i) {
            if (sizeData[i] != 0) {
                mKeyData[i] = key;
                mValidFromData[i] = entries[i].version;
                mValidToData[i] = validTo;
            }
            validTo = entries[i].version;
        }
    }
    if (startIdx < endIdx) {
        evaluateMainQueries(page, startIdx, endIdx);
    }
}
void ColumnMapScanProcessor::process() {
    for (auto i = pageIdx; i < pageEndIdx; ++i) {
        processMainPage(pages[i], 0, pages[i]->count);
    }

    auto insIter = logIter;
    while (insIter != logEnd) {
        if (!insIter->sealed()) {
            ++insIter;
            continue;
        }

        auto ptr = reinterpret_cast<const InsertLogEntry*>(insIter->data());
        ConstInsertRecord record(ptr);
        if (!record.valid()) {
            ++insIter;
            continue;
        }

        if (auto relocated = reinterpret_cast<const ColumnMapMainEntry*>(newestMainRecord(record.newest()))) {
            auto relocatedPage = mContext.pageFromEntry(relocated);
            auto relocatedStartIdx = ColumnMapContext::pageIndex(relocatedPage, relocated);
            auto relocatedEndIdx = relocatedStartIdx;

            for (++insIter; insIter != logEnd; ++insIter) {
                if (!insIter->sealed()) {
                    continue;
                }

                ptr = reinterpret_cast<const InsertLogEntry*>(insIter->data());
                record = ConstInsertRecord(ptr);

                relocated = reinterpret_cast<const ColumnMapMainEntry*>(newestMainRecord(record.newest()));
                if (relocated) {
                    if (mContext.pageFromEntry(relocated) != relocatedPage) {
                        break;
                    }
                    relocatedEndIdx = ColumnMapContext::pageIndex(relocatedPage, relocated);
                } else if (!record.valid()) {
                    continue;
                } else {
                    break;
                }
            }

            auto relocatedEntries = relocatedPage->entryData();
            auto key = relocatedEntries[relocatedEndIdx].key;
            for (++relocatedEndIdx; relocatedEndIdx < relocatedPage->count && relocatedEntries[relocatedEndIdx].key == key; ++relocatedEndIdx);

            processMainPage(relocatedPage, relocatedStartIdx, relocatedEndIdx);

            continue;
        }

        auto validTo = std::numeric_limits<uint64_t>::max();
        if (record.newest() != 0u) {
            auto lowestVersion = processUpdateRecord(reinterpret_cast<const UpdateLogEntry*>(record.newest()),
                    record.baseVersion(), validTo);

            if (ptr->version >= lowestVersion) {
                ++insIter;
                continue;
            }
        }
        auto entry = LogEntry::entryFromData(reinterpret_cast<const char*>(ptr));
        processRowRecord(ptr->key, ptr->version, validTo, ptr->data(), entry->size() - sizeof(InsertLogEntry));
        ++insIter;
    }
}