| // 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. |
| |
| #include "net/instaweb/apache/apache_rewrite_driver_factory.h" |
| |
| #include "apr_pools.h" |
| #include "net/instaweb/apache/apache_message_handler.h" |
| #include "net/instaweb/apache/apr_file_system.h" |
| #include "net/instaweb/apache/apr_mutex.h" |
| #include "net/instaweb/apache/apr_statistics.h" |
| #include "net/instaweb/apache/apr_timer.h" |
| #include "net/instaweb/apache/serf_url_async_fetcher.h" |
| #include "net/instaweb/apache/serf_url_fetcher.h" |
| #include "net/instaweb/htmlparse/public/html_parse.h" |
| #include "net/instaweb/rewriter/public/rewrite_driver.h" |
| #include "net/instaweb/rewriter/public/rewrite_options.h" |
| #include "net/instaweb/util/public/file_cache.h" |
| #include "net/instaweb/util/public/lru_cache.h" |
| #include "net/instaweb/util/public/md5_hasher.h" |
| #include "net/instaweb/util/public/threadsafe_cache.h" |
| #include "net/instaweb/util/public/write_through_cache.h" |
| |
| namespace net_instaweb { |
| |
| ApacheRewriteDriverFactory::ApacheRewriteDriverFactory(apr_pool_t* pool, |
| server_rec* server) |
| : server_rec_(server), |
| serf_url_fetcher_(NULL), |
| serf_url_async_fetcher_(NULL), |
| statistics_(NULL), |
| lru_cache_kb_per_process_(0), |
| lru_cache_byte_limit_(0), |
| file_cache_clean_interval_ms_(Timer::kHourMs), |
| file_cache_clean_size_kb_(100 * 1024), // 100 megabytes |
| fetcher_time_out_ms_(5 * Timer::kSecondMs), |
| slurp_flush_limit_(0), |
| enabled_(true) { |
| apr_pool_create(&pool_, pool); |
| cache_mutex_.reset(NewMutex()); |
| rewrite_drivers_mutex_.reset(NewMutex()); |
| |
| // In Apache, we default to using the "core filters". |
| SetRewriteLevel(RewriteOptions::kCoreFilters); |
| } |
| |
| ApacheRewriteDriverFactory::~ApacheRewriteDriverFactory() { |
| // We free all the resources before destroy the pool, because some of the |
| // resource uses the sub-pool and will destroy them on destruction. |
| ShutDown(); |
| apr_pool_destroy(pool_); |
| } |
| |
| FileSystem* ApacheRewriteDriverFactory::DefaultFileSystem() { |
| return new AprFileSystem(pool_); |
| } |
| |
| Hasher* ApacheRewriteDriverFactory::NewHasher() { |
| return new MD5Hasher(); |
| } |
| |
| Timer* ApacheRewriteDriverFactory::DefaultTimer() { |
| return new AprTimer(); |
| } |
| |
| MessageHandler* ApacheRewriteDriverFactory::DefaultHtmlParseMessageHandler() { |
| return new ApacheMessageHandler(server_rec_); |
| } |
| |
| MessageHandler* ApacheRewriteDriverFactory::DefaultMessageHandler() { |
| return new ApacheMessageHandler(server_rec_); |
| } |
| |
| CacheInterface* ApacheRewriteDriverFactory::DefaultCacheInterface() { |
| FileCache::CachePolicy* policy = new FileCache::CachePolicy( |
| timer(), file_cache_clean_interval_ms_, file_cache_clean_size_kb_); |
| CacheInterface* cache = new FileCache( |
| file_cache_path_, file_system(), filename_encoder(), policy, |
| message_handler()); |
| if (lru_cache_kb_per_process_ != 0) { |
| LRUCache* lru_cache = new LRUCache(lru_cache_kb_per_process_ * 1024); |
| |
| // We only add the threadsafe-wrapper to the LRUCache. The FileCache |
| // is naturally thread-safe because it's got no writable member variables. |
| // And surrounding that slower-running class with a mutex would likely |
| // cause contention. |
| ThreadsafeCache* ts_cache = new ThreadsafeCache(lru_cache, cache_mutex()); |
| WriteThroughCache* write_through_cache = |
| new WriteThroughCache(ts_cache, cache); |
| // By default, WriteThroughCache does not limit the size of entries going |
| // into its front cache. |
| if (lru_cache_byte_limit_ != 0) { |
| write_through_cache->set_cache1_limit(lru_cache_byte_limit_); |
| } |
| cache = write_through_cache; |
| } |
| return cache; |
| } |
| |
| UrlFetcher* ApacheRewriteDriverFactory::DefaultUrlFetcher() { |
| if (serf_url_fetcher_ == NULL) { |
| DefaultAsyncUrlFetcher(); // Create async fetcher if necessary. |
| serf_url_fetcher_ = new SerfUrlFetcher( |
| fetcher_time_out_ms_, serf_url_async_fetcher_); |
| } |
| return serf_url_fetcher_; |
| } |
| |
| UrlAsyncFetcher* ApacheRewriteDriverFactory::DefaultAsyncUrlFetcher() { |
| if (serf_url_async_fetcher_ == NULL) { |
| serf_url_async_fetcher_ = new SerfUrlAsyncFetcher( |
| fetcher_proxy_.c_str(), pool_, statistics_, timer()); |
| } |
| return serf_url_async_fetcher_; |
| } |
| |
| |
| HtmlParse* ApacheRewriteDriverFactory::DefaultHtmlParse() { |
| return new HtmlParse(html_parse_message_handler()); |
| } |
| |
| AbstractMutex* ApacheRewriteDriverFactory::NewMutex() { |
| return new AprMutex(pool_); |
| } |
| |
| RewriteDriver* ApacheRewriteDriverFactory::GetRewriteDriver() { |
| RewriteDriver* rewrite_driver = NULL; |
| if (!available_rewrite_drivers_.empty()) { |
| rewrite_driver = available_rewrite_drivers_.back(); |
| available_rewrite_drivers_.pop_back(); |
| } else { |
| ComputeResourceManager()->set_statistics(statistics_); |
| // Create a RewriteDriver using base class. |
| rewrite_driver = NewRewriteDriver(); |
| } |
| active_rewrite_drivers_.insert(rewrite_driver); |
| return rewrite_driver; |
| } |
| |
| void ApacheRewriteDriverFactory::ReleaseRewriteDriver( |
| RewriteDriver* rewrite_driver) { |
| int count = active_rewrite_drivers_.erase(rewrite_driver); |
| if (count != 1) { |
| LOG(ERROR) << "Remove rewrite driver from the active list."; |
| } else { |
| available_rewrite_drivers_.push_back(rewrite_driver); |
| } |
| } |
| |
| void ApacheRewriteDriverFactory::ShutDown() { |
| cache_mutex_.reset(NULL); |
| rewrite_drivers_mutex_.reset(NULL); |
| RewriteDriverFactory::ShutDown(); |
| } |
| |
| } // namespace net_instaweb |