blob: eb38f47ea0011973bf7dac30f6e4ad33a1e3bd7b [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.
*/
/***************************************************************************
LogConfigCollation.cc
This is a *huge* hack, in an attempt to isolate some of the collation
related code away from liblogging.a. Please fix this!
***************************************************************************/
#include "libts.h"
#include "ink_platform.h"
#include "LogFormatType.h"
#include "LogField.h"
#include "LogFilter.h"
#include "LogFormat.h"
#include "LogFile.h"
#include "LogBuffer.h"
#include "LogHost.h"
#include "LogObject.h"
#include "LogConfig.h"
#include "LogUtils.h"
#include "Log.h"
#include "SimpleTokenizer.h"
#if defined(IOCORE_LOG_COLLATION)
#include "LogCollationAccept.h"
#endif
void
LogConfig::create_pre_defined_objects_with_filter(const PreDefinedFormatInfoList & pre_def_info_list, size_t num_filters,
LogFilter ** filter, const char *filt_name, bool force_extension)
{
PreDefinedFormatInfo *pdi;
for (pdi = pre_def_info_list.head; pdi != NULL; pdi = (pdi->link).next) {
char *obj_fname;
char obj_filt_fname[PATH_MAX];
if (filt_name) {
ink_string_concatenate_strings_n(obj_filt_fname, PATH_MAX, pdi->filename, "-", filt_name, NULL);
obj_fname = obj_filt_fname;
} else {
obj_fname = pdi->filename;
}
if (force_extension) {
ink_string_append(obj_filt_fname,
(char *) (pdi->is_ascii ?
ASCII_LOG_OBJECT_FILENAME_EXTENSION :
BINARY_LOG_OBJECT_FILENAME_EXTENSION), PATH_MAX);
}
// create object with filters
//
LogObject *obj;
obj = NEW(new LogObject(pdi->format, logfile_dir, obj_fname,
pdi->is_ascii ? ASCII_LOG : BINARY_LOG,
pdi->header, rolling_enabled, rolling_interval_sec, rolling_offset_hr, rolling_size_mb));
if (collation_mode == SEND_STD_FMTS || collation_mode == SEND_STD_AND_NON_XML_CUSTOM_FMTS) {
LogHost *loghost = NEW(new LogHost(obj->get_full_filename(),
obj->get_signature()));
ink_assert(loghost != NULL);
loghost->set_name_port(collation_host, collation_port);
obj->add_loghost(loghost, false);
}
for (size_t i = 0; i < num_filters; ++i) {
obj->add_filter(filter[i]);
}
// give object to object manager
//
log_object_manager.manage_object(obj);
}
}
/*-------------------------------------------------------------------------
LogConfig::setup_collation
-------------------------------------------------------------------------*/
void
LogConfig::setup_collation(LogConfig * prev_config)
{
// Set-up the collation status, but only if collation is enabled and
// there are valid entries for the collation host and port.
//
if (collation_mode<NO_COLLATION || collation_mode>= N_COLLATION_MODES) {
Note("Invalid value %d for proxy.local.log.collation_mode"
" configuration variable (valid range is from %d to %d)\n"
"Log collation disabled", collation_mode, NO_COLLATION, N_COLLATION_MODES - 1);
} else if (collation_mode == NO_COLLATION) {
// if the previous configuration had a collation accept, delete it
//
if (prev_config && prev_config->m_log_collation_accept) {
delete prev_config->m_log_collation_accept;
prev_config->m_log_collation_accept = NULL;
}
} else {
if (!collation_port) {
Note("Cannot activate log collation, %d is and invalid " "collation port", collation_port);
} else if (collation_mode > COLLATION_HOST && strcmp(collation_host, "none") == 0) {
Note("Cannot activate log collation, \"%s\" is and invalid " "collation host", collation_host);
} else {
if (collation_mode == COLLATION_HOST) {
#if defined(IOCORE_LOG_COLLATION)
ink_debug_assert(m_log_collation_accept == 0);
if (prev_config && prev_config->m_log_collation_accept) {
if (prev_config->collation_port == collation_port) {
m_log_collation_accept = prev_config->m_log_collation_accept;
} else {
delete prev_config->m_log_collation_accept;
}
}
if (!m_log_collation_accept) {
Log::collation_port = collation_port;
m_log_collation_accept = NEW(new LogCollationAccept(collation_port));
}
#else
// since we are the collation host, we need to signal the
// collate_cond variable so that our collation thread wakes up.
//
ink_cond_signal(&Log::collate_cond);
#endif
Debug("log", "I am a collation host listening on port %d.", collation_port);
} else {
Debug("log", "I am a collation client (%d)."
" My collation host is %s:%d", collation_mode, collation_host, collation_port);
}
#ifdef IOCORE_LOG_COLLATION
Debug("log", "using iocore log collation");
#else
Debug("log", "using socket log collation");
#endif
if (collation_host_tagged) {
LogFormat::turn_tagging_on();
} else {
LogFormat::turn_tagging_off();
}
}
}
}
#if defined(IOCORE_LOG_COLLATION)
#include "LogCollationClientSM.h"
#endif
#define PING true
#define NOPING false
int
LogHost::write(LogBuffer * lb, size_t * to_disk, size_t * to_net, size_t * to_pipe)
{
NOWARN_UNUSED(to_pipe);
if (lb == NULL) {
Note("Cannot write LogBuffer to LogHost %s; LogBuffer is NULL", name());
return -1;
}
LogBufferHeader *buffer_header = lb->header();
if (buffer_header == NULL) {
Note("Cannot write LogBuffer to LogHost %s; LogBufferHeader is NULL", name());
return -1;
}
if (buffer_header->entry_count == 0) {
// no bytes to write
return 0;
}
#if !defined(IOCORE_LOG_COLLATION)
// make sure we're connected & authenticated
if (!connected(NOPING)) {
if (!connect()) {
Note("Cannot write LogBuffer to LogHost %s; not connected", name());
return orphan_write(lb);
}
}
// try sending the logbuffer
int bytes_to_send, bytes_sent;
bytes_to_send = buffer_header->byte_count;
lb->convert_to_network_order();
bytes_sent = m_sock->write(m_sock_fd, buffer_header, bytes_to_send);
if (bytes_to_send != bytes_sent) {
Note("Bad write to LogHost %s; bad send count %d/%d", name(), bytes_sent, bytes_to_send);
disconnect();
lb->convert_to_host_order();
return orphan_write(lb);
}
Debug("log-host", "%d bytes sent to LogHost %s:%u", bytes_sent, name(), port());
// BUGBUG:: fix this, Log Collation should work on NT as well
SUM_DYN_STAT(log_stat_bytes_sent_to_network_stat, bytes_sent);
return bytes_sent;
#else // !defined(IOCORE_LOG_COLLATION)
// make a copy of our log_buffer
int buffer_header_size = buffer_header->byte_count;
LogBufferHeader *buffer_header_copy = (LogBufferHeader *) NEW(new char[buffer_header_size]);
ink_assert(buffer_header_copy != NULL);
memcpy(buffer_header_copy, buffer_header, buffer_header_size);
LogBuffer *lb_copy = NEW(new LogBuffer(lb->get_owner(),
buffer_header_copy));
ink_assert(lb_copy != NULL);
// create a new collation client if necessary
if (m_log_collation_client_sm == NULL) {
m_log_collation_client_sm = NEW(new LogCollationClientSM(this));
ink_assert(m_log_collation_client_sm != NULL);
}
// send log_buffer; orphan if necessary
int bytes_sent = m_log_collation_client_sm->send(lb_copy);
if (bytes_sent <= 0) {
#ifndef TS_MICRO
bytes_sent = orphan_write_and_delete(lb_copy, to_disk);
#if defined(LOG_BUFFER_TRACKING)
Debug("log-buftrak", "[%d]LogHost::write - orphan write complete", lb_copy->header()->id);
#endif // defined(LOG_BUFFER_TRACKING)
#else
Note("Starting dropping log buffer due to overloading");
delete lb_copy;
lb_copy = 0;
#endif // TS_MICRO
} else {
if (to_net) {
*to_net += bytes_sent;
}
}
return bytes_sent;
#endif // !defined(IOCORE_LOG_COLLATION)
}