1 /** @file
2
3 A brief file description
4
5 @section license License
6
7 Licensed to the Apache Software Foundation (ASF) under one
8 or more contributor license agreements. See the NOTICE file
9 distributed with this work for additional information
10 regarding copyright ownership. The ASF licenses this file
11 to you under the Apache License, Version 2.0 (the
12 "License"); you may not use this file except in compliance
13 with the License. You may obtain a copy of the License at
14
15 http://www.apache.org/licenses/LICENSE-2.0
16
17 Unless required by applicable law or agreed to in writing, software
18 distributed under the License is distributed on an "AS IS" BASIS,
19 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 See the License for the specific language governing permissions and
21 limitations under the License.
22 */
23
24 #pragma once
25
26 #include "tscore/ink_platform.h"
27 #include "tscore/Diags.h"
28 #include "LogFormat.h"
29 #include "LogLimits.h"
30 #include "LogAccess.h"
31
32 class LogObject;
33 class LogConfig;
34 class LogBufferIterator;
35
36 #define LOG_SEGMENT_COOKIE 0xaceface
37 #define LOG_SEGMENT_VERSION 2
38
39 #if defined(linux)
40 #define LB_DEFAULT_ALIGN 512
41 #else
42 #define LB_DEFAULT_ALIGN 8
43 #endif
44
45 /*-------------------------------------------------------------------------
46 LogEntryHeader
47
48 This struct is automatically laid down at the head of each entry in the
49 buffer.
50 -------------------------------------------------------------------------*/
51
52 struct LogEntryHeader {
53 int64_t timestamp; // the seconds portion of the timestamp
54 int32_t timestamp_usec; // the microseconds portion of the timestamp
55 uint32_t entry_len;
56 };
57
58 /*-------------------------------------------------------------------------
59 LogBufferHeader
60
61 This struct is automatically laid down at the head of each buffer.
62 -------------------------------------------------------------------------*/
63
64 struct LogBufferHeader {
65 uint32_t cookie; // so we can find it on disk
66 uint32_t version; // in case we want to change it later
67 uint32_t format_type; // SQUID_LOG, COMMON_LOG, ...
68 uint32_t byte_count; // actual # of bytes for the segment
69 uint32_t entry_count; // actual number of entries stored
70 uint32_t low_timestamp; // lowest timestamp value of entries
71 uint32_t high_timestamp; // highest timestamp value of entries
72 uint32_t log_object_flags; // log object flags
73 uint64_t log_object_signature; // log object signature
74 #if defined(LOG_BUFFER_TRACKING)
75 uint32_t int id;
76 #endif // defined(LOG_BUFFER_TRACKING)
77
78 // all offsets are computed from the start of the buffer (ie, "this"),
79 // and so any valid offset will be at least sizeof(LogBufferHeader).
80
81 uint32_t fmt_name_offset; // offset to format name string
82 uint32_t fmt_fieldlist_offset; // offset to format fieldlist string
83 uint32_t fmt_printf_offset; // offset to format printf string
84 uint32_t src_hostname_offset; // offset to source (client) hostname
85 uint32_t log_filename_offset; // offset to log filename
86 uint32_t data_offset; // offset to start of data entry
87 // section
88
89 // some helper functions to return the header strings
90
91 char *fmt_fieldlist();
92 char *fmt_printf();
93 char *src_hostname();
94 char *log_filename();
95 };
96
97 union LB_State {
LB_State()98 LB_State() : ival(0) {}
LB_State(LB_State & vs)99 LB_State(LB_State &vs) { ival = vs.ival; }
100 LB_State &
101 operator=(LB_State &vs)
102 {
103 ival = vs.ival;
104 return *this;
105 }
106
107 int64_t ival; // ival is used to help do an atomic CAS for struct s
108 struct {
109 uint32_t offset; // buffer offset(bytes in buffer)
110 uint16_t num_entries; // number of entries in buffer
111 uint16_t full : 1; // not accepting more checkouts
112 uint16_t num_writers : 15; // number of writers
113 } s;
114 };
115
116 /*-------------------------------------------------------------------------
117 LogBuffer
118 -------------------------------------------------------------------------*/
119 class LogBuffer
120 {
121 public:
122 SLINK(LogBuffer, write_link);
123 enum LB_ResultCode {
124 LB_OK = 0,
125 LB_FULL_NO_WRITERS,
126 LB_FULL_ACTIVE_WRITERS,
127 LB_RETRY,
128 LB_ALL_WRITERS_DONE,
129 LB_BUSY,
130 LB_BUFFER_TOO_SMALL
131 };
132
133 LogBuffer(const LogConfig *cfg, LogObject *owner, size_t size, size_t buf_align = LB_DEFAULT_ALIGN,
134 size_t write_align = INK_MIN_ALIGN);
135 LogBuffer(LogObject *owner, LogBufferHeader *header);
136 ~LogBuffer();
137
138 char &
139 operator[](int idx)
140 {
141 ink_assert(idx >= 0);
142 ink_assert((size_t)idx < m_size);
143 return m_buffer[idx];
144 }
145
146 int
switch_state(LB_State & old_state,LB_State & new_state)147 switch_state(LB_State &old_state, LB_State &new_state)
148 {
149 INK_WRITE_MEMORY_BARRIER;
150 return (ink_atomic_cas(&m_state.ival, old_state.ival, new_state.ival));
151 }
152
153 LB_ResultCode checkout_write(size_t *write_offset, size_t write_size);
154 LB_ResultCode checkin_write(size_t write_offset);
155 void force_full();
156
157 LogBufferHeader *
header()158 header() const
159 {
160 return m_header;
161 }
162
163 long
expiration_time()164 expiration_time() const
165 {
166 return m_expiration_time;
167 }
168
169 // this should only be called when buffer is ready to be flushed
170 void update_header_data();
171
172 uint32_t
get_id()173 get_id() const
174 {
175 return m_id;
176 }
177
178 LogObject *
get_owner()179 get_owner() const
180 {
181 return m_owner;
182 }
183
184 LINK(LogBuffer, link);
185
186 // static variables
187 static int32_t M_ID;
188
189 // static functions
190 static size_t max_entry_bytes();
191 static int to_ascii(LogEntryHeader *entry, LogFormatType type, char *buf, int max_len, const char *symbol_str, char *printf_str,
192 unsigned buffer_version, const char *alt_format = nullptr);
193 static int resolve_custom_entry(LogFieldList *fieldlist, char *printf_str, char *read_from, char *write_to, int write_to_len,
194 long timestamp, long timestamp_us, unsigned buffer_version, LogFieldList *alt_fieldlist = nullptr,
195 char *alt_printf_str = nullptr);
196
197 static void
destroy(LogBuffer * & lb)198 destroy(LogBuffer *&lb)
199 {
200 // ink_atomic_increment() returns the previous value, so when it was 1, we are
201 // the thread that decremented to zero and should delete ...
202 int refcnt = ink_atomic_increment(&lb->m_references, -1);
203
204 if (refcnt == 1) {
205 delete lb;
206 lb = nullptr;
207 }
208
209 ink_release_assert(refcnt >= 0);
210 }
211
212 private:
213 char *m_unaligned_buffer; // the unaligned buffer
214 char *m_buffer; // the buffer
215 size_t m_size; // the buffer size
216 size_t m_buf_align; // the buffer alignment
217 size_t m_write_align; // the write alignment mask
218 int m_buffer_fast_allocator_size; // indicates whether the logbuffer is allocated from ioBuf
219
220 long m_expiration_time; // buffer expiration time
221
222 LogObject *m_owner; // the LogObject that owns this buf.
223 LogBufferHeader *m_header;
224
225 uint32_t m_id; // unique buffer id (for debugging)
226 public:
227 LB_State m_state; // buffer state
228 int m_references; // outstanding checkout_write references.
229
230 // noncopyable
231 // -- member functions that are not allowed --
232 LogBuffer(const LogBuffer &rhs) = delete;
233 LogBuffer &operator=(const LogBuffer &rhs) = delete;
234
235 private:
236 // private functions
237 size_t _add_buffer_header(const LogConfig *cfg);
238 unsigned add_header_str(const char *str, char *buf_ptr, unsigned buf_len);
239 void freeLogBuffer();
240
241 // -- member functions that are not allowed --
242 LogBuffer();
243
244 friend class LogBufferIterator;
245 };
246
247 class LogFile;
248
249 /*-------------------------------------------------------------------------
250 LogBufferList
251
252 Support atomic operations on a list of LogBuffer objects.
253 -------------------------------------------------------------------------*/
254
255 class LogBufferList
256 {
257 private:
258 Queue<LogBuffer> m_buffer_list;
259 ink_mutex m_mutex;
260 int m_size;
261
262 public:
263 LogBufferList();
264 ~LogBufferList();
265
266 void add(LogBuffer *lb);
267 LogBuffer *get();
268 int
get_size()269 get_size()
270 {
271 return m_size;
272 }
273 };
274
275 /*-------------------------------------------------------------------------
276 LogBufferIterator
277
278 This class will iterate over the entries in a LogBuffer.
279 -------------------------------------------------------------------------*/
280
281 class LogBufferIterator
282 {
283 public:
284 LogBufferIterator(LogBufferHeader *header, bool in_network_order = false);
285 ~LogBufferIterator();
286
287 LogEntryHeader *next();
288
289 // noncopyable
290 // -- member functions not allowed --
291 LogBufferIterator(const LogBufferIterator &) = delete;
292 LogBufferIterator &operator=(const LogBufferIterator &) = delete;
293
294 private:
295 bool m_in_network_order;
296 char *m_next;
297 unsigned m_iter_entry_count;
298 unsigned m_buffer_entry_count;
299
300 // -- member functions not allowed --
301 LogBufferIterator();
302 };
303
304 /*-------------------------------------------------------------------------
305 LogBufferIterator
306
307 This class provides the ability to iterate over the LogEntries stored
308 within a given LogBuffer.
309 -------------------------------------------------------------------------*/
310
LogBufferIterator(LogBufferHeader * header,bool in_network_order)311 inline LogBufferIterator::LogBufferIterator(LogBufferHeader *header, bool in_network_order)
312 : m_in_network_order(in_network_order), m_next(nullptr), m_iter_entry_count(0), m_buffer_entry_count(0)
313 {
314 ink_assert(header);
315
316 switch (header->version) {
317 case LOG_SEGMENT_VERSION:
318 m_next = (char *)header + header->data_offset;
319 m_buffer_entry_count = header->entry_count;
320 break;
321
322 default:
323 Note("Invalid LogBuffer version %d in LogBufferIterator; "
324 "current version is %d",
325 header->version, LOG_SEGMENT_VERSION);
326 break;
327 }
328 }
329
330 /*-------------------------------------------------------------------------
331 -------------------------------------------------------------------------*/
332
~LogBufferIterator()333 inline LogBufferIterator::~LogBufferIterator() {}
334