blob: e54cdd32eb09c3fe2cfd3da32d8d37d21f861b14 [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.
*/
#if !defined (INK_NO_LOG)
#ifndef LOG_BUFFER_H
#define LOG_BUFFER_H
#include "inktomi++.h"
#include "LogFormatType.h"
#include "LogLimits.h"
#include "LogBufferV1.h"
#include "LogAccess.h"
class LogObject;
class LogBufferIterator;
#define LOG_SEGMENT_COOKIE 0xaceface
#define LOG_SEGMENT_VERSION 2
#if defined(linux)
#define LB_DEFAULT_ALIGN 512
#else
#define LB_DEFAULT_ALIGN 8
#endif
/*-------------------------------------------------------------------------
LogEntryHeader
This struct is automatically laid down at the head of each entry in the
buffer.
-------------------------------------------------------------------------*/
struct LogEntryHeader
{
// unsigned timestamp;
long timestamp; // the seconds portion of the timestamp
long timestamp_usec; // the microseconds portion of the timestamp
unsigned entry_len;
};
/*-------------------------------------------------------------------------
LogBufferHeader
This struct is automatically laid down at the head of each buffer.
-------------------------------------------------------------------------*/
struct LogBufferHeader
{
unsigned cookie; // so we can find it on disk
unsigned version; // in case we want to change it later
unsigned format_type; // SQUID_LOG, COMMON_LOG, ...
unsigned byte_count; // acutal # of bytes for the segment
unsigned entry_count; // actual number of entries stored
unsigned low_timestamp; // lowest timestamp value of entries
unsigned high_timestamp; // highest timestamp value of entries
unsigned int log_object_flags; // log object flags
uint64 log_object_signature; // log object signature
#if defined(LOG_BUFFER_TRACKING)
unsigned int id;
#endif // defined(LOG_BUFFER_TRACKING)
// all offsets are computed from the start of the buffer (ie, "this"),
// and so any valid offset will be at least sizeof(LogBufferHeader).
unsigned fmt_name_offset; // offset to format name string
unsigned fmt_fieldlist_offset; // offset to format fieldlist string
unsigned fmt_printf_offset; // offset to format printf string
unsigned src_hostname_offset; // offset to source (client) hostname
unsigned log_filename_offset; // offset to log filename
unsigned data_offset; // offset to start of data entry
// section
// some helper functions to return the header strings
char *fmt_name(); // not used
char *fmt_fieldlist();
char *fmt_printf();
char *src_hostname();
char *log_filename();
};
union LB_State
{
LB_State():ival(0)
{
};
LB_State(volatile LB_State & vs)
{
ival = vs.ival;
};
LB_State & operator =(volatile LB_State & vs)
{
ival = vs.ival;
return *this;
}
uint64 ival;
struct
{
uint16 offset; // buffer should be <= 64KB
uint16 num_entries; // number of entries in buffer
uint16 byte_count; // bytes in buffer
uint16 full:1; // not accepting more checkouts
uint16 num_writers:15; // number of writers
} s;
};
/* ---------------------------------- iObject ------------------------------ */
class iObjectActivator;
class iObject
{
private:
static iObject *free_heap; /* list of free blocks */
static ink_mutex iObjectMutex; /* mutex for access to iObject class global variables */
size_t class_size; /* real class size */
iObject *next_object;
protected:
iObject(const iObject &); /* declared; not implemented - block copying and assignment */
iObject & operator=(const iObject &); /* ditto */
public:
static void Init(void);
void *operator new(size_t size);
void operator delete(void *p);
iObject()
{ /* nop */
}
virtual ~iObject()
{ /* nop */
}
friend class iObjectActivator;
};
/* ------------------------------ iLogBufferBuffer ------------------------- */
class iLogBufferBuffer
{
private:
static iLogBufferBuffer *free_heap; /* list of free blocks */
static ink_mutex iLogBufferBufferMutex; /* mutex for access iLogBufferBuffer class global variables */
iLogBufferBuffer *next;
size_t real_buf_size;
iLogBufferBuffer()
{
next = 0;
buf = 0;
real_buf_size = (size = 0);
}
~iLogBufferBuffer()
{
if (buf)
xfree(buf);
real_buf_size = (size = 0);
}
protected:
iLogBufferBuffer(const iLogBufferBuffer &); /* declared; not implemented - block copying and assignment */
iLogBufferBuffer & operator=(const iLogBufferBuffer &); /* ditto */
public:
char *buf;
size_t size;
static void Init(void);
static iLogBufferBuffer *New_iLogBufferBuffer(size_t _buf_size);
static iLogBufferBuffer *Delete_iLogBufferBuffer(iLogBufferBuffer * _b);
friend class iObjectActivator;
};
/* ---------------------------- iObjectActivator --------------------------- */
class iObjectActivator
{
public:
iObjectActivator()
{
iObject::Init();
iLogBufferBuffer::Init();
}
~iObjectActivator()
{ /* nop */
}
};
/*-------------------------------------------------------------------------
LogBuffer
-------------------------------------------------------------------------*/
#define CLASS_SIGN_LOGBUFFER 0xFACE5370 /* LogBuffer class signature */
class LogBuffer:public iObject
{
public:
unsigned long sign; /* class signature (must be CLASS_SIGN_LOGBUFFER) */
LogBuffer *next_flush; /* next in flush list */
LogBuffer *next_list; /* next in list */
enum LB_ResultCode
{
LB_OK = 0,
LB_FULL_NO_WRITERS,
LB_FULL_ACTIVE_WRITERS,
LB_RETRY,
LB_ALL_WRITERS_DONE,
LB_BUSY,
LB_BUFFER_TOO_SMALL
};
LogBuffer(LogObject * owner, size_t size,
size_t buf_align = LB_DEFAULT_ALIGN, size_t write_align = INK_MIN_ALIGN);
LogBuffer(LogObject * owner, LogBufferHeader * header);
~LogBuffer();
char &operator [] (int idx)
{
ink_debug_assert(idx >= 0);
ink_debug_assert((size_t) idx < m_size);
return m_buffer[idx];
};
int switch_state(LB_State & old_state, LB_State & new_state)
{
INK_WRITE_MEMORY_BARRIER;
return (ink_atomic_cas64((int64 *) & m_state.ival, old_state.ival, new_state.ival));
};
LB_ResultCode checkout_write(size_t * write_offset, size_t write_size);
LB_ResultCode checkin_write(size_t write_offset);
void force_full();
LogBufferHeader *header()
{
return m_header;
}
long expiration_time()
{
return m_expiration_time;
}
// this should only be called when buffer is ready to be flushed
void update_header_data();
void convert_to_network_order();
void convert_to_host_order();
uint32 get_id()
{
return m_id;
};
LogObject *get_owner() const
{
return m_owner;
};
Link<LogBuffer> link;
// static variables
static vint32 M_ID;
// static functions
static size_t max_entry_bytes();
static int to_ascii(LogEntryHeader * entry, LogFormatType type,
char *buf, int max_len, char *symbol_str, char *printf_str,
unsigned buffer_version, char *alt_format = NULL);
static int resolve_custom_entry(LogFieldList * fieldlist,
char *printf_str, char *read_from, char *write_to,
int write_to_len, long timestamp, long timestamp_us,
unsigned buffer_version, LogFieldList * alt_fieldlist = NULL,
char *alt_printf_str = NULL);
static void convert_to_network_order(LogBufferHeader * header);
static void convert_to_host_order(LogBufferHeader * header);
private:
iLogBufferBuffer * m_bb; // real buffer
char *m_new_buffer; // new buffer (must be free)
char *m_unaligned_buffer; // the unaligned buffer
char *m_buffer; // the buffer
size_t m_size; // the buffer size
size_t m_buf_align; // the buffer alignment
size_t m_write_align; // the write alignment mask
volatile LB_State m_state; // buffer state
int m_max_entries; // max number of entries allowed
long m_expiration_time; // buffer expiration time
LogObject *m_owner; // the LogObject that owns this buf.
LogBufferHeader *m_header;
uint32 m_id; // unique buffer id (for debugging)
// private functions
size_t _add_buffer_header();
unsigned add_header_str(char *str, char *buf_ptr, unsigned buf_len);
// -- member functions that are not allowed --
LogBuffer();
LogBuffer(const LogBuffer & rhs);
LogBuffer & operator=(const LogBuffer & rhs);
friend class LogBufferIterator;
};
class LogFile;
/*-------------------------------------------------------------------------
LogBufferList
Support atomic operations on a list of LogBuffer objects.
-------------------------------------------------------------------------*/
class LogBufferList
{
private:
LogBuffer * m_list;
LogBuffer *m_list_last_ptr;
ink_mutex m_mutex;
int m_size;
public:
LogBufferList();
~LogBufferList();
void add(LogBuffer * lb);
LogBuffer *get(void);
int get_size(void)
{
return m_size;
}
};
/*-------------------------------------------------------------------------
LogBufferIterator
This class will iterate over the entries in a LogBuffer.
-------------------------------------------------------------------------*/
class LogBufferIterator
{
public:
LogBufferIterator(LogBufferHeader * header, bool in_network_order = false);
~LogBufferIterator();
LogEntryHeader *next();
private:
bool m_in_network_order;
char *m_next;
unsigned m_iter_entry_count;
unsigned m_buffer_entry_count;
// -- member functions not allowed --
LogBufferIterator();
LogBufferIterator(const LogBufferIterator &);
LogBufferIterator & operator=(const LogBufferIterator &);
};
/*-------------------------------------------------------------------------
LogBufferIterator
This class provides the ability to iterate over the LogEntries stored
within a given LogBuffer.
-------------------------------------------------------------------------*/
inline
LogBufferIterator::LogBufferIterator(LogBufferHeader * header, bool in_network_order)
:
m_in_network_order(in_network_order)
,
m_next(0)
,
m_iter_entry_count(0)
,
m_buffer_entry_count(0)
{
ink_debug_assert(header);
switch (header->version) {
case LOG_SEGMENT_VERSION:
m_next = (char *) header + header->data_offset;
m_buffer_entry_count = header->entry_count;
break;
case 1:
m_next = (char *) header + ((LogBufferHeaderV1 *) header)->data_offset;
m_buffer_entry_count = ((LogBufferHeaderV1 *) header)->entry_count;
break;
default:
Note("Invalid LogBuffer version %d in LogBufferIterator; "
"current version is %d", header->version, LOG_SEGMENT_VERSION);
break;
}
}
/*-------------------------------------------------------------------------
-------------------------------------------------------------------------*/
inline
LogBufferIterator::~
LogBufferIterator()
{
}
#endif
#endif //INK_NO_LOG