Index: chrome/browser/nacl_host/pnacl_translation_cache.cc |
diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.cc b/chrome/browser/nacl_host/pnacl_translation_cache.cc |
index 8316ba7052137881205682015efe67f1ba7f657e..b7f8a366fa31d980265698ffd566402a1efaf904 100644 |
--- a/chrome/browser/nacl_host/pnacl_translation_cache.cc |
+++ b/chrome/browser/nacl_host/pnacl_translation_cache.cc |
@@ -33,80 +33,99 @@ const int kMaxDiskCacheSize = 1000 * 1024 * 1024; |
const int kMaxMemCacheSize = 100 * 1024 * 1024; |
////////////////////////////////////////////////////////////////////// |
-// Handle Storing to Cache. |
+// Handle Reading/Writing to Cache. |
-// PNaClTranslationCacheWriteEntry is a shim that provides storage for the |
+// PNaClTranslationCacheEntry is a shim that provides storage for the |
// 'key' and 'data' strings as the disk_cache is performing various async |
// operations. It also tracks the open disk_cache::Entry |
// and ensures that the entry is closed. |
-class PNaClTranslationCacheWriteEntry |
- : public base::RefCounted<PNaClTranslationCacheWriteEntry> { |
+class PNaClTranslationCacheEntry |
+ : public base::RefCounted<PNaClTranslationCacheEntry> { |
public: |
- PNaClTranslationCacheWriteEntry(base::WeakPtr<PNaClTranslationCache> cache, |
- const std::string& key, |
- const std::string& nexe, |
- const net::CompletionCallback& callback); |
+ PNaClTranslationCacheEntry(base::WeakPtr<PNaClTranslationCache> cache, |
+ const std::string& key, |
+ std::string* nexe, |
+ const CompletionCallback& callback, |
+ bool is_read); |
- void Cache(); |
+ void Start(); |
- // --- |
+ // Writes: --- |
// v | |
- // Cache -> Open Existing --------------> Write ---> Close |
+ // Start -> Open Existing --------------> Write ---> Close |
// \ ^ |
// \ / |
// --> Create -- |
+ // Reads: |
+ // Start -> Open --------Read ----> Close |
+ // | ^ |
+ // |__| |
enum CacheStep { |
UNINITIALIZED, |
OPEN_ENTRY, |
CREATE_ENTRY, |
- WRITE_ENTRY, |
+ TRANSFER_ENTRY, |
CLOSE_ENTRY |
}; |
private: |
- friend class base::RefCounted<PNaClTranslationCacheWriteEntry>; |
- ~PNaClTranslationCacheWriteEntry(); |
+ friend class base::RefCounted<PNaClTranslationCacheEntry>; |
+ ~PNaClTranslationCacheEntry(); |
void CreateEntry(); |
void OpenEntry(); |
- void WriteEntry(int bytes_to_skip); |
+ void WriteEntry(int offset, int len); |
+ void ReadEntry(int offset, int len); |
jvoung (off chromium)
2013/06/05 00:42:28
extra space between functions to be consistent
Derek Schuff
2013/06/05 05:01:59
even better; made consistent and added comments.
|
void CloseEntry(int rv); |
+ // Handles state transitions, tracks bytes transferred |
void DispatchNext(int rv); |
+ // Get the total transfer size. For reads, must be called after the entry |
+ // has been info has been fetched from the backend. |
+ int GetTransferSize(); |
+ |
base::WeakPtr<PNaClTranslationCache> cache_; |
std::string key_; |
- std::string nexe_; |
+ std::string* nexe_; |
disk_cache::Entry* entry_; |
CacheStep step_; |
+ bool is_read_; |
+ int bytes_transferred_; |
+ int bytes_to_transfer_; |
+ scoped_refptr<net::IOBufferWithSize> read_buf_; |
CompletionCallback finish_callback_; |
base::ThreadChecker thread_checker_; |
- DISALLOW_COPY_AND_ASSIGN(PNaClTranslationCacheWriteEntry); |
+ DISALLOW_COPY_AND_ASSIGN(PNaClTranslationCacheEntry); |
}; |
-PNaClTranslationCacheWriteEntry::PNaClTranslationCacheWriteEntry( |
+PNaClTranslationCacheEntry::PNaClTranslationCacheEntry( |
base::WeakPtr<PNaClTranslationCache> cache, |
const std::string& key, |
- const std::string& nexe, |
- const net::CompletionCallback& callback) |
+ std::string* nexe, |
+ const CompletionCallback& callback, |
+ bool is_read) |
: cache_(cache), |
key_(key), |
nexe_(nexe), |
entry_(NULL), |
step_(UNINITIALIZED), |
+ is_read_(is_read), |
+ bytes_transferred_(0), |
+ bytes_to_transfer_(-1), |
finish_callback_(callback) {} |
-PNaClTranslationCacheWriteEntry::~PNaClTranslationCacheWriteEntry() { |
+PNaClTranslationCacheEntry::~PNaClTranslationCacheEntry() { |
if (entry_) |
BrowserThread::PostTask( |
BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_)); |
} |
-void PNaClTranslationCacheWriteEntry::Cache() { |
+void PNaClTranslationCacheEntry::Start() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
step_ = OPEN_ENTRY; |
OpenEntry(); |
@@ -114,49 +133,71 @@ void PNaClTranslationCacheWriteEntry::Cache() { |
// OpenEntry, CreateEntry, WriteEntry, and CloseEntry are only called from |
// DispatchNext, so they know that cache_ is still valid. |
-void PNaClTranslationCacheWriteEntry::OpenEntry() { |
- int rv = cache_->backend()->OpenEntry( |
- key_, |
- &entry_, |
- base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this)); |
+void PNaClTranslationCacheEntry::OpenEntry() { |
+ int rv = cache_->backend() |
+ ->OpenEntry(key_, |
+ &entry_, |
+ base::Bind(&PNaClTranslationCacheEntry::DispatchNext, this)); |
if (rv != net::ERR_IO_PENDING) |
DispatchNext(rv); |
} |
-void PNaClTranslationCacheWriteEntry::CreateEntry() { |
+void PNaClTranslationCacheEntry::CreateEntry() { |
int rv = cache_->backend()->CreateEntry( |
key_, |
&entry_, |
- base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this)); |
+ base::Bind(&PNaClTranslationCacheEntry::DispatchNext, this)); |
if (rv != net::ERR_IO_PENDING) |
DispatchNext(rv); |
} |
-void PNaClTranslationCacheWriteEntry::WriteEntry(int bytes_to_skip) { |
- nexe_ = nexe_.substr(bytes_to_skip); |
- scoped_refptr<net::StringIOBuffer> io_buf = new net::StringIOBuffer(nexe_); |
+void PNaClTranslationCacheEntry::WriteEntry(int offset, int len) { |
+ scoped_refptr<net::StringIOBuffer> io_buf = |
+ new net::StringIOBuffer(nexe_->substr(offset, len)); |
int rv = entry_->WriteData( |
1, |
- 0, |
+ offset, |
io_buf, |
- nexe_.length(), |
- base::Bind(&PNaClTranslationCacheWriteEntry::DispatchNext, this), |
+ len, |
+ base::Bind(&PNaClTranslationCacheEntry::DispatchNext, this), |
false); |
if (rv != net::ERR_IO_PENDING) |
DispatchNext(rv); |
} |
-void PNaClTranslationCacheWriteEntry::CloseEntry(int rv) { |
- if (rv < 0) |
+void PNaClTranslationCacheEntry::ReadEntry(int offset, int len) { |
+ read_buf_ = new net::IOBufferWithSize(len); |
+ int rv = entry_->ReadData( |
+ 1, |
+ offset, |
+ read_buf_, |
+ len, |
+ base::Bind(&PNaClTranslationCacheEntry::DispatchNext, this)); |
+ if (rv != net::ERR_IO_PENDING) |
+ DispatchNext(rv); |
+} |
+ |
+int PNaClTranslationCacheEntry::GetTransferSize() { |
+ if (is_read_) { |
+ DCHECK(entry_); |
+ return entry_->GetDataSize(1); |
+ } |
+ return nexe_->size(); |
+} |
+ |
+void PNaClTranslationCacheEntry::CloseEntry(int rv) { |
+ if (entry_ && rv < 0) |
entry_->Doom(); |
if (!finish_callback_.is_null()) { |
finish_callback_.Run(rv); |
finish_callback_.Reset(); |
} |
- cache_->WriteComplete(this); |
+ if (!is_read_) |
+ delete nexe_; |
jvoung (off chromium)
2013/06/05 00:42:28
Perhaps the nexe shouldn't be the same field for b
Derek Schuff
2013/06/05 05:01:59
Yeah, we need to call CloseEntry anyway. Actually
jvoung (off chromium)
2013/06/05 17:52:29
Well, I think static factories might be better so
|
+ cache_->OpComplete(this); |
} |
-void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) { |
+void PNaClTranslationCacheEntry::DispatchNext(int rv) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
if (!cache_) |
return; |
@@ -168,9 +209,17 @@ void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) { |
case OPEN_ENTRY: |
if (rv == net::OK) { |
- step_ = WRITE_ENTRY; |
- WriteEntry(0); |
+ step_ = TRANSFER_ENTRY; |
+ bytes_to_transfer_ = GetTransferSize(); |
+ is_read_ ? ReadEntry(0, bytes_to_transfer_) |
+ : WriteEntry(0, bytes_to_transfer_); |
} else { |
+ if (is_read_) { |
+ // Just a cache miss, not necessarily an error. |
+ entry_ = NULL; |
jvoung (off chromium)
2013/06/05 00:42:28
It looks a bit odd to set entry_ to NULL then call
Derek Schuff
2013/06/05 05:01:59
Done.
|
+ CloseEntry(rv); |
+ break; |
+ } |
step_ = CREATE_ENTRY; |
CreateEntry(); |
} |
@@ -178,15 +227,16 @@ void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) { |
case CREATE_ENTRY: |
if (rv == net::OK) { |
- step_ = WRITE_ENTRY; |
- WriteEntry(0); |
+ step_ = TRANSFER_ENTRY; |
+ bytes_to_transfer_ = GetTransferSize(); |
+ WriteEntry(bytes_transferred_, bytes_to_transfer_ - bytes_transferred_); |
} else { |
- LOG(ERROR) << "Failed to Open/Create a PNaCl Translation Cache Entry"; |
+ LOG(ERROR) << "Failed to Create a PNaCl Translation Cache Entry"; |
CloseEntry(rv); |
} |
break; |
- case WRITE_ENTRY: |
+ case TRANSFER_ENTRY: |
if (rv < 0) { |
// We do not call DispatchNext directly if WriteEntry returns |
jvoung (off chromium)
2013/06/05 00:42:28
WriteEntry or ReadEntry now.
Derek Schuff
2013/06/05 05:01:59
Done.
|
// ERR_IO_PENDING, and the callback should not return that value either. |
@@ -196,15 +246,21 @@ void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) { |
step_ = CLOSE_ENTRY; |
CloseEntry(rv); |
break; |
+ } else if (rv > 0) { |
+ // For reads, copy the data that was just returned |
+ if (is_read_) |
+ nexe_->append(read_buf_->data(), rv); |
+ bytes_transferred_ += rv; |
+ if (bytes_transferred_ < bytes_to_transfer_) { |
+ int len = bytes_to_transfer_ - bytes_transferred_; |
+ is_read_ ? ReadEntry(bytes_transferred_, len) |
+ : WriteEntry(bytes_transferred_, len); |
+ break; |
+ } |
} |
- if (rv == 0) { |
- step_ = CLOSE_ENTRY; |
- CloseEntry(rv); |
- break; |
- } |
- // rv bytes were written; call WriteEntry again to skip them and try to |
- // write the rest. |
- WriteEntry(rv); |
+ // rv == 0 or we fell through (i.e. we have transferred all the bytes) |
+ step_ = CLOSE_ENTRY; |
+ CloseEntry(0); |
break; |
case CLOSE_ENTRY: |
@@ -214,8 +270,7 @@ void PNaClTranslationCacheWriteEntry::DispatchNext(int rv) { |
} |
////////////////////////////////////////////////////////////////////// |
-void PNaClTranslationCache::WriteComplete( |
- PNaClTranslationCacheWriteEntry* entry) { |
+void PNaClTranslationCache::OpComplete(PNaClTranslationCacheEntry* entry) { |
write_entries_.erase(entry); |
} |
@@ -224,27 +279,25 @@ void PNaClTranslationCache::WriteComplete( |
PNaClTranslationCache::PNaClTranslationCache() |
: disk_cache_(NULL), in_memory_(false) {} |
-PNaClTranslationCache::~PNaClTranslationCache() { |
- delete disk_cache_; |
-} |
+PNaClTranslationCache::~PNaClTranslationCache() { delete disk_cache_; } |
int PNaClTranslationCache::InitWithDiskBackend( |
const base::FilePath& cache_dir, |
int cache_size, |
- const net::CompletionCallback& callback) { |
+ const CompletionCallback& callback) { |
return Init(net::DISK_CACHE, cache_dir, cache_size, callback); |
} |
int PNaClTranslationCache::InitWithMemBackend( |
int cache_size, |
- const net::CompletionCallback& callback) { |
+ const CompletionCallback& callback) { |
return Init(net::MEMORY_CACHE, base::FilePath(), cache_size, callback); |
} |
int PNaClTranslationCache::Init(net::CacheType cache_type, |
const base::FilePath& cache_dir, |
int cache_size, |
- const net::CompletionCallback& callback) { |
+ const CompletionCallback& callback) { |
int rv = disk_cache::CreateCacheBackend( |
cache_type, |
net::CACHE_BACKEND_DEFAULT, |
@@ -273,35 +326,32 @@ void PNaClTranslationCache::OnCreateBackendComplete(int rv) { |
////////////////////////////////////////////////////////////////////// |
// High-level API |
-// TODO(dschuff): Surely there must be a way to just create a null callback? |
-static void NullCallback(int ignored) {} |
- |
void PNaClTranslationCache::StoreNexe(const std::string& key, |
const std::string& nexe) { |
- StoreNexe(key, nexe, base::Bind(NullCallback)); |
+ StoreNexe(key, nexe, CompletionCallback()); |
} |
void PNaClTranslationCache::StoreNexe(const std::string& key, |
const std::string& nexe, |
- const net::CompletionCallback& callback) { |
- PNaClTranslationCacheWriteEntry* entry = |
- new PNaClTranslationCacheWriteEntry(AsWeakPtr(), key, nexe, callback); |
+ const CompletionCallback& callback) { |
+ PNaClTranslationCacheEntry* entry = new PNaClTranslationCacheEntry( |
+ AsWeakPtr(), key, new std::string(nexe), callback, false); |
write_entries_[entry] = entry; |
- entry->Cache(); |
+ entry->Start(); |
} |
-int PNaClTranslationCache::GetNexe(const std::string& key, |
- std::string* nexe, |
- const net::CompletionCallback& callback) { |
- // TODO(dschuff): Actually find the entry, and do the right thing. |
- // Shader cache ended up making a separate ReadHelper, analogous |
- // to the PNaClTranslationCacheWriteEntry. |
- return net::OK; |
+void PNaClTranslationCache::GetNexe(const std::string& key, |
+ std::string* nexe, |
+ const CompletionCallback& callback) { |
+ PNaClTranslationCacheEntry* entry = |
+ new PNaClTranslationCacheEntry(AsWeakPtr(), key, nexe, callback, true); |
+ write_entries_[entry] = entry; |
+ entry->Start(); |
} |
int PNaClTranslationCache::InitCache(const base::FilePath& cache_directory, |
bool in_memory, |
- const net::CompletionCallback& callback) { |
+ const CompletionCallback& callback) { |
int rv; |
in_memory_ = in_memory; |
if (in_memory_) { |