Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(444)

Side by Side Diff: chrome/browser/nacl_host/pnacl_translation_cache.cc

Issue 16232011: Add PNaCl translation cache based on Chrome disk_cache (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix test type Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/nacl_host/pnacl_translation_cache.h"
6
7 #include <string>
8
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/threading/thread_checker.h"
12 #include "chrome/common/chrome_paths.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "net/base/io_buffer.h"
15 #include "net/base/net_errors.h"
16 #include "net/disk_cache/disk_cache.h"
17
18 using content::BrowserThread;
19
20 static const base::FilePath::CharType kDiskCacheDirectoryName[] =
21 FILE_PATH_LITERAL("PNaClTranslationCache");
22
23 namespace {
24
25 void CloseDiskCacheEntry(disk_cache::Entry* entry) { entry->Close(); }
26
27 } // namespace
28
29 namespace pnacl_cache {
30 // These are in pnacl_cache namespace instead of static so they can be used
31 // by the unit test.
32 const int kMaxDiskCacheSize = 1000 * 1024 * 1024;
33 const int kMaxMemCacheSize = 100 * 1024 * 1024;
34
35 //////////////////////////////////////////////////////////////////////
36 // Handle Storing to Cache.
37
38 // PNaClTranslationCacheWriteEntry is a shim that provides storage for the
39 // 'key' and 'data' strings as the disk_cache is performing various async
40 // operations. It also tracks the open disk_cache::Entry
41 // and ensures that the entry is closed.
42 class PNaClTranslationCacheWriteEntry
43 : public base::RefCounted<PNaClTranslationCacheWriteEntry> {
44 public:
45 PNaClTranslationCacheWriteEntry(base::WeakPtr<PNaClTranslationCache> cache,
46 const std::string& key,
47 const std::string& nexe,
48 const net::CompletionCallback& callback);
49
50 void Cache();
51
52 // ---
53 // v |
54 // Cache -> Open Existing --------------> Write ---> Close
55 // \ ^
56 // \ /
57 // --> Create --
58 enum CacheStep {
59 UNINITIALIZED,
60 OPEN_ENTRY,
61 CREATE_ENTRY,
62 WRITE_ENTRY,
63 CLOSE_ENTRY
64 };
65
66 private:
67 friend class base::RefCounted<PNaClTranslationCacheWriteEntry>;
68 ~PNaClTranslationCacheWriteEntry();
69
70 void CreateEntry();
71
72 void OpenEntry();
73
74 void WriteEntry(int bytes_to_skip);
75
76 void CloseEntry(int rv);
77
78 void DispatchNext(int rv);
79
80 base::WeakPtr<PNaClTranslationCache> cache_;
81
82 std::string key_;
83 std::string nexe_;
84 disk_cache::Entry* entry_;
85 CacheStep step_;
86 CompletionCallback finish_callback_;
87 base::ThreadChecker thread_checker_;
88 DISALLOW_COPY_AND_ASSIGN(PNaClTranslationCacheWriteEntry);
89 };
90
91 PNaClTranslationCacheWriteEntry::PNaClTranslationCacheWriteEntry(
92 base::WeakPtr<PNaClTranslationCache> cache,
93 const std::string& key,
94 const std::string& nexe,
95 const net::CompletionCallback& callback)
96 : cache_(cache),
97 key_(key),
98 nexe_(nexe),
99 entry_(NULL),
100 step_(UNINITIALIZED),
101 finish_callback_(callback) {}
102
103 PNaClTranslationCacheWriteEntry::~PNaClTranslationCacheWriteEntry() {
104 if (entry_)
105 BrowserThread::PostTask(
106 BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_));
107 }
108
109 void PNaClTranslationCacheWriteEntry::Cache() {
110 DCHECK(thread_checker_.CalledOnValidThread());
111 step_ = OPEN_ENTRY;
112 OpenEntry();
113 }
114
115 // OpenEntry, CreateEntry, WriteEntry, and CloseEntry are only called from
116 // DispatchNext, so they know that cache_ is still valid.
117 void PNaClTranslationCacheWriteEntry::OpenEntry() {
118 int rv = cache_->backend()->OpenEntry(
119 key_,
120 &entry_,
121 base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this));
122 if (rv != net::ERR_IO_PENDING)
123 DispatchNext(rv);
124 }
125
126 void PNaClTranslationCacheWriteEntry::CreateEntry() {
127 int rv = cache_->backend()->CreateEntry(
128 key_,
129 &entry_,
130 base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this));
131 if (rv != net::ERR_IO_PENDING)
132 DispatchNext(rv);
133 }
134
135 void PNaClTranslationCacheWriteEntry::WriteEntry(int bytes_to_skip) {
136 nexe_ = nexe_.substr(bytes_to_skip);
137 scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(nexe_);
138 int rv = entry_->WriteData(
139 1,
140 0,
141 io_buf,
142 nexe_.length(),
143 base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this),
144 false);
145 if (rv != net::ERR_IO_PENDING)
146 DispatchNext(rv);
147 }
148
149 void PNaClTranslationCacheWriteEntry::CloseEntry(int rv) {
150 if (rv < 0)
151 entry_->Doom();
152 if (!finish_callback_.is_null()) {
153 finish_callback_.Run(rv);
154 finish_callback_.Reset();
155 }
156 cache_->WriteComplete(this);
157 }
158
159 void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) {
160 DCHECK(thread_checker_.CalledOnValidThread());
161 if (!cache_)
162 return;
163
164 switch (step_) {
165 case UNINITIALIZED:
166 LOG(ERROR) << "Unexpected step in DispatchNext";
167 break;
168
169 case OPEN_ENTRY:
170 if (rv == net::OK) {
171 step_ = WRITE_ENTRY;
172 WriteEntry(0);
173 } else {
174 step_ = CREATE_ENTRY;
175 CreateEntry();
176 }
177 break;
178
179 case CREATE_ENTRY:
180 if (rv == net::OK) {
181 step_ = WRITE_ENTRY;
182 WriteEntry(0);
183 } else {
184 LOG(ERROR) << "Failed to Open/Create a PNaCl Translation Cache Entry";
185 CloseEntry(rv);
186 }
187 break;
188
189 case WRITE_ENTRY:
190 if (rv < 0) {
191 // We do not call DispatchNext directly if WriteEntry returns
192 // ERR_IO_PENDING, and the callback should not return that value either.
193 LOG(ERROR)
194 << "Failed to complete write to PNaCl Translation Cache Entry: "
195 << rv;
196 step_ = CLOSE_ENTRY;
197 CloseEntry(rv);
198 break;
199 }
200 if (rv == 0) {
201 step_ = CLOSE_ENTRY;
202 CloseEntry(rv);
203 break;
204 }
205 // rv bytes were written; call WriteEntry again to skip them and try to
206 // write the rest.
207 WriteEntry(rv);
208 break;
209
210 case CLOSE_ENTRY:
211 step_ = UNINITIALIZED;
212 break;
213 }
214 }
215
216 //////////////////////////////////////////////////////////////////////
217 void PNaClTranslationCache::WriteComplete(
218 PNaClTranslationCacheWriteEntry* entry) {
219 write_entries_.erase(entry);
220 }
221
222 //////////////////////////////////////////////////////////////////////
223 // Construction and cache backend initialization
224 PNaClTranslationCache::PNaClTranslationCache()
225 : disk_cache_(NULL), in_memory_(false) {}
226
227 PNaClTranslationCache::~PNaClTranslationCache() {}
228
229 int PNaClTranslationCache::InitWithDiskBackend(
230 const base::FilePath& cache_dir,
231 int cache_size,
232 const net::CompletionCallback& callback) {
233 return Init(net::DISK_CACHE, cache_dir, cache_size, callback);
234 }
235
236 int PNaClTranslationCache::InitWithMemBackend(
237 int cache_size,
238 const net::CompletionCallback& callback) {
239 return Init(net::MEMORY_CACHE, base::FilePath(), cache_size, callback);
240 }
241
242 int PNaClTranslationCache::Init(net::CacheType cache_type,
243 const base::FilePath& cache_dir,
244 int cache_size,
245 const net::CompletionCallback& callback) {
246 int rv = disk_cache::CreateCacheBackend(
247 cache_type,
248 net::CACHE_BACKEND_DEFAULT,
249 cache_dir,
250 cache_size,
251 true /* force_initialize */,
252 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE),
253 NULL, /* dummy net log */
254 &disk_cache_,
255 base::Bind(&PNaClTranslationCache::OnCreateBackendComplete, AsWeakPtr()));
256 init_callback_ = callback;
257 if (rv != net::ERR_IO_PENDING) {
258 OnCreateBackendComplete(rv);
259 }
260 return rv;
261 }
262
263 void PNaClTranslationCache::OnCreateBackendComplete(int rv) {
264 // Invoke our client's callback function.
265 if (!init_callback_.is_null()) {
266 init_callback_.Run(rv);
267 init_callback_.Reset();
268 }
269 }
270
271 //////////////////////////////////////////////////////////////////////
272 // High-level API
273
274 // TODO(dschuff): Surely there must be a way to just create a null callback?
275 static void NullCallback(int ignored) {}
276
277 void PNaClTranslationCache::StoreNexe(const std::string& key,
278 const std::string& nexe) {
279 StoreNexe(key, nexe, base::Bind(NullCallback));
280 }
281
282 void PNaClTranslationCache::StoreNexe(const std::string& key,
283 const std::string& nexe,
284 const net::CompletionCallback& callback) {
285 PNaClTranslationCacheWriteEntry* entry =
286 new PNaClTranslationCacheWriteEntry(AsWeakPtr(), key, nexe, callback);
287 write_entries_[entry] = entry;
288 entry->Cache();
289 }
290
291 int PNaClTranslationCache::GetNexe(const std::string& key,
292 std::string* nexe,
293 const net::CompletionCallback& callback) {
294 // TODO(dschuff): Actually find the entry, and do the right thing.
295 // Shader cache ended up making a separate ReadHelper, analogous
296 // to the PNaClTranslationCacheWriteEntry.
297 return net::OK;
298 }
299
300 int PNaClTranslationCache::InitCache(const base::FilePath& cache_directory,
301 bool in_memory,
302 const net::CompletionCallback& callback) {
303 int rv;
304 in_memory_ = in_memory;
305 if (in_memory_) {
306 rv = InitWithMemBackend(kMaxMemCacheSize, callback);
307 } else {
308 rv = InitWithDiskBackend(cache_directory.Append(kDiskCacheDirectoryName),
309 kMaxDiskCacheSize,
310 callback);
311 }
312
313 return rv;
314 }
315
316 int PNaClTranslationCache::Size() {
317 if (!disk_cache_)
318 return -1;
319 return disk_cache_->GetEntryCount();
320 }
321
322 } // namespace nacl_cache
OLDNEW
« no previous file with comments | « chrome/browser/nacl_host/pnacl_translation_cache.h ('k') | chrome/browser/nacl_host/pnacl_translation_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698