OLD | NEW |
---|---|
(Empty) | |
1 # Architecture | |
michaeln
2016/07/28 22:26:47
lgtm - maybe put a date on it, sometimes separate
jkarlin
2016/07/29 12:57:19
Done.
| |
2 This document descibes the browser-process implementation of the [Cache | |
3 Storage specification]( | |
4 https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html). | |
5 | |
6 ## Major Classes and Ownership | |
7 ### Ownership | |
8 Where '=>' represents ownership, '->' is a reference, and '~>' is a weak | |
9 reference. | |
10 | |
11 ##### `CacheStorageContextImpl`=>`CacheStorageManager`=>`CacheStorage`=>`CacheSt orageCache` | |
12 * A `CacheStorageManager` can own multiple `CacheStorage` objects. | |
13 * A `CacheStorage` can own multiple `CacheStorageCache` objects. | |
14 | |
15 ##### `StoragePartitionImpl`->`CacheStorageContextImpl` | |
16 * `StoragePartitionImpl` effectively owns the `CacheStorageContextImpl` in the | |
17 sense that it calls `CacheStorageContextImpl::Shutdown()` on deletion which | |
18 resets its `CacheStorageManager`. | |
19 | |
20 ##### `RenderProcessHost`->`CacheStorageDispatcherHost`->`CacheStorageContextImp l` | |
21 | |
22 ##### `CacheStorageDispatcherHost`=>`CacheStorageCacheHandle`~>`CacheStorageCach e` | |
23 * The `CacheStorageDispatcherHost` holds onto handles for: | |
24 * currently running operations | |
25 * JavaScript references to caches | |
26 * recently opened caches (to prevent open/close/open churn) | |
27 | |
28 ##### `CacheStorageCacheDataHandle`=>`CacheStorageCacheHandle`~>`CacheStorageCac he` | |
29 * `CacheStorageCacheDataHandle` is the blob data handle for a response body | |
30 and it holds a `CacheStorageCacheHandle`. It streams from the | |
31 `disk_cache::Entry` response stream. It's necessary that the | |
32 `disk_cache::Backend` (owned by `CacheStorageCache`) stays open so long as | |
33 one of its `disk_cache::Entry`s is reachable. Otherwise, a new backend might | |
34 open and clobber the entry. | |
35 | |
36 ### CacheStorageDispatcherHost | |
37 1. Receives IPC messages from a render process and creates the appropriate | |
38 `CacheStorageManager` or `CacheStorageCache` operation. | |
39 2. For each operation, holds a `CacheStorageCacheHandle` to keep the cache | |
40 alive since the operation is asynchronous. | |
41 3. For each cache reference held by the render process, holds a | |
42 `CacheStorageCacheHandle`. | |
43 4. Holds a newly opened cache open for a few seconds (by storing a handle) to | |
44 mitigate rapid opening/closing/opening churn. | |
45 | |
46 ### CacheStorageManager | |
47 1. Forwards calls to the appropriate `CacheStorage` for a given origin, | |
48 loading `CacheStorage`s on demand. | |
49 2. Handles `QuotaManager` and `BrowsingData` calls. | |
50 | |
51 ### CacheStorage | |
52 1. Manages the caches for a single origin. | |
53 2. Handles creation/deletion of caches and updates the index on disk | |
54 accordingly. | |
55 3. Manages operations that span multiple caches (e.g., `CacheStorage::Match`). | |
56 4. Backend-specific information is handled by `CacheStorage::CacheLoader` | |
57 | |
58 ### CacheStorageCache | |
59 1. Creates or opens a net::disk_cache (either `SimpleCache` or `MemoryCache`) | |
60 on initialization. | |
61 2. Handles add/put/delete/match/keys calls. | |
62 3. Owned by `CacheStorage` and deleted either when `CacheStorage` deletes or | |
63 when the last `CacheStorageCacheHandle` for the cache is gone. | |
64 | |
65 ### CacheStorageCacheHandle | |
66 1. Holds a weak reference to a `CacheStorageCache`. | |
67 2. When the last `CacheStorageCacheHandle` to a `CacheStorageCache` is | |
68 deleted, so to is the `CacheStorageCache`. | |
69 3. The `CacheStorageCache` may be deleted before the `CacheStorageCacheHandle` | |
70 (on `CacheStorage` destruction), so it must be checked for validity before | |
71 use. | |
72 | |
73 ## Directory Structure | |
74 $PROFILE/Service Worker/CacheStorage/`origin`/`cache`/ | |
75 | |
76 Where `origin` is a hash of the origin and `cache` is a GUID generated at the | |
77 cache's creation time. | |
78 | |
79 The reason a random directory is used for a cache is so that a cache can be | |
80 doomed and still used by old references while another cache with the same name | |
81 is created. | |
82 | |
83 ### Directory Contents | |
84 `CacheStorage` creates its own index file (index.txt), which contains a | |
85 mapping of cache names to its path on disk. On `CacheStorage` initialization, | |
86 directories not in the index are deleted. | |
87 | |
88 Each `CacheStorageCache` has a `disk_cache::Backend` backend, which writes in | |
89 the `CacheStorageCache`'s directory. | |
90 | |
91 ## Layout of the disk_cache::Backend | |
92 A cache is represented by a `disk_cache::Backend`. The Request/Response pairs | |
93 referred to in the specification are stored as `disk_cache::Entry`s. Each | |
94 `disk_cache::Entry` has three streams: one for storing a protobuf with the | |
95 request/response metadata (e.g., the headers, the request URL, and opacity | |
96 information), another for storing the response body, and a final stream for | |
97 storing any additional data (e.g., compiled JavaScript). | |
98 | |
99 The entries are keyed by full URL. This has a few ramifications: | |
100 1. Multiple vary responses for a single request URL are not supported. | |
101 2. Operations that may require scanning multiple URLs (e.g., `ignoreSearch`) | |
102 must scan every entry in the cache. | |
103 | |
104 *The above could be fixed by changes to the backend or by introducing indirect | |
105 entries in the cache. The indirect entries would be for the query-stripped | |
106 request URL. It would point to entries to each query request/response pair and | |
107 for each vary request/response pair.* | |
108 | |
109 ## Threads | |
110 * CacheStorage classes live on the IO thread. Exceptions include: | |
111 * `CacheStorageContextImpl` which is created on UI but otherwise runs and is | |
112 deleted on IO. | |
113 * `CacheStorageDispatcherHost` which is created on UI but otherwise runs and | |
114 is deleted on IO. | |
115 * Index file manipulation and directory creation/deletion occurs on a | |
116 `SequencedTaskRunner` assigned at `CacheStorageContextImpl` creation. | |
117 * The `disk_cache::Backend` lives on the IO thread and uses its own worker | |
118 pool to implement async operations. | |
119 | |
120 ## Asynchronous Idioms in CacheStorage and CacheStorageCache | |
121 1. All async methods should asynchronously run their callbacks. | |
122 2. The async methods often include several asynchronous steps. Each step | |
123 passes a continuation callback on to the next. The continuation includes | |
124 all of the necessary state for the operation. | |
125 3. Callbacks are guaranteed to run so long as the object | |
126 (`CacheStorageCacheCache` or `CacheStorage`) is still alive. Once the | |
127 object is deleted, the callbacks are dropped. We don't worry about dropped | |
128 callbacks on shutdown. If deleting prior to shutdown, one should `Close()` | |
129 a `CacheStorage` or `CacheStorageCache` to ensure that all operations have | |
130 completed before deleting it. | |
131 | |
132 ### Scheduling Operations | |
133 Operations are scheduled in a sequential scheduler (`CacheStorageScheduler`). | |
134 Each `CacheStorage` and `CacheStorageCache` has its own scheduler. If an | |
135 operation freezes, then the scheduler is frozen. If a `CacheStorage` call winds | |
136 up calling something from every `CacheStorageCache` (e.g., | |
137 `CacheStorage::Match`), then one frozen `CacheStorageCache` can freeze the | |
138 `CacheStorage` as well. This has happened in the past (`Cache::Put` called | |
139 `QuotaManager` to determine how much room was available, which in turn called | |
140 `Cache::Size`). Be careful to avoid situations in which one operation triggers | |
141 a dependency on another operation from the same scheduler. | |
142 | |
143 At the end of an operation, the scheduler needs to be kicked to start the next | |
144 operation. The idiom for this in CacheStorage/ is to wrap the operation's | |
145 callback with a function that will run the callback as well as advance the | |
146 scheduler. So long as the operation runs its wrapped callback the scheduler | |
147 will advance. | |
OLD | NEW |