Chromium Code Reviews| Index: ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
| diff --git a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
| index 3f8d25829e717f52f2181def6d554c3ea5fc0d66..1de105a34b16ecf8580d6857c32d1c886438063e 100644 |
| --- a/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
| +++ b/ppapi/native_client/src/trusted/plugin/pnacl_coordinator.cc |
| @@ -16,14 +16,15 @@ |
| #include "native_client/src/trusted/plugin/pnacl_translate_thread.h" |
| #include "native_client/src/trusted/plugin/service_runtime.h" |
| #include "native_client/src/trusted/plugin/temporary_file.h" |
| -#include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
| +#include "ppapi/c/pp_bool.h" |
| #include "ppapi/c/pp_errors.h" |
| #include "ppapi/c/ppb_file_io.h" |
| #include "ppapi/cpp/file_io.h" |
| namespace { |
| const char kPnaclTempDir[] = "/.pnacl"; |
| +const uint32_t kCopyBufSize = 131072; |
|
sehr (please use chromium)
2012/08/02 22:37:49
I usually prefer something like 128 << 10 for thes
jvoung - send to chromium...
2012/08/02 22:44:29
Done.
|
| } |
| namespace plugin { |
| @@ -182,8 +183,13 @@ PnaclCoordinator* PnaclCoordinator::BitcodeToNative( |
| PnaclCoordinator* coordinator = |
| new PnaclCoordinator(plugin, pexe_url, |
| cache_identity, translate_notify_callback); |
| - PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p)\n", |
| - reinterpret_cast<const void*>(coordinator->manifest_.get()))); |
| + coordinator->off_the_record_ = |
| + plugin->nacl_interface()->IsOffTheRecord(); |
| + PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p, " |
| + "off_the_record=%b)\n", |
| + reinterpret_cast<const void*>(coordinator->manifest_.get()), |
| + coordinator->off_the_record_)); |
| + |
| // Load llc and ld. |
| std::vector<nacl::string> resource_urls; |
| resource_urls.push_back(PnaclUrls::GetLlcUrl()); |
| @@ -234,7 +240,8 @@ PnaclCoordinator::PnaclCoordinator( |
| manifest_(new ExtensionManifest(plugin->url_util())), |
| pexe_url_(pexe_url), |
| cache_identity_(cache_identity), |
| - error_already_reported_(false) { |
| + error_already_reported_(false), |
| + off_the_record_(false) { |
| PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", |
| static_cast<void*>(this), static_cast<void*>(plugin))); |
| callback_factory_.Initialize(this); |
| @@ -294,51 +301,132 @@ void PnaclCoordinator::ReportPpapiError(int32_t pp_error) { |
| void PnaclCoordinator::TranslateFinished(int32_t pp_error) { |
| PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" |
| NACL_PRId32")\n", pp_error)); |
| - // Save the translate error code, and inspect after cleaning up junk files. |
| - // Note: If there was a surfaway and the file objects were actually |
| - // destroyed, then we are in trouble since the obj_file_, nexe_file_, |
| - // etc. may have been destroyed. |
| - // TODO(jvoung,sehr): Fix. |
| // If there was an error already set (e.g. pexe load failure) then we want |
| // to use the first one, (which might be something useful) rather than |
| // the one from the compiler, (which is always just PP_ERROR_FAILED) |
| if (translate_finish_error_ == PP_OK) translate_finish_error_ = pp_error; |
| - // Close the nexe temporary file. |
| - if (nexe_file_ != NULL) { |
| - pp::CompletionCallback cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasClosed); |
| - nexe_file_->Close(cb); |
| + // The nexe is written to the temp_nexe_file_. We must Reset() the file |
| + // pointer to be able to read it again from the beginning. |
| + temp_nexe_file_->Reset(); |
| + |
| + if (cache_identity_ != "" && cached_nexe_file_ != NULL) { |
| + // We are using a cache, but had a cache miss, which is why we did the |
| + // translation. Reset cached_nexe_file_ to have a random name, |
| + // for scratch purposes, before renaming to the final cache_identity_. |
| + cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| + nacl::string(kPnaclTempDir))); |
| + pp::CompletionCallback cb = callback_factory_.NewCallback( |
| + &PnaclCoordinator::CachedNexeOpenedForWrite); |
| + cached_nexe_file_->OpenWrite(cb); |
| + } else { |
| + // For now, tolerate bitcode that is missing a cache identity, and |
| + // tolerate the lack of caching in incognito mode. |
| + PLUGIN_PRINTF(("PnaclCoordinator -- not caching.\n")); |
| + NexeReadDidOpen(PP_OK); |
| } |
| } |
| -void PnaclCoordinator::NexeFileWasClosed(int32_t pp_error) { |
| - PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasClosed (pp_error=%" |
| - NACL_PRId32")\n", pp_error)); |
| +void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) { |
| if (pp_error != PP_OK) { |
| - ReportPpapiError(pp_error); |
| + ReportPpapiError(pp_error, "Failed to open cache file for write."); |
| return; |
| } |
| - // Now that cleanup of the obj file is done, check the old TranslateFinished |
| - // error code to see if we should proceed normally or not. |
| - if (translate_finish_error_ != PP_OK) { |
| - pp::CompletionCallback cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasDeleted); |
| - nexe_file_->Delete(cb); |
| + |
| + // Copy the contents from temp_nexe_file_ -> cached_nexe_file_, |
| + // then rename the cached_nexe_file_ file to the cache id. |
| + int64_t cur_offset = 0; |
| + nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); |
| + char buf[kCopyBufSize]; |
| + ssize_t num_read = read_wrapper->Read(buf, sizeof buf); |
| + // Hit EOF or something. |
| + if (num_read == 0) { |
| + NexeWasCopiedToCache(PP_OK); |
| + return; |
| + } |
| + if (num_read < 0) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::CachedNexeOpenedForWrite read failed " |
| + "(error=%"NACL_PRId32")\n", num_read)); |
| + NexeWasCopiedToCache(PP_ERROR_FAILED); |
| return; |
| } |
| + pp::CompletionCallback cb = callback_factory_.NewCallback( |
| + &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, cur_offset); |
| + cached_nexe_file_->write_file_io()->Write(cur_offset, buf, num_read, cb); |
| +} |
| - // Rename the nexe file to the cache id. |
| - if (cache_identity_ != "") { |
| - pp::CompletionCallback cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); |
| - nexe_file_->Rename(cache_identity_, cb); |
| - } else { |
| - // For now tolerate bitcode that is missing a cache identity. |
| - PLUGIN_PRINTF(("PnaclCoordinator -- WARNING: missing cache identity," |
| - " not caching.\n")); |
| - NexeFileWasRenamed(PP_OK); |
| +void PnaclCoordinator::DidCopyNexeToCachePartial(int32_t pp_error, |
| + int32_t num_read_prev, |
| + int64_t cur_offset) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial " |
| + "(pp_error=%"NACL_PRId32", num_read_prev=%"NACL_PRId32"" |
| + ", cur_offset=%"NACL_PRId64").\n", |
| + pp_error, num_read_prev, cur_offset)); |
| + // Assume we are done. |
| + if (pp_error == PP_OK) { |
| + NexeWasCopiedToCache(PP_OK); |
| + return; |
| + } |
| + if (pp_error < PP_OK) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial failed (err=%" |
| + NACL_PRId32")\n", pp_error)); |
| + NexeWasCopiedToCache(pp_error); |
| + return; |
| } |
| + |
| + // Check if we wrote as much as we read. |
| + nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); |
| + if (pp_error != num_read_prev) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial partial " |
| + "write (bytes_written=%"NACL_PRId32" vs " |
| + "read=%"NACL_PRId32")\n", pp_error, num_read_prev)); |
| + CHECK(pp_error < num_read_prev); |
| + // Seek back to re-read the bytes that were not written. |
| + nacl_off64_t seek_result = |
| + read_wrapper->Seek(pp_error - num_read_prev, SEEK_CUR); |
| + if (seek_result < 0) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial seek failed " |
| + "(err=%"NACL_PRId64")\n", seek_result)); |
| + NexeWasCopiedToCache(PP_ERROR_FAILED); |
| + return; |
| + } |
| + } |
| + |
| + int64_t next_offset = cur_offset + pp_error; |
| + char buf[kCopyBufSize]; |
| + ssize_t num_read = read_wrapper->Read(buf, sizeof buf); |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read (bytes=%" |
| + NACL_PRId32")\n", num_read)); |
| + // Hit EOF or something. |
| + if (num_read == 0) { |
| + NexeWasCopiedToCache(PP_OK); |
| + return; |
| + } |
| + if (num_read < 0) { |
| + PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read failed " |
| + "(error=%"NACL_PRId32")\n", num_read)); |
| + NexeWasCopiedToCache(PP_ERROR_FAILED); |
| + return; |
| + } |
| + pp::CompletionCallback cb = callback_factory_.NewCallback( |
| + &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, next_offset); |
| + PLUGIN_PRINTF(("PnaclCoordinator::CopyNexeToCache Writing (bytes=%d, " |
| + "buf=%p, file_io=%p)\n", num_read, buf, |
| + cached_nexe_file_->write_file_io())); |
| + cached_nexe_file_->write_file_io()->Write(next_offset, buf, num_read, cb); |
| +} |
| + |
| +void PnaclCoordinator::NexeWasCopiedToCache(int32_t pp_error) { |
| + if (pp_error != PP_OK) { |
| + // TODO(jvoung): This should probably try to delete the cache file |
| + // before returning... |
| + ReportPpapiError(pp_error, "Failed to copy nexe to cache."); |
| + return; |
| + } |
| + // Rename the cached_nexe_file_ file to the cache id, to finalize. |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); |
| + cached_nexe_file_->Rename(cache_identity_, cb); |
| } |
| void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { |
| @@ -350,11 +438,12 @@ void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { |
| ReportPpapiError(pp_error, "Failed to place cached bitcode translation."); |
| return; |
| } |
| - nexe_file_->FinishRename(); |
| - // Open the nexe temporary file for reading. |
| + |
| + cached_nexe_file_->FinishRename(); |
| + // Open the cache file for reading. |
| pp::CompletionCallback cb = |
| callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen); |
| - nexe_file_->OpenRead(cb); |
| + cached_nexe_file_->OpenRead(cb); |
| } |
| void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { |
| @@ -364,18 +453,17 @@ void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { |
| ReportPpapiError(pp_error, "Failed to open translated nexe."); |
| return; |
| } |
| - // Transfer ownership of the nexe wrapper to the coordinator. |
| - translated_fd_.reset(nexe_file_->release_read_wrapper()); |
| + |
| + // Transfer ownership of cache/temp file's wrapper to the coordinator. |
| + if (cached_nexe_file_ != NULL) { |
| + translated_fd_.reset(cached_nexe_file_->release_read_wrapper()); |
| + } else { |
| + translated_fd_.reset(temp_nexe_file_->release_read_wrapper()); |
| + } |
| plugin_->EnqueueProgressEvent(Plugin::kProgressEventProgress); |
| translate_notify_callback_.Run(pp_error); |
| } |
| -void PnaclCoordinator::NexeFileWasDeleted(int32_t pp_error) { |
| - PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasDeleted (pp_error=%" |
| - NACL_PRId32")\n", pp_error)); |
| - ReportPpapiError(translate_finish_error_); |
| -} |
| - |
| void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { |
| PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" |
| NACL_PRId32")\n", pp_error)); |
| @@ -383,12 +471,17 @@ void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { |
| ReportPpapiError(pp_error, "resources failed to load."); |
| return; |
| } |
| - // Open the local temporary file system to create the temporary files |
| - // for the object and nexe. |
| - pp::CompletionCallback cb = |
| - callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); |
| - if (!file_system_->Open(0, cb)) { |
| - ReportNonPpapiError("failed to open file system."); |
| + |
| + if (!off_the_record_) { |
| + // Open the local temporary FS to see if we get a hit in the cache. |
| + pp::CompletionCallback cb = |
| + callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); |
| + if (!file_system_->Open(0, cb)) { |
| + ReportNonPpapiError("failed to open file system."); |
| + } |
| + } else { |
| + // We don't have a cache, so do the non-cached codepath. |
| + CachedFileDidOpen(PP_ERROR_FAILED); |
| } |
| } |
| @@ -399,8 +492,7 @@ void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { |
| ReportPpapiError(pp_error, "file system didn't open."); |
| return; |
| } |
| - dir_ref_.reset(new pp::FileRef(*file_system_, |
| - kPnaclTempDir)); |
| + dir_ref_.reset(new pp::FileRef(*file_system_, kPnaclTempDir)); |
| // Attempt to create the directory. |
| pp::CompletionCallback cb = |
| callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); |
| @@ -416,12 +508,12 @@ void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { |
| return; |
| } |
| if (cache_identity_ != "") { |
| - nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| - nacl::string(kPnaclTempDir), |
| - cache_identity_)); |
| + cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| + nacl::string(kPnaclTempDir), |
| + cache_identity_)); |
| pp::CompletionCallback cb = |
| callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); |
| - nexe_file_->OpenRead(cb); |
| + cached_nexe_file_->OpenRead(cb); |
| } else { |
| // For now, tolerate lack of cache identity... |
| CachedFileDidOpen(PP_ERROR_FAILED); |
| @@ -469,9 +561,9 @@ void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { |
| PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" |
| NACL_PRId32")\n", pp_error)); |
| if (pp_error != PP_OK) { |
| - // Defer reporting the error and obj_file/nexe_file cleanup until after |
| - // the translation thread returns, because it may be accessing the |
| - // coordinator's objects or writing to the files. |
| + // Defer reporting the error and cleanup until after the translation |
| + // thread returns, because it may be accessing the coordinator's |
| + // objects or writing to the files. |
| translate_finish_error_ = pp_error; |
| error_info_.SetReport(ERROR_UNKNOWN, |
| nacl::string("PnaclCoordinator: pexe load failed.")); |
| @@ -501,11 +593,10 @@ void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) { |
| } |
| // Create the nexe file for connecting ld and sel_ldr. |
| // Start translation when done with this last step of setup! |
| - nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| - nacl::string(kPnaclTempDir))); |
| + temp_nexe_file_.reset(new TempFile(plugin_)); |
| pp::CompletionCallback cb = |
| callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); |
| - nexe_file_->OpenWrite(cb); |
| + temp_nexe_file_->Open(cb); |
| } |
| void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
| @@ -521,7 +612,7 @@ void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
| manifest_.get(), |
| ld_manifest_.get(), |
| obj_file_.get(), |
| - nexe_file_.get(), |
| + temp_nexe_file_.get(), |
| &error_info_, |
| resources_.get(), |
| plugin_); |