<!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>[191306] trunk/Source/WebKit2</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/191306">191306</a></dd>
<dt>Author</dt> <dd>cdumez@apple.com</dd>
<dt>Date</dt> <dd>2015-10-19 12:21:22 -0700 (Mon, 19 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WK2] Generalize NetworkCacheStorage API so it can store different types of metadata
https://bugs.webkit.org/show_bug.cgi?id=150221
&lt;rdar://problem/23149771&gt;

Reviewed by Darin Adler and Antti Koivisto.

Generalize NetworkCacheStorage API so it can store different types of
metadata alongside the network resources. This is a pre-requirement to
making our NetworkCache smarter by storing information about the
resources.

To keep the code simple, the entry type is now part of the entry key and
we store records of a specific type in a 'type' subfolder. The cache
structure looks like so:
- WebKitCache/Version 5/[Partition]/[Type]/[Hash]
- WebKitCache/Version 5/[Partition]/[Type]/[Hash]-blob (Optional)

Existing cache entries now that the 'resource' type as these are network
resources.

* NetworkProcess/cache/NetworkCache.cpp:
* NetworkProcess/cache/NetworkCacheKey.cpp:
* NetworkProcess/cache/NetworkCacheKey.h:
* NetworkProcess/cache/NetworkCacheStatistics.cpp:
* NetworkProcess/cache/NetworkCacheStorage.cpp:
* NetworkProcess/cache/NetworkCacheStorage.h:</pre>

<h3>Modified Paths</h3>
<ul>
<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="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeycpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeyh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticscpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStoragecpp">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageh">trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/ChangeLog        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -1,3 +1,32 @@
</span><ins>+2015-10-19  Chris Dumez  &lt;cdumez@apple.com&gt;
+
+        [WK2] Generalize NetworkCacheStorage API so it can store different types of metadata
+        https://bugs.webkit.org/show_bug.cgi?id=150221
+        &lt;rdar://problem/23149771&gt;
+
+        Reviewed by Darin Adler and Antti Koivisto.
+
+        Generalize NetworkCacheStorage API so it can store different types of
+        metadata alongside the network resources. This is a pre-requirement to
+        making our NetworkCache smarter by storing information about the
+        resources.
+
+        To keep the code simple, the entry type is now part of the entry key and
+        we store records of a specific type in a 'type' subfolder. The cache
+        structure looks like so:
+        - WebKitCache/Version 5/[Partition]/[Type]/[Hash]
+        - WebKitCache/Version 5/[Partition]/[Type]/[Hash]-blob (Optional)
+
+        Existing cache entries now that the 'resource' type as these are network
+        resources.
+
+        * NetworkProcess/cache/NetworkCache.cpp:
+        * NetworkProcess/cache/NetworkCacheKey.cpp:
+        * NetworkProcess/cache/NetworkCacheKey.h:
+        * NetworkProcess/cache/NetworkCacheStatistics.cpp:
+        * NetworkProcess/cache/NetworkCacheStorage.cpp:
+        * NetworkProcess/cache/NetworkCacheStorage.h:
+
</ins><span class="cx"> 2015-10-19  Tim Horton  &lt;timothy_horton@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Try to fix the iOS build
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCache.cpp        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include &lt;WebCore/ResourceRequest.h&gt;
</span><span class="cx"> #include &lt;WebCore/ResourceResponse.h&gt;
</span><span class="cx"> #include &lt;WebCore/SharedBuffer.h&gt;
</span><ins>+#include &lt;wtf/MainThread.h&gt;
</ins><span class="cx"> #include &lt;wtf/NeverDestroyed.h&gt;
</span><span class="cx"> #include &lt;wtf/RunLoop.h&gt;
</span><span class="cx"> #include &lt;wtf/text/StringBuilder.h&gt;
</span><span class="lines">@@ -50,6 +51,13 @@
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> namespace NetworkCache {
</span><span class="cx"> 
</span><ins>+static const AtomicString&amp; resourceType()
+{
+    ASSERT(WTF::isMainThread());
+    static NeverDestroyed&lt;const AtomicString&gt; resource(&quot;resource&quot;, AtomicString::ConstructFromLiteral);
+    return resource;
+}
+
</ins><span class="cx"> Cache&amp; singleton()
</span><span class="cx"> {
</span><span class="cx">     static NeverDestroyed&lt;Cache&gt; instance;
</span><span class="lines">@@ -113,7 +121,7 @@
</span><span class="cx">     // FIXME: This implements minimal Range header disk cache support. We don't parse
</span><span class="cx">     // ranges so only the same exact range request will be served from the cache.
</span><span class="cx">     String range = request.httpHeaderField(WebCore::HTTPHeaderName::Range);
</span><del>-    return { partition, range, request.url().string() };
</del><ins>+    return { partition, resourceType(), range, request.url().string() };
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static String headerValueForVary(const WebCore::ResourceRequest&amp; request, const String&amp; headerName)
</span><span class="lines">@@ -472,7 +480,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(isEnabled());
</span><span class="cx"> 
</span><del>-    m_storage-&gt;traverse(0, [traverseHandler](const Storage::Record* record, const Storage::RecordInfo&amp;) {
</del><ins>+    m_storage-&gt;traverse(resourceType(), 0, [traverseHandler](const Storage::Record* record, const Storage::RecordInfo&amp;) {
</ins><span class="cx">         if (!record) {
</span><span class="cx">             traverseHandler(nullptr);
</span><span class="cx">             return;
</span><span class="lines">@@ -509,7 +517,7 @@
</span><span class="cx">     Totals totals;
</span><span class="cx">     auto flags = Storage::TraverseFlag::ComputeWorth | Storage::TraverseFlag::ShareCount;
</span><span class="cx">     size_t capacity = m_storage-&gt;capacity();
</span><del>-    m_storage-&gt;traverse(flags, [fd, totals, capacity](const Storage::Record* record, const Storage::RecordInfo&amp; info) mutable {
</del><ins>+    m_storage-&gt;traverse(resourceType(), flags, [fd, totals, capacity](const Storage::Record* record, const Storage::RecordInfo&amp; info) mutable {
</ins><span class="cx">         if (!record) {
</span><span class="cx">             StringBuilder epilogue;
</span><span class="cx">             epilogue.appendLiteral(&quot;{}\n],\n&quot;);
</span><span class="lines">@@ -567,7 +575,8 @@
</span><span class="cx">         RunLoop::main().dispatch(completionHandler);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><del>-    m_storage-&gt;clear(modifiedSince, WTF::move(completionHandler));
</del><ins>+    String anyType;
+    m_storage-&gt;clear(anyType, modifiedSince, WTF::move(completionHandler));
</ins><span class="cx"> 
</span><span class="cx">     deleteDumpFile();
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.cpp        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -38,14 +38,16 @@
</span><span class="cx"> 
</span><span class="cx"> Key::Key(const Key&amp; o)
</span><span class="cx">     : m_partition(o.m_partition.isolatedCopy())
</span><ins>+    , m_type(o.m_type.isolatedCopy())
</ins><span class="cx">     , m_identifier(o.m_identifier.isolatedCopy())
</span><span class="cx">     , m_range(o.m_range.isolatedCopy())
</span><span class="cx">     , m_hash(o.m_hash)
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Key::Key(const String&amp; partition, const String&amp; range, const String&amp; identifier)
</del><ins>+Key::Key(const String&amp; partition, const String&amp; type, const String&amp; range, const String&amp; identifier)
</ins><span class="cx">     : m_partition(partition.isolatedCopy())
</span><ins>+    , m_type(type.isolatedCopy())
</ins><span class="cx">     , m_identifier(identifier.isolatedCopy())
</span><span class="cx">     , m_range(range.isolatedCopy())
</span><span class="cx">     , m_hash(computeHash())
</span><span class="lines">@@ -55,6 +57,7 @@
</span><span class="cx"> Key&amp; Key::operator=(const Key&amp; other)
</span><span class="cx"> {
</span><span class="cx">     m_partition = other.m_partition.isolatedCopy();
</span><ins>+    m_type = other.m_type.isolatedCopy();
</ins><span class="cx">     m_identifier = other.m_identifier.isolatedCopy();
</span><span class="cx">     m_range = other.m_range.isolatedCopy();
</span><span class="cx">     m_hash = other.m_hash;
</span><span class="lines">@@ -83,6 +86,7 @@
</span><span class="cx">     // SHA1 just happens to be suitably sized, fast and available.
</span><span class="cx">     SHA1 sha1;
</span><span class="cx">     hashString(sha1, m_partition);
</span><ins>+    hashString(sha1, m_type);
</ins><span class="cx">     hashString(sha1, m_identifier);
</span><span class="cx">     hashString(sha1, m_range);
</span><span class="cx">     SHA1::Digest hash;
</span><span class="lines">@@ -124,12 +128,13 @@
</span><span class="cx"> 
</span><span class="cx"> bool Key::operator==(const Key&amp; other) const
</span><span class="cx"> {
</span><del>-    return m_hash == other.m_hash &amp;&amp; m_partition == other.m_partition &amp;&amp; m_identifier == other.m_identifier &amp;&amp; m_range == other.m_range;
</del><ins>+    return m_hash == other.m_hash &amp;&amp; m_partition == other.m_partition &amp;&amp; m_type == other.m_type &amp;&amp; m_identifier == other.m_identifier &amp;&amp; m_range == other.m_range;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Key::encode(Encoder&amp; encoder) const
</span><span class="cx"> {
</span><span class="cx">     encoder &lt;&lt; m_partition;
</span><ins>+    encoder &lt;&lt; m_type;
</ins><span class="cx">     encoder &lt;&lt; m_identifier;
</span><span class="cx">     encoder &lt;&lt; m_range;
</span><span class="cx">     encoder &lt;&lt; m_hash;
</span><span class="lines">@@ -137,7 +142,7 @@
</span><span class="cx"> 
</span><span class="cx"> bool Key::decode(Decoder&amp; decoder, Key&amp; key)
</span><span class="cx"> {
</span><del>-    return decoder.decode(key.m_partition) &amp;&amp; decoder.decode(key.m_identifier) &amp;&amp; decoder.decode(key.m_range) &amp;&amp; decoder.decode(key.m_hash);
</del><ins>+    return decoder.decode(key.m_partition) &amp;&amp; decoder.decode(key.m_type) &amp;&amp; decoder.decode(key.m_identifier) &amp;&amp; decoder.decode(key.m_range) &amp;&amp; decoder.decode(key.m_hash);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheKey.h        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -44,7 +44,7 @@
</span><span class="cx">     Key() { }
</span><span class="cx">     Key(const Key&amp;);
</span><span class="cx">     Key(Key&amp;&amp;) = default;
</span><del>-    Key(const String&amp; partition, const String&amp; range, const String&amp; identifier);
</del><ins>+    Key(const String&amp; partition, const String&amp; type, const String&amp; range, const String&amp; identifier);
</ins><span class="cx"> 
</span><span class="cx">     Key&amp; operator=(const Key&amp;);
</span><span class="cx">     Key&amp; operator=(Key&amp;&amp;) = default;
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx"> 
</span><span class="cx">     const String&amp; partition() const { return m_partition; }
</span><span class="cx">     const String&amp; identifier() const { return m_identifier; }
</span><ins>+    const String&amp; type() const { return m_type; }
</ins><span class="cx"> 
</span><span class="cx">     HashType hash() const { return m_hash; }
</span><span class="cx"> 
</span><span class="lines">@@ -71,6 +72,7 @@
</span><span class="cx">     HashType computeHash() const;
</span><span class="cx"> 
</span><span class="cx">     String m_partition;
</span><ins>+    String m_type;
</ins><span class="cx">     String m_identifier;
</span><span class="cx">     String m_range;
</span><span class="cx">     HashType m_hash;
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStatisticscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStatistics.cpp        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -144,7 +144,10 @@
</span><span class="cx">     LOG(NetworkCache, &quot;(NetworkProcess) Bootstrapping the network cache statistics database from the network cache...&quot;);
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;StringCapture&gt; hashes;
</span><del>-    traverseRecordsFiles(networkCachePath, [&amp;hashes](const String&amp; hashString, const String&amp;) {
</del><ins>+    traverseRecordsFiles(networkCachePath, ASCIILiteral(&quot;resource&quot;), [&amp;hashes](const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath) {
+        if (isBodyBlob)
+            return;
+
</ins><span class="cx">         Key::HashType hash;
</span><span class="cx">         if (!Key::stringToHash(hashString, hash))
</span><span class="cx">             return;
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStoragecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.cpp        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx"> static const char versionDirectoryPrefix[] = &quot;Version &quot;;
</span><span class="cx"> static const char recordsDirectoryName[] = &quot;Records&quot;;
</span><span class="cx"> static const char blobsDirectoryName[] = &quot;Blobs&quot;;
</span><del>-static const char bodyPostfix[] = &quot;-body&quot;;
</del><ins>+static const char blobSuffix[] = &quot;-blob&quot;;
</ins><span class="cx"> 
</span><span class="cx"> static double computeRecordWorth(FileTimes);
</span><span class="cx"> 
</span><span class="lines">@@ -113,11 +113,13 @@
</span><span class="cx"> struct Storage::TraverseOperation {
</span><span class="cx">     WTF_MAKE_FAST_ALLOCATED;
</span><span class="cx"> public:
</span><del>-    TraverseOperation(TraverseFlags flags, const TraverseHandler&amp; handler)
-        : flags(flags)
</del><ins>+    TraverseOperation(const String&amp; type, TraverseFlags flags, const TraverseHandler&amp; handler)
+        : type(type)
+        , flags(flags)
</ins><span class="cx">         , handler(handler)
</span><span class="cx">     { }
</span><span class="cx"> 
</span><ins>+    const String type;
</ins><span class="cx">     const TraverseFlags flags;
</span><span class="cx">     const TraverseHandler handler;
</span><span class="cx"> 
</span><span class="lines">@@ -151,27 +153,49 @@
</span><span class="cx">     return WebCore::pathByAppendingComponent(makeVersionedDirectoryPath(baseDirectoryPath), blobsDirectoryName);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void traverseRecordsFiles(const String&amp; recordsPath, const std::function&lt;void (const String&amp;, const String&amp;)&gt;&amp; function)
</del><ins>+void traverseRecordsFiles(const String&amp; recordsPath, const String&amp; expectedType, const std::function&lt;void (const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath)&gt;&amp; function)
</ins><span class="cx"> {
</span><del>-    traverseDirectory(recordsPath, [&amp;recordsPath, &amp;function](const String&amp; subdirName, DirectoryEntryType type) {
-        if (type != DirectoryEntryType::Directory)
</del><ins>+    traverseDirectory(recordsPath, [&amp;recordsPath, &amp;function, &amp;expectedType](const String&amp; partitionName, DirectoryEntryType entryType) {
+        if (entryType != DirectoryEntryType::Directory)
</ins><span class="cx">             return;
</span><del>-        String partitionPath = WebCore::pathByAppendingComponent(recordsPath, subdirName);
-        traverseDirectory(partitionPath, [&amp;function, &amp;partitionPath](const String&amp; fileName, DirectoryEntryType type) {
-            if (type != DirectoryEntryType::File)
</del><ins>+        String partitionPath = WebCore::pathByAppendingComponent(recordsPath, partitionName);
+        traverseDirectory(partitionPath, [&amp;function, &amp;partitionPath, &amp;expectedType](const String&amp; actualType, DirectoryEntryType entryType) {
+            if (entryType != DirectoryEntryType::Directory)
</ins><span class="cx">                 return;
</span><del>-            function(fileName, partitionPath);
</del><ins>+            if (!actualType.isEmpty() &amp;&amp; expectedType != actualType)
+                return;
+            String recordDirectoryPath = WebCore::pathByAppendingComponent(partitionPath, actualType);
+            traverseDirectory(partitionPath, [&amp;function, &amp;recordDirectoryPath, &amp;actualType](const String&amp; fileName, DirectoryEntryType entryType) {
+                if (entryType != DirectoryEntryType::File || fileName.length() &lt; Key::hashStringLength())
+                    return;
+
+                String hashString = fileName.substring(0, Key::hashStringLength());
+                auto isBodyBlob = fileName.length() &gt; Key::hashStringLength() &amp;&amp; fileName.endsWith(blobSuffix);
+                function(fileName, hashString, actualType, isBodyBlob, recordDirectoryPath);
+            });
</ins><span class="cx">         });
</span><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> static void deleteEmptyRecordsDirectories(const String&amp; recordsPath)
</span><span class="cx"> {
</span><del>-    traverseDirectory(recordsPath, [&amp;recordsPath](const String&amp; subdirName, DirectoryEntryType type) {
</del><ins>+    traverseDirectory(recordsPath, [&amp;recordsPath](const String&amp; partitionName, DirectoryEntryType type) {
</ins><span class="cx">         if (type != DirectoryEntryType::Directory)
</span><span class="cx">             return;
</span><ins>+
+        // Delete [type] sub-folders.
+        String partitionPath = WebCore::pathByAppendingComponent(recordsPath, partitionName);
+        traverseDirectory(partitionPath, [&amp;partitionPath](const String&amp; subdirName, DirectoryEntryType entryType) {
+            if (entryType != DirectoryEntryType::Directory)
+                return;
+
+            // Let system figure out if it is really empty.
+            WebCore::deleteEmptyDirectory(WebCore::pathByAppendingComponent(partitionPath, subdirName));
+        });
+
+        // Delete [Partition] folders.
</ins><span class="cx">         // Let system figure out if it is really empty.
</span><del>-        WebCore::deleteEmptyDirectory(WebCore::pathByAppendingComponent(recordsPath, subdirName));
</del><ins>+        WebCore::deleteEmptyDirectory(WebCore::pathByAppendingComponent(recordsPath, partitionName));
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -225,14 +249,13 @@
</span><span class="cx"> 
</span><span class="cx">     backgroundIOQueue().dispatch([this] {
</span><span class="cx">         auto recordFilter = std::make_unique&lt;ContentsFilter&gt;();
</span><del>-        auto bodyFilter = std::make_unique&lt;ContentsFilter&gt;();
</del><ins>+        auto blobFilter = std::make_unique&lt;ContentsFilter&gt;();
</ins><span class="cx">         size_t recordsSize = 0;
</span><span class="cx">         unsigned count = 0;
</span><del>-        traverseRecordsFiles(recordsPath(), [&amp;recordFilter, &amp;bodyFilter, &amp;recordsSize, &amp;count](const String&amp; fileName, const String&amp; partitionPath) {
-            auto filePath = WebCore::pathByAppendingComponent(partitionPath, fileName);
</del><ins>+        String anyType;
+        traverseRecordsFiles(recordsPath(), anyType, [&amp;recordFilter, &amp;blobFilter, &amp;recordsSize, &amp;count](const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath) {
+            auto filePath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName);
</ins><span class="cx"> 
</span><del>-            bool isBody = fileName.endsWith(bodyPostfix);
-            String hashString = isBody ? fileName.substring(0, Key::hashStringLength()) : fileName;
</del><span class="cx">             Key::HashType hash;
</span><span class="cx">             if (!Key::stringToHash(hashString, hash)) {
</span><span class="cx">                 WebCore::deleteFile(filePath);
</span><span class="lines">@@ -244,31 +267,33 @@
</span><span class="cx">                 WebCore::deleteFile(filePath);
</span><span class="cx">                 return;
</span><span class="cx">             }
</span><del>-            if (isBody) {
-                bodyFilter-&gt;add(hash);
</del><ins>+
+            if (isBodyBlob) {
+                blobFilter-&gt;add(hash);
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><ins>+
</ins><span class="cx">             recordFilter-&gt;add(hash);
</span><span class="cx">             recordsSize += fileSize;
</span><span class="cx">             ++count;
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         auto* recordFilterPtr = recordFilter.release();
</span><del>-        auto* bodyFilterPtr = bodyFilter.release();
-        RunLoop::main().dispatch([this, recordFilterPtr, bodyFilterPtr, recordsSize] {
</del><ins>+        auto* blobFilterPtr = blobFilter.release();
+        RunLoop::main().dispatch([this, recordFilterPtr, blobFilterPtr, recordsSize] {
</ins><span class="cx">             auto recordFilter = std::unique_ptr&lt;ContentsFilter&gt;(recordFilterPtr);
</span><del>-            auto bodyFilter = std::unique_ptr&lt;ContentsFilter&gt;(bodyFilterPtr);
</del><ins>+            auto blobFilter = std::unique_ptr&lt;ContentsFilter&gt;(blobFilterPtr);
</ins><span class="cx"> 
</span><del>-            for (auto&amp; hash : m_recordFilterHashesAddedDuringSynchronization)
-                recordFilter-&gt;add(hash);
</del><ins>+            for (auto&amp; recordFilterKey : m_recordFilterHashesAddedDuringSynchronization)
+                recordFilter-&gt;add(recordFilterKey);
</ins><span class="cx">             m_recordFilterHashesAddedDuringSynchronization.clear();
</span><span class="cx"> 
</span><del>-            for (auto&amp; hash : m_bodyFilterHashesAddedDuringSynchronization)
-                bodyFilter-&gt;add(hash);
-            m_bodyFilterHashesAddedDuringSynchronization.clear();
</del><ins>+            for (auto&amp; hash : m_blobFilterHashesAddedDuringSynchronization)
+                blobFilter-&gt;add(hash);
+            m_blobFilterHashesAddedDuringSynchronization.clear();
</ins><span class="cx"> 
</span><span class="cx">             m_recordFilter = WTF::move(recordFilter);
</span><del>-            m_bodyFilter = WTF::move(bodyFilter);
</del><ins>+            m_blobFilter = WTF::move(blobFilter);
</ins><span class="cx">             m_approximateRecordsSize = recordsSize;
</span><span class="cx">             m_synchronizationInProgress = false;
</span><span class="cx">         });
</span><span class="lines">@@ -277,7 +302,7 @@
</span><span class="cx"> 
</span><span class="cx">         deleteEmptyRecordsDirectories(recordsPath());
</span><span class="cx"> 
</span><del>-        LOG(NetworkCacheStorage, &quot;(NetworkProcess) cache synchronization completed size=%zu count=%d&quot;, recordsSize, count);
</del><ins>+        LOG(NetworkCacheStorage, &quot;(NetworkProcess) cache synchronization completed size=%zu count=%u&quot;, recordsSize, count);
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -299,30 +324,32 @@
</span><span class="cx">     return !m_recordFilter || m_recordFilter-&gt;mayContain(key.hash());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-String Storage::partitionPathForKey(const Key&amp; key) const
</del><ins>+bool Storage::mayContainBlob(const Key&amp; key) const
</ins><span class="cx"> {
</span><del>-    ASSERT(!key.partition().isEmpty());
-    return WebCore::pathByAppendingComponent(recordsPath(), key.partition());
</del><ins>+    ASSERT(RunLoop::isMain());
+    return !m_blobFilter || m_blobFilter-&gt;mayContain(key.hash());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static String fileNameForKey(const Key&amp; key)
</del><ins>+String Storage::recordDirectoryPathForKey(const Key&amp; key) const
</ins><span class="cx"> {
</span><del>-    return key.hashAsString();
</del><ins>+    ASSERT(!key.partition().isEmpty());
+    ASSERT(!key.type().isEmpty());
+    return WebCore::pathByAppendingComponent(WebCore::pathByAppendingComponent(recordsPath(), key.partition()), key.type());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> String Storage::recordPathForKey(const Key&amp; key) const
</span><span class="cx"> {
</span><del>-    return WebCore::pathByAppendingComponent(partitionPathForKey(key), fileNameForKey(key));
</del><ins>+    return WebCore::pathByAppendingComponent(recordDirectoryPathForKey(key), key.hashAsString());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-static String bodyPathForRecordPath(const String&amp; recordPath)
</del><ins>+static String blobPathForRecordPath(const String&amp; recordPath)
</ins><span class="cx"> {
</span><del>-    return recordPath + bodyPostfix;
</del><ins>+    return recordPath + blobSuffix;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-String Storage::bodyPathForKey(const Key&amp; key) const
</del><ins>+String Storage::blobPathForKey(const Key&amp; key) const
</ins><span class="cx"> {
</span><del>-    return bodyPathForRecordPath(recordPathForKey(key));
</del><ins>+    return blobPathForRecordPath(recordPathForKey(key));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> struct RecordMetaData {
</span><span class="lines">@@ -452,20 +479,20 @@
</span><span class="cx"> 
</span><span class="cx"> Optional&lt;BlobStorage::Blob&gt; Storage::storeBodyAsBlob(WriteOperation&amp; writeOperation)
</span><span class="cx"> {
</span><del>-    auto bodyPath = bodyPathForKey(writeOperation.record.key);
</del><ins>+    auto blobPath = blobPathForKey(writeOperation.record.key);
</ins><span class="cx"> 
</span><span class="cx">     // Store the body.
</span><del>-    auto blob = m_blobStorage.add(bodyPath, writeOperation.record.body);
</del><ins>+    auto blob = m_blobStorage.add(blobPath, writeOperation.record.body);
</ins><span class="cx">     if (blob.data.isNull())
</span><span class="cx">         return { };
</span><span class="cx"> 
</span><span class="cx">     ++writeOperation.activeCount;
</span><span class="cx"> 
</span><span class="cx">     RunLoop::main().dispatch([this, blob, &amp;writeOperation] {
</span><del>-        if (m_bodyFilter)
-            m_bodyFilter-&gt;add(writeOperation.record.key.hash());
</del><ins>+        if (m_blobFilter)
+            m_blobFilter-&gt;add(writeOperation.record.key.hash());
</ins><span class="cx">         if (m_synchronizationInProgress)
</span><del>-            m_bodyFilterHashesAddedDuringSynchronization.append(writeOperation.record.key.hash());
</del><ins>+            m_blobFilterHashesAddedDuringSynchronization.append(writeOperation.record.key.hash());
</ins><span class="cx"> 
</span><span class="cx">         if (writeOperation.mappedBodyHandler)
</span><span class="cx">             writeOperation.mappedBodyHandler(blob.data);
</span><span class="lines">@@ -523,7 +550,7 @@
</span><span class="cx"> 
</span><span class="cx">     serialBackgroundIOQueue().dispatch([this, key] {
</span><span class="cx">         WebCore::deleteFile(recordPathForKey(key));
</span><del>-        m_blobStorage.remove(bodyPathForKey(key));
</del><ins>+        m_blobStorage.remove(blobPathForKey(key));
</ins><span class="cx">     });
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -546,7 +573,7 @@
</span><span class="cx">     const auto readTimeout = 1500_ms;
</span><span class="cx">     m_readOperationTimeoutTimer.startOneShot(readTimeout);
</span><span class="cx"> 
</span><del>-    bool shouldGetBodyBlob = !m_bodyFilter || m_bodyFilter-&gt;mayContain(readOperation.key.hash());
</del><ins>+    bool shouldGetBodyBlob = mayContainBlob(readOperation.key);
</ins><span class="cx"> 
</span><span class="cx">     ioQueue().dispatch([this, &amp;readOperation, shouldGetBodyBlob] {
</span><span class="cx">         auto recordPath = recordPathForKey(readOperation.key);
</span><span class="lines">@@ -563,9 +590,9 @@
</span><span class="cx">         });
</span><span class="cx"> 
</span><span class="cx">         if (shouldGetBodyBlob) {
</span><del>-            // Read the body blob in parallel with the record read.
-            auto bodyPath = bodyPathForKey(readOperation.key);
-            readOperation.resultBodyBlob = m_blobStorage.get(bodyPath);
</del><ins>+            // Read the blob in parallel with the record read.
+            auto blobPath = blobPathForKey(readOperation.key);
+            readOperation.resultBodyBlob = m_blobStorage.get(blobPath);
</ins><span class="cx">             finishReadOperation(readOperation);
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="lines">@@ -574,7 +601,7 @@
</span><span class="cx"> void Storage::finishReadOperation(ReadOperation&amp; readOperation)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(readOperation.activeCount);
</span><del>-    // Record and body blob reads must finish.
</del><ins>+    // Record and blob reads must finish.
</ins><span class="cx">     if (--readOperation.activeCount)
</span><span class="cx">         return;
</span><span class="cx"> 
</span><span class="lines">@@ -681,17 +708,17 @@
</span><span class="cx">     addToRecordFilter(writeOperation.record.key);
</span><span class="cx"> 
</span><span class="cx">     backgroundIOQueue().dispatch([this, &amp;writeOperation] {
</span><del>-        auto partitionPath = partitionPathForKey(writeOperation.record.key);
</del><ins>+        auto recordDirectorPath = recordDirectoryPathForKey(writeOperation.record.key);
</ins><span class="cx">         auto recordPath = recordPathForKey(writeOperation.record.key);
</span><span class="cx"> 
</span><del>-        WebCore::makeAllDirectories(partitionPath);
</del><ins>+        WebCore::makeAllDirectories(recordDirectorPath);
</ins><span class="cx"> 
</span><span class="cx">         ++writeOperation.activeCount;
</span><span class="cx"> 
</span><span class="cx">         bool shouldStoreAsBlob = shouldStoreBodyAsBlob(writeOperation.record.body);
</span><del>-        auto bodyBlob = shouldStoreAsBlob ? storeBodyAsBlob(writeOperation) : Nullopt;
</del><ins>+        auto blob = shouldStoreAsBlob ? storeBodyAsBlob(writeOperation) : Nullopt;
</ins><span class="cx"> 
</span><del>-        auto recordData = encodeRecord(writeOperation.record, bodyBlob);
</del><ins>+        auto recordData = encodeRecord(writeOperation.record, blob);
</ins><span class="cx"> 
</span><span class="cx">         auto channel = IOChannel::open(recordPath, IOChannel::Type::Create);
</span><span class="cx">         size_t recordSize = recordData.size();
</span><span class="lines">@@ -770,28 +797,30 @@
</span><span class="cx">     m_writeOperationDispatchTimer.startOneShot(initialWriteDelay);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Storage::traverse(TraverseFlags flags, TraverseHandler&amp;&amp; traverseHandler)
</del><ins>+void Storage::traverse(const String&amp; type, TraverseFlags flags, TraverseHandler&amp;&amp; traverseHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(RunLoop::isMain());
</span><span class="cx">     ASSERT(traverseHandler);
</span><span class="cx">     // Avoid non-thread safe std::function copies.
</span><span class="cx"> 
</span><del>-    auto traverseOperationPtr = std::make_unique&lt;TraverseOperation&gt;(flags, WTF::move(traverseHandler));
</del><ins>+    auto traverseOperationPtr = std::make_unique&lt;TraverseOperation&gt;(type, flags, WTF::move(traverseHandler));
</ins><span class="cx">     auto&amp; traverseOperation = *traverseOperationPtr;
</span><span class="cx">     m_activeTraverseOperations.add(WTF::move(traverseOperationPtr));
</span><span class="cx"> 
</span><span class="cx">     ioQueue().dispatch([this, &amp;traverseOperation] {
</span><del>-        traverseRecordsFiles(recordsPath(), [this, &amp;traverseOperation](const String&amp; fileName, const String&amp; partitionPath) {
-            if (fileName.length() != Key::hashStringLength())
</del><ins>+        traverseRecordsFiles(recordsPath(), traverseOperation.type, [this, &amp;traverseOperation](const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath) {
+            ASSERT(type == traverseOperation.type);
+            if (isBodyBlob)
</ins><span class="cx">                 return;
</span><del>-            auto recordPath = WebCore::pathByAppendingComponent(partitionPath, fileName);
</del><span class="cx"> 
</span><ins>+            auto recordPath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName);
+
</ins><span class="cx">             double worth = -1;
</span><span class="cx">             if (traverseOperation.flags &amp; TraverseFlag::ComputeWorth)
</span><span class="cx">                 worth = computeRecordWorth(fileTimes(recordPath));
</span><span class="cx">             unsigned bodyShareCount = 0;
</span><span class="cx">             if (traverseOperation.flags &amp; TraverseFlag::ShareCount)
</span><del>-                bodyShareCount = m_blobStorage.shareCount(bodyPathForRecordPath(recordPath));
</del><ins>+                bodyShareCount = m_blobStorage.shareCount(blobPathForRecordPath(recordPath));
</ins><span class="cx"> 
</span><span class="cx">             std::unique_lock&lt;Lock&gt; lock(traverseOperation.activeMutex);
</span><span class="cx">             ++traverseOperation.activeCount;
</span><span class="lines">@@ -856,24 +885,24 @@
</span><span class="cx">     shrinkIfNeeded();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void Storage::clear(std::chrono::system_clock::time_point modifiedSinceTime, std::function&lt;void ()&gt;&amp;&amp; completionHandler)
</del><ins>+void Storage::clear(const String&amp; type, std::chrono::system_clock::time_point modifiedSinceTime, std::function&lt;void ()&gt;&amp;&amp; completionHandler)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(RunLoop::isMain());
</span><span class="cx">     LOG(NetworkCacheStorage, &quot;(NetworkProcess) clearing cache&quot;);
</span><span class="cx"> 
</span><span class="cx">     if (m_recordFilter)
</span><span class="cx">         m_recordFilter-&gt;clear();
</span><del>-    if (m_bodyFilter)
-        m_bodyFilter-&gt;clear();
</del><ins>+    if (m_blobFilter)
+        m_blobFilter-&gt;clear();
</ins><span class="cx">     m_approximateRecordsSize = 0;
</span><span class="cx"> 
</span><span class="cx">     // Avoid non-thread safe std::function copies.
</span><span class="cx">     auto* completionHandlerPtr = completionHandler ? new std::function&lt;void ()&gt;(WTF::move(completionHandler)) : nullptr;
</span><del>-
-    ioQueue().dispatch([this, modifiedSinceTime, completionHandlerPtr] {
</del><ins>+    StringCapture typeCapture(type);
+    ioQueue().dispatch([this, modifiedSinceTime, completionHandlerPtr, typeCapture] {
</ins><span class="cx">         auto recordsPath = this-&gt;recordsPath();
</span><del>-        traverseRecordsFiles(recordsPath, [modifiedSinceTime](const String&amp; fileName, const String&amp; partitionPath) {
-            auto filePath = WebCore::pathByAppendingComponent(partitionPath, fileName);
</del><ins>+        traverseRecordsFiles(recordsPath, typeCapture.string(), [modifiedSinceTime](const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath) {
+            auto filePath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName);
</ins><span class="cx">             if (modifiedSinceTime &gt; std::chrono::system_clock::time_point::min()) {
</span><span class="cx">                 auto times = fileTimes(filePath);
</span><span class="cx">                 if (times.modification &lt; modifiedSinceTime)
</span><span class="lines">@@ -884,7 +913,7 @@
</span><span class="cx"> 
</span><span class="cx">         deleteEmptyRecordsDirectories(recordsPath);
</span><span class="cx"> 
</span><del>-        // This cleans unreferences blobs.
</del><ins>+        // This cleans unreferenced blobs.
</ins><span class="cx">         m_blobStorage.synchronize();
</span><span class="cx"> 
</span><span class="cx">         if (completionHandlerPtr) {
</span><span class="lines">@@ -950,14 +979,16 @@
</span><span class="cx"> 
</span><span class="cx">     backgroundIOQueue().dispatch([this] {
</span><span class="cx">         auto recordsPath = this-&gt;recordsPath();
</span><del>-        traverseRecordsFiles(recordsPath, [this](const String&amp; fileName, const String&amp; partitionPath) {
-            if (fileName.length() != Key::hashStringLength())
</del><ins>+        String anyType;
+        traverseRecordsFiles(recordsPath, anyType, [this](const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath) {
+            if (isBodyBlob)
</ins><span class="cx">                 return;
</span><del>-            auto recordPath = WebCore::pathByAppendingComponent(partitionPath, fileName);
-            auto bodyPath = bodyPathForRecordPath(recordPath);
</del><span class="cx"> 
</span><ins>+            auto recordPath = WebCore::pathByAppendingComponent(recordDirectoryPath, fileName);
+            auto blobPath = blobPathForRecordPath(recordPath);
+
</ins><span class="cx">             auto times = fileTimes(recordPath);
</span><del>-            unsigned bodyShareCount = m_blobStorage.shareCount(bodyPath);
</del><ins>+            unsigned bodyShareCount = m_blobStorage.shareCount(blobPath);
</ins><span class="cx">             auto probability = deletionProbability(times, bodyShareCount);
</span><span class="cx"> 
</span><span class="cx">             bool shouldDelete = randomNumber() &lt; probability;
</span><span class="lines">@@ -966,7 +997,7 @@
</span><span class="cx"> 
</span><span class="cx">             if (shouldDelete) {
</span><span class="cx">                 WebCore::deleteFile(recordPath);
</span><del>-                m_blobStorage.remove(bodyPath);
</del><ins>+                m_blobStorage.remove(blobPath);
</ins><span class="cx">             }
</span><span class="cx">         });
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscacheNetworkCacheStorageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h (191305 => 191306)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h        2015-10-19 19:19:09 UTC (rev 191305)
+++ trunk/Source/WebKit2/NetworkProcess/cache/NetworkCacheStorage.h        2015-10-19 19:21:22 UTC (rev 191306)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">     void store(const Record&amp;, MappedBodyHandler&amp;&amp;);
</span><span class="cx"> 
</span><span class="cx">     void remove(const Key&amp;);
</span><del>-    void clear(std::chrono::system_clock::time_point modifiedSinceTime, std::function&lt;void ()&gt;&amp;&amp; completionHandler);
</del><ins>+    void clear(const String&amp; type, std::chrono::system_clock::time_point modifiedSinceTime, std::function&lt;void ()&gt;&amp;&amp; completionHandler);
</ins><span class="cx"> 
</span><span class="cx">     struct RecordInfo {
</span><span class="cx">         size_t bodySize;
</span><span class="lines">@@ -80,13 +80,13 @@
</span><span class="cx">     typedef unsigned TraverseFlags;
</span><span class="cx">     typedef std::function&lt;void (const Record*, const RecordInfo&amp;)&gt; TraverseHandler;
</span><span class="cx">     // Null record signals end.
</span><del>-    void traverse(TraverseFlags, TraverseHandler&amp;&amp;);
</del><ins>+    void traverse(const String&amp; type, TraverseFlags, TraverseHandler&amp;&amp;);
</ins><span class="cx"> 
</span><span class="cx">     void setCapacity(size_t);
</span><span class="cx">     size_t capacity() const { return m_capacity; }
</span><span class="cx">     size_t approximateSize() const;
</span><span class="cx"> 
</span><del>-    static const unsigned version = 4;
</del><ins>+    static const unsigned version = 5;
</ins><span class="cx"> 
</span><span class="cx">     String basePath() const;
</span><span class="cx">     String versionPath() const;
</span><span class="lines">@@ -97,9 +97,9 @@
</span><span class="cx"> private:
</span><span class="cx">     Storage(const String&amp; directoryPath);
</span><span class="cx"> 
</span><del>-    String partitionPathForKey(const Key&amp;) const;
</del><ins>+    String recordDirectoryPathForKey(const Key&amp;) const;
</ins><span class="cx">     String recordPathForKey(const Key&amp;) const;
</span><del>-    String bodyPathForKey(const Key&amp;) const;
</del><ins>+    String blobPathForKey(const Key&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     void synchronize();
</span><span class="cx">     void deleteOldVersions();
</span><span class="lines">@@ -129,6 +129,7 @@
</span><span class="cx">     WorkQueue&amp; serialBackgroundIOQueue() { return m_serialBackgroundIOQueue.get(); }
</span><span class="cx"> 
</span><span class="cx">     bool mayContain(const Key&amp;) const;
</span><ins>+    bool mayContainBlob(const Key&amp;) const;
</ins><span class="cx"> 
</span><span class="cx">     void addToRecordFilter(const Key&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -141,13 +142,13 @@
</span><span class="cx">     // 2^18 bit filter can support up to 26000 entries with false positive rate &lt; 1%.
</span><span class="cx">     using ContentsFilter = BloomFilter&lt;18&gt;;
</span><span class="cx">     std::unique_ptr&lt;ContentsFilter&gt; m_recordFilter;
</span><del>-    std::unique_ptr&lt;ContentsFilter&gt; m_bodyFilter;
</del><ins>+    std::unique_ptr&lt;ContentsFilter&gt; m_blobFilter;
</ins><span class="cx"> 
</span><span class="cx">     bool m_synchronizationInProgress { false };
</span><span class="cx">     bool m_shrinkInProgress { false };
</span><span class="cx"> 
</span><span class="cx">     Vector&lt;Key::HashType&gt; m_recordFilterHashesAddedDuringSynchronization;
</span><del>-    Vector&lt;Key::HashType&gt; m_bodyFilterHashesAddedDuringSynchronization;
</del><ins>+    Vector&lt;Key::HashType&gt; m_blobFilterHashesAddedDuringSynchronization;
</ins><span class="cx"> 
</span><span class="cx">     static const int maximumRetrievePriority = 4;
</span><span class="cx">     Deque&lt;std::unique_ptr&lt;ReadOperation&gt;&gt; m_pendingReadOperationsByPriority[maximumRetrievePriority + 1];
</span><span class="lines">@@ -169,7 +170,7 @@
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> // FIXME: Remove, used by NetworkCacheStatistics only.
</span><del>-void traverseRecordsFiles(const String&amp; recordsPath, const std::function&lt;void (const String&amp;, const String&amp;)&gt;&amp;);
</del><ins>+void traverseRecordsFiles(const String&amp; recordsPath, const String&amp; type, const std::function&lt;void (const String&amp; fileName, const String&amp; hashString, const String&amp; type, bool isBodyBlob, const String&amp; recordDirectoryPath)&gt;&amp;);
</ins><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>