Changeset 180894 in webkit


Ignore:
Timestamp:
Mar 2, 2015 1:51:13 PM (9 years ago)
Author:
Antti Koivisto
Message:

Add way to dump cache meta data to file
https://bugs.webkit.org/show_bug.cgi?id=142183

Reviewed by Andreas Kling.

Source/JavaScriptCore:

Export appendQuotedJSONStringToBuilder.

  • bytecompiler/NodesCodegen.cpp:

(JSC::ObjectPatternNode::toString):

  • runtime/JSONObject.cpp:

(JSC::appendQuotedJSONStringToBuilder):
(JSC::Stringifier::appendQuotedString):
(JSC::escapeStringToBuilder): Deleted.

  • runtime/JSONObject.h:

Source/WebKit2:

Dump goes to WebKitCache/dump.json. On OSX it can be triggered with

notifyutil -p com.apple.WebKit.Cache.dump

  • NetworkProcess/cache/NetworkCache.cpp:

(WebKit::NetworkCache::initialize):
(WebKit::NetworkCache::dumpFilePath):
(WebKit::entryAsJSON):
(WebKit::NetworkCache::dumpContentsToFile):
(WebKit::NetworkCache::clear):

Also clear any dumps.

  • NetworkProcess/cache/NetworkCache.h:
  • NetworkProcess/cache/NetworkCacheStorage.h:

(WebKit::NetworkCacheStorage::baseDirectoryPath):

  • NetworkProcess/cache/NetworkCacheStorageCocoa.mm:

(WebKit::fileNameForKey):
(WebKit::filePathForKey):
(WebKit::openFile):
(WebKit::openFileForKey):
(WebKit::decodeEntryHeader):

Separate header decoding.

(WebKit::decodeEntry):
(WebKit::NetworkCacheStorage::traverse):

Add asynchronous cache traversal inteface.

Location:
trunk/Source
Files:
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r180891 r180894  
     12015-03-02  Antti Koivisto  <antti@apple.com>
     2
     3        Add way to dump cache meta data to file
     4        https://bugs.webkit.org/show_bug.cgi?id=142183
     5
     6        Reviewed by Andreas Kling.
     7
     8        Export appendQuotedJSONStringToBuilder.
     9
     10        * bytecompiler/NodesCodegen.cpp:
     11        (JSC::ObjectPatternNode::toString):
     12        * runtime/JSONObject.cpp:
     13        (JSC::appendQuotedJSONStringToBuilder):
     14        (JSC::Stringifier::appendQuotedString):
     15        (JSC::escapeStringToBuilder): Deleted.
     16        * runtime/JSONObject.h:
     17
    1182015-03-02  Joseph Pecoraro  <pecoraro@apple.com>
    219
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r180875 r180894  
    29282928    builder.append('{');
    29292929    for (size_t i = 0; i < m_targetPatterns.size(); i++) {
    2930         if (m_targetPatterns[i].wasString) {
    2931             builder.append('"');
    2932             escapeStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
    2933             builder.append('"');
    2934         } else
     2930        if (m_targetPatterns[i].wasString)
     2931            appendQuotedJSONStringToBuilder(builder, m_targetPatterns[i].propertyName.string());
     2932        else
    29352933            builder.append(m_targetPatterns[i].propertyName.string());
    29362934        builder.append(':');
  • trunk/Source/JavaScriptCore/runtime/JSONObject.cpp

    r179429 r180894  
    305305}
    306306
    307 void escapeStringToBuilder(StringBuilder& builder, const String& message)
    308 {
     307void appendQuotedJSONStringToBuilder(StringBuilder& builder, const String& message)
     308{
     309    builder.append('"');
     310
    309311    if (message.is8Bit())
    310312        appendStringToStringBuilder(builder, message.characters8(), message.length());
    311313    else
    312314        appendStringToStringBuilder(builder, message.characters16(), message.length());
     315
     316    builder.append('"');
    313317}
    314318
    315319void Stringifier::appendQuotedString(StringBuilder& builder, const String& value)
    316320{
    317     int length = value.length();
    318 
    319     builder.append('"');
    320 
    321     if (value.is8Bit())
    322         appendStringToStringBuilder<LChar>(builder, value.characters8(), length);
    323     else
    324         appendStringToStringBuilder<UChar>(builder, value.characters16(), length);
    325 
    326     builder.append('"');
     321    appendQuotedJSONStringToBuilder(builder, value);
    327322}
    328323
  • trunk/Source/JavaScriptCore/runtime/JSONObject.h

    r173269 r180894  
    6363JS_EXPORT_PRIVATE String JSONStringify(ExecState*, JSValue, unsigned indent);
    6464
    65 void escapeStringToBuilder(StringBuilder&, const String&);
     65JS_EXPORT_PRIVATE void appendQuotedJSONStringToBuilder(StringBuilder&, const String&);
     66
    6667   
    6768} // namespace JSC
  • trunk/Source/WebKit2/ChangeLog

    r180892 r180894  
     12015-03-02  Antti Koivisto  <antti@apple.com>
     2
     3        Add way to dump cache meta data to file
     4        https://bugs.webkit.org/show_bug.cgi?id=142183
     5
     6        Reviewed by Andreas Kling.
     7
     8        Dump goes to WebKitCache/dump.json. On OSX it can be triggered with
     9
     10        notifyutil -p com.apple.WebKit.Cache.dump
     11
     12        * NetworkProcess/cache/NetworkCache.cpp:
     13        (WebKit::NetworkCache::initialize):
     14        (WebKit::NetworkCache::dumpFilePath):
     15        (WebKit::entryAsJSON):
     16        (WebKit::NetworkCache::dumpContentsToFile):
     17        (WebKit::NetworkCache::clear):
     18
     19            Also clear any dumps.
     20
     21        * NetworkProcess/cache/NetworkCache.h:
     22        * NetworkProcess/cache/NetworkCacheStorage.h:
     23        (WebKit::NetworkCacheStorage::baseDirectoryPath):
     24        * NetworkProcess/cache/NetworkCacheStorageCocoa.mm:
     25        (WebKit::fileNameForKey):
     26        (WebKit::filePathForKey):
     27        (WebKit::openFile):
     28        (WebKit::openFileForKey):
     29        (WebKit::decodeEntryHeader):
     30
     31            Separate header decoding.
     32
     33        (WebKit::decodeEntry):
     34        (WebKit::NetworkCacheStorage::traverse):
     35
     36            Add asynchronous cache traversal inteface.
     37
    1382015-03-02  Anders Carlsson  <andersca@apple.com>
    239
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp

    r180456 r180894  
    3535#include "NetworkResourceLoader.h"
    3636#include "WebCoreArgumentCoders.h"
     37#include <JavaScriptCore/JSONObject.h>
    3738#include <WebCore/CacheValidation.h>
     39#include <WebCore/FileSystem.h>
    3840#include <WebCore/HTTPHeaderNames.h>
    3941#include <WebCore/ResourceResponse.h>
     
    4345#include <wtf/text/StringBuilder.h>
    4446
     47#if PLATFORM(COCOA)
     48#include <notify.h>
     49#endif
     50
    4551namespace WebKit {
    4652
     
    5763    if (enableEfficacyLogging)
    5864        m_statistics = NetworkCacheStatistics::open(cachePath);
     65
     66#if PLATFORM(COCOA)
     67    // Triggers with "notifyutil -p com.apple.WebKit.Cache.dump".
     68    if (m_storage) {
     69        int token;
     70        notify_register_dispatch("com.apple.WebKit.Cache.dump", &token, dispatch_get_main_queue(), ^(int) {
     71            dumpContentsToFile();
     72        });
     73    }
     74#endif
    5975
    6076    LOG(NetworkCache, "(NetworkProcess) opened cache storage, success %d", !!m_storage);
     
    355371}
    356372
     373String NetworkCache::dumpFilePath() const
     374{
     375    return WebCore::pathByAppendingComponent(m_storage->baseDirectoryPath(), "dump.json");
     376}
     377
     378static bool entryAsJSON(StringBuilder& json, const NetworkCacheKey& key, const NetworkCacheStorage::Entry& entry)
     379{
     380    NetworkCacheDecoder decoder(entry.header.data(), entry.header.size());
     381    WebCore::ResourceResponse cachedResponse;
     382    if (!decoder.decode(cachedResponse))
     383        return false;
     384    json.append("{\n");
     385    json.append("\"hash\": ");
     386    JSC::appendQuotedJSONStringToBuilder(json, key.hashAsString());
     387    json.append(",\n");
     388    json.append("\"partition\": ");
     389    JSC::appendQuotedJSONStringToBuilder(json, key.partition());
     390    json.append(",\n");
     391    json.append("\"timestamp\": ");
     392    json.appendNumber(entry.timeStamp.count());
     393    json.append(",\n");
     394    json.append("\"URL\": ");
     395    JSC::appendQuotedJSONStringToBuilder(json, cachedResponse.url().string());
     396    json.append(",\n");
     397    json.append("\"headers\": {\n");
     398    bool firstHeader = true;
     399    for (auto& header : cachedResponse.httpHeaderFields()) {
     400        if (!firstHeader)
     401            json.append(",\n");
     402        firstHeader = false;
     403        json.append("    ");
     404        JSC::appendQuotedJSONStringToBuilder(json, header.key);
     405        json.append(": ");
     406        JSC::appendQuotedJSONStringToBuilder(json, header.value);
     407    }
     408    json.append("\n}\n");
     409    json.append("}");
     410    return true;
     411}
     412
     413void NetworkCache::dumpContentsToFile()
     414{
     415    if (!m_storage)
     416        return;
     417    auto dumpFileHandle = WebCore::openFile(dumpFilePath(), WebCore::OpenForWrite);
     418    if (!dumpFileHandle)
     419        return;
     420    WebCore::writeToFile(dumpFileHandle, "[\n", 2);
     421    m_storage->traverse([dumpFileHandle](const NetworkCacheKey& key, const NetworkCacheStorage::Entry* entry) {
     422        if (!entry) {
     423            WebCore::writeToFile(dumpFileHandle, "{}\n]\n", 5);
     424            auto handle = dumpFileHandle;
     425            WebCore::closeFile(handle);
     426        }
     427        StringBuilder json;
     428        if (!entryAsJSON(json, key, *entry))
     429            return;
     430        json.append(",\n");
     431        auto writeData = json.toString().utf8();
     432        WebCore::writeToFile(dumpFileHandle, writeData.data(), writeData.length());
     433    });
     434}
     435
    357436void NetworkCache::clear()
    358437{
    359438    LOG(NetworkCache, "(NetworkProcess) clearing cache");
    360     if (m_storage)
     439    if (m_storage) {
    361440        m_storage->clear();
     441
     442        auto queue = WorkQueue::create("com.apple.WebKit.Cache.delete");
     443        StringCapture dumpFilePathCapture(dumpFilePath());
     444        queue->dispatch([dumpFilePathCapture] {
     445            WebCore::deleteFile(dumpFilePathCapture.string());
     446        });
     447    }
    362448    if (m_statistics)
    363449        m_statistics->clear();
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h

    r180456 r180894  
    102102    void clear();
    103103
     104    void dumpContentsToFile();
     105
    104106    String storagePath() const;
    105107
     
    107109    NetworkCache() = default;
    108110    ~NetworkCache() = delete;
     111
     112    String dumpFilePath() const;
    109113
    110114    std::unique_ptr<NetworkCacheStorage> m_storage;
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h

    r180008 r180894  
    149149    void update(const NetworkCacheKey&, const Entry& updateEntry, const Entry& existingEntry, StoreCompletionHandler&&);
    150150
     151    // Null entry signals end.
     152    void traverse(std::function<void (const NetworkCacheKey&, const Entry*)>&&);
     153
    151154    void setMaximumSize(size_t);
    152155    void clear();
     
    154157    static const unsigned version = 2;
    155158
     159    const String& baseDirectoryPath() const { return m_baseDirectoryPath; }
    156160    const String& directoryPath() const { return m_directoryPath; }
    157161
  • trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm

    r180869 r180894  
    141141}
    142142
     143static String fileNameForKey(const NetworkCacheKey& key)
     144{
     145    return key.hashAsString();
     146}
     147
    143148static String filePathForKey(const NetworkCacheKey& key, const String& cachePath)
    144149{
    145     return WebCore::pathByAppendingComponent(directoryPathForKey(key, cachePath), key.hashAsString());
     150    return WebCore::pathByAppendingComponent(directoryPathForKey(key, cachePath), fileNameForKey(key));
    146151}
    147152
    148153enum class FileOpenType { Read, Write, Create };
    149 static DispatchPtr<dispatch_io_t> openFileForKey(const NetworkCacheKey& key, FileOpenType type, const String& cachePath, int& fd)
     154static DispatchPtr<dispatch_io_t> openFile(const String& fileName, const String& directoryPath, FileOpenType type, int& fd)
    150155{
    151156    int oflag;
     
    156161        oflag = O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK;
    157162        mode = S_IRUSR | S_IWUSR;
    158         WebCore::makeAllDirectories(directoryPathForKey(key, cachePath));
     163        WebCore::makeAllDirectories(directoryPath);
    159164        break;
    160165    case FileOpenType::Write:
     
    167172    }
    168173
    169     CString path = WebCore::fileSystemRepresentation(filePathForKey(key, cachePath));
     174    CString path = WebCore::fileSystemRepresentation(WebCore::pathByAppendingComponent(directoryPath, fileName));
    170175    fd = ::open(path.data(), oflag, mode);
    171176
     
    182187
    183188    return channel;
     189}
     190
     191static DispatchPtr<dispatch_io_t> openFileForKey(const NetworkCacheKey& key, FileOpenType type, const String& cachePath, int& fd)
     192{
     193    return openFile(fileNameForKey(key), directoryPathForKey(key, cachePath), type, fd);
    184194}
    185195
     
    251261}
    252262
     263static bool decodeEntryHeader(dispatch_data_t fileData, EntryMetaData& metaData, NetworkCacheStorage::Data& data)
     264{
     265    if (!decodeEntryMetaData(metaData, fileData))
     266        return false;
     267    if (metaData.cacheStorageVersion != NetworkCacheStorage::version)
     268        return false;
     269    if (metaData.headerOffset + metaData.headerSize > metaData.bodyOffset)
     270        return false;
     271
     272    auto headerData = adoptDispatch(dispatch_data_create_subrange(fileData, metaData.headerOffset, metaData.headerSize));
     273    if (metaData.headerChecksum != hashData(headerData.get())) {
     274        LOG(NetworkCacheStorage, "(NetworkProcess) header checksum mismatch");
     275        return false;
     276    }
     277    data =  NetworkCacheStorage::Data { headerData };
     278    return true;
     279}
     280
    253281static std::unique_ptr<NetworkCacheStorage::Entry> decodeEntry(dispatch_data_t fileData, int fd, const NetworkCacheKey& key)
    254282{
    255283    EntryMetaData metaData;
    256     if (!decodeEntryMetaData(metaData, fileData))
     284    NetworkCacheStorage::Data headerData;
     285    if (!decodeEntryHeader(fileData, metaData, headerData))
    257286        return nullptr;
    258287
    259     if (metaData.cacheStorageVersion != NetworkCacheStorage::version)
    260         return nullptr;
    261288    if (metaData.key != key)
    262         return nullptr;
    263     if (metaData.headerOffset + metaData.headerSize > metaData.bodyOffset)
    264289        return nullptr;
    265290    if (metaData.bodyOffset + metaData.bodySize != dispatch_data_get_size(fileData))
    266291        return nullptr;
    267 
    268     auto headerData = adoptDispatch(dispatch_data_create_subrange(fileData, metaData.headerOffset, metaData.headerSize));
    269     if (metaData.headerChecksum != hashData(headerData.get())) {
    270         LOG(NetworkCacheStorage, "(NetworkProcess) header checksum mismatch");
    271         return nullptr;
    272     }
    273292
    274293    auto bodyData = mapFile(fd, metaData.bodyOffset, metaData.bodySize);
     
    285304    return std::make_unique<NetworkCacheStorage::Entry>(NetworkCacheStorage::Entry {
    286305        metaData.timeStamp,
    287         NetworkCacheStorage::Data { headerData },
     306        headerData,
    288307        NetworkCacheStorage::Data { bodyData, NetworkCacheStorage::Data::Backing::Map }
    289308    });
     
    472491}
    473492
     493void NetworkCacheStorage::traverse(std::function<void (const NetworkCacheKey&, const Entry*)>&& traverseHandler)
     494{
     495    StringCapture cachePathCapture(m_directoryPath);
     496    dispatch_async(m_ioQueue.get(), [this, cachePathCapture, traverseHandler] {
     497        String cachePath = cachePathCapture.string();
     498        auto semaphore = adoptDispatch(dispatch_semaphore_create(0));
     499        traverseCacheFiles(cachePath, [this, &semaphore, &traverseHandler](const String& fileName, const String& partitionPath) {
     500            int fd;
     501            auto channel = openFile(fileName, partitionPath, FileOpenType::Read, fd);
     502            const size_t headerReadSize = 16 << 10;
     503            dispatch_io_read(channel.get(), 0, headerReadSize, dispatch_get_main_queue(), [this, fd, &semaphore, &traverseHandler](bool done, dispatch_data_t fileData, int) {
     504                EntryMetaData metaData;
     505                NetworkCacheStorage::Data headerData;
     506                if (decodeEntryHeader(fileData, metaData, headerData)) {
     507                    Entry entry { metaData.timeStamp, headerData, Data() };
     508                    traverseHandler(metaData.key, &entry);
     509                }
     510                if (done)
     511                    dispatch_semaphore_signal(semaphore.get());
     512            });
     513            dispatch_semaphore_wait(semaphore.get(), DISPATCH_TIME_FOREVER);
     514        });
     515        dispatch_async(dispatch_get_main_queue(), [this, traverseHandler] {
     516            traverseHandler({ }, nullptr);
     517        });
     518    });
     519}
     520
    474521void NetworkCacheStorage::dispatchPendingWriteOperations()
    475522{
Note: See TracChangeset for help on using the changeset viewer.