Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 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 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 5 | #include "ppapi/native_client/src/trusted/plugin/pnacl_coordinator.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 6 | |
| 7 | #include <utility> |
| 8 | #include <vector> |
| 9 | |
| 10 | #include "native_client/src/include/checked_cast.h" |
| 11 | #include "native_client/src/include/portability_io.h" |
| 12 | #include "native_client/src/shared/platform/nacl_check.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 13 | #include "native_client/src/trusted/service_runtime/include/sys/stat.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 14 | |
| 15 | #include "ppapi/c/pp_bool.h" |
| 16 | #include "ppapi/c/pp_errors.h" |
| 17 | #include "ppapi/c/ppb_file_io.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 18 | #include "ppapi/c/private/ppb_uma_private.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 19 | #include "ppapi/cpp/file_io.h" |
| 20 | |
Ben Murdoch | ca12bfa | 2013-07-23 11:17:05 +0100 | [diff] [blame] | 21 | #include "ppapi/native_client/src/trusted/plugin/local_temp_file.h" |
| 22 | #include "ppapi/native_client/src/trusted/plugin/manifest.h" |
| 23 | #include "ppapi/native_client/src/trusted/plugin/nacl_http_response_headers.h" |
| 24 | #include "ppapi/native_client/src/trusted/plugin/plugin.h" |
| 25 | #include "ppapi/native_client/src/trusted/plugin/plugin_error.h" |
| 26 | #include "ppapi/native_client/src/trusted/plugin/pnacl_translate_thread.h" |
| 27 | #include "ppapi/native_client/src/trusted/plugin/service_runtime.h" |
| 28 | #include "ppapi/native_client/src/trusted/plugin/temporary_file.h" |
| 29 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 30 | namespace { |
| 31 | const char kPnaclTempDir[] = "/.pnacl"; |
| 32 | const uint32_t kCopyBufSize = 512 << 10; |
| 33 | } |
| 34 | |
| 35 | namespace plugin { |
| 36 | |
| 37 | ////////////////////////////////////////////////////////////////////// |
| 38 | // Pnacl-specific manifest support. |
| 39 | ////////////////////////////////////////////////////////////////////// |
| 40 | |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 41 | // The PNaCl linker gets file descriptors via the service runtime's |
| 42 | // reverse service lookup. The reverse service lookup requires a manifest. |
| 43 | // Normally, that manifest is an NMF containing mappings for shared libraries. |
| 44 | // Here, we provide a manifest that redirects to PNaCl component files |
| 45 | // that are part of Chrome. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 46 | class PnaclManifest : public Manifest { |
| 47 | public: |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 48 | PnaclManifest() : manifest_base_url_(PnaclUrls::GetBaseUrl()) { } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 49 | virtual ~PnaclManifest() { } |
| 50 | |
| 51 | virtual bool GetProgramURL(nacl::string* full_url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 52 | PnaclOptions* pnacl_options, |
| 53 | ErrorInfo* error_info) const { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 54 | // Does not contain program urls. |
| 55 | UNREFERENCED_PARAMETER(full_url); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 56 | UNREFERENCED_PARAMETER(pnacl_options); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 57 | UNREFERENCED_PARAMETER(error_info); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 58 | PLUGIN_PRINTF(("PnaclManifest does not contain a program\n")); |
| 59 | error_info->SetReport(ERROR_MANIFEST_GET_NEXE_URL, |
| 60 | "pnacl manifest does not contain a program."); |
| 61 | return false; |
| 62 | } |
| 63 | |
| 64 | virtual bool ResolveURL(const nacl::string& relative_url, |
| 65 | nacl::string* full_url, |
| 66 | ErrorInfo* error_info) const { |
| 67 | // Does not do general URL resolution, simply appends relative_url to |
| 68 | // the end of manifest_base_url_. |
| 69 | UNREFERENCED_PARAMETER(error_info); |
| 70 | *full_url = manifest_base_url_ + relative_url; |
| 71 | return true; |
| 72 | } |
| 73 | |
| 74 | virtual bool GetFileKeys(std::set<nacl::string>* keys) const { |
| 75 | // Does not support enumeration. |
| 76 | PLUGIN_PRINTF(("PnaclManifest does not support key enumeration\n")); |
| 77 | UNREFERENCED_PARAMETER(keys); |
| 78 | return false; |
| 79 | } |
| 80 | |
| 81 | virtual bool ResolveKey(const nacl::string& key, |
| 82 | nacl::string* full_url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 83 | PnaclOptions* pnacl_options, |
| 84 | ErrorInfo* error_info) const { |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 85 | // All of the component files are native (do not require pnacl translate). |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 86 | pnacl_options->set_translate(false); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 87 | // We can only resolve keys in the files/ namespace. |
| 88 | const nacl::string kFilesPrefix = "files/"; |
| 89 | size_t files_prefix_pos = key.find(kFilesPrefix); |
| 90 | if (files_prefix_pos == nacl::string::npos) { |
| 91 | error_info->SetReport(ERROR_MANIFEST_RESOLVE_URL, |
| 92 | "key did not start with files/"); |
| 93 | return false; |
| 94 | } |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 95 | // Resolve the full URL to the file. Provide it with a platform-specific |
| 96 | // prefix. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 97 | nacl::string key_basename = key.substr(kFilesPrefix.length()); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 98 | return ResolveURL(PnaclUrls::PrependPlatformPrefix(key_basename), |
| 99 | full_url, error_info); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | private: |
| 103 | NACL_DISALLOW_COPY_AND_ASSIGN(PnaclManifest); |
| 104 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 105 | nacl::string manifest_base_url_; |
| 106 | }; |
| 107 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 108 | ////////////////////////////////////////////////////////////////////// |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 109 | // UMA stat helpers. |
| 110 | ////////////////////////////////////////////////////////////////////// |
| 111 | |
| 112 | namespace { |
| 113 | |
| 114 | // Assume translation time metrics *can be* large. |
| 115 | // Up to 12 minutes. |
| 116 | const int64_t kTimeLargeMin = 10; // in ms |
| 117 | const int64_t kTimeLargeMax = 720000; // in ms |
| 118 | const uint32_t kTimeLargeBuckets = 100; |
| 119 | |
| 120 | const int32_t kSizeKBMin = 1; |
| 121 | const int32_t kSizeKBMax = 512*1024; // very large .pexe / .nexe. |
| 122 | const uint32_t kSizeKBBuckets = 100; |
| 123 | |
| 124 | const int32_t kRatioMin = 10; |
| 125 | const int32_t kRatioMax = 10*100; // max of 10x difference. |
| 126 | const uint32_t kRatioBuckets = 100; |
| 127 | |
| 128 | const int32_t kKBPSMin = 1; |
| 129 | const int32_t kKBPSMax = 30*1000; // max of 30 MB / sec. |
| 130 | const uint32_t kKBPSBuckets = 100; |
| 131 | |
| 132 | const PPB_UMA_Private* uma_interface = NULL; |
| 133 | |
| 134 | const PPB_UMA_Private* GetUMAInterface() { |
| 135 | if (uma_interface != NULL) { |
| 136 | return uma_interface; |
| 137 | } |
| 138 | pp::Module *module = pp::Module::Get(); |
| 139 | DCHECK(module); |
| 140 | uma_interface = static_cast<const PPB_UMA_Private*>( |
| 141 | module->GetBrowserInterface(PPB_UMA_PRIVATE_INTERFACE)); |
| 142 | return uma_interface; |
| 143 | } |
| 144 | |
| 145 | void HistogramTime(const std::string& name, int64_t ms) { |
| 146 | if (ms < 0) return; |
| 147 | |
| 148 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 149 | if (ptr == NULL) return; |
| 150 | |
| 151 | ptr->HistogramCustomTimes(pp::Var(name).pp_var(), |
| 152 | ms, |
| 153 | kTimeLargeMin, kTimeLargeMax, |
| 154 | kTimeLargeBuckets); |
| 155 | } |
| 156 | |
| 157 | void HistogramSizeKB(const std::string& name, int32_t kb) { |
| 158 | if (kb < 0) return; |
| 159 | |
| 160 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 161 | if (ptr == NULL) return; |
| 162 | |
| 163 | ptr->HistogramCustomCounts(pp::Var(name).pp_var(), |
| 164 | kb, |
| 165 | kSizeKBMin, kSizeKBMax, |
| 166 | kSizeKBBuckets); |
| 167 | } |
| 168 | |
| 169 | void HistogramRatio(const std::string& name, int64_t a, int64_t b) { |
| 170 | if (a < 0 || b <= 0) return; |
| 171 | |
| 172 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 173 | if (ptr == NULL) return; |
| 174 | |
| 175 | ptr->HistogramCustomCounts(pp::Var(name).pp_var(), |
| 176 | 100 * a / b, |
| 177 | kRatioMin, kRatioMax, |
| 178 | kRatioBuckets); |
| 179 | } |
| 180 | |
| 181 | void HistogramKBPerSec(const std::string& name, double kb, double s) { |
| 182 | if (kb < 0.0 || s <= 0.0) return; |
| 183 | |
| 184 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 185 | if (ptr == NULL) return; |
| 186 | |
| 187 | ptr->HistogramCustomCounts(pp::Var(name).pp_var(), |
| 188 | static_cast<int64_t>(kb / s), |
| 189 | kKBPSMin, kKBPSMax, |
| 190 | kKBPSBuckets); |
| 191 | } |
| 192 | |
| 193 | void HistogramEnumerateTranslationCache(bool hit) { |
| 194 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 195 | if (ptr == NULL) return; |
| 196 | ptr->HistogramEnumeration(pp::Var("NaCl.Perf.PNaClCache.IsHit").pp_var(), |
| 197 | hit, 2); |
| 198 | } |
| 199 | |
| 200 | // Opt level is expected to be 0 to 3. Treating 4 as unknown. |
| 201 | const int8_t kOptUnknown = 4; |
| 202 | |
| 203 | void HistogramOptLevel(int8_t opt_level) { |
| 204 | const PPB_UMA_Private* ptr = GetUMAInterface(); |
| 205 | if (ptr == NULL) return; |
| 206 | if (opt_level < 0 || opt_level > 3) { |
| 207 | opt_level = kOptUnknown; |
| 208 | } |
| 209 | ptr->HistogramEnumeration(pp::Var("NaCl.Options.PNaCl.OptLevel").pp_var(), |
| 210 | opt_level, kOptUnknown+1); |
| 211 | } |
| 212 | |
| 213 | } // namespace |
| 214 | |
| 215 | |
| 216 | ////////////////////////////////////////////////////////////////////// |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 217 | // The coordinator class. |
| 218 | ////////////////////////////////////////////////////////////////////// |
| 219 | |
| 220 | // Out-of-line destructor to keep it from getting put in every .o where |
| 221 | // callback_source.h is included |
| 222 | template<> |
| 223 | CallbackSource<FileStreamData>::~CallbackSource() {} |
| 224 | |
| 225 | PnaclCoordinator* PnaclCoordinator::BitcodeToNative( |
| 226 | Plugin* plugin, |
| 227 | const nacl::string& pexe_url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 228 | const PnaclOptions& pnacl_options, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 229 | const pp::CompletionCallback& translate_notify_callback) { |
| 230 | PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (plugin=%p, pexe=%s)\n", |
| 231 | static_cast<void*>(plugin), pexe_url.c_str())); |
| 232 | PnaclCoordinator* coordinator = |
| 233 | new PnaclCoordinator(plugin, pexe_url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 234 | pnacl_options, |
| 235 | translate_notify_callback); |
| 236 | coordinator->pnacl_init_time_ = NaClGetTimeOfDayMicroseconds(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 237 | coordinator->off_the_record_ = |
| 238 | plugin->nacl_interface()->IsOffTheRecord(); |
| 239 | PLUGIN_PRINTF(("PnaclCoordinator::BitcodeToNative (manifest=%p, " |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 240 | "off_the_record=%d)\n", |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 241 | reinterpret_cast<const void*>(coordinator->manifest_.get()), |
| 242 | coordinator->off_the_record_)); |
| 243 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 244 | // Loading resources (e.g. llc and ld nexes) is done with PnaclResources. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 245 | coordinator->resources_.reset( |
| 246 | new PnaclResources(plugin, |
| 247 | coordinator, |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 248 | coordinator->manifest_.get())); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 249 | CHECK(coordinator->resources_ != NULL); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 250 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 251 | // The first step of loading resources: read the resource info file. |
| 252 | pp::CompletionCallback resource_info_read_cb = |
| 253 | coordinator->callback_factory_.NewCallback( |
| 254 | &PnaclCoordinator::ResourceInfoWasRead); |
| 255 | coordinator->resources_->ReadResourceInfo(PnaclUrls::GetResourceInfoUrl(), |
| 256 | resource_info_read_cb); |
| 257 | return coordinator; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 258 | } |
| 259 | |
| 260 | PnaclCoordinator::PnaclCoordinator( |
| 261 | Plugin* plugin, |
| 262 | const nacl::string& pexe_url, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 263 | const PnaclOptions& pnacl_options, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 264 | const pp::CompletionCallback& translate_notify_callback) |
| 265 | : translate_finish_error_(PP_OK), |
| 266 | plugin_(plugin), |
| 267 | translate_notify_callback_(translate_notify_callback), |
| 268 | file_system_(new pp::FileSystem(plugin, PP_FILESYSTEMTYPE_LOCALTEMPORARY)), |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 269 | manifest_(new PnaclManifest()), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 270 | pexe_url_(pexe_url), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 271 | pnacl_options_(pnacl_options), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 272 | use_new_cache_(false), |
| 273 | is_cache_hit_(PP_FALSE), |
| 274 | nexe_handle_(PP_kInvalidFileHandle), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 275 | error_already_reported_(false), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 276 | off_the_record_(false), |
| 277 | pnacl_init_time_(0), |
| 278 | pexe_size_(0), |
| 279 | pexe_bytes_compiled_(0), |
| 280 | expected_pexe_size_(-1) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 281 | PLUGIN_PRINTF(("PnaclCoordinator::PnaclCoordinator (this=%p, plugin=%p)\n", |
| 282 | static_cast<void*>(this), static_cast<void*>(plugin))); |
| 283 | callback_factory_.Initialize(this); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 284 | if (getenv("PNACL_USE_NEW_CACHE")) { |
| 285 | PLUGIN_PRINTF(("PnaclCoordinator using new translation cache\n")); |
| 286 | use_new_cache_ = true; |
| 287 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | PnaclCoordinator::~PnaclCoordinator() { |
| 291 | PLUGIN_PRINTF(("PnaclCoordinator::~PnaclCoordinator (this=%p, " |
| 292 | "translate_thread=%p\n", |
| 293 | static_cast<void*>(this), translate_thread_.get())); |
| 294 | // Stopping the translate thread will cause the translate thread to try to |
| 295 | // run translation_complete_callback_ on the main thread. This destructor is |
| 296 | // running from the main thread, and by the time it exits, callback_factory_ |
| 297 | // will have been destroyed. This will result in the cancellation of |
| 298 | // translation_complete_callback_, so no notification will be delivered. |
| 299 | if (translate_thread_.get() != NULL) { |
| 300 | translate_thread_->AbortSubprocesses(); |
| 301 | } |
| 302 | } |
| 303 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 304 | void PnaclCoordinator::ReportNonPpapiError(enum PluginErrorCode err_code, |
| 305 | const nacl::string& message) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 306 | error_info_.SetReport(err_code, message); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 307 | ExitWithError(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 308 | } |
| 309 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 310 | void PnaclCoordinator::ReportPpapiError(enum PluginErrorCode err_code, |
| 311 | int32_t pp_error, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 312 | const nacl::string& message) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 313 | nacl::stringstream ss; |
| 314 | ss << "PnaclCoordinator: " << message << " (pp_error=" << pp_error << ")."; |
| 315 | error_info_.SetReport(err_code, ss.str()); |
| 316 | ExitWithError(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 317 | } |
| 318 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 319 | void PnaclCoordinator::ExitWithError() { |
| 320 | PLUGIN_PRINTF(("PnaclCoordinator::ExitWithError (error_code=%d, " |
| 321 | "message='%s')\n", |
| 322 | error_info_.error_code(), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 323 | error_info_.message().c_str())); |
| 324 | plugin_->ReportLoadError(error_info_); |
| 325 | // Free all the intermediate callbacks we ever created. |
| 326 | // Note: this doesn't *cancel* the callbacks from the factories attached |
| 327 | // to the various helper classes (e.g., pnacl_resources). Thus, those |
| 328 | // callbacks may still run asynchronously. We let those run but ignore |
| 329 | // any other errors they may generate so that they do not end up running |
| 330 | // translate_notify_callback_, which has already been freed. |
| 331 | callback_factory_.CancelAll(); |
| 332 | if (!error_already_reported_) { |
| 333 | error_already_reported_ = true; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 334 | translate_notify_callback_.Run(PP_ERROR_FAILED); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 335 | } else { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 336 | PLUGIN_PRINTF(("PnaclCoordinator::ExitWithError an earlier error was " |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 337 | "already reported -- Skipping.\n")); |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | // Signal that Pnacl translation completed normally. |
| 342 | void PnaclCoordinator::TranslateFinished(int32_t pp_error) { |
| 343 | PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 344 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 345 | // Bail out if there was an earlier error (e.g., pexe load failure). |
| 346 | if (translate_finish_error_ != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 347 | ExitWithError(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 348 | return; |
| 349 | } |
| 350 | // Bail out if there is an error from the translation thread. |
| 351 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 352 | ExitWithError(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 353 | return; |
| 354 | } |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 355 | // Send out one last progress event, to finish up the progress events |
| 356 | // that were delayed (see the delay inserted in BitcodeGotCompiled). |
| 357 | if (ExpectedProgressKnown()) { |
| 358 | pexe_bytes_compiled_ = expected_pexe_size_; |
| 359 | plugin_->EnqueueProgressEvent(plugin::Plugin::kProgressEventProgress, |
| 360 | pexe_url_, |
| 361 | plugin::Plugin::LENGTH_IS_COMPUTABLE, |
| 362 | pexe_bytes_compiled_, |
| 363 | expected_pexe_size_); |
| 364 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 365 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 366 | // If there are no errors, report stats from this thread (the main thread). |
| 367 | HistogramOptLevel(pnacl_options_.opt_level()); |
| 368 | const plugin::PnaclTimeStats& time_stats = translate_thread_->GetTimeStats(); |
| 369 | HistogramTime("NaCl.Perf.PNaClLoadTime.LoadCompiler", |
| 370 | time_stats.pnacl_llc_load_time / NACL_MICROS_PER_MILLI); |
| 371 | HistogramTime("NaCl.Perf.PNaClLoadTime.CompileTime", |
| 372 | time_stats.pnacl_compile_time / NACL_MICROS_PER_MILLI); |
| 373 | HistogramKBPerSec("NaCl.Perf.PNaClLoadTime.CompileKBPerSec", |
| 374 | pexe_size_ / 1024.0, |
| 375 | time_stats.pnacl_compile_time / 1000000.0); |
| 376 | HistogramTime("NaCl.Perf.PNaClLoadTime.LoadLinker", |
| 377 | time_stats.pnacl_ld_load_time / NACL_MICROS_PER_MILLI); |
| 378 | HistogramTime("NaCl.Perf.PNaClLoadTime.LinkTime", |
| 379 | time_stats.pnacl_link_time / NACL_MICROS_PER_MILLI); |
| 380 | HistogramSizeKB("NaCl.Perf.Size.Pexe", |
| 381 | static_cast<int64_t>(pexe_size_ / 1024)); |
| 382 | |
| 383 | struct nacl_abi_stat stbuf; |
| 384 | struct NaClDesc* desc = temp_nexe_file_->read_wrapper()->desc(); |
| 385 | int stat_ret; |
| 386 | if (0 != (stat_ret = (*((struct NaClDescVtbl const *) desc->base.vtbl)-> |
| 387 | Fstat)(desc, &stbuf))) { |
| 388 | PLUGIN_PRINTF(("PnaclCoordinator::TranslateFinished can't stat nexe.\n")); |
| 389 | } else { |
| 390 | size_t nexe_size = stbuf.nacl_abi_st_size; |
| 391 | HistogramSizeKB("NaCl.Perf.Size.PNaClTranslatedNexe", |
| 392 | static_cast<int64_t>(nexe_size / 1024)); |
| 393 | HistogramRatio("NaCl.Perf.Size.PexeNexeSizePct", pexe_size_, nexe_size); |
| 394 | } |
| 395 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 396 | // The nexe is written to the temp_nexe_file_. We must Reset() the file |
| 397 | // pointer to be able to read it again from the beginning. |
| 398 | temp_nexe_file_->Reset(); |
| 399 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 400 | if (use_new_cache_) { |
| 401 | // Report to the browser that translation finished. The browser will take |
| 402 | // care of caching. |
| 403 | plugin_->nacl_interface()->ReportTranslationFinished( |
| 404 | plugin_->pp_instance()); |
| 405 | NexeReadDidOpen(PP_OK); |
| 406 | return; |
| 407 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 408 | if (pnacl_options_.HasCacheKey() && cached_nexe_file_ != NULL) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 409 | // We are using a cache, but had a cache miss, which is why we did the |
| 410 | // translation. Reset cached_nexe_file_ to have a random name, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 411 | // for scratch purposes, before renaming to the final cache_identity. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 412 | cached_nexe_file_.reset(new LocalTempFile(plugin_, file_system_.get(), |
| 413 | nacl::string(kPnaclTempDir))); |
| 414 | pp::CompletionCallback cb = callback_factory_.NewCallback( |
| 415 | &PnaclCoordinator::CachedNexeOpenedForWrite); |
| 416 | cached_nexe_file_->OpenWrite(cb); |
| 417 | } else { |
| 418 | // For now, tolerate bitcode that is missing a cache identity, and |
| 419 | // tolerate the lack of caching in incognito mode. |
| 420 | PLUGIN_PRINTF(("PnaclCoordinator -- not caching.\n")); |
| 421 | NexeReadDidOpen(PP_OK); |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | void PnaclCoordinator::CachedNexeOpenedForWrite(int32_t pp_error) { |
| 426 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 427 | if (pp_error == PP_ERROR_NOACCESS) { |
| 428 | ReportPpapiError( |
| 429 | ERROR_PNACL_CACHE_FILEOPEN_NOACCESS, |
| 430 | pp_error, |
| 431 | "PNaCl translation cache failed to open file for write " |
| 432 | "(no access)."); |
| 433 | return; |
| 434 | } |
| 435 | if (pp_error == PP_ERROR_NOQUOTA) { |
| 436 | ReportPpapiError( |
| 437 | ERROR_PNACL_CACHE_FILEOPEN_NOQUOTA, |
| 438 | pp_error, |
| 439 | "PNaCl translation cache failed to open file for write " |
| 440 | "(no quota)."); |
| 441 | return; |
| 442 | } |
| 443 | if (pp_error == PP_ERROR_NOSPACE) { |
| 444 | ReportPpapiError( |
| 445 | ERROR_PNACL_CACHE_FILEOPEN_NOSPACE, |
| 446 | pp_error, |
| 447 | "PNaCl translation cache failed to open file for write " |
| 448 | "(no space)."); |
| 449 | return; |
| 450 | } |
| 451 | if (pp_error == PP_ERROR_NOTAFILE) { |
| 452 | ReportPpapiError(ERROR_PNACL_CACHE_FILEOPEN_NOTAFILE, |
| 453 | pp_error, |
| 454 | "PNaCl translation cache failed to open file for write." |
| 455 | " File already exists as a directory."); |
| 456 | return; |
| 457 | } |
| 458 | ReportPpapiError(ERROR_PNACL_CACHE_FILEOPEN_OTHER, |
| 459 | pp_error, |
| 460 | "PNaCl translation cache failed to open file for write."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 461 | return; |
| 462 | } |
| 463 | |
| 464 | // Copy the contents from temp_nexe_file_ -> cached_nexe_file_, |
| 465 | // then rename the cached_nexe_file_ file to the cache id. |
| 466 | int64_t cur_offset = 0; |
| 467 | nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); |
| 468 | char buf[kCopyBufSize]; |
| 469 | int32_t num_read = |
| 470 | nacl::assert_cast<int32_t>(read_wrapper->Read(buf, sizeof buf)); |
| 471 | // Hit EOF or something. |
| 472 | if (num_read == 0) { |
| 473 | NexeWasCopiedToCache(PP_OK); |
| 474 | return; |
| 475 | } |
| 476 | if (num_read < 0) { |
| 477 | PLUGIN_PRINTF(("PnaclCoordinator::CachedNexeOpenedForWrite read failed " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 478 | "(error=%" NACL_PRId32 ")\n", num_read)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 479 | NexeWasCopiedToCache(PP_ERROR_FAILED); |
| 480 | return; |
| 481 | } |
| 482 | pp::CompletionCallback cb = callback_factory_.NewCallback( |
| 483 | &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, cur_offset); |
| 484 | cached_nexe_file_->write_file_io()->Write(cur_offset, buf, num_read, cb); |
| 485 | } |
| 486 | |
| 487 | void PnaclCoordinator::DidCopyNexeToCachePartial(int32_t pp_error, |
| 488 | int32_t num_read_prev, |
| 489 | int64_t cur_offset) { |
| 490 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 491 | "(pp_error=%" NACL_PRId32 ", num_read_prev=%" NACL_PRId32 |
| 492 | ", cur_offset=%" NACL_PRId64 ").\n", |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 493 | pp_error, num_read_prev, cur_offset)); |
| 494 | // Assume we are done. |
| 495 | if (pp_error == PP_OK) { |
| 496 | NexeWasCopiedToCache(PP_OK); |
| 497 | return; |
| 498 | } |
| 499 | if (pp_error < PP_OK) { |
| 500 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial failed (err=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 501 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 502 | NexeWasCopiedToCache(pp_error); |
| 503 | return; |
| 504 | } |
| 505 | |
| 506 | // Check if we wrote as much as we read. |
| 507 | nacl::DescWrapper* read_wrapper = temp_nexe_file_->read_wrapper(); |
| 508 | if (pp_error != num_read_prev) { |
| 509 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial partial " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 510 | "write (bytes_written=%" NACL_PRId32 " vs " |
| 511 | "read=%" NACL_PRId32 ")\n", pp_error, num_read_prev)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 512 | CHECK(pp_error < num_read_prev); |
| 513 | // Seek back to re-read the bytes that were not written. |
| 514 | nacl_off64_t seek_result = |
| 515 | read_wrapper->Seek(pp_error - num_read_prev, SEEK_CUR); |
| 516 | if (seek_result < 0) { |
| 517 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial seek failed " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 518 | "(err=%" NACL_PRId64 ")\n", seek_result)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 519 | NexeWasCopiedToCache(PP_ERROR_FAILED); |
| 520 | return; |
| 521 | } |
| 522 | } |
| 523 | |
| 524 | int64_t next_offset = cur_offset + pp_error; |
| 525 | char buf[kCopyBufSize]; |
| 526 | int32_t num_read = |
| 527 | nacl::assert_cast<int32_t>(read_wrapper->Read(buf, sizeof buf)); |
| 528 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read (bytes=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 529 | NACL_PRId32 ")\n", num_read)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 530 | // Hit EOF or something. |
| 531 | if (num_read == 0) { |
| 532 | NexeWasCopiedToCache(PP_OK); |
| 533 | return; |
| 534 | } |
| 535 | if (num_read < 0) { |
| 536 | PLUGIN_PRINTF(("PnaclCoordinator::DidCopyNexeToCachePartial read failed " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 537 | "(error=%" NACL_PRId32 ")\n", num_read)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 538 | NexeWasCopiedToCache(PP_ERROR_FAILED); |
| 539 | return; |
| 540 | } |
| 541 | pp::CompletionCallback cb = callback_factory_.NewCallback( |
| 542 | &PnaclCoordinator::DidCopyNexeToCachePartial, num_read, next_offset); |
| 543 | PLUGIN_PRINTF(("PnaclCoordinator::CopyNexeToCache Writing (" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 544 | "bytes=%" NACL_PRId32 ", buf=%p, file_io=%p)\n", num_read, buf, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 545 | cached_nexe_file_->write_file_io())); |
| 546 | cached_nexe_file_->write_file_io()->Write(next_offset, buf, num_read, cb); |
| 547 | } |
| 548 | |
| 549 | void PnaclCoordinator::NexeWasCopiedToCache(int32_t pp_error) { |
| 550 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 551 | // Try to delete the partially written not-yet-committed cache file before |
| 552 | // returning. We pass the current pp_error along so that it can be reported |
| 553 | // before returning. |
| 554 | pp::CompletionCallback cb = callback_factory_.NewCallback( |
| 555 | &PnaclCoordinator::CorruptCacheFileWasDeleted, pp_error); |
| 556 | cached_nexe_file_->Delete(cb); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 557 | return; |
| 558 | } |
| 559 | // Rename the cached_nexe_file_ file to the cache id, to finalize. |
| 560 | pp::CompletionCallback cb = |
| 561 | callback_factory_.NewCallback(&PnaclCoordinator::NexeFileWasRenamed); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 562 | cached_nexe_file_->Rename(pnacl_options_.GetCacheKey(), cb); |
| 563 | } |
| 564 | |
| 565 | void PnaclCoordinator::CorruptCacheFileWasDeleted(int32_t delete_pp_error, |
| 566 | int32_t orig_pp_error) { |
| 567 | if (delete_pp_error != PP_OK) { |
| 568 | // The cache file was certainly already opened by the time we tried |
| 569 | // to write to it, so it should certainly be deletable. |
| 570 | PLUGIN_PRINTF(("PnaclCoordinator::CorruptCacheFileWasDeleted " |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 571 | "delete failed with pp_error=%" NACL_PRId32 "\n", |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 572 | delete_pp_error)); |
| 573 | // fall through and report the original error. |
| 574 | } |
| 575 | // Report the original error that caused us to consider the |
| 576 | // cache file corrupted. |
| 577 | if (orig_pp_error == PP_ERROR_NOQUOTA) { |
| 578 | ReportPpapiError(ERROR_PNACL_CACHE_FINALIZE_COPY_NOQUOTA, |
| 579 | orig_pp_error, |
| 580 | "Failed to copy translated nexe to cache (no quota)."); |
| 581 | return; |
| 582 | } |
| 583 | if (orig_pp_error == PP_ERROR_NOSPACE) { |
| 584 | ReportPpapiError(ERROR_PNACL_CACHE_FINALIZE_COPY_NOSPACE, |
| 585 | orig_pp_error, |
| 586 | "Failed to copy translated nexe to cache (no space)."); |
| 587 | return; |
| 588 | } |
| 589 | ReportPpapiError(ERROR_PNACL_CACHE_FINALIZE_COPY_OTHER, |
| 590 | orig_pp_error, |
| 591 | "Failed to copy translated nexe to cache."); |
| 592 | return; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 593 | } |
| 594 | |
| 595 | void PnaclCoordinator::NexeFileWasRenamed(int32_t pp_error) { |
| 596 | PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasRenamed (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 597 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 598 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 599 | if (pp_error == PP_ERROR_NOACCESS) { |
| 600 | ReportPpapiError(ERROR_PNACL_CACHE_FINALIZE_RENAME_NOACCESS, |
| 601 | pp_error, |
| 602 | "Failed to finalize cached translation (no access)."); |
| 603 | return; |
| 604 | } else if (pp_error != PP_ERROR_FILEEXISTS) { |
| 605 | ReportPpapiError(ERROR_PNACL_CACHE_FINALIZE_RENAME_OTHER, |
| 606 | pp_error, |
| 607 | "Failed to finalize cached translation."); |
| 608 | return; |
| 609 | } else { // pp_error == PP_ERROR_FILEEXISTS. |
| 610 | // NOTE: if the file already existed, it looks like the rename will |
| 611 | // happily succeed. However, we should add a test for this. |
| 612 | // Could be a hash collision, or it could also be two tabs racing to |
| 613 | // translate the same pexe. We may want UMA stats to know if this happens. |
| 614 | // For now, assume that it is a race and try to continue. |
| 615 | // If there is truly a corrupted file, then sel_ldr should prevent the |
| 616 | // file from loading due to the file size not matching the ELF header. |
| 617 | PLUGIN_PRINTF(("PnaclCoordinator::NexeFileWasRenamed file existed\n")); |
| 618 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 619 | } |
| 620 | |
| 621 | cached_nexe_file_->FinishRename(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 622 | |
| 623 | int64_t total_time = NaClGetTimeOfDayMicroseconds() - pnacl_init_time_; |
| 624 | HistogramTime("NaCl.Perf.PNaClLoadTime.TotalUncachedTime", |
| 625 | total_time / NACL_MICROS_PER_MILLI); |
| 626 | HistogramKBPerSec("NaCl.Perf.PNaClLoadTime.TotalUncachedKBPerSec", |
| 627 | pexe_size_ / 1024.0, |
| 628 | total_time / 1000000.0); |
| 629 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 630 | // Open the cache file for reading. |
| 631 | pp::CompletionCallback cb = |
| 632 | callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen); |
| 633 | cached_nexe_file_->OpenRead(cb); |
| 634 | } |
| 635 | |
| 636 | void PnaclCoordinator::NexeReadDidOpen(int32_t pp_error) { |
| 637 | PLUGIN_PRINTF(("PnaclCoordinator::NexeReadDidOpen (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 638 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 639 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 640 | if (pp_error == PP_ERROR_FILENOTFOUND) { |
| 641 | ReportPpapiError(ERROR_PNACL_CACHE_FETCH_NOTFOUND, |
| 642 | pp_error, |
| 643 | "Failed to open translated nexe (not found)."); |
| 644 | return; |
| 645 | } |
| 646 | if (pp_error == PP_ERROR_NOACCESS) { |
| 647 | ReportPpapiError(ERROR_PNACL_CACHE_FETCH_NOACCESS, |
| 648 | pp_error, |
| 649 | "Failed to open translated nexe (no access)."); |
| 650 | return; |
| 651 | } |
| 652 | ReportPpapiError(ERROR_PNACL_CACHE_FETCH_OTHER, |
| 653 | pp_error, |
| 654 | "Failed to open translated nexe."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 655 | return; |
| 656 | } |
| 657 | |
| 658 | // Transfer ownership of cache/temp file's wrapper to the coordinator. |
| 659 | if (cached_nexe_file_ != NULL) { |
| 660 | translated_fd_.reset(cached_nexe_file_->release_read_wrapper()); |
| 661 | } else { |
| 662 | translated_fd_.reset(temp_nexe_file_->release_read_wrapper()); |
| 663 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 664 | translate_notify_callback_.Run(pp_error); |
| 665 | } |
| 666 | |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 667 | void PnaclCoordinator::ResourceInfoWasRead(int32_t pp_error) { |
| 668 | PLUGIN_PRINTF(("PluginCoordinator::ResourceInfoWasRead (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 669 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 90dce4d | 2013-05-29 14:40:03 +0100 | [diff] [blame] | 670 | // Second step of loading resources: call StartLoad. |
| 671 | pp::CompletionCallback resources_cb = |
| 672 | callback_factory_.NewCallback(&PnaclCoordinator::ResourcesDidLoad); |
| 673 | resources_->StartLoad(resources_cb); |
| 674 | } |
| 675 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 676 | void PnaclCoordinator::ResourcesDidLoad(int32_t pp_error) { |
| 677 | PLUGIN_PRINTF(("PnaclCoordinator::ResourcesDidLoad (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 678 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 679 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 680 | // Finer-grained error code should have already been reported by |
| 681 | // the PnaclResources class. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 682 | return; |
| 683 | } |
| 684 | |
| 685 | if (!off_the_record_) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 686 | if (use_new_cache_) { |
| 687 | OpenBitcodeStream(); |
| 688 | } else { |
| 689 | // Open the local temporary FS to see if we get a hit in the cache. |
| 690 | pp::CompletionCallback cb = |
| 691 | callback_factory_.NewCallback(&PnaclCoordinator::FileSystemDidOpen); |
| 692 | int32_t open_error = file_system_->Open(0, cb); |
| 693 | if (open_error != PP_OK_COMPLETIONPENDING) { |
| 694 | // At this point, no async request has kicked off to check for |
| 695 | // permissions, space, etc., so the only error that can be detected |
| 696 | // now is that an open() is already in progress (or a really terrible |
| 697 | // error). |
| 698 | if (pp_error == PP_ERROR_INPROGRESS) { |
| 699 | ReportPpapiError( |
| 700 | ERROR_PNACL_CACHE_OPEN_INPROGRESS, |
| 701 | pp_error, |
| 702 | "File system for PNaCl translation cache failed to open " |
| 703 | "(in progress)."); |
| 704 | return; |
| 705 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 706 | ReportPpapiError( |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 707 | ERROR_PNACL_CACHE_OPEN_OTHER, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 708 | pp_error, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 709 | "File system for PNaCl translation cache failed to open."); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 710 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 711 | } |
| 712 | } else { |
| 713 | // We don't have a cache, so do the non-cached codepath. |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 714 | OpenBitcodeStream(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 715 | } |
| 716 | } |
| 717 | |
| 718 | void PnaclCoordinator::FileSystemDidOpen(int32_t pp_error) { |
| 719 | PLUGIN_PRINTF(("PnaclCoordinator::FileSystemDidOpen (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 720 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 721 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 722 | if (pp_error == PP_ERROR_NOACCESS) { |
| 723 | ReportPpapiError( |
| 724 | ERROR_PNACL_CACHE_OPEN_NOACCESS, |
| 725 | pp_error, |
| 726 | "File system for PNaCl translation cache failed to open " |
| 727 | "(no access)."); |
| 728 | return; |
| 729 | } |
| 730 | if (pp_error == PP_ERROR_NOQUOTA) { |
| 731 | ReportPpapiError( |
| 732 | ERROR_PNACL_CACHE_OPEN_NOQUOTA, |
| 733 | pp_error, |
| 734 | "File system for PNaCl translation cache failed to open " |
| 735 | "(no quota)."); |
| 736 | return; |
| 737 | } |
| 738 | if (pp_error == PP_ERROR_NOSPACE) { |
| 739 | ReportPpapiError( |
| 740 | ERROR_PNACL_CACHE_OPEN_NOSPACE, |
| 741 | pp_error, |
| 742 | "File system for PNaCl translation cache failed to open " |
| 743 | "(no space)."); |
| 744 | return; |
| 745 | } |
| 746 | ReportPpapiError(ERROR_PNACL_CACHE_OPEN_OTHER, |
| 747 | pp_error, |
| 748 | "File system for PNaCl translation cache failed to open."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 749 | } |
| 750 | dir_ref_.reset(new pp::FileRef(*file_system_, kPnaclTempDir)); |
| 751 | // Attempt to create the directory. |
| 752 | pp::CompletionCallback cb = |
| 753 | callback_factory_.NewCallback(&PnaclCoordinator::DirectoryWasCreated); |
| 754 | dir_ref_->MakeDirectory(cb); |
| 755 | } |
| 756 | |
| 757 | void PnaclCoordinator::DirectoryWasCreated(int32_t pp_error) { |
| 758 | PLUGIN_PRINTF(("PnaclCoordinator::DirectoryWasCreated (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 759 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 760 | if (pp_error != PP_ERROR_FILEEXISTS && pp_error != PP_OK) { |
| 761 | // Directory did not exist and could not be created. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 762 | if (pp_error == PP_ERROR_NOACCESS) { |
| 763 | ReportPpapiError( |
| 764 | ERROR_PNACL_CACHE_DIRECTORY_CREATE, |
| 765 | pp_error, |
| 766 | "PNaCl translation cache directory creation/check failed " |
| 767 | "(no access)."); |
| 768 | return; |
| 769 | } |
| 770 | ReportPpapiError( |
| 771 | ERROR_PNACL_CACHE_DIRECTORY_CREATE, |
| 772 | pp_error, |
| 773 | "PNaCl translation cache directory creation/check failed."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 774 | return; |
| 775 | } |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 776 | OpenBitcodeStream(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 777 | } |
| 778 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 779 | void PnaclCoordinator::OpenBitcodeStream() { |
| 780 | // Now open the pexe stream. |
| 781 | streaming_downloader_.reset(new FileDownloader()); |
| 782 | streaming_downloader_->Initialize(plugin_); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 783 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 784 | // Even though we haven't started downloading, create the translation |
| 785 | // thread object immediately. This ensures that any pieces of the file |
| 786 | // that get downloaded before the compilation thread is accepting |
| 787 | // SRPCs won't get dropped. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 788 | translate_thread_.reset(new PnaclTranslateThread()); |
| 789 | if (translate_thread_ == NULL) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 790 | ReportNonPpapiError( |
| 791 | ERROR_PNACL_THREAD_CREATE, |
| 792 | "PnaclCoordinator: could not allocate translation thread."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 793 | return; |
| 794 | } |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 795 | if (!use_new_cache_) { |
| 796 | // We also want to open the object file now so the |
| 797 | // translator can start writing to it during streaming translation. |
| 798 | obj_file_.reset(new TempFile(plugin_)); |
| 799 | pp::CompletionCallback obj_cb = |
| 800 | callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); |
| 801 | obj_file_->Open(obj_cb, true); |
| 802 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 803 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 804 | pp::CompletionCallback cb = |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 805 | callback_factory_.NewCallback(&PnaclCoordinator::BitcodeStreamDidOpen); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 806 | if (!streaming_downloader_->OpenStream(pexe_url_, cb, this)) { |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 807 | ReportNonPpapiError( |
| 808 | ERROR_PNACL_PEXE_FETCH_OTHER, |
| 809 | nacl::string("PnaclCoordinator: failed to open stream ") + pexe_url_); |
| 810 | return; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 811 | } |
| 812 | } |
| 813 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 814 | void PnaclCoordinator::BitcodeStreamDidOpen(int32_t pp_error) { |
| 815 | if (pp_error != PP_OK) { |
| 816 | BitcodeStreamDidFinish(pp_error); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 817 | // In the new cache case, we have not spun up the translation process yet, |
| 818 | // so we need to call TranslateFinished here. |
| 819 | if (use_new_cache_) |
| 820 | TranslateFinished(pp_error); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 821 | return; |
| 822 | } |
| 823 | |
| 824 | if (!off_the_record_) { |
| 825 | // Get the cache key and try to open an existing entry. |
| 826 | nacl::string headers = streaming_downloader_->GetResponseHeaders(); |
| 827 | NaClHttpResponseHeaders parser; |
| 828 | parser.Parse(headers); |
| 829 | nacl::string cache_validators = parser.GetCacheValidators(); |
| 830 | if (parser.CacheControlNoStore() || cache_validators.empty()) { |
| 831 | // We can't cache in this case. |
| 832 | pnacl_options_.set_cache_validators(""); |
| 833 | CachedFileDidOpen(PP_ERROR_FAILED); |
| 834 | return; |
| 835 | } else { |
| 836 | nacl::string url = streaming_downloader_->url(); |
| 837 | // For now, combine the cache_validators + the URL as the key. |
| 838 | // When we change the cache backend to be not-origin-specific |
| 839 | // we should send the URL separately, and check in the browser's |
| 840 | // RenderViewHost / SiteInstance's IsSameWebsite() to prevent |
| 841 | // people from forging the URL for a different origin. |
| 842 | pnacl_options_.set_cache_validators(cache_validators + url); |
| 843 | } |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 844 | if (use_new_cache_) { |
| 845 | pp::CompletionCallback cb = |
| 846 | callback_factory_.NewCallback(&PnaclCoordinator::NexeFdDidOpen); |
| 847 | int32_t nexe_fd_err = |
| 848 | plugin_->nacl_interface()->GetNexeFd( |
| 849 | plugin_->pp_instance(), |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 850 | streaming_downloader_->url().c_str(), |
| 851 | // TODO(dschuff): use the right abi version here. |
| 852 | 0, |
| 853 | pnacl_options_.opt_level(), |
| 854 | parser.GetHeader("last-modified").c_str(), |
| 855 | parser.GetHeader("etag").c_str(), |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 856 | &is_cache_hit_, |
| 857 | &nexe_handle_, |
| 858 | cb.pp_completion_callback()); |
| 859 | if (nexe_fd_err < PP_OK_COMPLETIONPENDING) { |
| 860 | ReportPpapiError(ERROR_PNACL_CREATE_TEMP, nexe_fd_err, |
| 861 | nacl::string("Call to GetNexeFd failed")); |
| 862 | return; |
| 863 | } |
| 864 | } else { |
| 865 | cached_nexe_file_.reset(new LocalTempFile( |
| 866 | plugin_, file_system_.get(), |
| 867 | nacl::string(kPnaclTempDir), |
| 868 | pnacl_options_.GetCacheKey())); |
| 869 | pp::CompletionCallback cb = |
| 870 | callback_factory_.NewCallback(&PnaclCoordinator::CachedFileDidOpen); |
| 871 | cached_nexe_file_->OpenRead(cb); |
| 872 | } |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 873 | } else { |
| 874 | // No cache case. |
| 875 | CachedFileDidOpen(PP_ERROR_FAILED); |
| 876 | } |
| 877 | } |
| 878 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 879 | void PnaclCoordinator::NexeFdDidOpen(int32_t pp_error) { |
| 880 | PLUGIN_PRINTF(("PnaclCoordinator::NexeFdDidOpen (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 881 | NACL_PRId32 ", hit=%d, handle=%d)\n", pp_error, |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 882 | is_cache_hit_ == PP_TRUE, |
| 883 | nexe_handle_)); |
| 884 | if (pp_error < PP_OK) { |
| 885 | ReportPpapiError(ERROR_PNACL_CREATE_TEMP, pp_error, |
| 886 | nacl::string("GetNexeFd failed")); |
| 887 | return; |
| 888 | } |
| 889 | temp_nexe_file_.reset(new TempFile(plugin_)); |
| 890 | if (!temp_nexe_file_->SetExistingFd(nexe_handle_)) { |
| 891 | ReportNonPpapiError( |
| 892 | ERROR_PNACL_CREATE_TEMP, |
| 893 | nacl::string( |
| 894 | "PnaclCoordinator: Got bad temp file handle from GetNexeFd")); |
| 895 | return; |
| 896 | } |
| 897 | if (is_cache_hit_ == PP_TRUE) { |
| 898 | // Cache hit -- no need to stream the rest of the file. |
| 899 | streaming_downloader_.reset(NULL); |
| 900 | // TODO(dschuff): update UMA stats for hit/miss once there could actually |
| 901 | // be hits/misses. |
| 902 | // Open it for reading as the cached nexe file. |
| 903 | pp::CompletionCallback cb = |
| 904 | callback_factory_.NewCallback(&PnaclCoordinator::NexeReadDidOpen); |
| 905 | temp_nexe_file_->Open(cb, false); |
| 906 | } else { |
| 907 | // Open an object file first so the translator can start writing to it |
| 908 | // during streaming translation. |
| 909 | obj_file_.reset(new TempFile(plugin_)); |
| 910 | pp::CompletionCallback obj_cb = |
| 911 | callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen); |
| 912 | obj_file_->Open(obj_cb, true); |
| 913 | |
| 914 | // Meanwhile, a miss means we know we need to stream the bitcode, so stream |
| 915 | // the rest of it now. (Calling FinishStreaming means that the downloader |
| 916 | // will begin handing data to the coordinator, which is safe any time after |
| 917 | // the translate_thread_ object has been initialized). |
| 918 | pp::CompletionCallback finish_cb = callback_factory_.NewCallback( |
| 919 | &PnaclCoordinator::BitcodeStreamDidFinish); |
| 920 | streaming_downloader_->FinishStreaming(finish_cb); |
| 921 | } |
| 922 | } |
| 923 | |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 924 | void PnaclCoordinator::CachedFileDidOpen(int32_t pp_error) { |
| 925 | PLUGIN_PRINTF(("PnaclCoordinator::CachedFileDidOpen (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 926 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 927 | if (pp_error == PP_OK) { |
| 928 | // Cache hit -- no need to stream the rest of the file. |
| 929 | streaming_downloader_.reset(NULL); |
| 930 | HistogramEnumerateTranslationCache(true); |
| 931 | NexeReadDidOpen(PP_OK); |
| 932 | return; |
| 933 | } |
| 934 | // Otherwise, the cache file is missing so we must translate. |
| 935 | HistogramEnumerateTranslationCache(false); |
| 936 | |
| 937 | // Continue streaming. |
| 938 | pp::CompletionCallback cb = |
| 939 | callback_factory_.NewCallback(&PnaclCoordinator::BitcodeStreamDidFinish); |
| 940 | streaming_downloader_->FinishStreaming(cb); |
| 941 | } |
| 942 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 943 | void PnaclCoordinator::BitcodeStreamDidFinish(int32_t pp_error) { |
| 944 | PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamDidFinish (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 945 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 946 | if (pp_error != PP_OK) { |
| 947 | // Defer reporting the error and cleanup until after the translation |
| 948 | // thread returns, because it may be accessing the coordinator's |
| 949 | // objects or writing to the files. |
| 950 | translate_finish_error_ = pp_error; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 951 | if (pp_error == PP_ERROR_ABORTED) { |
| 952 | error_info_.SetReport(ERROR_PNACL_PEXE_FETCH_ABORTED, |
| 953 | "PnaclCoordinator: pexe load failed (aborted)."); |
| 954 | } |
| 955 | if (pp_error == PP_ERROR_NOACCESS) { |
| 956 | error_info_.SetReport(ERROR_PNACL_PEXE_FETCH_NOACCESS, |
| 957 | "PnaclCoordinator: pexe load failed (no access)."); |
| 958 | } else { |
| 959 | nacl::stringstream ss; |
| 960 | ss << "PnaclCoordinator: pexe load failed (pp_error=" << pp_error << ")."; |
| 961 | error_info_.SetReport(ERROR_PNACL_PEXE_FETCH_OTHER, ss.str()); |
| 962 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 963 | translate_thread_->AbortSubprocesses(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 964 | } else { |
| 965 | // Compare download completion pct (100% now), to compile completion pct. |
| 966 | HistogramRatio("NaCl.Perf.PNaClLoadTime.PctCompiledWhenFullyDownloaded", |
| 967 | pexe_bytes_compiled_, pexe_size_); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 968 | } |
| 969 | } |
| 970 | |
| 971 | void PnaclCoordinator::BitcodeStreamGotData(int32_t pp_error, |
| 972 | FileStreamData data) { |
| 973 | PLUGIN_PRINTF(("PnaclCoordinator::BitcodeStreamGotData (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 974 | NACL_PRId32 ", data=%p)\n", pp_error, data ? &(*data)[0] : 0)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 975 | DCHECK(translate_thread_.get()); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 976 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 977 | translate_thread_->PutBytes(data, pp_error); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 978 | // If pp_error > 0, then it represents the number of bytes received. |
| 979 | if (data && pp_error > 0) { |
| 980 | pexe_size_ += pp_error; |
| 981 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 982 | } |
| 983 | |
| 984 | StreamCallback PnaclCoordinator::GetCallback() { |
| 985 | return callback_factory_.NewCallbackWithOutput( |
| 986 | &PnaclCoordinator::BitcodeStreamGotData); |
| 987 | } |
| 988 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 989 | void PnaclCoordinator::BitcodeGotCompiled(int32_t pp_error, |
| 990 | int64_t bytes_compiled) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 991 | pexe_bytes_compiled_ += bytes_compiled; |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 992 | // If we don't know the expected total yet, ask. |
| 993 | if (!ExpectedProgressKnown()) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 994 | int64_t amount_downloaded; // dummy variable. |
| 995 | streaming_downloader_->GetDownloadProgress(&amount_downloaded, |
| 996 | &expected_pexe_size_); |
| 997 | } |
Torne (Richard Coles) | a93a17c | 2013-05-15 11:34:50 +0100 | [diff] [blame] | 998 | // Hold off reporting the last few bytes of progress, since we don't know |
| 999 | // when they are actually completely compiled. "bytes_compiled" only means |
| 1000 | // that bytes were sent to the compiler. |
| 1001 | if (ExpectedProgressKnown()) { |
| 1002 | if (!ShouldDelayProgressEvent()) { |
| 1003 | plugin_->EnqueueProgressEvent(plugin::Plugin::kProgressEventProgress, |
| 1004 | pexe_url_, |
| 1005 | plugin::Plugin::LENGTH_IS_COMPUTABLE, |
| 1006 | pexe_bytes_compiled_, |
| 1007 | expected_pexe_size_); |
| 1008 | } |
| 1009 | } else { |
| 1010 | plugin_->EnqueueProgressEvent(plugin::Plugin::kProgressEventProgress, |
| 1011 | pexe_url_, |
| 1012 | plugin::Plugin::LENGTH_IS_NOT_COMPUTABLE, |
| 1013 | pexe_bytes_compiled_, |
| 1014 | expected_pexe_size_); |
| 1015 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1016 | } |
| 1017 | |
| 1018 | pp::CompletionCallback PnaclCoordinator::GetCompileProgressCallback( |
| 1019 | int64_t bytes_compiled) { |
| 1020 | return callback_factory_.NewCallback(&PnaclCoordinator::BitcodeGotCompiled, |
| 1021 | bytes_compiled); |
| 1022 | } |
| 1023 | |
| 1024 | void PnaclCoordinator::GetCurrentProgress(int64_t* bytes_loaded, |
| 1025 | int64_t* bytes_total) { |
| 1026 | *bytes_loaded = pexe_bytes_compiled_; |
| 1027 | *bytes_total = expected_pexe_size_; |
| 1028 | } |
| 1029 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1030 | void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) { |
| 1031 | PLUGIN_PRINTF(("PnaclCoordinator::ObjectFileDidOpen (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 1032 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1033 | if (pp_error != PP_OK) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1034 | ReportPpapiError(ERROR_PNACL_CREATE_TEMP, |
| 1035 | pp_error, |
| 1036 | "Failed to open scratch object file."); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1037 | return; |
| 1038 | } |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 1039 | // Open the nexe file for connecting ld and sel_ldr. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1040 | // Start translation when done with this last step of setup! |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 1041 | if (!use_new_cache_) |
| 1042 | // In the new cache case, the TempFile has already been created. |
| 1043 | temp_nexe_file_.reset(new TempFile(plugin_)); |
| 1044 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1045 | pp::CompletionCallback cb = |
| 1046 | callback_factory_.NewCallback(&PnaclCoordinator::RunTranslate); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 1047 | temp_nexe_file_->Open(cb, true); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1048 | } |
| 1049 | |
| 1050 | void PnaclCoordinator::RunTranslate(int32_t pp_error) { |
| 1051 | PLUGIN_PRINTF(("PnaclCoordinator::RunTranslate (pp_error=%" |
Ben Murdoch | bbcdd45 | 2013-07-25 10:06:34 +0100 | [diff] [blame^] | 1052 | NACL_PRId32 ")\n", pp_error)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1053 | // Invoke llc followed by ld off the main thread. This allows use of |
| 1054 | // blocking RPCs that would otherwise block the JavaScript main thread. |
| 1055 | pp::CompletionCallback report_translate_finished = |
| 1056 | callback_factory_.NewCallback(&PnaclCoordinator::TranslateFinished); |
| 1057 | |
| 1058 | CHECK(translate_thread_ != NULL); |
| 1059 | translate_thread_->RunTranslate(report_translate_finished, |
| 1060 | manifest_.get(), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1061 | obj_file_.get(), |
| 1062 | temp_nexe_file_.get(), |
| 1063 | &error_info_, |
| 1064 | resources_.get(), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 1065 | &pnacl_options_, |
| 1066 | this, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1067 | plugin_); |
| 1068 | } |
| 1069 | |
| 1070 | } // namespace plugin |