| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| // Author: sligocki@google.com (Shawn Ligocki) |
| |
| #include "net/instaweb/rewriter/public/rewrite_driver_factory.h" |
| |
| #include "base/logging.h" |
| #include "net/instaweb/config/rewrite_options_manager.h" |
| #include "net/instaweb/http/public/http_cache.h" |
| #include "net/instaweb/http/public/http_dump_url_async_writer.h" |
| #include "net/instaweb/http/public/http_dump_url_fetcher.h" |
| #include "net/instaweb/http/public/request_context.h" |
| #include "net/instaweb/http/public/url_async_fetcher.h" |
| #include "net/instaweb/rewriter/public/beacon_critical_images_finder.h" |
| #include "net/instaweb/rewriter/public/beacon_critical_line_info_finder.h" |
| #include "net/instaweb/rewriter/public/compatible_central_controller.h" |
| #include "net/instaweb/rewriter/public/critical_css_finder.h" |
| #include "net/instaweb/rewriter/public/critical_images_finder.h" |
| #include "net/instaweb/rewriter/public/critical_line_info_finder.h" |
| #include "net/instaweb/rewriter/public/critical_selector_finder.h" |
| #include "net/instaweb/rewriter/public/experiment_matcher.h" |
| #include "net/instaweb/rewriter/public/mobilize_cached_finder.h" |
| #include "net/instaweb/rewriter/public/process_context.h" |
| #include "net/instaweb/rewriter/public/rewrite_driver.h" |
| #include "net/instaweb/rewriter/public/rewrite_options.h" |
| #include "net/instaweb/rewriter/public/rewrite_stats.h" |
| #include "net/instaweb/rewriter/public/server_context.h" |
| #include "net/instaweb/rewriter/public/static_asset_manager.h" |
| #include "net/instaweb/rewriter/public/url_namer.h" |
| #include "net/instaweb/rewriter/public/usage_data_reporter.h" |
| #include "net/instaweb/util/public/property_store.h" |
| #include "pagespeed/kernel/base/abstract_mutex.h" |
| #include "pagespeed/kernel/base/checking_thread_system.h" |
| #include "pagespeed/kernel/base/file_system.h" |
| #include "pagespeed/kernel/base/function.h" |
| #include "pagespeed/kernel/base/hasher.h" |
| #include "pagespeed/kernel/base/hostname_util.h" |
| #include "pagespeed/kernel/base/message_handler.h" |
| #include "pagespeed/kernel/base/named_lock_manager.h" |
| #include "pagespeed/kernel/base/scoped_ptr.h" |
| #include "pagespeed/kernel/base/sha1_signature.h" |
| #include "pagespeed/kernel/base/stl_util.h" |
| #include "pagespeed/kernel/base/string.h" |
| #include "pagespeed/kernel/base/string_util.h" |
| #include "pagespeed/kernel/base/thread_system.h" |
| #include "pagespeed/kernel/base/timer.h" |
| #include "pagespeed/kernel/cache/cache_batcher.h" |
| #include "pagespeed/kernel/http/http_options.h" |
| #include "pagespeed/kernel/http/user_agent_matcher.h" |
| #include "pagespeed/kernel/http/user_agent_normalizer.h" |
| #include "pagespeed/kernel/thread/queued_worker_pool.h" |
| #include "pagespeed/kernel/thread/scheduler.h" |
| #include "pagespeed/kernel/util/file_system_lock_manager.h" |
| #include "pagespeed/kernel/util/nonce_generator.h" |
| #include "pagespeed/opt/http/property_cache.h" |
| |
| namespace net_instaweb { |
| |
| RewriteDriverFactory::RewriteDriverFactory( |
| const ProcessContext& process_context, ThreadSystem* thread_system) |
| : url_async_fetcher_(NULL), |
| distributed_async_fetcher_(NULL), |
| js_tokenizer_patterns_(process_context.js_tokenizer_patterns()), |
| force_caching_(false), |
| slurp_read_only_(false), |
| slurp_print_urls_(false), |
| #ifdef NDEBUG |
| // For release binaries, use the thread-system directly. |
| thread_system_(thread_system), |
| #else |
| // When compiling for debug, interpose a layer that CHECKs for clean mutex |
| // semantics. |
| thread_system_(new CheckingThreadSystem(thread_system)), |
| #endif |
| server_context_mutex_(thread_system_->NewMutex()), |
| statistics_(&null_statistics_), |
| worker_pools_(kNumWorkerPools, NULL), |
| hostname_(GetHostname()) { |
| // Pre-initializes the default options. IMPORTANT: subclasses overridding |
| // NewRewriteOptions() should re-call this method from their constructor |
| // so that the correct rewrite_options_ object gets reset. |
| InitializeDefaultOptions(); |
| } |
| |
| void RewriteDriverFactory::InitializeDefaultOptions() { |
| default_options_.reset(NewRewriteOptions()); |
| InitializeDefaultOptions(default_options_.get()); |
| // Note that we do not need to compute a signature on the default options. |
| // We will never be serving requests with these options: they are just used |
| // as a source for merging. |
| } |
| |
| void RewriteDriverFactory::InitializeDefaultOptions(RewriteOptions* options) { |
| // We default to using the "core filters". Note that this is not |
| // the only place the default is applied --- for directories with .htaccess |
| // files it is given in create_dir_config in mod_instaweb.cc |
| options->SetDefaultRewriteLevel(RewriteOptions::kCoreFilters); |
| options->DisallowTroublesomeResources(); |
| } |
| |
| void RewriteDriverFactory::reset_default_options(RewriteOptions* new_defaults) { |
| default_options_.reset(new_defaults); |
| } |
| |
| RewriteDriverFactory::~RewriteDriverFactory() { |
| ShutDown(); |
| |
| { |
| ScopedMutex lock(server_context_mutex_.get()); |
| STLDeleteElements(&server_contexts_); |
| } |
| |
| for (int c = 0; c < kNumWorkerPools; ++c) { |
| delete worker_pools_[c]; |
| worker_pools_[c] = NULL; |
| } |
| |
| // Avoid double-destructing the url fetchers if they were not overridden |
| // programmatically |
| if ((url_async_fetcher_ != NULL) && |
| (url_async_fetcher_ != base_url_async_fetcher_.get())) { |
| delete url_async_fetcher_; |
| } |
| url_async_fetcher_ = NULL; |
| |
| if ((distributed_async_fetcher_ != NULL) && |
| (distributed_async_fetcher_ != base_distributed_async_fetcher_.get())) { |
| delete distributed_async_fetcher_; |
| } |
| distributed_async_fetcher_ = NULL; |
| |
| for (int i = 0, n = deferred_cleanups_.size(); i < n; ++i) { |
| deferred_cleanups_[i]->CallRun(); |
| } |
| |
| // Delete the lock-manager before we delete the scheduler. |
| lock_manager_.reset(NULL); |
| } |
| |
| void RewriteDriverFactory::set_html_parse_message_handler( |
| MessageHandler* message_handler) { |
| html_parse_message_handler_.reset(message_handler); |
| } |
| |
| void RewriteDriverFactory::set_message_handler( |
| MessageHandler* message_handler) { |
| message_handler_.reset(message_handler); |
| } |
| |
| bool RewriteDriverFactory::FetchersComputed() const { |
| return (url_async_fetcher_ != NULL); |
| } |
| |
| void RewriteDriverFactory::set_slurp_directory(const StringPiece& dir) { |
| CHECK(!FetchersComputed()) |
| << "Cannot call set_slurp_directory " |
| << " after ComputeUrl*Fetcher has been called"; |
| dir.CopyToString(&slurp_directory_); |
| } |
| |
| void RewriteDriverFactory::set_slurp_read_only(bool read_only) { |
| CHECK(!FetchersComputed()) |
| << "Cannot call set_slurp_read_only " |
| << " after ComputeUrl*Fetcher has been called"; |
| slurp_read_only_ = read_only; |
| } |
| |
| void RewriteDriverFactory::set_slurp_print_urls(bool print_urls) { |
| CHECK(!FetchersComputed()) |
| << "Cannot call set_slurp_print_urls " |
| << " after ComputeUrl*Fetcher has been called"; |
| slurp_print_urls_ = print_urls; |
| } |
| |
| void RewriteDriverFactory::set_file_system(FileSystem* file_system) { |
| file_system_.reset(file_system); |
| } |
| |
| void RewriteDriverFactory::set_base_url_async_fetcher( |
| UrlAsyncFetcher* url_async_fetcher) { |
| CHECK(!FetchersComputed()) |
| << "Cannot call set_base_url_async_fetcher " |
| << " after ComputeUrlAsyncFetcher has been called"; |
| base_url_async_fetcher_.reset(url_async_fetcher); |
| } |
| |
| void RewriteDriverFactory::set_base_distributed_async_fetcher( |
| UrlAsyncFetcher* distributed_fetcher) { |
| CHECK(distributed_async_fetcher_ == NULL) |
| << "Cannot call set_base_distributed_async_fetcher " |
| << "after ComputeDistributedFetcher has been called"; |
| base_distributed_async_fetcher_.reset(distributed_fetcher); |
| } |
| |
| |
| void RewriteDriverFactory::set_hasher(Hasher* hasher) { |
| hasher_.reset(hasher); |
| } |
| |
| void RewriteDriverFactory::set_signature(SHA1Signature* signature) { |
| signature_.reset(signature); |
| } |
| |
| void RewriteDriverFactory::set_timer(Timer* timer) { |
| timer_.reset(timer); |
| } |
| |
| void RewriteDriverFactory::set_nonce_generator(NonceGenerator* gen) { |
| nonce_generator_.reset(gen); |
| } |
| |
| void RewriteDriverFactory::set_url_namer(UrlNamer* url_namer) { |
| url_namer_.reset(url_namer); |
| } |
| |
| void RewriteDriverFactory::set_usage_data_reporter( |
| UsageDataReporter* reporter) { |
| usage_data_reporter_.reset(reporter); |
| } |
| |
| MessageHandler* RewriteDriverFactory::html_parse_message_handler() { |
| if (html_parse_message_handler_ == NULL) { |
| html_parse_message_handler_.reset(DefaultHtmlParseMessageHandler()); |
| } |
| return html_parse_message_handler_.get(); |
| } |
| |
| MessageHandler* RewriteDriverFactory::message_handler() { |
| if (message_handler_ == NULL) { |
| message_handler_.reset(DefaultMessageHandler()); |
| } |
| return message_handler_.get(); |
| } |
| |
| FileSystem* RewriteDriverFactory::file_system() { |
| if (file_system_ == NULL) { |
| file_system_.reset(DefaultFileSystem()); |
| } |
| return file_system_.get(); |
| } |
| |
| NonceGenerator* RewriteDriverFactory::nonce_generator() { |
| if (nonce_generator_ == NULL) { |
| nonce_generator_.reset(DefaultNonceGenerator()); |
| } |
| return nonce_generator_.get(); |
| } |
| |
| NonceGenerator* RewriteDriverFactory::DefaultNonceGenerator() { |
| // By default return NULL (no nonce generator). |
| return NULL; |
| } |
| |
| Timer* RewriteDriverFactory::DefaultTimer() { |
| return thread_system()->NewTimer(); |
| } |
| |
| Timer* RewriteDriverFactory::timer() { |
| if (timer_ == NULL) { |
| timer_.reset(DefaultTimer()); |
| } |
| return timer_.get(); |
| } |
| |
| UrlNamer* RewriteDriverFactory::url_namer() { |
| if (url_namer_ == NULL) { |
| url_namer_.reset(DefaultUrlNamer()); |
| } |
| return url_namer_.get(); |
| } |
| |
| UserAgentMatcher* RewriteDriverFactory::user_agent_matcher() { |
| if (user_agent_matcher_ == NULL) { |
| user_agent_matcher_.reset(DefaultUserAgentMatcher()); |
| } |
| return user_agent_matcher_.get(); |
| } |
| |
| StaticAssetManager* RewriteDriverFactory::static_asset_manager() { |
| if (static_asset_manager_ == NULL) { |
| static_asset_manager_.reset(DefaultStaticAssetManager()); |
| InitStaticAssetManager(static_asset_manager_.get()); |
| } |
| return static_asset_manager_.get(); |
| } |
| |
| RewriteOptionsManager* RewriteDriverFactory::NewRewriteOptionsManager() { |
| return new RewriteOptionsManager; |
| } |
| |
| Scheduler* RewriteDriverFactory::scheduler() { |
| if (scheduler_ == NULL) { |
| scheduler_.reset(CreateScheduler()); |
| } |
| return scheduler_.get(); |
| } |
| |
| Hasher* RewriteDriverFactory::hasher() { |
| if (hasher_ == NULL) { |
| hasher_.reset(NewHasher()); |
| } |
| return hasher_.get(); |
| } |
| |
| SHA1Signature* RewriteDriverFactory::signature() { |
| if (signature_ == NULL) { |
| signature_.reset(DefaultSignature()); |
| } |
| return signature_.get(); |
| } |
| |
| UsageDataReporter* RewriteDriverFactory::usage_data_reporter() { |
| if (usage_data_reporter_ == NULL) { |
| usage_data_reporter_.reset(DefaultUsageDataReporter()); |
| } |
| return usage_data_reporter_.get(); |
| } |
| |
| const std::vector<const UserAgentNormalizer*>& |
| RewriteDriverFactory::user_agent_normalizers() { |
| if (user_agent_normalizers_.empty()) { |
| // Note: it's possible that we may want separate lists of normalizers for |
| // different applications in the future. For now, though, we centralize |
| // one list, because: |
| // a) It's simpler b) Regexp compilation isn't free. |
| AndroidUserAgentNormalizer* an = new AndroidUserAgentNormalizer(); |
| IEUserAgentNormalizer* ien = new IEUserAgentNormalizer(); |
| TakeOwnership(an); |
| TakeOwnership(ien); |
| user_agent_normalizers_.push_back(an); |
| user_agent_normalizers_.push_back(ien); |
| AddPlatformSpecificUserAgentNormalizers(&user_agent_normalizers_); |
| } |
| return user_agent_normalizers_; |
| } |
| |
| NamedLockManager* RewriteDriverFactory::DefaultLockManager() { |
| return new FileSystemLockManager(file_system(), LockFilePrefix(), |
| scheduler(), message_handler()); |
| } |
| |
| UrlNamer* RewriteDriverFactory::DefaultUrlNamer() { |
| return new UrlNamer(); |
| } |
| |
| UserAgentMatcher* RewriteDriverFactory::DefaultUserAgentMatcher() { |
| return new UserAgentMatcher(); |
| } |
| |
| StaticAssetManager* RewriteDriverFactory::DefaultStaticAssetManager() { |
| return new StaticAssetManager(url_namer()->proxy_domain(), |
| thread_system(), |
| hasher(), |
| message_handler()); |
| } |
| |
| CriticalCssFinder* RewriteDriverFactory::DefaultCriticalCssFinder() { |
| return NULL; |
| } |
| |
| CriticalImagesFinder* RewriteDriverFactory::DefaultCriticalImagesFinder( |
| ServerContext* server_context) { |
| // TODO(pulkitg): Don't create BeaconCriticalImagesFinder if beacon cohort is |
| // not added. |
| return new BeaconCriticalImagesFinder( |
| server_context->beacon_cohort(), nonce_generator(), statistics()); |
| } |
| |
| CriticalSelectorFinder* RewriteDriverFactory::DefaultCriticalSelectorFinder( |
| ServerContext* server_context) { |
| if (server_context->beacon_cohort() != NULL) { |
| return new BeaconCriticalSelectorFinder(server_context->beacon_cohort(), |
| nonce_generator(), statistics()); |
| } |
| return NULL; |
| } |
| |
| MobilizeCachedFinder* RewriteDriverFactory::DefaultMobilizeCachedFinder( |
| ServerContext* server_context) { |
| return NULL; |
| } |
| |
| SHA1Signature* RewriteDriverFactory::DefaultSignature() { |
| return new SHA1Signature(); |
| } |
| |
| FlushEarlyInfoFinder* RewriteDriverFactory::DefaultFlushEarlyInfoFinder() { |
| return NULL; |
| } |
| |
| CacheHtmlInfoFinder* RewriteDriverFactory::DefaultCacheHtmlInfoFinder( |
| PropertyCache* cache, ServerContext* server_context) { |
| return NULL; |
| } |
| |
| CriticalLineInfoFinder* RewriteDriverFactory::DefaultCriticalLineInfoFinder( |
| ServerContext* server_context) { |
| return new BeaconCriticalLineInfoFinder(server_context->beacon_cohort(), |
| nonce_generator()); |
| } |
| |
| UsageDataReporter* RewriteDriverFactory::DefaultUsageDataReporter() { |
| return new UsageDataReporter; |
| } |
| |
| QueuedWorkerPool* RewriteDriverFactory::CreateWorkerPool( |
| WorkerPoolCategory pool, StringPiece name) { |
| return new QueuedWorkerPool(1, name, thread_system()); |
| } |
| |
| int RewriteDriverFactory::LowPriorityLoadSheddingThreshold() const { |
| return QueuedWorkerPool::kNoLoadShedding; |
| } |
| |
| Scheduler* RewriteDriverFactory::CreateScheduler() { |
| return new Scheduler(thread_system(), timer()); |
| } |
| |
| NamedLockManager* RewriteDriverFactory::lock_manager() { |
| if (lock_manager_ == NULL) { |
| lock_manager_.reset(DefaultLockManager()); |
| } |
| return lock_manager_.get(); |
| } |
| |
| QueuedWorkerPool* RewriteDriverFactory::WorkerPool(WorkerPoolCategory pool) { |
| if (worker_pools_[pool] == NULL) { |
| StringPiece name; |
| switch (pool) { |
| case kHtmlWorkers: |
| name = "html"; |
| break; |
| case kRewriteWorkers: |
| name = "rewrite"; |
| break; |
| case kLowPriorityRewriteWorkers: |
| name = "slow_rewrite"; |
| break; |
| default: |
| LOG(DFATAL) << "Unhandled enum value " << pool; |
| name = "unknown_worker"; |
| break; |
| } |
| |
| worker_pools_[pool] = CreateWorkerPool(pool, name); |
| worker_pools_[pool]->set_queue_size_stat( |
| rewrite_stats()->thread_queue_depth(pool)); |
| if (pool == kLowPriorityRewriteWorkers) { |
| worker_pools_[pool]->SetLoadSheddingThreshold( |
| LowPriorityLoadSheddingThreshold()); |
| } |
| } |
| |
| return worker_pools_[pool]; |
| } |
| |
| bool RewriteDriverFactory::set_filename_prefix(StringPiece p) { |
| p.CopyToString(&filename_prefix_); |
| if (file_system()->IsDir(filename_prefix_.c_str(), |
| message_handler()).is_true()) { |
| return true; |
| } |
| |
| if (!file_system()->RecursivelyMakeDir(filename_prefix_, message_handler())) { |
| message_handler()->FatalError( |
| filename_prefix_.c_str(), 0, |
| "Directory does not exist and cannot be created"); |
| return false; |
| } |
| |
| AddCreatedDirectory(filename_prefix_); |
| return true; |
| } |
| |
| StringPiece RewriteDriverFactory::filename_prefix() { |
| return filename_prefix_; |
| } |
| |
| ServerContext* RewriteDriverFactory::CreateServerContext() { |
| ServerContext* server_context = NewServerContext(); |
| InitServerContext(server_context); |
| return server_context; |
| } |
| |
| void RewriteDriverFactory::InitServerContext(ServerContext* server_context) { |
| ScopedMutex lock(server_context_mutex_.get()); |
| |
| // Init CentralController. This is not strictly related to the ServerContext, |
| // but needs to happen before the ServerContext starts up. |
| set_central_controller_interface(CreateCentralController()); |
| |
| server_context->ComputeSignature(server_context->global_options()); |
| server_context->set_scheduler(scheduler()); |
| server_context->set_timer(timer()); |
| if (server_context->statistics() == NULL) { |
| server_context->set_statistics(statistics()); |
| } |
| if (server_context->rewrite_stats() == NULL) { |
| server_context->set_rewrite_stats(rewrite_stats()); |
| } |
| SetupCaches(server_context); |
| if (server_context->lock_manager() == NULL) { |
| server_context->set_lock_manager(lock_manager()); |
| } |
| if (!server_context->has_default_system_fetcher()) { |
| server_context->set_default_system_fetcher(ComputeUrlAsyncFetcher()); |
| } |
| if (!server_context->has_default_distributed_fetcher()) { |
| UrlAsyncFetcher* fetcher = ComputeDistributedFetcher(); |
| if (fetcher != NULL) { |
| server_context->set_default_distributed_fetcher(fetcher); |
| } |
| } |
| server_context->set_url_namer(url_namer()); |
| server_context->SetRewriteOptionsManager(NewRewriteOptionsManager()); |
| server_context->set_user_agent_matcher(user_agent_matcher()); |
| server_context->set_file_system(file_system()); |
| server_context->set_filename_prefix(filename_prefix_); |
| server_context->set_hasher(hasher()); |
| server_context->set_signature(signature()); |
| server_context->set_message_handler(message_handler()); |
| server_context->set_static_asset_manager(static_asset_manager()); |
| PropertyCache* pcache = server_context->page_property_cache(); |
| server_context->set_critical_css_finder(DefaultCriticalCssFinder()); |
| server_context->set_critical_images_finder( |
| DefaultCriticalImagesFinder(server_context)); |
| server_context->set_critical_selector_finder( |
| DefaultCriticalSelectorFinder(server_context)); |
| server_context->set_flush_early_info_finder(DefaultFlushEarlyInfoFinder()); |
| server_context->set_cache_html_info_finder( |
| DefaultCacheHtmlInfoFinder(pcache, server_context)); |
| server_context->set_critical_line_info_finder( |
| DefaultCriticalLineInfoFinder(server_context)); |
| server_context->set_mobilize_cached_finder( |
| DefaultMobilizeCachedFinder(server_context)); |
| server_context->set_hostname(hostname_); |
| server_context->PostInitHook(); |
| InitDecodingDriver(server_context); |
| server_contexts_.insert(server_context); |
| |
| // Make sure that all lazy state gets initialized, even if we don't copy it to |
| // ServerContext |
| user_agent_normalizers(); |
| // Fetch the remote options so that they will be cached. |
| HttpOptions fetch_options; |
| fetch_options.implicit_cache_ttl_ms = |
| server_context->global_options()->implicit_cache_ttl_ms(); |
| fetch_options.respect_vary = false; |
| // Minimum TTL for cachable resources, -1 for no minimum. |
| fetch_options.min_cache_ttl_ms = -1; |
| RequestContextPtr request_ctx(new RequestContext( |
| fetch_options, server_context->thread_system()->NewMutex(), |
| server_context->timer())); |
| scoped_ptr<RewriteOptions> remote_options( |
| server_context->global_options()->Clone()); |
| server_context->GetRemoteOptions(remote_options.get(), |
| true /* startup fetch */); |
| } |
| |
| CentralControllerInterface* RewriteDriverFactory::CreateCentralController() { |
| return new CompatibleCentralController( |
| default_options()->image_max_rewrites_at_once(), statistics()); |
| } |
| |
| void RewriteDriverFactory::RebuildDecodingDriverForTests( |
| ServerContext* server_context) { |
| decoding_driver_.reset(NULL); |
| InitDecodingDriver(server_context); |
| } |
| |
| void RewriteDriverFactory::InitDecodingDriver(ServerContext* server_context) { |
| if (decoding_driver_.get() == NULL) { |
| decoding_server_context_.reset(NewDecodingServerContext()); |
| // decoding_driver_ takes ownership. |
| RewriteOptions* options = default_options_->Clone(); |
| options->ComputeSignature(); |
| decoding_driver_.reset( |
| decoding_server_context_->NewUnmanagedRewriteDriver( |
| NULL, options, RequestContextPtr(NULL))); |
| decoding_driver_->set_externally_managed(true); |
| |
| // Apply platform configuration mutation for consistency's sake. |
| ApplyPlatformSpecificConfiguration(decoding_driver_.get()); |
| // Inserts platform-specific rewriters into the resource_filter_map_, so |
| // that the decoding process can recognize those rewriter ids. |
| AddPlatformSpecificDecodingPasses(decoding_driver_.get()); |
| // This call is for backwards compatibility. When adding new platform |
| // specific rewriters to implementations of RewriteDriverFactory, please |
| // do not rely on this call to include them in the decoding process. |
| // Instead, add them to your implementation of |
| // AddPlatformSpecificDecodingPasses. |
| AddPlatformSpecificRewritePasses(decoding_driver_.get()); |
| decoding_server_context_->set_decoding_driver(decoding_driver_.get()); |
| } |
| server_context->set_decoding_driver(decoding_driver_.get()); |
| } |
| |
| void RewriteDriverFactory::InitStubDecodingServerContext(ServerContext* sc) { |
| sc->set_timer(timer()); |
| sc->set_url_namer(url_namer()); |
| sc->set_hasher(hasher()); |
| sc->set_message_handler(message_handler()); |
| NullStatistics* null_stats = new NullStatistics(); |
| TakeOwnership(null_stats); |
| InitStats(null_stats); |
| sc->set_statistics(null_stats); |
| sc->set_hasher(hasher()); |
| sc->set_signature(signature()); |
| sc->PostInitHook(); |
| } |
| |
| void RewriteDriverFactory::AddPlatformSpecificDecodingPasses( |
| RewriteDriver* driver) { |
| } |
| |
| void RewriteDriverFactory::AddPlatformSpecificRewritePasses( |
| RewriteDriver* driver) { |
| } |
| |
| void RewriteDriverFactory::ApplyPlatformSpecificConfiguration( |
| RewriteDriver* driver) { |
| } |
| |
| void RewriteDriverFactory::AddPlatformSpecificUserAgentNormalizers( |
| std::vector<const UserAgentNormalizer*>* out) { |
| } |
| |
| UrlAsyncFetcher* RewriteDriverFactory::ComputeUrlAsyncFetcher() { |
| if (url_async_fetcher_ == NULL) { |
| // Run any hooks like setting up slurp directory. |
| FetcherSetupHooks(); |
| if (slurp_directory_.empty()) { |
| if (base_url_async_fetcher_.get() == NULL) { |
| url_async_fetcher_ = DefaultAsyncUrlFetcher(); |
| } else { |
| url_async_fetcher_ = base_url_async_fetcher_.get(); |
| } |
| } else { |
| SetupSlurpDirectories(); |
| } |
| } |
| return url_async_fetcher_; |
| } |
| |
| UrlAsyncFetcher* RewriteDriverFactory::ComputeDistributedFetcher() { |
| if (distributed_async_fetcher_ == NULL) { |
| if (base_distributed_async_fetcher_.get() == NULL) { |
| distributed_async_fetcher_ = DefaultDistributedUrlFetcher(); |
| } else { |
| distributed_async_fetcher_ = base_distributed_async_fetcher_.get(); |
| } |
| } |
| return distributed_async_fetcher_; |
| } |
| |
| void RewriteDriverFactory::SetupSlurpDirectories() { |
| CHECK(!FetchersComputed()); |
| if (slurp_read_only_) { |
| CHECK(!FetchersComputed()); |
| HttpDumpUrlFetcher* dump_fetcher = new HttpDumpUrlFetcher( |
| slurp_directory_, file_system(), timer()); |
| dump_fetcher->set_print_urls(slurp_print_urls_); |
| url_async_fetcher_ = dump_fetcher; |
| } else { |
| // Check to see if the factory already had set_base_url_async_fetcher |
| // called on it. If so, then we'll want to use that fetcher |
| // as the mechanism for the dump-writer to retrieve missing |
| // content from the internet so it can be saved in the slurp |
| // directory. |
| url_async_fetcher_ = base_url_async_fetcher_.get(); |
| if (url_async_fetcher_ == NULL) { |
| url_async_fetcher_ = DefaultAsyncUrlFetcher(); |
| } |
| HttpDumpUrlAsyncWriter* dump_writer = new HttpDumpUrlAsyncWriter( |
| slurp_directory_, url_async_fetcher_, file_system(), timer()); |
| dump_writer->set_print_urls(slurp_print_urls_); |
| url_async_fetcher_ = dump_writer; |
| } |
| } |
| |
| void RewriteDriverFactory::FetcherSetupHooks() { |
| } |
| |
| StringPiece RewriteDriverFactory::LockFilePrefix() { |
| return filename_prefix_; |
| } |
| |
| void RewriteDriverFactory::StopCacheActivity() { |
| ScopedMutex lock(server_context_mutex_.get()); |
| |
| // Make sure we tell HTTP cache not to write out fetch failures, as |
| // fetcher shutdown may create artificial ones, and we don't want to |
| // remember those. |
| // |
| // Note that we also cannot access our own http_cache_ since it may be |
| // NULL in case like Apache where server contexts get their own. |
| for (ServerContextSet::iterator p = server_contexts_.begin(); |
| p != server_contexts_.end(); ++p) { |
| HTTPCache* cache = (*p)->http_cache(); |
| if (cache != NULL) { |
| cache->SetIgnoreFailurePuts(); |
| } |
| } |
| |
| // Similarly stop metadata cache writes. |
| for (ServerContextSet::iterator p = server_contexts_.begin(); |
| p != server_contexts_.end(); ++p) { |
| ServerContext* server_context = *p; |
| server_context->set_shutting_down(); |
| } |
| } |
| |
| bool RewriteDriverFactory::TerminateServerContext(ServerContext* sc) { |
| ScopedMutex lock(server_context_mutex_.get()); |
| server_contexts_.erase(sc); |
| return server_contexts_.empty(); |
| } |
| |
| void RewriteDriverFactory::ShutDown() { |
| StopCacheActivity(); // Maybe already stopped, but no harm stopping it twice. |
| |
| // We first shutdown the low-priority rewrite threads, as they're meant to |
| // be robust against cancellation, and it will make the jobs wrap up |
| // much quicker. |
| if (worker_pools_[kLowPriorityRewriteWorkers] != NULL) { |
| worker_pools_[kLowPriorityRewriteWorkers]->ShutDown(); |
| } |
| |
| // Now get active RewriteDrivers for each manager to wrap up. |
| for (ServerContextSet::iterator p = server_contexts_.begin(); |
| p != server_contexts_.end(); ++p) { |
| ServerContext* server_context = *p; |
| server_context->ShutDownDrivers(); |
| } |
| |
| // Shut down the remaining worker threads, to quiesce the system while |
| // leaving the QueuedWorkerPool & QueuedWorkerPool::Sequence objects |
| // live. The QueuedWorkerPools will be deleted when the ServerContext |
| // is destructed. |
| for (int i = 0, n = worker_pools_.size(); i < n; ++i) { |
| QueuedWorkerPool* worker_pool = worker_pools_[i]; |
| if (worker_pool != NULL) { |
| worker_pool->ShutDown(); |
| } |
| } |
| |
| // Make sure we destroy the decoding driver here, before any of the |
| // server contexts get destroyed, since it's tied to one. Also clear |
| // all of the references to it. |
| for (ServerContextSet::iterator p = server_contexts_.begin(); |
| p != server_contexts_.end(); ++p) { |
| ServerContext* server_context = *p; |
| server_context->set_decoding_driver(NULL); |
| } |
| decoding_driver_.reset(NULL); |
| } |
| |
| void RewriteDriverFactory::AddCreatedDirectory(const GoogleString& dir) { |
| created_directories_.insert(dir); |
| } |
| |
| void RewriteDriverFactory::InitStats(Statistics* statistics) { |
| HTTPCache::InitStats(statistics); |
| RewriteDriver::InitStats(statistics); |
| RewriteStats::InitStats(statistics); |
| CacheBatcher::InitStats(statistics); |
| CompatibleCentralController::InitStats(statistics); |
| CriticalImagesFinder::InitStats(statistics); |
| CriticalCssFinder::InitStats(statistics); |
| CriticalSelectorFinder::InitStats(statistics); |
| MobilizeCachedFinder::InitStats(statistics); |
| PropertyStoreGetCallback::InitStats(statistics); |
| } |
| |
| void RewriteDriverFactory::Initialize() { |
| RewriteDriver::Initialize(); |
| } |
| |
| void RewriteDriverFactory::Terminate() { |
| RewriteDriver::Terminate(); |
| } |
| |
| void RewriteDriverFactory::SetStatistics(Statistics* statistics) { |
| statistics_ = statistics; |
| rewrite_stats_.reset(NULL); |
| } |
| |
| RewriteStats* RewriteDriverFactory::rewrite_stats() { |
| if (rewrite_stats_.get() == NULL) { |
| rewrite_stats_.reset(new RewriteStats(statistics_, thread_system_.get(), |
| timer())); |
| } |
| return rewrite_stats_.get(); |
| } |
| |
| void RewriteDriverFactory::set_central_controller_interface( |
| CentralControllerInterface* interface) { |
| central_controller_interface_.reset( |
| new CentralControllerInterfaceAdapter(interface)); |
| } |
| |
| RewriteOptions* RewriteDriverFactory::NewRewriteOptions() { |
| return new RewriteOptions(thread_system()); |
| } |
| |
| RewriteOptions* RewriteDriverFactory::NewRewriteOptionsForQuery() { |
| return NewRewriteOptions(); |
| } |
| |
| ExperimentMatcher* RewriteDriverFactory::NewExperimentMatcher() { |
| return new ExperimentMatcher; |
| } |
| |
| void RewriteDriverFactory::ScheduleExpensiveOperation( |
| ExpensiveOperationCallback* callback) { |
| central_controller_interface()->ScheduleExpensiveOperation(callback); |
| } |
| |
| } // namespace net_instaweb |