OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/nacl_host/pnacl_translation_cache.h" | 5 #include "chrome/browser/nacl_host/pnacl_translation_cache.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/strings/string_number_conversions.h" | |
12 #include "base/threading/thread_checker.h" | 11 #include "base/threading/thread_checker.h" |
13 #include "components/nacl/common/pnacl_types.h" | |
14 #include "content/public/browser/browser_thread.h" | 12 #include "content/public/browser/browser_thread.h" |
15 #include "net/base/io_buffer.h" | 13 #include "net/base/io_buffer.h" |
16 #include "net/base/net_errors.h" | 14 #include "net/base/net_errors.h" |
17 #include "net/disk_cache/disk_cache.h" | 15 #include "net/disk_cache/disk_cache.h" |
18 | 16 |
19 using base::IntToString; | |
20 using content::BrowserThread; | 17 using content::BrowserThread; |
21 | 18 |
22 namespace { | 19 namespace { |
23 | 20 |
24 void CloseDiskCacheEntry(disk_cache::Entry* entry) { entry->Close(); } | 21 void CloseDiskCacheEntry(disk_cache::Entry* entry) { entry->Close(); } |
25 | 22 |
26 } // namespace | 23 } // namespace |
27 | 24 |
28 namespace pnacl { | 25 namespace pnacl { |
29 // These are in pnacl namespace instead of static so they can be used | 26 // These are in pnacl_cache namespace instead of static so they can be used |
30 // by the unit test. | 27 // by the unit test. |
31 const int kMaxDiskCacheSize = 1000 * 1024 * 1024; | 28 const int kMaxDiskCacheSize = 1000 * 1024 * 1024; |
32 const int kMaxMemCacheSize = 100 * 1024 * 1024; | 29 const int kMaxMemCacheSize = 100 * 1024 * 1024; |
33 | 30 |
34 ////////////////////////////////////////////////////////////////////// | 31 ////////////////////////////////////////////////////////////////////// |
35 // Handle Reading/Writing to Cache. | 32 // Handle Reading/Writing to Cache. |
36 | 33 |
37 // PnaclTranslationCacheEntry is a shim that provides storage for the | 34 // PnaclTranslationCacheEntry is a shim that provides storage for the |
38 // 'key' and 'data' strings as the disk_cache is performing various async | 35 // 'key' and 'data' strings as the disk_cache is performing various async |
39 // operations. It also tracks the open disk_cache::Entry | 36 // operations. It also tracks the open disk_cache::Entry |
40 // and ensures that the entry is closed. | 37 // and ensures that the entry is closed. |
41 class PnaclTranslationCacheEntry | 38 class PnaclTranslationCacheEntry |
42 : public base::RefCounted<PnaclTranslationCacheEntry> { | 39 : public base::RefCounted<PnaclTranslationCacheEntry> { |
43 public: | 40 public: |
44 static PnaclTranslationCacheEntry* GetReadEntry( | 41 PnaclTranslationCacheEntry(base::WeakPtr<PnaclTranslationCache> cache, |
45 base::WeakPtr<PnaclTranslationCache> cache, | 42 const std::string& key, |
46 const std::string& key, | 43 std::string* read_nexe, |
47 const GetNexeCallback& callback); | 44 const std::string& write_nexe, |
48 static PnaclTranslationCacheEntry* GetWriteEntry( | 45 const CompletionCallback& callback, |
49 base::WeakPtr<PnaclTranslationCache> cache, | 46 bool is_read); |
50 const std::string& key, | |
51 net::DrainableIOBuffer* write_nexe, | |
52 const CompletionCallback& callback); | |
53 | |
54 void Start(); | 47 void Start(); |
55 | 48 |
56 // Writes: --- | 49 // Writes: --- |
57 // v | | 50 // v | |
58 // Start -> Open Existing --------------> Write ---> Close | 51 // Start -> Open Existing --------------> Write ---> Close |
59 // \ ^ | 52 // \ ^ |
60 // \ / | 53 // \ / |
61 // --> Create -- | 54 // --> Create -- |
62 // Reads: | 55 // Reads: |
63 // Start -> Open --------Read ----> Close | 56 // Start -> Open --------Read ----> Close |
64 // | ^ | 57 // | ^ |
65 // |__| | 58 // |__| |
66 enum CacheStep { | 59 enum CacheStep { |
67 UNINITIALIZED, | 60 UNINITIALIZED, |
68 OPEN_ENTRY, | 61 OPEN_ENTRY, |
69 CREATE_ENTRY, | 62 CREATE_ENTRY, |
70 TRANSFER_ENTRY, | 63 TRANSFER_ENTRY, |
71 CLOSE_ENTRY | 64 CLOSE_ENTRY |
72 }; | 65 }; |
73 | 66 |
74 private: | 67 private: |
75 friend class base::RefCounted<PnaclTranslationCacheEntry>; | 68 friend class base::RefCounted<PnaclTranslationCacheEntry>; |
76 PnaclTranslationCacheEntry(base::WeakPtr<PnaclTranslationCache> cache, | |
77 const std::string& key, | |
78 bool is_read); | |
79 ~PnaclTranslationCacheEntry(); | 69 ~PnaclTranslationCacheEntry(); |
80 | 70 |
81 // Try to open an existing entry in the backend | 71 // Try to open an existing entry in the backend |
82 void OpenEntry(); | 72 void OpenEntry(); |
83 // Create a new entry in the backend (for writes) | 73 // Create a new entry in the backend (for writes) |
84 void CreateEntry(); | 74 void CreateEntry(); |
85 // Write |len| bytes to the backend, starting at |offset| | 75 // Write |len| bytes to the backend, starting at |offset| |
86 void WriteEntry(int offset, int len); | 76 void WriteEntry(int offset, int len); |
87 // Read |len| bytes from the backend, starting at |offset| | 77 // Read |len| bytes from the backend, starting at |offset| |
88 void ReadEntry(int offset, int len); | 78 void ReadEntry(int offset, int len); |
89 // If there was an error, doom the entry. Then post a task to the IO | 79 // If there was an error, doom the entry. Then post a task to the IO |
90 // thread to close (and delete) it. | 80 // thread to close (and delete) it. |
91 void CloseEntry(int rv); | 81 void CloseEntry(int rv); |
92 // Call the user callback, and signal to the cache to delete this. | 82 // Call the user callback, and signal to the cache to delete this. |
93 void Finish(int rv); | 83 void Finish(int rv); |
94 // Used as the callback for all operations to the backend. Handle state | 84 // Used as the callback for all operations to the backend. Handle state |
95 // transitions, track bytes transferred, and call the other helper methods. | 85 // transitions, track bytes transferred, and call the other helper methods. |
96 void DispatchNext(int rv); | 86 void DispatchNext(int rv); |
| 87 // Get the total transfer size. For reads, must be called after the backend |
| 88 // entry has been opened. |
| 89 int GetTransferSize(); |
97 | 90 |
98 base::WeakPtr<PnaclTranslationCache> cache_; | 91 base::WeakPtr<PnaclTranslationCache> cache_; |
| 92 |
99 std::string key_; | 93 std::string key_; |
| 94 std::string* read_nexe_; |
| 95 std::string write_nexe_; |
100 disk_cache::Entry* entry_; | 96 disk_cache::Entry* entry_; |
101 CacheStep step_; | 97 CacheStep step_; |
102 bool is_read_; | 98 bool is_read_; |
103 GetNexeCallback read_callback_; | 99 int bytes_transferred_; |
104 CompletionCallback write_callback_; | 100 int bytes_to_transfer_; |
105 scoped_refptr<net::DrainableIOBuffer> io_buf_; | 101 scoped_refptr<net::IOBufferWithSize> read_buf_; |
| 102 CompletionCallback finish_callback_; |
106 base::ThreadChecker thread_checker_; | 103 base::ThreadChecker thread_checker_; |
107 DISALLOW_COPY_AND_ASSIGN(PnaclTranslationCacheEntry); | 104 DISALLOW_COPY_AND_ASSIGN(PnaclTranslationCacheEntry); |
108 }; | 105 }; |
109 | 106 |
110 // static | |
111 PnaclTranslationCacheEntry* PnaclTranslationCacheEntry::GetReadEntry( | |
112 base::WeakPtr<PnaclTranslationCache> cache, | |
113 const std::string& key, | |
114 const GetNexeCallback& callback) { | |
115 PnaclTranslationCacheEntry* entry( | |
116 new PnaclTranslationCacheEntry(cache, key, true)); | |
117 entry->read_callback_ = callback; | |
118 return entry; | |
119 } | |
120 | |
121 // static | |
122 PnaclTranslationCacheEntry* PnaclTranslationCacheEntry::GetWriteEntry( | |
123 base::WeakPtr<PnaclTranslationCache> cache, | |
124 const std::string& key, | |
125 net::DrainableIOBuffer* write_nexe, | |
126 const CompletionCallback& callback) { | |
127 PnaclTranslationCacheEntry* entry( | |
128 new PnaclTranslationCacheEntry(cache, key, false)); | |
129 entry->io_buf_ = write_nexe; | |
130 entry->write_callback_ = callback; | |
131 return entry; | |
132 } | |
133 | |
134 PnaclTranslationCacheEntry::PnaclTranslationCacheEntry( | 107 PnaclTranslationCacheEntry::PnaclTranslationCacheEntry( |
135 base::WeakPtr<PnaclTranslationCache> cache, | 108 base::WeakPtr<PnaclTranslationCache> cache, |
136 const std::string& key, | 109 const std::string& key, |
| 110 std::string* read_nexe, |
| 111 const std::string& write_nexe, |
| 112 const CompletionCallback& callback, |
137 bool is_read) | 113 bool is_read) |
138 : cache_(cache), | 114 : cache_(cache), |
139 key_(key), | 115 key_(key), |
| 116 read_nexe_(read_nexe), |
| 117 write_nexe_(write_nexe), |
140 entry_(NULL), | 118 entry_(NULL), |
141 step_(UNINITIALIZED), | 119 step_(UNINITIALIZED), |
142 is_read_(is_read) {} | 120 is_read_(is_read), |
| 121 bytes_transferred_(0), |
| 122 bytes_to_transfer_(-1), |
| 123 finish_callback_(callback) {} |
143 | 124 |
144 PnaclTranslationCacheEntry::~PnaclTranslationCacheEntry() { | 125 PnaclTranslationCacheEntry::~PnaclTranslationCacheEntry() { |
145 // Ensure we have called the user's callback | 126 // Ensure we have called the user's callback |
146 DCHECK(read_callback_.is_null()); | 127 DCHECK(finish_callback_.is_null()); |
147 DCHECK(write_callback_.is_null()); | |
148 } | 128 } |
149 | 129 |
150 void PnaclTranslationCacheEntry::Start() { | 130 void PnaclTranslationCacheEntry::Start() { |
151 DCHECK(thread_checker_.CalledOnValidThread()); | 131 DCHECK(thread_checker_.CalledOnValidThread()); |
152 step_ = OPEN_ENTRY; | 132 step_ = OPEN_ENTRY; |
153 OpenEntry(); | 133 OpenEntry(); |
154 } | 134 } |
155 | 135 |
156 // OpenEntry, CreateEntry, WriteEntry, ReadEntry and CloseEntry are only called | 136 // OpenEntry, CreateEntry, WriteEntry, ReadEntry and CloseEntry are only called |
157 // from DispatchNext, so they know that cache_ is still valid. | 137 // from DispatchNext, so they know that cache_ is still valid. |
158 void PnaclTranslationCacheEntry::OpenEntry() { | 138 void PnaclTranslationCacheEntry::OpenEntry() { |
159 int rv = cache_->backend() | 139 int rv = cache_->backend() |
160 ->OpenEntry(key_, | 140 ->OpenEntry(key_, |
161 &entry_, | 141 &entry_, |
162 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); | 142 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); |
163 if (rv != net::ERR_IO_PENDING) | 143 if (rv != net::ERR_IO_PENDING) |
164 DispatchNext(rv); | 144 DispatchNext(rv); |
165 } | 145 } |
166 | 146 |
167 void PnaclTranslationCacheEntry::CreateEntry() { | 147 void PnaclTranslationCacheEntry::CreateEntry() { |
168 int rv = cache_->backend()->CreateEntry( | 148 int rv = cache_->backend()->CreateEntry( |
169 key_, | 149 key_, |
170 &entry_, | 150 &entry_, |
171 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); | 151 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); |
172 if (rv != net::ERR_IO_PENDING) | 152 if (rv != net::ERR_IO_PENDING) |
173 DispatchNext(rv); | 153 DispatchNext(rv); |
174 } | 154 } |
175 | 155 |
176 void PnaclTranslationCacheEntry::WriteEntry(int offset, int len) { | 156 void PnaclTranslationCacheEntry::WriteEntry(int offset, int len) { |
177 DCHECK(io_buf_->BytesRemaining() == len); | 157 scoped_refptr<net::StringIOBuffer> io_buf = |
| 158 new net::StringIOBuffer(write_nexe_.substr(offset, len)); |
178 int rv = entry_->WriteData( | 159 int rv = entry_->WriteData( |
179 1, | 160 1, |
180 offset, | 161 offset, |
181 io_buf_.get(), | 162 io_buf.get(), |
182 len, | 163 len, |
183 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this), | 164 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this), |
184 false); | 165 false); |
185 if (rv != net::ERR_IO_PENDING) | 166 if (rv != net::ERR_IO_PENDING) |
186 DispatchNext(rv); | 167 DispatchNext(rv); |
187 } | 168 } |
188 | 169 |
189 void PnaclTranslationCacheEntry::ReadEntry(int offset, int len) { | 170 void PnaclTranslationCacheEntry::ReadEntry(int offset, int len) { |
| 171 read_buf_ = new net::IOBufferWithSize(len); |
190 int rv = entry_->ReadData( | 172 int rv = entry_->ReadData( |
191 1, | 173 1, |
192 offset, | 174 offset, |
193 io_buf_.get(), | 175 read_buf_.get(), |
194 len, | 176 len, |
195 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); | 177 base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this)); |
196 if (rv != net::ERR_IO_PENDING) | 178 if (rv != net::ERR_IO_PENDING) |
197 DispatchNext(rv); | 179 DispatchNext(rv); |
198 } | 180 } |
199 | 181 |
| 182 int PnaclTranslationCacheEntry::GetTransferSize() { |
| 183 if (is_read_) { |
| 184 DCHECK(entry_); |
| 185 return entry_->GetDataSize(1); |
| 186 } |
| 187 return write_nexe_.size(); |
| 188 } |
| 189 |
200 void PnaclTranslationCacheEntry::CloseEntry(int rv) { | 190 void PnaclTranslationCacheEntry::CloseEntry(int rv) { |
201 DCHECK(entry_); | 191 DCHECK(entry_); |
202 if (rv < 0) | 192 if (rv < 0) |
203 entry_->Doom(); | 193 entry_->Doom(); |
204 BrowserThread::PostTask( | 194 BrowserThread::PostTask( |
205 BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_)); | 195 BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_)); |
206 Finish(rv); | 196 Finish(rv); |
207 } | 197 } |
208 | 198 |
209 void PnaclTranslationCacheEntry::Finish(int rv) { | 199 void PnaclTranslationCacheEntry::Finish(int rv) { |
210 if (is_read_) { | 200 if (!finish_callback_.is_null()) { |
211 if (!read_callback_.is_null()) { | 201 finish_callback_.Run(rv); |
212 read_callback_.Run(rv, io_buf_); | 202 finish_callback_.Reset(); |
213 read_callback_.Reset(); | |
214 } | |
215 } else { | |
216 if (!write_callback_.is_null()) { | |
217 write_callback_.Run(rv); | |
218 write_callback_.Reset(); | |
219 } | |
220 } | 203 } |
221 cache_->OpComplete(this); | 204 cache_->OpComplete(this); |
222 } | 205 } |
223 | 206 |
224 void PnaclTranslationCacheEntry::DispatchNext(int rv) { | 207 void PnaclTranslationCacheEntry::DispatchNext(int rv) { |
225 DCHECK(thread_checker_.CalledOnValidThread()); | 208 DCHECK(thread_checker_.CalledOnValidThread()); |
226 if (!cache_) | 209 if (!cache_) |
227 return; | 210 return; |
228 | 211 |
229 switch (step_) { | 212 switch (step_) { |
230 case UNINITIALIZED: | 213 case UNINITIALIZED: |
231 LOG(ERROR) << "Unexpected step in DispatchNext"; | 214 LOG(ERROR) << "Unexpected step in DispatchNext"; |
232 break; | 215 break; |
233 | 216 |
234 case OPEN_ENTRY: | 217 case OPEN_ENTRY: |
235 if (rv == net::OK) { | 218 if (rv == net::OK) { |
236 step_ = TRANSFER_ENTRY; | 219 step_ = TRANSFER_ENTRY; |
237 if (is_read_) { | 220 bytes_to_transfer_ = GetTransferSize(); |
238 int bytes_to_transfer = entry_->GetDataSize(1); | 221 is_read_ ? ReadEntry(0, bytes_to_transfer_) |
239 io_buf_ = new net::DrainableIOBuffer( | 222 : WriteEntry(0, bytes_to_transfer_); |
240 new net::IOBuffer(bytes_to_transfer), bytes_to_transfer); | |
241 ReadEntry(0, bytes_to_transfer); | |
242 } else { | |
243 WriteEntry(0, io_buf_->size()); | |
244 } | |
245 } else { | 223 } else { |
246 if (is_read_) { | 224 if (is_read_) { |
247 // Just a cache miss, not necessarily an error. | 225 // Just a cache miss, not necessarily an error. |
248 entry_ = NULL; | 226 entry_ = NULL; |
249 Finish(rv); | 227 Finish(rv); |
250 } else { | 228 break; |
251 step_ = CREATE_ENTRY; | |
252 CreateEntry(); | |
253 } | 229 } |
| 230 step_ = CREATE_ENTRY; |
| 231 CreateEntry(); |
254 } | 232 } |
255 break; | 233 break; |
256 | 234 |
257 case CREATE_ENTRY: | 235 case CREATE_ENTRY: |
258 if (rv == net::OK) { | 236 if (rv == net::OK) { |
259 step_ = TRANSFER_ENTRY; | 237 step_ = TRANSFER_ENTRY; |
260 WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining()); | 238 bytes_to_transfer_ = GetTransferSize(); |
| 239 WriteEntry(bytes_transferred_, bytes_to_transfer_ - bytes_transferred_); |
261 } else { | 240 } else { |
262 LOG(ERROR) << "Failed to Create a PNaCl Translation Cache Entry"; | 241 LOG(ERROR) << "Failed to Create a PNaCl Translation Cache Entry"; |
263 Finish(rv); | 242 Finish(rv); |
264 } | 243 } |
265 break; | 244 break; |
266 | 245 |
267 case TRANSFER_ENTRY: | 246 case TRANSFER_ENTRY: |
268 if (rv < 0) { | 247 if (rv < 0) { |
269 // We do not call DispatchNext directly if WriteEntry/ReadEntry returns | 248 // We do not call DispatchNext directly if WriteEntry/ReadEntry returns |
270 // ERR_IO_PENDING, and the callback should not return that value either. | 249 // ERR_IO_PENDING, and the callback should not return that value either. |
271 LOG(ERROR) | 250 LOG(ERROR) |
272 << "Failed to complete write to PNaCl Translation Cache Entry: " | 251 << "Failed to complete write to PNaCl Translation Cache Entry: " |
273 << rv; | 252 << rv; |
274 step_ = CLOSE_ENTRY; | 253 step_ = CLOSE_ENTRY; |
275 CloseEntry(rv); | 254 CloseEntry(rv); |
276 break; | 255 break; |
277 } else if (rv > 0) { | 256 } else if (rv > 0) { |
278 io_buf_->DidConsume(rv); | 257 // For reads, copy the data that was just returned |
279 if (io_buf_->BytesRemaining() > 0) { | 258 if (is_read_) |
280 is_read_ | 259 read_nexe_->append(read_buf_->data(), rv); |
281 ? ReadEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining()) | 260 bytes_transferred_ += rv; |
282 : WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining()); | 261 if (bytes_transferred_ < bytes_to_transfer_) { |
| 262 int len = bytes_to_transfer_ - bytes_transferred_; |
| 263 is_read_ ? ReadEntry(bytes_transferred_, len) |
| 264 : WriteEntry(bytes_transferred_, len); |
283 break; | 265 break; |
284 } | 266 } |
285 } | 267 } |
286 // rv == 0 or we fell through (i.e. we have transferred all the bytes) | 268 // rv == 0 or we fell through (i.e. we have transferred all the bytes) |
287 step_ = CLOSE_ENTRY; | 269 step_ = CLOSE_ENTRY; |
288 DCHECK(io_buf_->BytesConsumed() == io_buf_->size()); | |
289 if (is_read_) | |
290 io_buf_->SetOffset(0); | |
291 CloseEntry(0); | 270 CloseEntry(0); |
292 break; | 271 break; |
293 | 272 |
294 case CLOSE_ENTRY: | 273 case CLOSE_ENTRY: |
295 step_ = UNINITIALIZED; | 274 step_ = UNINITIALIZED; |
296 break; | 275 break; |
297 } | 276 } |
298 } | 277 } |
299 | 278 |
300 ////////////////////////////////////////////////////////////////////// | 279 ////////////////////////////////////////////////////////////////////// |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 if (!init_callback_.is_null()) { | 327 if (!init_callback_.is_null()) { |
349 init_callback_.Run(rv); | 328 init_callback_.Run(rv); |
350 init_callback_.Reset(); | 329 init_callback_.Reset(); |
351 } | 330 } |
352 } | 331 } |
353 | 332 |
354 ////////////////////////////////////////////////////////////////////// | 333 ////////////////////////////////////////////////////////////////////// |
355 // High-level API | 334 // High-level API |
356 | 335 |
357 void PnaclTranslationCache::StoreNexe(const std::string& key, | 336 void PnaclTranslationCache::StoreNexe(const std::string& key, |
358 net::DrainableIOBuffer* nexe_data) { | 337 const std::string& nexe) { |
359 StoreNexe(key, nexe_data, CompletionCallback()); | 338 StoreNexe(key, nexe, CompletionCallback()); |
360 } | 339 } |
361 | 340 |
362 void PnaclTranslationCache::StoreNexe(const std::string& key, | 341 void PnaclTranslationCache::StoreNexe(const std::string& key, |
363 net::DrainableIOBuffer* nexe_data, | 342 const std::string& nexe, |
364 const CompletionCallback& callback) { | 343 const CompletionCallback& callback) { |
365 PnaclTranslationCacheEntry* entry = PnaclTranslationCacheEntry::GetWriteEntry( | 344 PnaclTranslationCacheEntry* entry = new PnaclTranslationCacheEntry( |
366 AsWeakPtr(), key, nexe_data, callback); | 345 AsWeakPtr(), key, NULL, nexe, callback, false); |
367 open_entries_[entry] = entry; | 346 open_entries_[entry] = entry; |
368 entry->Start(); | 347 entry->Start(); |
369 } | 348 } |
370 | 349 |
371 void PnaclTranslationCache::GetNexe(const std::string& key, | 350 void PnaclTranslationCache::GetNexe(const std::string& key, |
372 const GetNexeCallback& callback) { | 351 std::string* nexe, |
373 PnaclTranslationCacheEntry* entry = | 352 const CompletionCallback& callback) { |
374 PnaclTranslationCacheEntry::GetReadEntry(AsWeakPtr(), key, callback); | 353 PnaclTranslationCacheEntry* entry = new PnaclTranslationCacheEntry( |
| 354 AsWeakPtr(), key, nexe, std::string(), callback, true); |
375 open_entries_[entry] = entry; | 355 open_entries_[entry] = entry; |
376 entry->Start(); | 356 entry->Start(); |
377 } | 357 } |
378 | 358 |
379 int PnaclTranslationCache::InitCache(const base::FilePath& cache_directory, | 359 int PnaclTranslationCache::InitCache(const base::FilePath& cache_directory, |
380 bool in_memory, | 360 bool in_memory, |
381 const CompletionCallback& callback) { | 361 const CompletionCallback& callback) { |
382 int rv; | 362 int rv; |
383 in_memory_ = in_memory; | 363 in_memory_ = in_memory; |
384 if (in_memory_) { | 364 if (in_memory_) { |
385 rv = InitWithMemBackend(kMaxMemCacheSize, callback); | 365 rv = InitWithMemBackend(kMaxMemCacheSize, callback); |
386 } else { | 366 } else { |
387 rv = InitWithDiskBackend(cache_directory, kMaxDiskCacheSize, callback); | 367 rv = InitWithDiskBackend(cache_directory, |
| 368 kMaxDiskCacheSize, |
| 369 callback); |
388 } | 370 } |
389 | 371 |
390 return rv; | 372 return rv; |
391 } | 373 } |
392 | 374 |
393 int PnaclTranslationCache::Size() { | 375 int PnaclTranslationCache::Size() { |
394 if (!disk_cache_) | 376 if (!disk_cache_) |
395 return -1; | 377 return -1; |
396 return disk_cache_->GetEntryCount(); | 378 return disk_cache_->GetEntryCount(); |
397 } | 379 } |
398 | 380 |
399 // static | |
400 std::string PnaclTranslationCache::GetKey(const nacl::PnaclCacheInfo& info) { | |
401 if (!info.pexe_url.is_valid() || info.abi_version < 0 || info.opt_level < 0) | |
402 return std::string(); | |
403 std::string retval("ABI:"); | |
404 retval += IntToString(info.abi_version) + ";" + | |
405 "opt:" + IntToString(info.opt_level) + ";" + | |
406 "URL:"; | |
407 // Filter the username, password, and ref components from the URL | |
408 GURL::Replacements replacements; | |
409 replacements.ClearUsername(); | |
410 replacements.ClearPassword(); | |
411 replacements.ClearRef(); | |
412 GURL key_url(info.pexe_url.ReplaceComponents(replacements)); | |
413 retval += key_url.spec() + ";"; | |
414 // You would think that there is already code to format base::Time values | |
415 // somewhere, but I haven't found it yet. In any case, doing it ourselves | |
416 // here means we can keep the format stable. | |
417 base::Time::Exploded exploded; | |
418 info.last_modified.UTCExplode(&exploded); | |
419 retval += "modified:" + IntToString(exploded.year) + ":" + | |
420 IntToString(exploded.month) + ":" + | |
421 IntToString(exploded.day_of_month) + ":" + | |
422 IntToString(exploded.hour) + ":" + IntToString(exploded.minute) + ":" + | |
423 IntToString(exploded.second) + ":" + | |
424 IntToString(exploded.millisecond) + ":UTC;"; | |
425 retval += "etag:" + info.etag; | |
426 return retval; | |
427 } | |
428 } // namespace pnacl | 381 } // namespace pnacl |
OLD | NEW |