c253c3ba80
It turns out to be possible to initialize logging earlier by grabbing the log from a global ngx_cycle structure. This makes us start logging earlier, yet loses the "No threading detected ..." messages both from stderr and in error.log when nginx initially starts. With this change, these messages will now be logged as we start logging earlier: " flush . " These originate from SystemCachePath::CacheKey which appends newlines to the key, and the resulting cache key ends up being logged. We might want to change that, because the resulting lines in error.log look weird and might raise questions. Fixes https://github.com/pagespeed/ngx_pagespeed/issues/895
254 lines
8.4 KiB
C++
254 lines
8.4 KiB
C++
/*
|
|
* Copyright 2012 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: jefftk@google.com (Jeff Kaufman)
|
|
|
|
#include "ngx_rewrite_driver_factory.h"
|
|
|
|
#include <cstdio>
|
|
|
|
#include "log_message_handler.h"
|
|
#include "ngx_message_handler.h"
|
|
#include "ngx_rewrite_options.h"
|
|
#include "ngx_server_context.h"
|
|
#include "ngx_url_async_fetcher.h"
|
|
|
|
#include "net/instaweb/http/public/rate_controller.h"
|
|
#include "net/instaweb/http/public/rate_controlling_url_async_fetcher.h"
|
|
#include "net/instaweb/http/public/wget_url_fetcher.h"
|
|
#include "net/instaweb/rewriter/public/rewrite_driver.h"
|
|
#include "net/instaweb/rewriter/public/rewrite_driver_factory.h"
|
|
#include "net/instaweb/rewriter/public/server_context.h"
|
|
#include "net/instaweb/util/public/property_cache.h"
|
|
#include "pagespeed/kernel/base/google_message_handler.h"
|
|
#include "pagespeed/kernel/base/null_shared_mem.h"
|
|
#include "pagespeed/kernel/base/posix_timer.h"
|
|
#include "pagespeed/kernel/base/stdio_file_system.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/sharedmem/shared_circular_buffer.h"
|
|
#include "pagespeed/kernel/sharedmem/shared_mem_statistics.h"
|
|
#include "pagespeed/kernel/thread/pthread_shared_mem.h"
|
|
#include "pagespeed/kernel/thread/scheduler_thread.h"
|
|
#include "pagespeed/kernel/thread/slow_worker.h"
|
|
#include "pagespeed/system/in_place_resource_recorder.h"
|
|
#include "pagespeed/system/serf_url_async_fetcher.h"
|
|
#include "pagespeed/system/system_caches.h"
|
|
#include "pagespeed/system/system_rewrite_options.h"
|
|
|
|
namespace net_instaweb {
|
|
|
|
class FileSystem;
|
|
class Hasher;
|
|
class MessageHandler;
|
|
class Statistics;
|
|
class Timer;
|
|
class UrlAsyncFetcher;
|
|
class UrlFetcher;
|
|
class Writer;
|
|
|
|
class SharedCircularBuffer;
|
|
|
|
NgxRewriteDriverFactory::NgxRewriteDriverFactory(
|
|
const ProcessContext& process_context,
|
|
SystemThreadSystem* system_thread_system, StringPiece hostname, int port)
|
|
: SystemRewriteDriverFactory(process_context, system_thread_system,
|
|
NULL /* default shared memory runtime */, hostname, port),
|
|
main_conf_(NULL),
|
|
threads_started_(false),
|
|
ngx_message_handler_(
|
|
new NgxMessageHandler(timer(), thread_system()->NewMutex())),
|
|
ngx_html_parse_message_handler_(
|
|
new NgxMessageHandler(timer(), thread_system()->NewMutex())),
|
|
log_(NULL),
|
|
resolver_timeout_(NGX_CONF_UNSET_MSEC),
|
|
use_native_fetcher_(false),
|
|
// 100 Aligns to nginx's server-side default.
|
|
native_fetcher_max_keepalive_requests_(100),
|
|
ngx_shared_circular_buffer_(NULL),
|
|
hostname_(hostname.as_string()),
|
|
port_(port),
|
|
process_script_variables_(false),
|
|
process_script_variables_set_(false),
|
|
shut_down_(false) {
|
|
InitializeDefaultOptions();
|
|
default_options()->set_beacon_url("/ngx_pagespeed_beacon");
|
|
SystemRewriteOptions* system_options = dynamic_cast<SystemRewriteOptions*>(
|
|
default_options());
|
|
system_options->set_file_cache_clean_inode_limit(500000);
|
|
system_options->set_avoid_renaming_introspective_javascript(true);
|
|
set_message_handler(ngx_message_handler_);
|
|
set_html_parse_message_handler(ngx_html_parse_message_handler_);
|
|
}
|
|
|
|
NgxRewriteDriverFactory::~NgxRewriteDriverFactory() {
|
|
ShutDown();
|
|
ngx_shared_circular_buffer_ = NULL;
|
|
STLDeleteElements(&uninitialized_server_contexts_);
|
|
}
|
|
|
|
Hasher* NgxRewriteDriverFactory::NewHasher() {
|
|
return new MD5Hasher;
|
|
}
|
|
|
|
UrlAsyncFetcher* NgxRewriteDriverFactory::AllocateFetcher(
|
|
SystemRewriteOptions* config) {
|
|
if (use_native_fetcher_) {
|
|
NgxUrlAsyncFetcher* fetcher = new NgxUrlAsyncFetcher(
|
|
config->fetcher_proxy().c_str(),
|
|
log_,
|
|
resolver_timeout_,
|
|
config->blocking_fetch_timeout_ms(),
|
|
resolver_,
|
|
native_fetcher_max_keepalive_requests_,
|
|
thread_system(),
|
|
message_handler());
|
|
ngx_url_async_fetchers_.push_back(fetcher);
|
|
return fetcher;
|
|
} else {
|
|
return SystemRewriteDriverFactory::AllocateFetcher(config);
|
|
}
|
|
}
|
|
|
|
MessageHandler* NgxRewriteDriverFactory::DefaultHtmlParseMessageHandler() {
|
|
return ngx_html_parse_message_handler_;
|
|
}
|
|
|
|
MessageHandler* NgxRewriteDriverFactory::DefaultMessageHandler() {
|
|
return ngx_message_handler_;
|
|
}
|
|
|
|
FileSystem* NgxRewriteDriverFactory::DefaultFileSystem() {
|
|
return new StdioFileSystem();
|
|
}
|
|
|
|
Timer* NgxRewriteDriverFactory::DefaultTimer() {
|
|
return new PosixTimer;
|
|
}
|
|
|
|
NamedLockManager* NgxRewriteDriverFactory::DefaultLockManager() {
|
|
CHECK(false);
|
|
return NULL;
|
|
}
|
|
|
|
RewriteOptions* NgxRewriteDriverFactory::NewRewriteOptions() {
|
|
NgxRewriteOptions* options = new NgxRewriteOptions(thread_system());
|
|
options->SetRewriteLevel(RewriteOptions::kCoreFilters);
|
|
return options;
|
|
}
|
|
|
|
bool NgxRewriteDriverFactory::CheckResolver() {
|
|
if (use_native_fetcher_ && resolver_ == NULL) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
NgxServerContext* NgxRewriteDriverFactory::MakeNgxServerContext(
|
|
StringPiece hostname, int port) {
|
|
NgxServerContext* server_context = new NgxServerContext(this, hostname, port);
|
|
uninitialized_server_contexts_.insert(server_context);
|
|
return server_context;
|
|
}
|
|
|
|
ServerContext* NgxRewriteDriverFactory::NewDecodingServerContext() {
|
|
ServerContext* sc = new NgxServerContext(this, hostname_, port_);
|
|
InitStubDecodingServerContext(sc);
|
|
return sc;
|
|
}
|
|
|
|
ServerContext* NgxRewriteDriverFactory::NewServerContext() {
|
|
LOG(DFATAL) << "MakeNgxServerContext should be used instead";
|
|
return NULL;
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::ShutDown() {
|
|
if (!shut_down_) {
|
|
shut_down_ = true;
|
|
SystemRewriteDriverFactory::ShutDown();
|
|
}
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::ShutDownMessageHandlers() {
|
|
ngx_message_handler_->set_buffer(NULL);
|
|
ngx_html_parse_message_handler_->set_buffer(NULL);
|
|
for (NgxMessageHandlerSet::iterator p =
|
|
server_context_message_handlers_.begin();
|
|
p != server_context_message_handlers_.end(); ++p) {
|
|
(*p)->set_buffer(NULL);
|
|
}
|
|
server_context_message_handlers_.clear();
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::StartThreads() {
|
|
if (threads_started_) {
|
|
return;
|
|
}
|
|
// TODO(jefftk): use a native nginx timer instead of running our own thread.
|
|
// See issue #111.
|
|
SchedulerThread* thread = new SchedulerThread(thread_system(), scheduler());
|
|
bool ok = thread->Start();
|
|
CHECK(ok) << "Unable to start scheduler thread";
|
|
defer_cleanup(thread->MakeDeleter());
|
|
threads_started_ = true;
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::LoggingInit(
|
|
ngx_log_t* log, bool may_install_crash_handler) {
|
|
log_ = log;
|
|
net_instaweb::log_message_handler::Install(log);
|
|
if (may_install_crash_handler && install_crash_handler()) {
|
|
NgxMessageHandler::InstallCrashHandler(log);
|
|
}
|
|
ngx_message_handler_->set_log(log);
|
|
ngx_html_parse_message_handler_->set_log(log);
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::SetCircularBuffer(
|
|
SharedCircularBuffer* buffer) {
|
|
ngx_shared_circular_buffer_ = buffer;
|
|
ngx_message_handler_->set_buffer(buffer);
|
|
ngx_html_parse_message_handler_->set_buffer(buffer);
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::SetServerContextMessageHandler(
|
|
ServerContext* server_context, ngx_log_t* log) {
|
|
NgxMessageHandler* handler = new NgxMessageHandler(
|
|
timer(), thread_system()->NewMutex());
|
|
handler->set_log(log);
|
|
// The ngx_shared_circular_buffer_ will be NULL if MessageBufferSize hasn't
|
|
// been raised from its default of 0.
|
|
handler->set_buffer(ngx_shared_circular_buffer_);
|
|
server_context_message_handlers_.insert(handler);
|
|
defer_cleanup(new Deleter<NgxMessageHandler>(handler));
|
|
server_context->set_message_handler(handler);
|
|
}
|
|
|
|
void NgxRewriteDriverFactory::InitStats(Statistics* statistics) {
|
|
// Init standard PSOL stats.
|
|
SystemRewriteDriverFactory::InitStats(statistics);
|
|
RewriteDriverFactory::InitStats(statistics);
|
|
RateController::InitStats(statistics);
|
|
|
|
// Init Ngx-specific stats.
|
|
NgxServerContext::InitStats(statistics);
|
|
InPlaceResourceRecorder::InitStats(statistics);
|
|
}
|
|
|
|
} // namespace net_instaweb
|