45ba8b0bb749ed634388fd8ac88e4c62e34983de
[WebKit.git] / Source / WebKit / NetworkProcess / cache / NetworkCacheStorage.h
1 /*
2  * Copyright (C) 2014-2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #pragma once
27
28 #include "NetworkCacheBlobStorage.h"
29 #include "NetworkCacheData.h"
30 #include "NetworkCacheKey.h"
31 #include <WebCore/Timer.h>
32 #include <wtf/BloomFilter.h>
33 #include <wtf/Deque.h>
34 #include <wtf/Function.h>
35 #include <wtf/HashSet.h>
36 #include <wtf/Optional.h>
37 #include <wtf/WorkQueue.h>
38 #include <wtf/text/WTFString.h>
39
40 namespace WebKit {
41 namespace NetworkCache {
42
43 class IOChannel;
44
45 class Storage : public ThreadSafeRefCounted<Storage> {
46 public:
47     enum class Mode { Normal, Testing };
48     static RefPtr<Storage> open(const String& cachePath, Mode);
49
50     struct Record {
51         WTF_MAKE_FAST_ALLOCATED;
52     public:
53         Key key;
54         std::chrono::system_clock::time_point timeStamp;
55         Data header;
56         Data body;
57         std::optional<SHA1::Digest> bodyHash;
58     };
59     // This may call completion handler synchronously on failure.
60     typedef Function<bool (std::unique_ptr<Record>)> RetrieveCompletionHandler;
61     void retrieve(const Key&, unsigned priority, RetrieveCompletionHandler&&);
62
63     typedef Function<void (const Data& mappedBody)> MappedBodyHandler;
64     void store(const Record&, MappedBodyHandler&&);
65
66     void remove(const Key&);
67     void remove(const Vector<Key>&, Function<void ()>&&);
68     void clear(const String& type, std::chrono::system_clock::time_point modifiedSinceTime, Function<void ()>&& completionHandler);
69
70     struct RecordInfo {
71         size_t bodySize;
72         double worth; // 0-1 where 1 is the most valuable.
73         unsigned bodyShareCount;
74         String bodyHash;
75     };
76     enum TraverseFlag {
77         ComputeWorth = 1 << 0,
78         ShareCount = 1 << 1,
79     };
80     typedef unsigned TraverseFlags;
81     typedef Function<void (const Record*, const RecordInfo&)> TraverseHandler;
82     // Null record signals end.
83     void traverse(const String& type, TraverseFlags, TraverseHandler&&);
84
85     void setCapacity(size_t);
86     size_t capacity() const { return m_capacity; }
87     size_t approximateSize() const;
88
89     static const unsigned version = 11;
90 #if PLATFORM(MAC)
91     /// Allow the last stable version of the cache to co-exist with the latest development one.
92     static const unsigned lastStableVersion = 11;
93 #endif
94
95     String basePath() const;
96     String versionPath() const;
97     String recordsPath() const;
98
99     const Salt& salt() const { return m_salt; }
100
101     bool canUseSharedMemoryForBodyData() const { return m_canUseSharedMemoryForBodyData; }
102
103     ~Storage();
104
105     void writeWithoutWaiting() { m_initialWriteDelay = 0_s; };
106
107 private:
108     Storage(const String& directoryPath, Mode, Salt);
109
110     String recordDirectoryPathForKey(const Key&) const;
111     String recordPathForKey(const Key&) const;
112     String blobPathForKey(const Key&) const;
113
114     void synchronize();
115     void deleteOldVersions();
116     void shrinkIfNeeded();
117     void shrink();
118
119     struct ReadOperation;
120     void dispatchReadOperation(std::unique_ptr<ReadOperation>);
121     void dispatchPendingReadOperations();
122     void finishReadOperation(ReadOperation&);
123     void cancelAllReadOperations();
124
125     struct WriteOperation;
126     void dispatchWriteOperation(std::unique_ptr<WriteOperation>);
127     void dispatchPendingWriteOperations();
128     void finishWriteOperation(WriteOperation&);
129
130     std::optional<BlobStorage::Blob> storeBodyAsBlob(WriteOperation&);
131     Data encodeRecord(const Record&, std::optional<BlobStorage::Blob>);
132     void readRecord(ReadOperation&, const Data&);
133
134     void updateFileModificationTime(const String& path);
135     void removeFromPendingWriteOperations(const Key&);
136
137     WorkQueue& ioQueue() { return m_ioQueue.get(); }
138     WorkQueue& backgroundIOQueue() { return m_backgroundIOQueue.get(); }
139     WorkQueue& serialBackgroundIOQueue() { return m_serialBackgroundIOQueue.get(); }
140
141     bool mayContain(const Key&) const;
142     bool mayContainBlob(const Key&) const;
143
144     void addToRecordFilter(const Key&);
145     void deleteFiles(const Key&);
146
147     const String m_basePath;
148     const String m_recordsPath;
149     
150     const Mode m_mode;
151     const Salt m_salt;
152     const bool m_canUseSharedMemoryForBodyData;
153
154     size_t m_capacity { std::numeric_limits<size_t>::max() };
155     size_t m_approximateRecordsSize { 0 };
156
157     // 2^18 bit filter can support up to 26000 entries with false positive rate < 1%.
158     using ContentsFilter = BloomFilter<18>;
159     std::unique_ptr<ContentsFilter> m_recordFilter;
160     std::unique_ptr<ContentsFilter> m_blobFilter;
161
162     bool m_synchronizationInProgress { false };
163     bool m_shrinkInProgress { false };
164
165     Vector<Key::HashType> m_recordFilterHashesAddedDuringSynchronization;
166     Vector<Key::HashType> m_blobFilterHashesAddedDuringSynchronization;
167
168     static const int maximumRetrievePriority = 4;
169     Deque<std::unique_ptr<ReadOperation>> m_pendingReadOperationsByPriority[maximumRetrievePriority + 1];
170     HashSet<std::unique_ptr<ReadOperation>> m_activeReadOperations;
171     WebCore::Timer m_readOperationTimeoutTimer;
172
173     Deque<std::unique_ptr<WriteOperation>> m_pendingWriteOperations;
174     HashSet<std::unique_ptr<WriteOperation>> m_activeWriteOperations;
175     WebCore::Timer m_writeOperationDispatchTimer;
176
177     struct TraverseOperation;
178     HashSet<std::unique_ptr<TraverseOperation>> m_activeTraverseOperations;
179
180     Ref<WorkQueue> m_ioQueue;
181     Ref<WorkQueue> m_backgroundIOQueue;
182     Ref<WorkQueue> m_serialBackgroundIOQueue;
183
184     BlobStorage m_blobStorage;
185
186     // By default, delay the start of writes a bit to avoid affecting early page load.
187     // Completing writes will dispatch more writes without delay.
188     Seconds m_initialWriteDelay { 1_s };
189 };
190
191 // FIXME: Remove, used by NetworkCacheStatistics only.
192 using RecordFileTraverseFunction = Function<void (const String& fileName, const String& hashString, const String& type, bool isBlob, const String& recordDirectoryPath)>;
193 void traverseRecordsFiles(const String& recordsPath, const String& type, const RecordFileTraverseFunction&);
194
195 }
196 }