blob: aae732c4fd1cab463ef60c091b90b88298835c94 [file] [log] [blame]
/*
* 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: jmarantz@google.com (Joshua Marantz)
// and sligocki@google.com (Shawn Ligocki)
#ifndef NET_INSTAWEB_REWRITER_PUBLIC_SERVER_CONTEXT_H_
#define NET_INSTAWEB_REWRITER_PUBLIC_SERVER_CONTEXT_H_
#include <cstddef> // for size_t
#include <set>
#include <utility>
#include <vector>
#include "net/instaweb/http/public/cache_url_async_fetcher.h"
#include "net/instaweb/http/public/http_cache.h"
#include "net/instaweb/http/public/request_context.h"
#include "net/instaweb/http/public/url_async_fetcher.h"
#include "net/instaweb/rewriter/public/output_resource.h"
#include "net/instaweb/rewriter/public/resource.h"
#include "net/instaweb/util/public/property_cache.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/atomic_bool.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/cache_interface.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/hasher.h"
#include "pagespeed/kernel/base/md5_hasher.h"
#include "pagespeed/kernel/base/ref_counted_ptr.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/thread_system.h"
#include "pagespeed/kernel/http/content_type.h"
#include "pagespeed/kernel/http/request_headers.h"
#include "pagespeed/kernel/http/response_headers.h"
#include "pagespeed/kernel/thread/queued_worker_pool.h"
#include "pagespeed/kernel/util/simple_random.h"
namespace pagespeed { namespace js { struct JsTokenizerPatterns; } }
namespace net_instaweb {
class AsyncFetch;
class CacheHtmlInfoFinder;
class CachePropertyStore;
class CriticalCssFinder;
class CriticalImagesFinder;
class CriticalLineInfoFinder;
class CriticalSelectorFinder;
class RequestProperties;
class ExperimentMatcher;
class FileSystem;
class FlushEarlyInfoFinder;
class GoogleUrl;
class MessageHandler;
class MobilizeCachedFinder;
class NamedLock;
class NamedLockManager;
class PropertyStore;
class RewriteDriver;
class RewriteDriverFactory;
class RewriteDriverPool;
class RewriteFilter;
class RewriteOptions;
class RewriteOptionsManager;
class RewriteQuery;
class RewriteStats;
class SHA1Signature;
class Scheduler;
class StaticAssetManager;
class Statistics;
class ThreadSynchronizer;
class Timer;
class UrlNamer;
class UsageDataReporter;
class UserAgentMatcher;
typedef RefCountedPtr<OutputResource> OutputResourcePtr;
typedef std::vector<OutputResourcePtr> OutputResourceVector;
// Server-specific context and platform adaption: threads, file system, locking,
// and so on.
// TODO(piatek): This file was renamed from resource_manager.h -- there are
// some associated fixes outstanding --
// 1. abc of includes and class declarations.
// 2. Rename variables, data members, parameters, etc.
// 3. Rename methods.
class ServerContext {
public:
typedef std::pair<RewriteOptions*, bool> OptionsBoolPair;
// The lifetime for cache-extended generated resources, in milliseconds.
static const int64 kGeneratedMaxAgeMs;
// Short lifetime for generated resources fetched with mismatching hash.
static const int64 kCacheTtlForMismatchedContentMs;
// This value is a shared constant so that it can also be used in
// the Apache-specific code that repairs our caching headers downstream
// of mod_headers.
static const char kResourceEtagValue[];
static const char kCacheKeyResourceNamePrefix[];
// Default statistics group name.
static const char kStatisticsGroup[];
explicit ServerContext(RewriteDriverFactory* factory);
virtual ~ServerContext();
// Set time and cache headers with long TTL (including Date, Last-Modified,
// Cache-Control, Etags, Expires).
//
// Also sets Content-Type headers if content_type is provided.
// If content_type is null, the Content-Type header is omitted.
//
// Sets charset if it's non-empty and content_type is non-NULL.
//
// If cache_control suffix is non-empty, adds that to the Cache-Control
void SetDefaultLongCacheHeaders(
const ContentType* content_type, StringPiece charset,
StringPiece cache_control_suffix, ResponseHeaders* header) const;
void set_filename_prefix(const StringPiece& file_prefix);
void set_statistics(Statistics* x) { statistics_ = x; }
void set_rewrite_stats(RewriteStats* x) { rewrite_stats_ = x; }
void set_lock_manager(NamedLockManager* x) { lock_manager_ = x; }
void set_enable_property_cache(bool enabled);
void set_message_handler(MessageHandler* x) { message_handler_ = x; }
StringPiece filename_prefix() const { return file_prefix_; }
Statistics* statistics() const { return statistics_; }
NamedLockManager* lock_manager() const { return lock_manager_; }
RewriteDriverFactory* factory() const { return factory_; }
ThreadSynchronizer* thread_synchronizer() {
return thread_synchronizer_.get();
}
ExperimentMatcher* experiment_matcher() { return experiment_matcher_.get(); }
// Computes the most restrictive Cache-Control intersection of the input
// resources, and the provided headers, and sets that cache-control on the
// provided headers. Does nothing if all of the resources are fully
// cacheable, since in that case we will want to cache-extend.
//
// Disregards Cache-Control directives other than max-age, no-cache, no-store,
// and private, and strips them if any resource is no-cache or private. By
// assumption, a resource can only be no-store if it is also no-cache.
void ApplyInputCacheControl(const ResourceVector& inputs,
ResponseHeaders* headers);
// Is this URL a ref to a Pagespeed resource?
bool IsPagespeedResource(const GoogleUrl& url) const;
// Returns a filter to be used for decoding URLs & options for given
// filter id. This should not be used for actual fetches.
const RewriteFilter* FindFilterForDecoding(const StringPiece& id) const;
// See RewriteDriver::DecodeUrl.
bool DecodeUrlGivenOptions(const GoogleUrl& url,
const RewriteOptions* options,
const UrlNamer* url_namer,
StringVector* decoded_urls) const;
void ComputeSignature(RewriteOptions* rewrite_options) const;
// TODO(jmarantz): check thread safety in Apache.
Hasher* hasher() const { return hasher_; }
const Hasher* lock_hasher() const { return &lock_hasher_; }
const Hasher* contents_hasher() const { return &contents_hasher_; }
FileSystem* file_system() { return file_system_; }
void set_file_system(FileSystem* fs ) { file_system_ = fs; }
UrlNamer* url_namer() const { return url_namer_; }
void set_url_namer(UrlNamer* n) { url_namer_ = n; }
RewriteOptionsManager* rewrite_options_manager() const {
return rewrite_options_manager_.get();
}
SHA1Signature* signature() const { return signature_; }
// Takes ownership of RewriteOptionsManager.
void SetRewriteOptionsManager(RewriteOptionsManager* rom);
StaticAssetManager* static_asset_manager() const {
return static_asset_manager_;
}
void set_static_asset_manager(StaticAssetManager* manager) {
static_asset_manager_ = manager;
}
Scheduler* scheduler() const { return scheduler_; }
void set_scheduler(Scheduler* s) { scheduler_ = s; }
bool has_default_system_fetcher() const {
return default_system_fetcher_ != NULL;
}
bool has_default_distributed_fetcher() {
return default_distributed_fetcher_ != NULL;
}
// Note: for rewriting user content, you want to use RewriteDriver's
// async_fetcher() instead, as it may apply session-specific optimizations.
UrlAsyncFetcher* DefaultSystemFetcher() { return default_system_fetcher_; }
UrlAsyncFetcher* DefaultDistributedFetcher() {
return default_distributed_fetcher_;
}
// Creates a caching-fetcher based on the specified options. If you call
// this with DefaultSystemFetcher() then it will not include any loopback
// fetching installed in the RewriteDriver.
CacheUrlAsyncFetcher* CreateCustomCacheFetcher(
const RewriteOptions* options, const GoogleString& fragment,
CacheUrlAsyncFetcher::AsyncOpHooks* hooks, UrlAsyncFetcher* fetcher);
Timer* timer() const { return timer_; }
// Note: doesn't take ownership.
void set_timer(Timer* timer) { timer_ = timer; }
HTTPCache* http_cache() const { return http_cache_.get(); }
void set_http_cache(HTTPCache* x) { http_cache_.reset(x); }
// Creates PagePropertyCache object with the provided PropertyStore object.
void MakePagePropertyCache(PropertyStore* property_store);
PropertyCache* page_property_cache() const {
return page_property_cache_.get();
}
const PropertyCache::Cohort* dom_cohort() const { return dom_cohort_; }
void set_dom_cohort(const PropertyCache::Cohort* c) { dom_cohort_ = c; }
const PropertyCache::Cohort* blink_cohort() const { return blink_cohort_; }
void set_blink_cohort(const PropertyCache::Cohort* c) { blink_cohort_ = c; }
const PropertyCache::Cohort* beacon_cohort() const { return beacon_cohort_; }
void set_beacon_cohort(const PropertyCache::Cohort* c) { beacon_cohort_ = c; }
const PropertyCache::Cohort* fix_reflow_cohort() const {
return fix_reflow_cohort_;
}
void set_fix_reflow_cohort(const PropertyCache::Cohort* c) {
fix_reflow_cohort_ = c;
}
// Cache for storing file system metadata. It must be private to a server,
// preferably but not necessarily shared between its processes, and is
// required if using load-from-file and memcached (or any cache shared
// between servers). This class does not take ownership.
CacheInterface* filesystem_metadata_cache() const {
return filesystem_metadata_cache_;
}
void set_filesystem_metadata_cache(CacheInterface* x) {
filesystem_metadata_cache_ = x;
}
// Cache for small non-HTTP objects. This class does not take ownership.
//
// Note that this might share namespace with the HTTP cache, so make sure
// your key names do not start with http://.
CacheInterface* metadata_cache() const { return metadata_cache_; }
void set_metadata_cache(CacheInterface* x) { metadata_cache_ = x; }
CriticalCssFinder* critical_css_finder() const {
return critical_css_finder_.get();
}
void set_critical_css_finder(CriticalCssFinder* finder);
CriticalImagesFinder* critical_images_finder() const {
return critical_images_finder_.get();
}
void set_critical_images_finder(CriticalImagesFinder* finder);
CriticalSelectorFinder* critical_selector_finder() const {
return critical_selector_finder_.get();
}
void set_critical_selector_finder(CriticalSelectorFinder* finder);
FlushEarlyInfoFinder* flush_early_info_finder() const {
return flush_early_info_finder_.get();
}
void set_flush_early_info_finder(FlushEarlyInfoFinder* finder);
// May be NULL
MobilizeCachedFinder* mobilize_cached_finder() const {
return mobilize_cached_finder_.get();
}
void set_mobilize_cached_finder(MobilizeCachedFinder* finder);
UserAgentMatcher* user_agent_matcher() const {
return user_agent_matcher_;
}
void set_user_agent_matcher(UserAgentMatcher* n) { user_agent_matcher_ = n; }
CacheHtmlInfoFinder* cache_html_info_finder() const {
return cache_html_info_finder_.get();
}
SimpleRandom* simple_random() {
return &simple_random_;
}
void set_cache_html_info_finder(CacheHtmlInfoFinder* finder);
CriticalLineInfoFinder* critical_line_info_finder() const {
return critical_line_info_finder_.get();
}
// Takes ownership of the passed in finder.
void set_critical_line_info_finder(CriticalLineInfoFinder* finder);
// Whether or not dumps of rewritten resources should be stored to
// the filesystem. This is meant for testing purposes only.
bool store_outputs_in_file_system() { return store_outputs_in_file_system_; }
void set_store_outputs_in_file_system(bool store) {
store_outputs_in_file_system_ = store;
}
RewriteStats* rewrite_stats() const { return rewrite_stats_; }
MessageHandler* message_handler() const { return message_handler_; }
// Allocate an NamedLock to guard the creation of the given resource. If the
// object is expensive to create, this lock should be held during its creation
// to avoid multiple rewrites happening at once. The lock will be unlocked
// when creation_lock is reset or destructed.
NamedLock* MakeCreationLock(const GoogleString& name);
// Attempt to obtain a named lock without blocking. Return true if we do so.
void TryLockForCreation(NamedLock* creation_lock, Function* callback);
// Attempt to obtain a named lock. When the lock has been obtained, queue the
// callback on the given worker Sequence. If the lock times out, cancel the
// callback, running the cancel on the worker.
void LockForCreation(NamedLock* creation_lock,
QueuedWorkerPool::Sequence* worker, Function* callback);
// Setters should probably only be used in testing.
void set_hasher(Hasher* hasher) { hasher_ = hasher; }
void set_signature(SHA1Signature* signature) { signature_ = signature; }
void set_default_system_fetcher(UrlAsyncFetcher* fetcher) {
default_system_fetcher_ = fetcher;
}
void set_default_distributed_fetcher(UrlAsyncFetcher* fetcher) {
default_distributed_fetcher_ = fetcher;
}
// Handles an incoming beacon request by incrementing the appropriate
// variables. Returns true if the url was parsed and handled correctly; in
// this case a 204 No Content response should be sent. Returns false if the
// url could not be parsed; in this case the request should be declined. body
// should be either the query params or the POST body, depending on how the
// beacon was sent, from the beacon request.
bool HandleBeacon(StringPiece body,
StringPiece user_agent,
const RequestContextPtr& request_context);
// Returns a pointer to the master global_options. These are not used
// directly in RewriteDrivers, but are Cloned into the drivers as they
// are created. We generally do not expect global_options() to change once
// the system is processing requests, except in Apache when someone does
// a cache-flush by touching a file "cache.flush" in the file-cache directory.
RewriteOptions* global_options();
// Returns a pointer to the master global_options without modifying the
// ServerContext.
const RewriteOptions* global_options() const;
// Note that you have to ensure the argument has the right type in case
// a subclass of RewriteOptions is in use. This should also not be called
// once request processing has commenced.
void reset_global_options(RewriteOptions* options);
// Makes a new, empty set of RewriteOptions.
RewriteOptions* NewOptions();
// Runs the rewrite_query parser for any options set in query-params
// or in the headers. If all the pagespeed options that were parsed
// were valid, they are available either in rewrite_query->options() or in
// request_context if they are not actual options. The passed-in domain
// options control how options are handled, notably whether we allow related
// options or allow options to be specified by cookies. If you don't have
// domain specific options, pass NULL and global_options() will be used.
//
// True is returned in two cases:
// - Valid PageSpeed query params or headers were parsed
// - No PageSpeed query-parameters or headers were found.
// False is returned if there were PageSpeed-related options but they were
// not valid.
//
// It also strips off the PageSpeed query parameters and headers from the
// request_url, request headers, and response headers respectively. Stripped
// query params are copied into rewrite_query->pagespeed_query_params() and
// any PageSpeed option cookies are copied into
// rewrite_query->pagespeed_option_cookies().
bool GetQueryOptions(const RequestContextPtr& request_context,
const RewriteOptions* domain_options,
GoogleUrl* request_url,
RequestHeaders* request_headers,
ResponseHeaders* response_headers,
RewriteQuery* rewrite_query);
// Fetches the remote configuration from the url specified in the
// remote_configuration option, and applies the received options if cached. If
// not cached, the options will be cached, and applied on the next request.
// Query options should be applied after remote options, to be able to
// override any option set in the remote configuration for debugging purposes.
// This method calls a blocking fetch of the remote configuration file.
// Methods remote_configuration_url() and remote_configuration_timeout_ms()
// are called from *remote_options. If on_startup is true, the fetch is
// backgrounded and the result is ignored. Startup fetches are only used for
// populating the cache.
void GetRemoteOptions(RewriteOptions* remote_options, bool on_startup);
// Checks the url for the split html ATF/BTF query param. If present, it
// strips the param from the url, and sets a bit in the request context
// indicating which chunk of the split response was requested.
// Returns true if it found a query param.
static bool ScanSplitHtmlRequest(const RequestContextPtr& ctx,
const RewriteOptions* options,
GoogleString* url);
// Returns any custom options required for this request, incorporating
// any domain-specific options from the UrlNamer, options set in query-params,
// and options set in request headers.
// Takes ownership of domain_options and query_options.
RewriteOptions* GetCustomOptions(RequestHeaders* request_headers,
RewriteOptions* domain_options,
RewriteOptions* query_options);
// Returns the RewriteOptions signature hash.
// Returns empty string if RewriteOptions is NULL.
GoogleString GetRewriteOptionsSignatureHash(const RewriteOptions* options);
// Generates a new managed RewriteDriver using the RewriteOptions
// managed by this class. Each RewriteDriver is not thread-safe,
// but you can generate a RewriteDriver* for each thread. The
// returned drivers manage themselves: when the HTML parsing and
// rewriting is done they will be returned to the pool.
//
// Filters allocated using this mechanism have their filter-chain
// already frozen (see AddFilters()).
RewriteDriver* NewRewriteDriver(const RequestContextPtr& request_ctx);
// As above, but uses a specific RewriteDriverPool to determine the options
// and manage the lifetime of the result. 'pool' must not be NULL.
RewriteDriver* NewRewriteDriverFromPool(
RewriteDriverPool* pool, const RequestContextPtr& request_ctx);
// Generates a new unmanaged RewriteDriver with given RewriteOptions,
// which are assumed to correspond to drivers managed by 'pool'
// (which may be NULL if the options are custom). Each RewriteDriver is
// not thread-safe, but you can generate a RewriteDriver* for each thread.
// The returned drivers must be explicitly deleted by the caller.
//
// RewriteDrivers allocated using this mechanism have not yet frozen
// their filters, and so callers may explicitly enable individual
// filters on the driver -- beyond those indicated in the options.
// After all extra filters are added, AddFilters must be called to
// freeze them and instantiate the filter-chain.
//
// Takes ownership of 'options'.
RewriteDriver* NewUnmanagedRewriteDriver(
RewriteDriverPool* pool, RewriteOptions* options,
const RequestContextPtr& request_ctx);
// Like NewUnmanagedRewriteDriver, but uses standard semi-automatic
// memory management for RewriteDrivers.
//
// NOTE: This does not merge custom_options with global_options(), the
// caller must do that if they want them merged.
//
// Filters allocated using this mechanism have their filter-chain
// already frozen (see AddFilters()).
//
// Takes ownership of 'custom_options'.
RewriteDriver* NewCustomRewriteDriver(
RewriteOptions* custom_options, const RequestContextPtr& request_ctx);
// Puts a RewriteDriver back on the free pool. This is intended to
// be called by a RewriteDriver on itself, once all pending
// activites on it have completed, including HTML Parsing
// (FinishParse) and all pending Rewrites.
//
// TODO(jmarantz): this cannot recycle RewriteDrivers with custom
// rewrite options, which is a potential performance issue for Apache
// installations that set custom options in .htaccess files, where
// essentially every RewriteDriver will be a custom driver. To
// resolve this we need to make a comparator for RewriteOptions
// so that we can determine option-equivalence and, potentially,
// keep free-lists for each unique option-set.
void ReleaseRewriteDriver(RewriteDriver* rewrite_driver);
ThreadSystem* thread_system() { return thread_system_; }
UsageDataReporter* usage_data_reporter() { return usage_data_reporter_; }
// Calling this method will stop results of rewrites being cached in the
// metadata cache. This is meant for the shutdown sequence.
void set_shutting_down() {
shutting_down_.set_value(true);
}
bool shutting_down() const {
return shutting_down_.value();
}
// Waits a bounded amount of time for all currently running jobs to
// complete. This is meant for use when shutting down processing,
// so that jobs running in background do not access objects that are
// about to be deleted. If there are long-running outstanding tasks,
// the drivers may stay running past this call.
//
// TODO(jmarantz): Change New*RewriteDriver() calls to return NULL
// when run after shutdown. This requires changing call-sites to
// null-check their drivers and gracefully fail.
void ShutDownDrivers();
// Take any headers that are not caching-related, and not otherwise
// filled in by SetDefaultLongCacheHeaders or SetContentType, but
// *were* set on the input resource, and copy them to the output
// resource. This allows user headers to be preserved. This must
// be called as needed by individual filters, prior to Write().
//
// Note that this API is only usable for single-input rewriters.
// Combiners will need to execute some kind of merge, union, or
// intersection policy, if we wish to preserve origin response
// headers.
//
// Note: this does not call ComputeCaching() on the output headers,
// so that method must be called prior to invoking any caching predicates
// on the output's ResponseHeader. In theory we shouldn't mark the
// caching bits dirty because we are only adding headers that will
// not affect caching, but at the moment the dirty-bit is set independent
// of that.
//
// TODO(jmarantz): avoid setting caching_dirty bit in ResponseHeaders when
// the header is not caching-related.
void MergeNonCachingResponseHeaders(const ResourcePtr& input,
const OutputResourcePtr& output) {
MergeNonCachingResponseHeaders(*input->response_headers(),
output->response_headers());
}
// Entry-point with the same functionality, exposed for easier testing.
void MergeNonCachingResponseHeaders(const ResponseHeaders& input_headers,
ResponseHeaders* output_headers);
// Pool of worker-threads that can be used to handle html-parsing.
QueuedWorkerPool* html_workers() { return html_workers_; }
// Pool of worker-threads that can be used to handle resource rewriting.
QueuedWorkerPool* rewrite_workers() { return rewrite_workers_; }
// Pool of worker-threads that can be used to handle low-priority/high CPU
// portions of resource rewriting.
QueuedWorkerPool* low_priority_rewrite_workers() {
return low_priority_rewrite_workers_;
}
// Returns the number of rewrite drivers that we were aware of at the
// time of the call. This includes those created via NewCustomRewriteDriver
// and NewRewriteDriver, but not via NewUnmanagedRewriteDriver.
size_t num_active_rewrite_drivers();
// A ServerContext may be created in one phase, and later populated
// with all its dependencies. This populates the worker threads.
void InitWorkers();
// To set up AdminSite for SystemServerContext.
virtual void PostInitHook();
// Returns whether or not this attribute can be merged into headers
// without additional considerations.
static bool IsExcludedAttribute(const char* attribute);
// Determines whether we can assume that the response headers we see
// in rewrite_drivers when filters are applied reflect the final
// form from the origin. In proxy applications, this is generally
// true. But in Apache, it depends when the output_filter is
// applied relative to mod_headers and mod_expires.
//
// The default-value is 'true'.
bool response_headers_finalized() const {
return response_headers_finalized_;
}
void set_response_headers_finalized(bool x) {
response_headers_finalized_ = x;
}
// Returns the RewriteDriverPool that's used by NewRewriteDriver (so calling
// NewRewriteDriverFromPool(standard_rewrite_driver_pool()) is equivalent to
// calling NewRewriteDriver.
RewriteDriverPool* standard_rewrite_driver_pool() {
return available_rewrite_drivers_.get();
}
// Returns the current server hostname.
const GoogleString& hostname() const {
return hostname_;
}
void set_hostname(const GoogleString& x) {
hostname_ = x;
}
// Adds an X-Original-Content-Length header to the response headers
// based on the size of the input resources.
void AddOriginalContentLengthHeader(const ResourceVector& inputs,
ResponseHeaders* headers);
// Chooses a driver pool based on the request protocol.
virtual RewriteDriverPool* SelectDriverPool(bool using_spdy);
// Provides a hook for ServerContext implementations to determine
// the fetcher implementation based on the request.
virtual void ApplySessionFetchers(const RequestContextPtr& req,
RewriteDriver* driver);
// Determines whether in this server, it makes sense to proxy HTML
// from external sources. If we're acting as a reverse proxy that
// talks to the backend over HTTP, it makes sense to set this to
// 'true'. The JavaScript loaded from the HTML on the origin
// domain will be given full access to cookies on the proxied
// domain.
//
// For resource-proxying (e.g. ModPagespeedMapProxyDomain) this should
// be set to 'false' as that command is intended only for reosurces, not
// for HTML.
virtual bool ProxiesHtml() const = 0;
// Makes a new RequestProperties.
RequestProperties* NewRequestProperties();
// Puts the cache on a list to be destroyed at the last phase of system
// shutdown.
void DeleteCacheOnDestruction(CacheInterface* cache);
void set_cache_property_store(CachePropertyStore* p);
// Set the RewriteDriver that will be used to decode .pagespeed. URLs.
// Does not take ownership.
void set_decoding_driver(RewriteDriver* rd) { decoding_driver_ = rd; }
// Creates CachePropertyStore object which will be used by PagePropertyCache.
virtual PropertyStore* CreatePropertyStore(CacheInterface* cache_backend);
// Establishes a new Cohort for this property.
// This will also call CachePropertyStore::AddCohort() if CachePropertyStore
// is used.
const PropertyCache::Cohort* AddCohort(
const GoogleString& cohort_name,
PropertyCache* pcache);
// Establishes a new Cohort to be backed by the specified CacheInterface.
// NOTE: Does not take ownership of the CacheInterface object.
// This also calls CachePropertyStore::AddCohort() to set the cache backend
// for the given cohort.
const PropertyCache::Cohort* AddCohortWithCache(
const GoogleString& cohort_name,
CacheInterface* cache,
PropertyCache* pcache);
// Returns the cache backend associated with CachePropertyStore.
// Returns NULL if non-CachePropertyStore is used.
const CacheInterface* pcache_cache_backend();
const pagespeed::js::JsTokenizerPatterns* js_tokenizer_patterns() const {
return js_tokenizer_patterns_;
}
enum Format {
kFormatAsHtml,
kFormatAsJson
};
// Shows cached data related to a URL. Ownership of options is transferred
// to this function. If should_delete is true, deletes the entry as well.
void ShowCacheHandler(Format format, StringPiece url, StringPiece ua,
bool should_delete, AsyncFetch* fetch,
RewriteOptions* options);
// Returns an HTML form for entering a URL for ShowCacheHandler. If
// the user_agent is non-null, then it's used to prepopulate the
// "User Agent" field in the form.
static GoogleString ShowCacheForm(StringPiece user_agent);
// Returns the format for specifying a configuration file option. E.g.
// for option_name="EnableCachePurge", args="on", returns:
// nginx: "pagespeed EnableCachePurge on;"
// apache: "ModPagespeed EnableCachePurge on"
// The base class simply returns "EnableCachePurge on".
virtual GoogleString FormatOption(StringPiece option_name, StringPiece args);
protected:
// Takes ownership of the given pool, making sure to clean it up at the
// appropriate spot during shutdown.
void ManageRewriteDriverPool(RewriteDriverPool* pool) {
additional_driver_pools_.push_back(pool);
}
private:
friend class ServerContextTest;
typedef std::set<RewriteDriver*> RewriteDriverSet;
// Must be called with rewrite_drivers_mutex_ held.
void ReleaseRewriteDriverImpl(RewriteDriver* rewrite_driver);
// Applies the remote configuration options, by feeding each line in the
// config to ApplyConfigLine.
void ApplyRemoteConfig(const GoogleString& config, RewriteOptions* options);
// Applies one line of configuration to the RewriteOptions.
void ApplyConfigLine(StringPiece linesp, RewriteOptions* options);
// Fetches the remote configuration file using CacheUrlAsyncFetcher, if the
// remote configuration is specified in config. This can block for a maximum
// of timeout_ms. If on_startup is true, the fetch is backgrounded and the
// result is ignored. Startup fetches are only used for populating the cache.
GoogleString FetchRemoteConfig(const GoogleString& url, int64 timeout_ms,
bool on_startup,
RequestContextPtr request_ctx);
// These are normally owned by the RewriteDriverFactory that made 'this'.
ThreadSystem* thread_system_;
RewriteStats* rewrite_stats_;
GoogleString file_prefix_;
FileSystem* file_system_;
UrlNamer* url_namer_;
scoped_ptr<RewriteOptionsManager> rewrite_options_manager_;
UserAgentMatcher* user_agent_matcher_;
Scheduler* scheduler_;
UrlAsyncFetcher* default_system_fetcher_;
UrlAsyncFetcher* default_distributed_fetcher_;
Hasher* hasher_;
SHA1Signature* signature_;
scoped_ptr<CriticalImagesFinder> critical_images_finder_;
scoped_ptr<CriticalCssFinder> critical_css_finder_;
scoped_ptr<CriticalSelectorFinder> critical_selector_finder_;
scoped_ptr<CacheHtmlInfoFinder> cache_html_info_finder_;
scoped_ptr<FlushEarlyInfoFinder> flush_early_info_finder_;
scoped_ptr<CriticalLineInfoFinder> critical_line_info_finder_;
scoped_ptr<MobilizeCachedFinder> mobilize_cached_finder_;
// hasher_ is often set to a mock within unit tests, but some parts of the
// system will not work sensibly if the "hash algorithm" used always returns
// constants. For those, we have two separate hashers.
MD5Hasher lock_hasher_; // Used to compute named lock names.
// Used to hash file contents to see if inputs to a rewrites have actually
// changed (and didn't just expire).
MD5Hasher contents_hasher_;
Statistics* statistics_;
Timer* timer_;
scoped_ptr<HTTPCache> http_cache_;
scoped_ptr<PropertyCache> page_property_cache_;
CacheInterface* filesystem_metadata_cache_;
CacheInterface* metadata_cache_;
bool store_outputs_in_file_system_;
bool response_headers_finalized_;
bool enable_property_cache_;
NamedLockManager* lock_manager_;
MessageHandler* message_handler_;
const PropertyCache::Cohort* dom_cohort_;
const PropertyCache::Cohort* blink_cohort_;
const PropertyCache::Cohort* beacon_cohort_;
const PropertyCache::Cohort* fix_reflow_cohort_;
// RewriteDrivers that were previously allocated, but have
// been released with ReleaseRewriteDriver, and are ready
// for re-use with NewRewriteDriver.
// Protected by rewrite_drivers_mutex_.
// TODO(morlovich): Give this a better name in an immediate follow up.
scoped_ptr<RewriteDriverPool> available_rewrite_drivers_;
// Other RewriteDriverPool's whose lifetime we help manage for our subclasses.
std::vector<RewriteDriverPool*> additional_driver_pools_;
// RewriteDrivers that are currently in use. This is retained
// as a sanity check to make sure our system is coherent,
// and to facilitate complete cleanup if a Shutdown occurs
// while a request is in flight.
// Protected by rewrite_drivers_mutex_.
RewriteDriverSet active_rewrite_drivers_;
// If this value is true ReleaseRewriteDriver will just insert its
// argument into deferred_release_rewrite_drivers_ rather
// than try to delete or recycle it. This is used for shutdown
// so that the main thread does not have to worry about rewrite threads
// deleting RewriteDrivers or altering active_rewrite_drivers_.
//
// Protected by rewrite_drivers_mutex_.
bool trying_to_cleanup_rewrite_drivers_;
RewriteDriverSet deferred_release_rewrite_drivers_;
bool shutdown_drivers_called_;
// If set, a RewriteDriverFactory provides a mechanism to add
// platform-specific filters to a RewriteDriver.
RewriteDriverFactory* factory_;
scoped_ptr<AbstractMutex> rewrite_drivers_mutex_;
// All access, even internal to the class, should be via options() so
// subclasses can override.
scoped_ptr<RewriteOptions> base_class_options_;
// This is owned by the RewriteDriverFactory. We use it for just for decoding
// resource URLs, using the default options. This is possible because the
// id->RewriteFilter table is fully constructed independent of the options.
RewriteDriver* decoding_driver_;
QueuedWorkerPool* html_workers_; // Owned by the factory
QueuedWorkerPool* rewrite_workers_; // Owned by the factory
QueuedWorkerPool* low_priority_rewrite_workers_; // Owned by the factory
AtomicBool shutting_down_;
// Used to create URLs for various filter static js and image files.
StaticAssetManager* static_asset_manager_;
// Used to help inject sync-points into thread-intensive code for the purposes
// of controlling thread interleaving to test code for possible races.
scoped_ptr<ThreadSynchronizer> thread_synchronizer_;
// Used to match clients or sessions to a specific experiment.
scoped_ptr<ExperimentMatcher> experiment_matcher_;
UsageDataReporter* usage_data_reporter_;
// A convenient central place to store the hostname we're running on.
GoogleString hostname_;
// A simple (and always seeded with the same default!) random number
// generator. Do not use for security purposes.
SimpleRandom simple_random_;
// Owned by RewriteDriverFactory.
const pagespeed::js::JsTokenizerPatterns* js_tokenizer_patterns_;
scoped_ptr<CachePropertyStore> cache_property_store_;
DISALLOW_COPY_AND_ASSIGN(ServerContext);
};
} // namespace net_instaweb
#endif // NET_INSTAWEB_REWRITER_PUBLIC_SERVER_CONTEXT_H_