<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[179804] trunk/Source</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/179804">179804</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-02-08 14:06:06 -0800 (Sun, 08 Feb 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WK2] Add logging to validate the network cache efficacy (Part 1)
https://bugs.webkit.org/show_bug.cgi?id=141269
&lt;rdar://problem/19632080&gt;

Reviewed by Antti Koivisto.

Source/WebCore:

Export an extra symbol.

* WebCore.exp.in:

Source/WebKit2:

Add console logging to validate the network cache efficacy. This will
tell us if how the network cache satisties requests, in particular:
- Request cannot be handled by the cache
- Entry was not in the cache but is no longer there (pruned)
- Entry is in the cache but is not usable
- Entry is in the cache and is used.

This patch introduces a SQLite-based network cache statistics storage
that is used to store requests we have seen before, and query if we
have seen a request before. The storage is lightweight as it only
stores hashes in the database, in a background thread.

The statistics cache is initially bootstapped from the network disk
cache so that we have data initially and get as accurate statistics
as possible from the start.

To maintain an acceptable level of performance, we have a hard limit
on the number of unique requests that are retained set to 100000.

Diagnostic logging for this will be added in a follow-up patch.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreWebCoreexpin">trunk/Source/WebCore/WebCore.exp.in</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageCocoamm">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkProcessCocoamm">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2SharedNetworkNetworkProcessCreationParameterscpp">trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedNetworkNetworkProcessCreationParametersh">trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessCocoaWebProcessPoolCocoamm">trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheFileSystemPosixh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsCocoamm">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebCore/ChangeLog        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2015-02-08  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Add logging to validate the network cache efficacy (Part 1)
+        https://bugs.webkit.org/show_bug.cgi?id=141269
+        &lt;rdar://problem/19632080&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Export an extra symbol.
+
+        * WebCore.exp.in:
+
</ins><span class="cx"> 2015-02-07  Chris Fleizach  &lt;cfleizach@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         AX: The input element with type=&quot;search&quot; has no default focus outline
</span></span></pre></div>
<a id="trunkSourceWebCoreWebCoreexpin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/WebCore.exp.in (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/WebCore.exp.in        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebCore/WebCore.exp.in        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -2262,6 +2262,7 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> #if !ASSERT_DISABLED
</span><ins>+__ZN7WebCore21SQLiteDatabaseTracker24hasTransactionInProgressEv
</ins><span class="cx"> __ZN7WebCore27NoExceptionAssertionCheckerC1EPKci
</span><span class="cx"> __ZN7WebCore27NoExceptionAssertionCheckerD1Ev
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/ChangeLog        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-02-08  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Add logging to validate the network cache efficacy (Part 1)
+        https://bugs.webkit.org/show_bug.cgi?id=141269
+        &lt;rdar://problem/19632080&gt;
+
+        Reviewed by Antti Koivisto.
+
+        Add console logging to validate the network cache efficacy. This will
+        tell us if how the network cache satisties requests, in particular:
+        - Request cannot be handled by the cache
+        - Entry was not in the cache but is no longer there (pruned)
+        - Entry is in the cache but is not usable
+        - Entry is in the cache and is used.
+
+        This patch introduces a SQLite-based network cache statistics storage
+        that is used to store requests we have seen before, and query if we
+        have seen a request before. The storage is lightweight as it only
+        stores hashes in the database, in a background thread.
+
+        The statistics cache is initially bootstapped from the network disk
+        cache so that we have data initially and get as accurate statistics
+        as possible from the start.
+
+        To maintain an acceptable level of performance, we have a hard limit
+        on the number of unique requests that are retained set to 100000.
+
+        Diagnostic logging for this will be added in a follow-up patch.
+
</ins><span class="cx"> 2015-02-07  Chris Dumez  &lt;cdumez@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Add Vector::removeFirstMatching() / removeAllMatching() methods taking lambda functions
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;NetworkCacheCoders.h&quot;
</span><ins>+#include &quot;NetworkCacheStatistics.h&quot;
</ins><span class="cx"> #include &quot;NetworkCacheStorage.h&quot;
</span><span class="cx"> #include &quot;NetworkResourceLoader.h&quot;
</span><span class="cx"> #include &quot;WebCoreArgumentCoders.h&quot;
</span><span class="lines">@@ -49,10 +50,13 @@
</span><span class="cx">     return instance;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-bool NetworkCache::initialize(const String&amp; cachePath)
</del><ins>+bool NetworkCache::initialize(const String&amp; cachePath, bool enableEfficacyLogging)
</ins><span class="cx"> {
</span><span class="cx">     m_storage = NetworkCacheStorage::open(cachePath);
</span><span class="cx"> 
</span><ins>+    if (enableEfficacyLogging)
+        m_statistics = NetworkCacheStatistics::open(cachePath);
+
</ins><span class="cx">     LOG(NetworkCache, &quot;(NetworkProcess) opened cache storage, success %d&quot;, !!m_storage);
</span><span class="cx">     return !!m_storage;
</span><span class="cx"> }
</span><span class="lines">@@ -220,23 +224,33 @@
</span><span class="cx"> 
</span><span class="cx">     LOG(NetworkCache, &quot;(NetworkProcess) retrieving %s priority %u&quot;, originalRequest.url().string().ascii().data(), originalRequest.priority());
</span><span class="cx"> 
</span><ins>+    NetworkCacheKey storageKey = makeCacheKey(originalRequest);
</ins><span class="cx">     if (!canRetrieve(originalRequest)) {
</span><ins>+        if (m_statistics)
+            m_statistics-&gt;recordNotUsingCacheForRequest(storageKey, originalRequest);
+
</ins><span class="cx">         completionHandler(nullptr);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     auto startTime = std::chrono::system_clock::now();
</span><del>-    NetworkCacheKey storageKey = makeCacheKey(originalRequest);
</del><span class="cx">     unsigned priority = originalRequest.priority();
</span><span class="cx"> 
</span><del>-    m_storage-&gt;retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime](std::unique_ptr&lt;NetworkCacheStorage::Entry&gt; entry) {
</del><ins>+    m_storage-&gt;retrieve(storageKey, priority, [this, originalRequest, completionHandler, startTime, storageKey](std::unique_ptr&lt;NetworkCacheStorage::Entry&gt; entry) {
</ins><span class="cx">         if (!entry) {
</span><span class="cx">             LOG(NetworkCache, &quot;(NetworkProcess) not found in storage&quot;);
</span><ins>+
+            if (m_statistics)
+                m_statistics-&gt;recordRetrievalFailure(storageKey, originalRequest);
+
</ins><span class="cx">             completionHandler(nullptr);
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx">         auto decodedEntry = decodeStorageEntry(*entry, originalRequest);
</span><span class="cx">         bool success = !!decodedEntry;
</span><ins>+        if (m_statistics)
+            m_statistics-&gt;recordRetrievedCachedEntry(storageKey, originalRequest, success);
+
</ins><span class="cx"> #if !LOG_DISABLED
</span><span class="cx">         auto elapsedMS = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::system_clock::now() - startTime).count();
</span><span class="cx"> #endif
</span><span class="lines">@@ -331,8 +345,15 @@
</span><span class="cx">     LOG(NetworkCache, &quot;(NetworkProcess) clearing cache&quot;);
</span><span class="cx">     if (m_storage)
</span><span class="cx">         m_storage-&gt;clear();
</span><ins>+    if (m_statistics)
+        m_statistics-&gt;clear();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+String NetworkCache::storagePath() const
+{
+    return m_storage ? m_storage-&gt;directoryPath() : String();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+}
+
</ins><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.h        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -41,13 +41,15 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><ins>+class NetworkCacheStatistics;
+
</ins><span class="cx"> class NetworkCache {
</span><span class="cx">     WTF_MAKE_NONCOPYABLE(NetworkCache);
</span><span class="cx">     friend class WTF::NeverDestroyed&lt;NetworkCache&gt;;
</span><span class="cx"> public:
</span><span class="cx">     static NetworkCache&amp; singleton();
</span><span class="cx"> 
</span><del>-    bool initialize(const String&amp; cachePath);
</del><ins>+    bool initialize(const String&amp; cachePath, bool enableEfficacyLogging);
</ins><span class="cx">     void setMaximumSize(size_t);
</span><span class="cx"> 
</span><span class="cx">     bool isEnabled() const { return !!m_storage; }
</span><span class="lines">@@ -75,11 +77,14 @@
</span><span class="cx"> 
</span><span class="cx">     void clear();
</span><span class="cx"> 
</span><ins>+    String storagePath() const;
+
</ins><span class="cx"> private:
</span><span class="cx">     NetworkCache() = default;
</span><span class="cx">     ~NetworkCache() = delete;
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;NetworkCacheStorage&gt; m_storage;
</span><ins>+    std::unique_ptr&lt;NetworkCacheStatistics&gt; m_statistics;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheFileSystemPosixh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h (0 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h                                (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheFileSystemPosix.h        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -0,0 +1,73 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheFileSystemPosix_h
+#define NetworkCacheFileSystemPosix_h
+
+#if ENABLE(NETWORK_CACHE)
+
+#include &quot;NetworkCacheKey.h&quot;
+#include &lt;WebCore/FileSystem.h&gt;
+#include &lt;dirent.h&gt;
+#include &lt;wtf/text/CString.h&gt;
+
+namespace WebKit {
+
+template &lt;typename Function&gt;
+static void traverseDirectory(const String&amp; path, uint8_t type, const Function&amp; function)
+{
+    DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data());
+    if (!dir)
+        return;
+    struct dirent* dp;
+    while ((dp = readdir(dir))) {
+        if (dp-&gt;d_type != type)
+            continue;
+        const char* name = dp-&gt;d_name;
+        if (!strcmp(name, &quot;.&quot;) || !strcmp(name, &quot;..&quot;))
+            continue;
+        function(String(name));
+    }
+    closedir(dir);
+}
+
+inline void traverseCacheFiles(const String&amp; cachePath, std::function&lt;void (const String&amp; fileName, const String&amp; partitionPath)&gt; function)
+{
+    traverseDirectory(cachePath, DT_DIR, [&amp;cachePath, &amp;function](const String&amp; subdirName) {
+        String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName);
+        traverseDirectory(partitionPath, DT_REG, [&amp;function, &amp;partitionPath](const String&amp; fileName) {
+            if (fileName.length() != NetworkCacheKey::hashStringLength())
+                return;
+            function(fileName, partitionPath);
+        });
+    });
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
+
+#endif // NetworkCacheFileSystemPosix_h
+
</ins></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsh"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h (0 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h                                (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.h        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -0,0 +1,82 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NetworkCacheStatistics_h
+#define NetworkCacheStatistics_h
+
+#if ENABLE(NETWORK_CACHE)
+
+#include &quot;NetworkCacheKey.h&quot;
+#include &quot;NetworkCacheStorage.h&quot;
+#include &lt;WebCore/SQLiteDatabase.h&gt;
+
+namespace WebCore {
+class ResourceRequest;
+}
+
+namespace WebKit {
+
+class NetworkCacheStatistics {
+public:
+    static std::unique_ptr&lt;NetworkCacheStatistics&gt; open(const String&amp; cachePath);
+
+    void clear();
+
+    void recordNotUsingCacheForRequest(const NetworkCacheKey&amp;, const WebCore::ResourceRequest&amp;);
+    void recordRetrievalFailure(const NetworkCacheKey&amp;, const WebCore::ResourceRequest&amp;);
+    void recordRetrievedCachedEntry(const NetworkCacheKey&amp;, const WebCore::ResourceRequest&amp;, bool success);
+
+private:
+    explicit NetworkCacheStatistics(const String&amp; databasePath);
+
+    void initialize(const String&amp; databasePath);
+    void bootstrapFromNetworkCache(const String&amp; networkCachePath);
+    void shrinkIfNeeded();
+
+    void addHashToDatabase(const String&amp; hash);
+
+    typedef std::function&lt;void (bool wasEverRequested)&gt; RequestedCompletionHandler;
+    void queryWasEverRequested(const String&amp;, const RequestedCompletionHandler&amp;);
+    void markAsRequested(const String&amp; hash);
+
+    struct EverRequestedQuery {
+        String hash;
+        RequestedCompletionHandler completionHandler;
+    };
+
+    std::atomic&lt;size_t&gt; m_approximateEntryCount { 0 };
+
+#if PLATFORM(COCOA)
+    mutable DispatchPtr&lt;dispatch_queue_t&gt; m_backgroundIOQueue;
+#endif
+    mutable HashSet&lt;std::unique_ptr&lt;const EverRequestedQuery&gt;&gt; m_activeQueries;
+    WebCore::SQLiteDatabase m_database;
+};
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
+
+#endif // NetworkCacheStatistics_h
</ins></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticsCocoamm"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm (0 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm                                (rev 0)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatisticsCocoa.mm        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -0,0 +1,274 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+
+#if ENABLE(NETWORK_CACHE)
+#include &quot;NetworkCacheStatistics.h&quot;
+
+#include &quot;Logging.h&quot;
+#include &quot;NetworkCache.h&quot;
+#include &quot;NetworkCacheFileSystemPosix.h&quot;
+#include &lt;WebCore/ResourceRequest.h&gt;
+#include &lt;WebCore/SQLiteDatabaseTracker.h&gt;
+#include &lt;WebCore/SQLiteStatement.h&gt;
+#include &lt;WebCore/SQLiteTransaction.h&gt;
+#include &lt;wtf/RunLoop.h&gt;
+
+namespace WebKit {
+
+static const char* networkCacheStatisticsDatabaseName = &quot;WebKitCacheStatistics.db&quot;;
+
+static bool executeSQLCommand(WebCore::SQLiteDatabase&amp; database, const String&amp; sql)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+    ASSERT(database.isOpen());
+
+    bool result = database.executeCommand(sql);
+    if (!result)
+        LOG_ERROR(&quot;Network cache statistics: failed to execute statement \&quot;%s\&quot; error \&quot;%s\&quot;&quot;, sql.utf8().data(), database.lastErrorMsg());
+
+    return result;
+}
+
+static bool executeSQLStatement(WebCore::SQLiteStatement&amp; statement)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+    ASSERT(statement.database().isOpen());
+
+    bool result = statement.executeCommand();
+    if (!result)
+        LOG_ERROR(&quot;Network cache statistics: failed to execute statement \&quot;%s\&quot; error \&quot;%s\&quot;&quot;, statement.query().utf8().data(), statement.database().lastErrorMsg());
+
+    return result;
+}
+
+std::unique_ptr&lt;NetworkCacheStatistics&gt; NetworkCacheStatistics::open(const String&amp; cachePath)
+{
+    ASSERT(RunLoop::isMain());
+
+    String databasePath = WebCore::pathByAppendingComponent(cachePath, networkCacheStatisticsDatabaseName);
+    return std::unique_ptr&lt;NetworkCacheStatistics&gt;(new NetworkCacheStatistics(databasePath));
+}
+
+NetworkCacheStatistics::NetworkCacheStatistics(const String&amp; databasePath)
+    : m_backgroundIOQueue(adoptDispatch(dispatch_queue_create(&quot;com.apple.WebKit.Cache.Statistics.Background&quot;, DISPATCH_QUEUE_SERIAL)))
+{
+    dispatch_set_target_queue(m_backgroundIOQueue.get(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0));
+
+    initialize(databasePath);
+}
+
+void NetworkCacheStatistics::initialize(const String&amp; databasePath)
+{
+    ASSERT(RunLoop::isMain());
+
+    auto startTime = std::chrono::system_clock::now();
+
+    StringCapture databasePathCapture(databasePath);
+    StringCapture networkCachePathCapture(NetworkCache::singleton().storagePath());
+    dispatch_async(m_backgroundIOQueue.get(), [this, databasePathCapture, networkCachePathCapture, startTime] {
+        WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+
+        String databasePath = databasePathCapture.string();
+        if (!WebCore::makeAllDirectories(WebCore::directoryName(databasePath)))
+            return;
+
+        LOG(NetworkCache, &quot;(NetworkProcess) Opening network cache statistics database at %s...&quot;, databasePath.utf8().data());
+        m_database.open(databasePath);
+        m_database.disableThreadingChecks();
+        if (!m_database.isOpen()) {
+            LOG_ERROR(&quot;Network cache statistics: Failed to open / create the network cache statistics database&quot;);
+            return;
+        }
+
+        executeSQLCommand(m_database, ASCIILiteral(&quot;CREATE TABLE IF NOT EXISTS AlreadyRequested (hash TEXT PRIMARY KEY)&quot;));
+        WebCore::SQLiteStatement statement(m_database, ASCIILiteral(&quot;SELECT count(*) FROM AlreadyRequested&quot;));
+        if (statement.prepareAndStep() != WebCore::SQLResultRow) {
+            LOG_ERROR(&quot;Network cache statistics: Failed to count the number of rows in AlreadyRequested table&quot;);
+            return;
+        }
+
+        m_approximateEntryCount = statement.getColumnInt(0);
+
+#if !LOG_DISABLED
+        auto elapsedMS = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::system_clock::now() - startTime).count();
+#endif
+        LOG(NetworkCache, &quot;(NetworkProcess) Network cache statistics database load complete, entries=%lu time=%lldms&quot;, static_cast&lt;size_t&gt;(m_approximateEntryCount), elapsedMS);
+
+        if (!m_approximateEntryCount) {
+            bootstrapFromNetworkCache(networkCachePathCapture.string());
+#if !LOG_DISABLED
+            elapsedMS = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(std::chrono::system_clock::now() - startTime).count();
+#endif
+            LOG(NetworkCache, &quot;(NetworkProcess) Network cache statistics database bootstrapping complete, entries=%lu time=%lldms&quot;, static_cast&lt;size_t&gt;(m_approximateEntryCount), elapsedMS);
+        }
+    });
+}
+
+void NetworkCacheStatistics::bootstrapFromNetworkCache(const String&amp; networkCachePath)
+{
+    ASSERT(!RunLoop::isMain());
+
+    LOG(NetworkCache, &quot;(NetworkProcess) Bootstrapping the network cache statistics database from the network cache...&quot;);
+
+    WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+    WebCore::SQLiteTransaction bootstrapTransaction(m_database);
+    bootstrapTransaction.begin();
+
+    traverseCacheFiles(networkCachePath, [this](const String&amp; hash, const String&amp;) {
+        addHashToDatabase(hash);
+    });
+    bootstrapTransaction.commit();
+}
+
+void NetworkCacheStatistics::shrinkIfNeeded()
+{
+    ASSERT(RunLoop::isMain());
+    const size_t maxEntries = 100000;
+
+    if (m_approximateEntryCount &lt; maxEntries)
+        return;
+
+    LOG(NetworkCache, &quot;(NetworkProcess) shrinking statistics cache m_approximateEntryCount=%lu, maxEntries=%lu&quot;, static_cast&lt;size_t&gt;(m_approximateEntryCount), maxEntries);
+
+    clear();
+
+    StringCapture networkCachePathCapture(NetworkCache::singleton().storagePath());
+    dispatch_async(m_backgroundIOQueue.get(), [this, networkCachePathCapture] {
+        bootstrapFromNetworkCache(networkCachePathCapture.string());
+        LOG(NetworkCache, &quot;(NetworkProcess) statistics cache shrink completed m_approximateEntryCount=%lu&quot;, static_cast&lt;size_t&gt;(m_approximateEntryCount));
+    });
+}
+
+void NetworkCacheStatistics::recordNotUsingCacheForRequest(const NetworkCacheKey&amp; key, const WebCore::ResourceRequest&amp; request)
+{
+    String hash = key.hashAsString();
+    WebCore::URL requestURL = request.url();
+    queryWasEverRequested(hash, [this, hash, requestURL](bool wasEverRequested) {
+        if (wasEverRequested) {
+            LOG(NetworkCache, &quot;(NetworkProcess) %s was previously requested but is not handled by the cache&quot;, requestURL.string().ascii().data());
+            // FIXME: Do diagnostic logging.
+        } else
+            markAsRequested(hash);
+    });
+}
+
+void NetworkCacheStatistics::recordRetrievalFailure(const NetworkCacheKey&amp; key, const WebCore::ResourceRequest&amp; request)
+{
+    String hash = key.hashAsString();
+    WebCore::URL requestURL = request.url();
+    queryWasEverRequested(hash, [this, hash, requestURL](bool wasPreviouslyRequested) {
+        if (wasPreviouslyRequested) {
+            LOG(NetworkCache, &quot;(NetworkProcess) %s was previously cached but is no longer in the cache&quot;, requestURL.string().ascii().data());
+            // FIXME: Do diagnostic logging.
+        } else
+            markAsRequested(hash);
+    });
+}
+
+void NetworkCacheStatistics::recordRetrievedCachedEntry(const NetworkCacheKey&amp; key, const WebCore::ResourceRequest&amp; request, bool success)
+{
+    WebCore::URL requestURL = request.url();
+    if (success)
+        LOG(NetworkCache, &quot;(NetworkProcess) %s is in the cache and is used&quot;, requestURL.string().ascii().data());
+    else
+        LOG(NetworkCache, &quot;(NetworkProcess) %s is in the cache but wasn't used&quot;, requestURL.string().ascii().data());
+    // FIXME: Do diagnostic logging.
+}
+
+void NetworkCacheStatistics::markAsRequested(const String&amp; hash)
+{
+    ASSERT(RunLoop::isMain());
+
+    StringCapture hashCapture(hash);
+    dispatch_async(m_backgroundIOQueue.get(), [this, hashCapture] {
+        WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+        if (m_database.isOpen())
+            addHashToDatabase(hashCapture.string());
+    });
+
+    shrinkIfNeeded();
+}
+
+void NetworkCacheStatistics::queryWasEverRequested(const String&amp; hash, const RequestedCompletionHandler&amp; completionHandler)
+{
+    ASSERT(RunLoop::isMain());
+
+    auto everRequestedQuery = std::make_unique&lt;EverRequestedQuery&gt;(EverRequestedQuery { hash, completionHandler });
+    auto&amp; query = *everRequestedQuery;
+    m_activeQueries.add(WTF::move(everRequestedQuery));
+    dispatch_async(m_backgroundIOQueue.get(), [this, &amp;query] {
+        WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+        bool wasAlreadyRequested = false;
+        if (m_database.isOpen()) {
+            WebCore::SQLiteStatement statement(m_database, ASCIILiteral(&quot;SELECT hash FROM AlreadyRequested WHERE hash=?&quot;));
+            if (statement.prepare() == WebCore::SQLResultOk) {
+                statement.bindText(1, query.hash);
+                wasAlreadyRequested = statement.step() == WebCore::SQLResultRow;
+            }
+        }
+        dispatch_async(dispatch_get_main_queue(), [this, &amp;query, wasAlreadyRequested] {
+            query.completionHandler(wasAlreadyRequested);
+            m_activeQueries.remove(&amp;query);
+        });
+    });
+}
+
+void NetworkCacheStatistics::clear()
+{
+    ASSERT(RunLoop::isMain());
+
+    dispatch_async(m_backgroundIOQueue.get(), [this] {
+        WebCore::SQLiteTransactionInProgressAutoCounter transactionCounter;
+        if (m_database.isOpen()) {
+            executeSQLCommand(m_database, ASCIILiteral(&quot;DELETE FROM AlreadyRequested&quot;));
+            m_approximateEntryCount = 0;
+        }
+    });
+}
+
+void NetworkCacheStatistics::addHashToDatabase(const String&amp; hash)
+{
+    ASSERT(!RunLoop::isMain());
+    ASSERT(WebCore::SQLiteDatabaseTracker::hasTransactionInProgress());
+    ASSERT(m_database.isOpen());
+
+    WebCore::SQLiteStatement statement(m_database, ASCIILiteral(&quot;INSERT OR IGNORE INTO AlreadyRequested (hash) VALUES (?)&quot;));
+    if (statement.prepare() != WebCore::SQLResultOk)
+        return;
+
+    statement.bindText(1, hash);
+    if (!executeSQLStatement(statement))
+        return;
+
+    ++m_approximateEntryCount;
+}
+
+} // namespace WebKit
+
+#endif // ENABLE(NETWORK_CACHE)
</ins></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -155,6 +155,8 @@
</span><span class="cx"> 
</span><span class="cx">     static const unsigned version = 2;
</span><span class="cx"> 
</span><ins>+    const String&amp; directoryPath() const { return m_directoryPath; }
+
</ins><span class="cx"> private:
</span><span class="cx">     NetworkCacheStorage(const String&amp; directoryPath);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorageCocoa.mm        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -30,8 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;Logging.h&quot;
</span><span class="cx"> #include &quot;NetworkCacheCoders.h&quot;
</span><del>-#include &lt;WebCore/FileSystem.h&gt;
-#include &lt;dirent.h&gt;
</del><ins>+#include &quot;NetworkCacheFileSystemPosix.h&quot;
</ins><span class="cx"> #include &lt;dispatch/dispatch.h&gt;
</span><span class="cx"> #include &lt;sys/mman.h&gt;
</span><span class="cx"> #include &lt;sys/stat.h&gt;
</span><span class="lines">@@ -44,36 +43,6 @@
</span><span class="cx"> static const char networkCacheSubdirectory[] = &quot;WebKitCache&quot;;
</span><span class="cx"> static const char versionDirectoryPrefix[] = &quot;Version &quot;;
</span><span class="cx"> 
</span><del>-template &lt;typename Function&gt;
-static void traverseDirectory(const String&amp; path, uint8_t type, const Function&amp; function)
-{
-    DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data());
-    if (!dir)
-        return;
-    struct dirent* dp;
-    while ((dp = readdir(dir))) {
-        if (dp-&gt;d_type != type)
-            continue;
-        const char* name = dp-&gt;d_name;
-        if (!strcmp(name, &quot;.&quot;) || !strcmp(name, &quot;..&quot;))
-            continue;
-        function(String(name));
-    }
-    closedir(dir);
-}
-
-static void traverseCacheFiles(const String&amp; cachePath, std::function&lt;void (const String&amp; fileName, const String&amp; partitionPath)&gt; function)
-{
-    traverseDirectory(cachePath, DT_DIR, [&amp;cachePath, &amp;function](const String&amp; subdirName) {
-        String partitionPath = WebCore::pathByAppendingComponent(cachePath, subdirName);
-        traverseDirectory(partitionPath, DT_REG, [&amp;function, &amp;partitionPath](const String&amp; fileName) {
-            if (fileName.length() != NetworkCacheKey::hashStringLength())
-                return;
-            function(fileName, partitionPath);
-        });
-    });
-}
-
</del><span class="cx"> NetworkCacheStorage::Data::Data(const uint8_t* data, size_t size)
</span><span class="cx">     : m_dispatchData(adoptDispatch(dispatch_data_create(data, size, nullptr, DISPATCH_DATA_DESTRUCTOR_DEFAULT)))
</span><span class="cx">     , m_size(size)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkProcessCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkProcessCocoa.mm        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -64,7 +64,7 @@
</span><span class="cx">     if (!m_diskCacheDirectory.isNull()) {
</span><span class="cx">         SandboxExtension::consumePermanently(parameters.diskCacheDirectoryExtensionHandle);
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><del>-        if (parameters.shouldEnableNetworkCache &amp;&amp; NetworkCache::singleton().initialize(m_diskCacheDirectory)) {
</del><ins>+        if (parameters.shouldEnableNetworkCache &amp;&amp; NetworkCache::singleton().initialize(m_diskCacheDirectory, parameters.shouldEnableNetworkCacheEfficacyLogging)) {
</ins><span class="cx">             RetainPtr&lt;NSURLCache&gt; urlCache(adoptNS([[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]));
</span><span class="cx">             [NSURLCache setSharedURLCache:urlCache.get()];
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedNetworkNetworkProcessCreationParameterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.cpp        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx">     encoder &lt;&lt; diskCacheDirectoryExtensionHandle;
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">     encoder &lt;&lt; shouldEnableNetworkCache;
</span><ins>+    encoder &lt;&lt; shouldEnableNetworkCacheEfficacyLogging;
</ins><span class="cx"> #endif
</span><span class="cx">     encoder &lt;&lt; cookieStorageDirectory;
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="lines">@@ -86,6 +87,8 @@
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">     if (!decoder.decode(result.shouldEnableNetworkCache))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(result.shouldEnableNetworkCacheEfficacyLogging))
+        return false;
</ins><span class="cx"> #endif
</span><span class="cx">     if (!decoder.decode(result.cookieStorageDirectory))
</span><span class="cx">         return false;
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedNetworkNetworkProcessCreationParametersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/Shared/Network/NetworkProcessCreationParameters.h        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -58,6 +58,7 @@
</span><span class="cx">     SandboxExtension::Handle diskCacheDirectoryExtensionHandle;
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">     bool shouldEnableNetworkCache;
</span><ins>+    bool shouldEnableNetworkCacheEfficacyLogging;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     String cookieStorageDirectory;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessCocoaWebProcessPoolCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/UIProcess/Cocoa/WebProcessPoolCocoa.mm        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -81,6 +81,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx"> static NSString * const WebKitNetworkCacheEnabledDefaultsKey = @&quot;WebKitNetworkCacheEnabled&quot;;
</span><ins>+static NSString * const WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey = @&quot;WebKitNetworkCacheEfficacyLoggingEnabled&quot;;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -106,6 +107,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">     [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEnabledDefaultsKey];
</span><ins>+    [registrationDictionary setObject:[NSNumber numberWithBool:YES] forKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     [[NSUserDefaults standardUserDefaults] registerDefaults:registrationDictionary];
</span><span class="lines">@@ -252,6 +254,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(NETWORK_CACHE)
</span><span class="cx">     parameters.shouldEnableNetworkCache = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitNetworkCacheEnabledDefaultsKey];
</span><ins>+    parameters.shouldEnableNetworkCacheEfficacyLogging = [[NSUserDefaults standardUserDefaults] boolForKey:WebKitNetworkCacheEfficacyLoggingEnabledDefaultsKey];
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (179803 => 179804)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2015-02-08 20:22:32 UTC (rev 179803)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2015-02-08 22:06:06 UTC (rev 179804)
</span><span class="lines">@@ -1147,6 +1147,9 @@
</span><span class="cx">                 7CF47FFE17276AE3008ACB91 /* WKBundlePageBannerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7CF47FFC17276AE3008ACB91 /* WKBundlePageBannerMac.mm */; };
</span><span class="cx">                 7CF47FFF17276AE3008ACB91 /* WKBundlePageBannerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 7EC4F0FB18E4ACBB008056AF /* NetworkProcessCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */; };
</span><ins>+                834B250F1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */; };
+                834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */; };
+                834B25131A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */; };
</ins><span class="cx">                 8372DB251A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 8372DB241A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 8372DB281A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8372DB261A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp */; };
</span><span class="cx">                 8372DB291A67562800C697C5 /* WebPageDiagnosticLoggingClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 8372DB271A67562800C697C5 /* WebPageDiagnosticLoggingClient.h */; };
</span><span class="lines">@@ -3321,6 +3324,9 @@
</span><span class="cx">                 7CF47FFC17276AE3008ACB91 /* WKBundlePageBannerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKBundlePageBannerMac.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CF47FFD17276AE3008ACB91 /* WKBundlePageBannerMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundlePageBannerMac.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7EC4F0F918E4A945008056AF /* NetworkProcessCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = NetworkProcessCocoa.mm; path = NetworkProcess/cocoa/NetworkProcessCocoa.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheFileSystemPosix.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkCacheStatistics.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = NetworkCacheStatisticsCocoa.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 8372DB241A674C8F00C697C5 /* WKPageDiagnosticLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPageDiagnosticLoggingClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 8372DB261A67562800C697C5 /* WebPageDiagnosticLoggingClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPageDiagnosticLoggingClient.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 8372DB271A67562800C697C5 /* WebPageDiagnosticLoggingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPageDiagnosticLoggingClient.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -7382,8 +7388,11 @@
</span><span class="cx">                                 E489D2871A0A2DB80078C06A /* NetworkCacheDecoder.h */,
</span><span class="cx">                                 E489D2881A0A2DB80078C06A /* NetworkCacheEncoder.cpp */,
</span><span class="cx">                                 E489D2891A0A2DB80078C06A /* NetworkCacheEncoder.h */,
</span><ins>+                                834B250E1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h */,
</ins><span class="cx">                                 E4436EC01A0CFDB200EAD204 /* NetworkCacheKey.cpp */,
</span><span class="cx">                                 E4436EC11A0CFDB200EAD204 /* NetworkCacheKey.h */,
</span><ins>+                                834B25101A842C8700CFB150 /* NetworkCacheStatistics.h */,
+                                834B25111A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm */,
</ins><span class="cx">                                 E4436EC21A0CFDB200EAD204 /* NetworkCacheStorage.h */,
</span><span class="cx">                                 E4436EC31A0CFDB200EAD204 /* NetworkCacheStorageCocoa.mm */,
</span><span class="cx">                         );
</span><span class="lines">@@ -7500,6 +7509,7 @@
</span><span class="cx">                                 1AC1336C18565C7A00F3EC05 /* APIPageHandle.h in Headers */,
</span><span class="cx">                                 1AFDD3151891B54000153970 /* APIPolicyClient.h in Headers */,
</span><span class="cx">                                 7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */,
</span><ins>+                                834B25121A842C8700CFB150 /* NetworkCacheStatistics.h in Headers */,
</ins><span class="cx">                                 F634445612A885C8000612D8 /* APISecurityOrigin.h in Headers */,
</span><span class="cx">                                 75A8D2E1187DEC1A00C39C9E /* APISession.h in Headers */,
</span><span class="cx">                                 1AFDE6621954E9B100C48FFA /* APISessionState.h in Headers */,
</span><span class="lines">@@ -7686,6 +7696,7 @@
</span><span class="cx">                                 1A2161B011F37664008AD0F5 /* NPRuntimeObjectMap.h in Headers */,
</span><span class="cx">                                 1A2162B111F38971008AD0F5 /* NPRuntimeUtilities.h in Headers */,
</span><span class="cx">                                 1A2D84A3127F6AD1001EB962 /* NPVariantData.h in Headers */,
</span><ins>+                                834B250F1A831A8D00CFB150 /* NetworkCacheFileSystemPosix.h in Headers */,
</ins><span class="cx">                                 BC8ACA1316670D89004C1941 /* ObjCObjectGraph.h in Headers */,
</span><span class="cx">                                 BCCF672D12C7EDF7008F9C35 /* OriginAndDatabases.h in Headers */,
</span><span class="cx">                                 7CF47FFB17275C57008ACB91 /* PageBanner.h in Headers */,
</span><span class="lines">@@ -9885,6 +9896,7 @@
</span><span class="cx">                                 1C8E293A12761E5B00BC7BD0 /* WKInspector.cpp in Sources */,
</span><span class="cx">                                 0F3C725C196F605200AEDD0C /* WKInspectorHighlightView.mm in Sources */,
</span><span class="cx">                                 A54293A5195A43DD002782C7 /* WKInspectorNodeSearchGestureRecognizer.mm in Sources */,
</span><ins>+                                834B25131A842C8700CFB150 /* NetworkCacheStatisticsCocoa.mm in Sources */,
</ins><span class="cx">                                 51A9E10A1315CD18009E7031 /* WKKeyValueStorageManager.cpp in Sources */,
</span><span class="cx">                                 33D3A3B51339600B00709BE4 /* WKMediaCacheManager.cpp in Sources */,
</span><span class="cx">                                 BC4075FD124FF0270068F20A /* WKMutableArray.cpp in Sources */,
</span></span></pre>
</div>
</div>

</body>
</html>