blob: 620ea390efc4ee8727ca2b19d313bd96f5331c91 [file] [log] [blame]
/** @file
A brief file description
@section license License
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
*/
/***************************************************************************
LogStandalone.cc
***************************************************************************/
#include "tscore/ink_platform.h"
#include "tscore/ink_lockfile.h"
#include "tscore/ink_sys_control.h"
#include "tscore/signals.h"
#include "DiagsConfig.h"
#include "P_EventSystem.h"
#include "records/P_RecProcess.h"
#include "ProcessManager.h"
#include "MgmtUtils.h"
// Needs LibRecordsConfigInit()
#include "RecordsConfig.h"
#define LOG_FILENAME_SIZE 255
class HttpBodyFactory;
// globals the rest of the system depends on
extern int fds_limit;
extern int cluster_port_number;
int command_flag = 0;
int http_accept_port_number = 0;
int http_accept_file_descriptor = 0;
int remote_management_flag = 0;
int auto_clear_hostdb_flag = 0;
char proxy_name[MAXDNAME + 1] = "unknown";
char error_tags[1024] = "";
char action_tags[1024] = "";
char command_string[512] = "";
// Diags *diags = NULL;
DiagsConfig *diagsConfig = nullptr;
HttpBodyFactory *body_factory = nullptr;
AppVersionInfo appVersionInfo;
/*-------------------------------------------------------------------------
init_system
-------------------------------------------------------------------------*/
// Handle fatal signals by logging and core dumping ...
static void
logging_crash_handler(int signo, siginfo_t *info, void *ptr)
{
signal_format_siginfo(signo, info, appVersionInfo.AppStr);
signal_crash_handler(signo, info, ptr);
}
static void
init_system(bool notify_syslog)
{
fds_limit = ink_max_out_rlimit(RLIMIT_NOFILE);
signal_register_crash_handler(logging_crash_handler);
if (notify_syslog) {
syslog(LOG_NOTICE, "NOTE: --- %s Starting ---", appVersionInfo.AppStr);
syslog(LOG_NOTICE, "NOTE: %s Version: %s", appVersionInfo.AppStr, appVersionInfo.FullVersionInfoStr);
}
}
/*-------------------------------------------------------------------------
initialize_process_manager
-------------------------------------------------------------------------*/
static void
initialize_process_manager()
{
mgmt_use_syslog();
// Temporary Hack to Enable Communication with LocalManager
if (getenv("PROXY_REMOTE_MGMT")) {
remote_management_flag = true;
}
// diags should have been initialized by caller, e.g.: sac.cc
ink_assert(diags);
RecProcessInit(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE, diags);
LibRecordsConfigInit();
// Start up manager
pmgmt = new ProcessManager(remote_management_flag);
pmgmt->start();
RecProcessInitMessage(remote_management_flag ? RECM_CLIENT : RECM_STAND_ALONE);
pmgmt->reconfigure();
//
// Define version info records
//
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.short", appVersionInfo.VersionStr, RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.long", appVersionInfo.FullVersionInfoStr, RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.build_number", appVersionInfo.BldNumStr, RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.build_time", appVersionInfo.BldTimeStr, RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.build_date", appVersionInfo.BldDateStr, RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.build_machine", appVersionInfo.BldMachineStr,
RECP_NON_PERSISTENT);
RecRegisterStatString(RECT_PROCESS, "proxy.process.version.server.build_person", appVersionInfo.BldPersonStr,
RECP_NON_PERSISTENT);
// RecRegisterStatString(RECT_PROCESS,
// "proxy.process.version.server.build_compile_flags",
// appVersionInfo.BldCompileFlagsStr,
// RECP_NON_PERSISTENT);
}
/*-------------------------------------------------------------------------
check_lockfile
-------------------------------------------------------------------------*/
static void
check_lockfile()
{
int err;
pid_t holding_pid;
char *lockfile = nullptr;
if (access(Layout::get()->runtimedir.c_str(), R_OK | W_OK) == -1) {
fprintf(stderr, "unable to access() dir'%s': %d, %s\n", Layout::get()->runtimedir.c_str(), errno, strerror(errno));
fprintf(stderr, " please set correct path in env variable TS_ROOT \n");
::exit(1);
}
lockfile = ats_stringdup(Layout::relative_to(Layout::get()->runtimedir, SERVER_LOCK));
Lockfile server_lockfile(lockfile);
err = server_lockfile.Get(&holding_pid);
if (err != 1) {
char *reason = strerror(-err);
fprintf(stderr, "FATAL: Can't acquire lockfile '%s'", lockfile);
if ((err == 0) && (holding_pid != -1)) {
#if defined(solaris)
fprintf(stderr, " (Lock file held by process ID %d)\n", (int)holding_pid);
#else
fprintf(stderr, " (Lock file held by process ID %d)\n", holding_pid);
#endif
} else if ((err == 0) && (holding_pid == -1)) {
fprintf(stderr, " (Lock file exists, but can't read process ID)\n");
} else if (reason) {
fprintf(stderr, " (%s)\n", reason);
} else {
fprintf(stderr, "\n");
}
::exit(1);
}
ats_free(lockfile);
}
/*-------------------------------------------------------------------------
init_log_standalone
This routine should be called from the main() function of the standalone
program.
-------------------------------------------------------------------------*/
void
init_log_standalone(const char *pgm_name, bool one_copy)
{
char logfile[LOG_FILENAME_SIZE];
// ensure that only one copy of the sac is running
//
if (one_copy) {
check_lockfile();
}
snprintf(logfile, sizeof(logfile), "%s.log", pgm_name);
// set stdin/stdout to be unbuffered
//
setbuf(stdin, nullptr);
setbuf(stdout, nullptr);
openlog(pgm_name, LOG_PID | LOG_NDELAY | LOG_NOWAIT, LOG_DAEMON);
init_system(true);
initialize_process_manager();
diagsConfig = new DiagsConfig(pgm_name, logfile, error_tags, action_tags);
}
/*-------------------------------------------------------------------------
init_log_standalone_basic
This routine is similar to init_log_standalone, but it is intended for
simple standalone applications that do not read the records.config file
and that do not need a process manager, thus it:
1) does not call initialize_process_manager
2) initializes the diags with use_records = false
3) does not call Machine::init()
4) assumes multiple copies of the application can run, so does not
do lock checking
-------------------------------------------------------------------------*/
void
init_log_standalone_basic(const char *pgm_name)
{
char logfile[LOG_FILENAME_SIZE];
snprintf(logfile, sizeof(logfile), "%s.log", pgm_name);
openlog(pgm_name, LOG_PID | LOG_NDELAY | LOG_NOWAIT, LOG_DAEMON);
init_system(false);
const bool use_records = false;
diagsConfig = new DiagsConfig(pgm_name, logfile, error_tags, action_tags, use_records);
// set stdin/stdout to be unbuffered
//
setbuf(stdin, nullptr);
setbuf(stdout, nullptr);
}