1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
|
/*
ELAPI
Private header file continaing internal data for the ELAPI interface.
Copyright (C) Dmitri Pal <dpal@redhat.com> 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ELAPI_PRIV_H
#define ELAPI_PRIV_H
#include <stdint.h>
#include "collection.h"
#include "elapi_async.h"
#include "elapi_sink.h"
/* Classes of the collections used by ELAPI internally */
#define COL_CLASS_ELAPI_BASE 21000
#define COL_CLASS_ELAPI_EVENT COL_CLASS_ELAPI_BASE + 0
#define COL_CLASS_ELAPI_TEMPLATE COL_CLASS_ELAPI_BASE + 1
#define COL_CLASS_ELAPI_SINK COL_CLASS_ELAPI_BASE + 2
#define COL_CLASS_ELAPI_TARGET COL_CLASS_ELAPI_BASE + 3
#define COL_CLASS_ELAPI_SINK_REF COL_CLASS_ELAPI_BASE + 4
/* Names for the collections */
#define E_TEMPLATE_NAME "template"
#define E_EVENT_NAME "event"
/* Constants used in INI file and in
* the internal collection objects.
*/
#define ELAPI_DISPATCHER "dispatcher"
#define ELAPI_SINKS "sinks"
#define ELAPI_TARGETS "targets"
#define ELAPI_SINK_REFS "srefs"
#define ELAPI_TARGET_VALUE "value"
#define ELAPI_SINK_PROVIDER "provider"
#define ELAPI_SINK_REQUIRED "required"
#define ELAPI_SINK_ONERROR "onerror"
#define ELAPI_SINK_TIMEOUT "timeout"
#define ELAPI_SINK_SYNCH "synch"
/* Default timout before dispatcher tries to revive sink.
* The actual value is configurable on per sink basis
* so I do not see a value in making this a compile time
* option (at least at the moment).
*/
#define ELAPI_SINK_DEFAULT_TIMEOUT 60
/* Names of embedded providers */
#define ELAPI_EMB_PRVDR_FILE "file"
#define ELAPI_EMB_PRVDR_SYSLOG "syslog"
/* Numbers for embedded providers */
#define ELAPI_EMB_PRVDR_FILENUM 0
#define ELAPI_EMB_PRVDR_SYSLOGNUM 1
#define ELAPI_TARGET_ALL 0xFFFF /* 65k targets should be enough */
/* Possible values for onerror config parameter */
#define ELAPI_ONERROR_REVIVE 0
#define ELAPI_ONERROR_DISABLE 1
struct elapi_dispatcher {
/* Application name */
char *appname;
/* List of target names and chars */
char **targets;
/* Collection of targets */
struct collection_item *target_list;
/* Counter of the targets */
int target_counter;
/* Collection of sinks */
struct collection_item *sink_list;
/* Configuration */
struct collection_item *ini_config;
/* Default event template */
struct collection_item *default_template;
/* Async processing related data */
struct elapi_async_ctx *async_ctx;
/* Indicator of our synch mode
* FIXME: Do we need it?
*/
uint32_t async_mode;
/* Time offset */
int32_t offset;
};
/* Structure to pass data from logging function to targets */
struct elapi_tgt_data {
struct collection_item *event;
struct elapi_dispatcher *handle;
uint32_t target_mask;
};
/* This is a structure that holds the information
* about the target.
*/
struct elapi_tgt_ctx {
/* Value associted with the
* target in the config file.
*/
uint32_t target_value;
/* Collection of pointers to sink objects */
struct collection_item *sink_ref_list;
/* FIXME - other things that belong here are:
* state of the chain
* reference to the current sink
* reference to the preferred sink
* etc.
*/
};
/* Structure that hols sink's error status */
struct sink_status {
int suspended;
time_t lasttry;
};
/* Common configuration items for all sinks */
struct elapi_sink_cfg {
char *provider;
uint32_t required;
uint32_t onerror;
uint32_t timeout;
uint32_t synch;
void *priv_ctx;
void *libhandle;
sink_cpb_fn ability;
struct sink_cpb cpb_cb;
};
/* The structure that describes the sink in the dispatcher */
struct elapi_sink_ctx {
/* Input queue of a sink */
struct collection_item *in_queue;
/* Pending list */
struct collection_item *pending;
/* Sink's error status */
struct sink_status status;
/* Synch/asynch mode */
uint32_t async_mode;
/* Sink configuration data */
struct elapi_sink_cfg sink_cfg;
/* Back pointer to the target context.
* This is needed for the cases
* when we detect that sink
* is failed and we need
* to fail over for the next one.
*/
struct elapi_tgt_ctx *tgt_ctx;
};
/* The structure to hold the event and its context */
/* FIXME The event should be turned into this object
* on the high level before going
* into any target.
* and then this should be passed around
* instead of the actual event.
*/
struct elapi_event_ctx {
/* This is a copy of the event */
/* We have to copy it for two reasons:
* a) It needs to be flattened so
* that we do not get unnecesary naming
* collisions if same key appears on different
* levels
* b) In case of async logging we need
* the original event until we are sure
* it is actually logged. If we do not
* keep it around the application can modify
* it or delete it before we figured out
* that sink is broken and we need to fail over.
* If in this case we go to another sink
* and if we do not have the original event
* we are screwed.
*/
struct collection_item *event;
/* Reference count */
int refcount;
/* Event time */
time_t tm;
/* Resolved message */
char *message;
/* Time offset */
int32_t offset;
};
/* Lookup structure for searching for providers */
struct elapi_prvdr_lookup {
const char *name;
sink_cpb_fn ability;
};
/* The structure to hold a command and a result of the command execution */
struct elapi_get_sink {
int action;
int found;
};
/* Function to create event using arg list */
int elapi_create_event_with_vargs(struct collection_item **event,
struct collection_item *template,
struct collection_item *collection,
int mode, va_list args);
/* Function to create event template using arg list */
int elapi_create_event_template_with_vargs(struct collection_item **template,
unsigned base,
va_list args);
/* Sink handler function */
int elapi_sink_cb(const char *sink,
int sink_len,
int type,
void *data,
int length,
void *passed_data,
int *stop);
/* Internal sink cleanup function */
int elapi_sink_free_cb(const char *sink,
int sink_len,
int type,
void *data,
int length,
void *passed_data,
int *stop);
/* Function to add a sink based on configuration */
int elapi_sink_add(struct collection_item **sink_ref,
const char *sink,
struct elapi_dispatcher *handle);
/* Function to create a sink */
int elapi_sink_create(struct elapi_sink_ctx **sink_ctx,
const char *name,
struct collection_item *ini_config,
const char *appname);
/* Destroy sink */
void elapi_sink_destroy(struct elapi_sink_ctx *context);
/* Send event into the sink */
int elapi_sink_submit(struct elapi_sink_ctx *sink_ctx,
struct collection_item *event);
/* Create target object */
int elapi_tgt_create(struct elapi_tgt_ctx **context,
const char *target,
struct elapi_dispatcher *handle);
/* Destroy target object */
void elapi_tgt_destroy(struct elapi_tgt_ctx *context);
/* Internal target cleanup function */
int elapi_tgt_free_cb(const char *sink,
int sink_len,
int type,
void *data,
int length,
void *passed_data,
int *stop);
/* Handler for logging through the targets */
int elapi_tgt_cb(const char *target,
int target_len,
int type,
void *data,
int length,
void *passed_data,
int *stop);
/* Submit event into the target */
int elapi_tgt_submit(struct elapi_dispatcher *handle,
struct elapi_tgt_ctx *context,
struct collection_item *event);
/* Create list of targets for a dispatcher */
int elapi_tgt_mklist(struct elapi_dispatcher *handle);
/* Send ELAPI config errors into a file */
void elapi_dump_ini_err(struct collection_item *error_list);
#ifdef ELAPI_VERBOSE
/* Print dispatcher internals for testing and debugging purposes */
void elapi_print_dispatcher(struct elapi_dispatcher *handle);
/* Print sink context details */
void elapi_print_sink_ctx(struct elapi_sink_ctx *sink_context);
#else
#define elapi_print_dispatcher(arg)
#endif
#endif
|