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