Changeset 221942 in webkit


Ignore:
Timestamp:
Sep 12, 2017 4:13:17 PM (7 years ago)
Author:
commit-queue@webkit.org
Message:

Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
https://bugs.webkit.org/show_bug.cgi?id=176579

Patch by Youenn Fablet <youenn@apple.com> on 2017-09-12
Reviewed by Alex Christensen.

Source/WebCore:

No change of behavior.

Introducing another version of queryCacheMatch used for the NetworkProcess implementation of the Cache.
Exporting the copy of a response body to be used also there.

  • Modules/cache/DOMCacheEngine.cpp:

(WebCore::DOMCacheEngine::matchURLs):
(WebCore::DOMCacheEngine::queryCacheMatch):
(WebCore::DOMCacheEngine::copyResponseBody):

  • Modules/cache/DOMCacheEngine.h:

Source/WebKit:

Introducing RecordData that splits its stored data in mandatory data,
used to check a record with a request and optional data that is
necessary to build a CacheStorageEngine::Record used by WebProcess.

The mandatory data contains the URL, Vary header information and identifiers.
Adding routines to go from a Record to RecordData and vice versa.
Storing in CacheStorage::Cache RecordData instead of Record.

  • NetworkProcess/cache/CacheStorageEngineCache.cpp:

(WebKit::CacheStorage::queryCache):
(WebKit::CacheStorage::updateVaryInformation):
(WebKit::CacheStorage::toRecord):
(WebKit::CacheStorage::toRecordData):
(WebKit::CacheStorage::Cache::retrieveRecords const):
(WebKit::CacheStorage::Cache::addRecord):
(WebKit::CacheStorage::Cache::recordsFromURL):
(WebKit::CacheStorage::Cache::recordsFromURL const):
(WebKit::CacheStorage::Cache::put):
(WebKit::CacheStorage::Cache::writeRecordToDisk):
(WebKit::CacheStorage::Cache::removeRecordFromDisk):

  • NetworkProcess/cache/CacheStorageEngineCache.h:
Location:
trunk/Source
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r221941 r221942  
     12017-09-12  Youenn Fablet  <youenn@apple.com>
     2
     3        Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
     4        https://bugs.webkit.org/show_bug.cgi?id=176579
     5
     6        Reviewed by Alex Christensen.
     7
     8        No change of behavior.
     9
     10        Introducing another version of queryCacheMatch used for the NetworkProcess implementation of the Cache.
     11        Exporting the copy of a response body to be used also there.
     12
     13        * Modules/cache/DOMCacheEngine.cpp:
     14        (WebCore::DOMCacheEngine::matchURLs):
     15        (WebCore::DOMCacheEngine::queryCacheMatch):
     16        (WebCore::DOMCacheEngine::copyResponseBody):
     17        * Modules/cache/DOMCacheEngine.h:
     18
    1192017-09-12  Antti Koivisto  <antti@apple.com>
    220
  • trunk/Source/WebCore/Modules/cache/DOMCacheEngine.cpp

    r221478 r221942  
    5050}
    5151
    52 bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse& cachedResponse, const CacheQueryOptions& options)
     52static inline bool matchURLs(const ResourceRequest& request, const URL& cachedURL, const CacheQueryOptions& options)
    5353{
    5454    ASSERT(options.ignoreMethod || request.httpMethod() == "GET");
    5555
    5656    URL requestURL = request.url();
    57     URL cachedRequestURL = cachedRequest.url();
     57    URL cachedRequestURL = cachedURL;
    5858
    5959    if (options.ignoreSearch) {
    60         requestURL.setQuery({ });
    61         cachedRequestURL.setQuery({ });
     60        if (requestURL.hasQuery())
     61            requestURL.setQuery({ });
     62        if (cachedRequestURL.hasQuery())
     63            cachedRequestURL.setQuery({ });
    6264    }
    63     if (!equalIgnoringFragmentIdentifier(requestURL, cachedRequestURL))
     65    return equalIgnoringFragmentIdentifier(requestURL, cachedRequestURL);
     66}
     67
     68bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse& cachedResponse, const CacheQueryOptions& options)
     69{
     70    if (!matchURLs(request, cachedRequest.url(), options))
    6471        return false;
    6572
     
    7178        return true;
    7279
    73     // FIXME: This is inefficient, we should be able to split and trim whitespaces at the same time.
    74     Vector<String> varyHeaderNames;
    75     varyValue.split(',', false, varyHeaderNames);
    76     for (auto& name : varyHeaderNames) {
    77         if (stripLeadingAndTrailingHTTPSpaces(name) == "*")
    78             return false;
    79         if (cachedRequest.httpHeaderField(name) != request.httpHeaderField(name))
     80    bool isVarying = false;
     81    varyValue.split(',', false, [&](StringView view) {
     82        if (isVarying)
     83            return;
     84        auto nameView = stripLeadingAndTrailingHTTPSpaces(view);
     85        if (nameView == "*") {
     86            isVarying = true;
     87            return;
     88        }
     89        auto name = nameView.toString();
     90        isVarying = cachedRequest.httpHeaderField(name) != request.httpHeaderField(name);
     91    });
     92
     93    return !isVarying;
     94}
     95
     96bool queryCacheMatch(const ResourceRequest& request, const URL& url, bool hasVaryStar, const HashMap<String, String>& varyHeaders, const CacheQueryOptions& options)
     97{
     98    if (!matchURLs(request, url, options))
     99        return false;
     100
     101    if (options.ignoreVary)
     102        return true;
     103
     104    if (hasVaryStar)
     105        return false;
     106
     107    for (const auto& pair : varyHeaders) {
     108        if (pair.value != request.httpHeaderField(pair.key))
    80109            return false;
    81110    }
     
    94123}
    95124
    96 static inline ResponseBody copyResponseBody(const DOMCacheEngine::ResponseBody& body)
     125ResponseBody copyResponseBody(const ResponseBody& body)
    97126{
    98127    return WTF::switchOn(body, [](const Ref<FormData>& formData) {
  • trunk/Source/WebCore/Modules/cache/DOMCacheEngine.h

    r221506 r221942  
    4949
    5050WEBCORE_EXPORT bool queryCacheMatch(const ResourceRequest& request, const ResourceRequest& cachedRequest, const ResourceResponse&, const CacheQueryOptions&);
     51WEBCORE_EXPORT bool queryCacheMatch(const ResourceRequest& request, const URL& url, bool hasVaryStar, const HashMap<String, String>& varyHeaders, const CacheQueryOptions&);
    5152
    5253using ResponseBody = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>;
    5354ResponseBody isolatedResponseBody(const ResponseBody&);
     55WEBCORE_EXPORT ResponseBody copyResponseBody(const ResponseBody&);
    5456
    5557struct Record {
  • trunk/Source/WebKit/ChangeLog

    r221934 r221942  
     12017-09-12  Youenn Fablet  <youenn@apple.com>
     2
     3        Introduce a RecordData for Cache to efficiently check whether it matches a corresponding request or not
     4        https://bugs.webkit.org/show_bug.cgi?id=176579
     5
     6        Reviewed by Alex Christensen.
     7
     8        Introducing RecordData that splits its stored data in mandatory data,
     9        used to check a record with a request and optional data that is
     10        necessary to build a CacheStorageEngine::Record used by WebProcess.
     11
     12        The mandatory data contains the URL, Vary header information and identifiers.
     13        Adding routines to go from a Record to RecordData and vice versa.
     14        Storing in CacheStorage::Cache RecordData instead of Record.
     15
     16        * NetworkProcess/cache/CacheStorageEngineCache.cpp:
     17        (WebKit::CacheStorage::queryCache):
     18        (WebKit::CacheStorage::updateVaryInformation):
     19        (WebKit::CacheStorage::toRecord):
     20        (WebKit::CacheStorage::toRecordData):
     21        (WebKit::CacheStorage::Cache::retrieveRecords const):
     22        (WebKit::CacheStorage::Cache::addRecord):
     23        (WebKit::CacheStorage::Cache::recordsFromURL):
     24        (WebKit::CacheStorage::Cache::recordsFromURL const):
     25        (WebKit::CacheStorage::Cache::put):
     26        (WebKit::CacheStorage::Cache::writeRecordToDisk):
     27        (WebKit::CacheStorage::Cache::removeRecordFromDisk):
     28        * NetworkProcess/cache/CacheStorageEngineCache.h:
     29
    1302017-09-12  Dan Bernstein  <mitz@apple.com>
    231
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.cpp

    r221710 r221942  
    3232#include "NetworkProcess.h"
    3333#include <WebCore/CacheQueryOptions.h>
     34#include <WebCore/HTTPParsers.h>
    3435#include <pal/SessionID.h>
    3536#include <wtf/CurrentTime.h>
     
    5152namespace CacheStorage {
    5253
    53 static inline Vector<uint64_t> queryCache(const Vector<Record>* records, const ResourceRequest& request, const CacheQueryOptions& options)
     54static inline Vector<uint64_t> queryCache(const Vector<RecordData>* records, const ResourceRequest& request, const CacheQueryOptions& options)
    5455{
    5556    if (!records)
     
    6162    Vector<uint64_t> results;
    6263    for (const auto& record : *records) {
    63         if (WebCore::DOMCacheEngine::queryCacheMatch(request, record.request, record.response, options))
     64        if (WebCore::DOMCacheEngine::queryCacheMatch(request, record.url, record.hasVaryStar, record.varyHeaders, options))
    6465            results.append(record.identifier);
    6566    }
    6667    return results;
     68}
     69
     70static inline void updateVaryInformation(RecordData& recordData)
     71{
     72    auto varyValue = recordData.data->response.httpHeaderField(WebCore::HTTPHeaderName::Vary);
     73    if (varyValue.isNull()) {
     74        recordData.hasVaryStar = false;
     75        recordData.varyHeaders = { };
     76        return;
     77    }
     78
     79    varyValue.split(',', false, [&](StringView view) {
     80        if (!recordData.hasVaryStar && stripLeadingAndTrailingHTTPSpaces(view) == "*")
     81            recordData.hasVaryStar = true;
     82        String headerName = view.toString();
     83        recordData.varyHeaders.add(headerName, recordData.data->request.httpHeaderField(headerName));
     84    });
     85
     86    if (recordData.hasVaryStar)
     87        recordData.varyHeaders = { };
     88}
     89
     90static inline Record toRecord(const RecordData& record)
     91{
     92    return { record.identifier, record.updateResponseCounter, record.data->requestHeadersGuard, record.data->request, record.data->options, record.data->referrer, record.data->responseHeadersGuard, record.data->response, copyResponseBody(record.data->responseBody) };
     93}
     94
     95static inline RecordData toRecordData(Record&& record)
     96{
     97    auto url = record.request.url();
     98    RecordData::Data data = { record.requestHeadersGuard, WTFMove(record.request), WTFMove(record.options), WTFMove(record.referrer), WTFMove(record.responseHeadersGuard), WTFMove(record.response), WTFMove(record.responseBody) };
     99    RecordData recordData = { { }, monotonicallyIncreasingTimeMS(), record.identifier, 0, url, false, { }, WTFMove(data) };
     100
     101    updateVaryInformation(recordData);
     102
     103    return recordData;
    67104}
    68105
     
    132169        for (auto& records : m_records.values()) {
    133170            for (auto& record : records)
    134                 result.append(record.copy());
     171                result.append(toRecord(record));
    135172        }
    136173        std::sort(result.begin(), result.end(), [](const auto& a, const auto& b) {
     
    147184    result.reserveInitialCapacity(records->size());
    148185    for (auto& record : *records)
    149         result.uncheckedAppend(record.copy());
     186        result.append(toRecord(record));
    150187    return result;
    151188}
     
    160197}
    161198
    162 Record& Cache::addNewURLRecord(Record&& record)
    163 {
    164     auto key = computeKeyURL(record.request.url());
    165     ASSERT(!m_records.contains(key));
    166 
    167     Vector<Record> newRecords;
    168     newRecords.reserveInitialCapacity(1);
    169     newRecords.uncheckedAppend(WTFMove(record));
    170     return m_records.set(key, WTFMove(newRecords)).iterator->value.last();
    171 }
    172 
    173 Vector<Record>* Cache::recordsFromURL(const URL& url)
     199RecordData& Cache::addRecord(Vector<RecordData>* records, Record&& record)
     200{
     201    if (!records) {
     202        auto key = computeKeyURL(record.request.url());
     203        ASSERT(!m_records.contains(key));
     204        records = &m_records.set(key, Vector<RecordData> { }).iterator->value;
     205    }
     206    records->append(toRecordData(WTFMove(record)));
     207    return records->last();
     208}
     209
     210Vector<RecordData>* Cache::recordsFromURL(const URL& url)
    174211{
    175212    auto iterator = m_records.find(computeKeyURL(url));
     
    179216}
    180217
    181 const Vector<Record>* Cache::recordsFromURL(const URL& url) const
     218const Vector<RecordData>* Cache::recordsFromURL(const URL& url) const
    182219{
    183220    auto iterator = m_records.find(computeKeyURL(url));
     
    202239
    203240            shouldWriteRecordList = true;
    204             if (!sameURLRecords) {
    205                 auto& recordToWrite = addNewURLRecord(WTFMove(record));
    206                 writeRecordToDisk(recordToWrite);
    207             } else {
    208                 sameURLRecords->append(WTFMove(record));
    209                 writeRecordToDisk(sameURLRecords->last());
    210             }
     241            auto& recordToWrite = addRecord(sameURLRecords, WTFMove(record));
     242            writeRecordToDisk(recordToWrite);
    211243        } else {
    212244            auto identifier = matchingRecords[0];
     
    216248                auto& existingRecord = (*sameURLRecords)[position];
    217249                recordIdentifiers.uncheckedAppend(identifier);
    218                 existingRecord.responseHeadersGuard = record.responseHeadersGuard;
    219                 existingRecord.response = WTFMove(record.response);
    220                 existingRecord.responseBody = WTFMove(record.responseBody);
    221250                ++existingRecord.updateResponseCounter;
    222251
     252                // FIXME: Handle the case where data is null.
     253                ASSERT(existingRecord.data);
     254                existingRecord.data->responseHeadersGuard = record.responseHeadersGuard;
     255                existingRecord.data->response = WTFMove(record.response);
     256                existingRecord.data->responseBody = WTFMove(record.responseBody);
     257                updateVaryInformation(existingRecord);
    223258                writeRecordToDisk(existingRecord);
    224259            }
     
    276311}
    277312
    278 void Cache::writeRecordToDisk(Record& record)
     313void Cache::writeRecordToDisk(RecordData&)
    279314{
    280315    // FIXME: Implement this.
    281316}
    282317
    283 void Cache::removeRecordFromDisk(Record& record)
     318void Cache::removeRecordFromDisk(RecordData&)
    284319{
    285320    // FIXME: Implement this.
  • trunk/Source/WebKit/NetworkProcess/cache/CacheStorageEngineCache.h

    r221710 r221942  
    2626#pragma once
    2727
     28#include "NetworkCacheKey.h"
    2829#include <WebCore/DOMCacheEngine.h>
    2930#include <wtf/Vector.h>
     
    3536
    3637class Caches;
     38
     39struct RecordData {
     40    NetworkCache::Key key;
     41    double insertionTime { 0 };
     42
     43    uint64_t identifier { 0 };
     44    uint64_t updateResponseCounter { 0 };
     45
     46    WebCore::URL url;
     47    bool hasVaryStar { false };
     48    HashMap<String, String> varyHeaders;
     49
     50    struct Data {
     51        WebCore::FetchHeaders::Guard requestHeadersGuard;
     52        WebCore::ResourceRequest request;
     53        WebCore::FetchOptions options;
     54        String referrer;
     55
     56        WebCore::FetchHeaders::Guard responseHeadersGuard;
     57        WebCore::ResourceResponse response;
     58        WebCore::DOMCacheEngine::ResponseBody responseBody;
     59    };
     60
     61    std::optional<Data> data;
     62};
    3763
    3864class Cache {
     
    5783 
    5884private:
    59     Vector<WebCore::DOMCacheEngine::Record>* recordsFromURL(const WebCore::URL&);
    60     const Vector<WebCore::DOMCacheEngine::Record>* recordsFromURL(const WebCore::URL&) const;
    61     WebCore::DOMCacheEngine::Record& addNewURLRecord(WebCore::DOMCacheEngine::Record&&);
     85    Vector<RecordData>* recordsFromURL(const WebCore::URL&);
     86    const Vector<RecordData>* recordsFromURL(const WebCore::URL&) const;
     87    RecordData& addRecord(Vector<RecordData>*, WebCore::DOMCacheEngine::Record&&);
    6288
    6389    void finishOpening(WebCore::DOMCacheEngine::CompletionCallback&&, std::optional<WebCore::DOMCacheEngine::Error>&&);
     
    6591    void readRecordsList(WebCore::DOMCacheEngine::CompletionCallback&&);
    6692    void writeRecordsList(WebCore::DOMCacheEngine::CompletionCallback&&);
    67     void writeRecordToDisk(WebCore::DOMCacheEngine::Record&);
    68     void removeRecordFromDisk(WebCore::DOMCacheEngine::Record&);
     93    void writeRecordToDisk(RecordData&);
     94    void removeRecordFromDisk(RecordData&);
    6995
    7096    Caches& m_caches;
     
    7298    uint64_t m_identifier { 0 };
    7399    String m_name;
    74     HashMap<String, Vector<WebCore::DOMCacheEngine::Record>> m_records;
     100    HashMap<String, Vector<RecordData>> m_records;
    75101    uint64_t m_nextRecordIdentifier { 0 };
    76102    Vector<WebCore::DOMCacheEngine::CompletionCallback> m_pendingOpeningCallbacks;
Note: See TracChangeset for help on using the changeset viewer.