2
* Copyright (c) 2002-2010 BalaBit IT Ltd, Budapest, Hungary
3
* Copyright (c) 1998-2010 Balázs Scheidler
5
* This program is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 as published
7
* by the Free Software Foundation, or (at your option) any later version.
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
* As an additional exemption you are allowed to compile & link against the
19
* OpenSSL libraries as published by the OpenSSL project. See the file
20
* COPYING for details.
27
#include "serialize.h"
32
#include <sys/types.h>
42
affile_open_file(gchar *name, gint flags,
43
gint uid, gint gid, gint mode,
44
gint dir_uid, gint dir_gid, gint dir_mode,
45
gboolean create_dirs, gboolean privileged, gboolean is_pipe, gint *fd)
50
if (strstr(name, "../") || strstr(name, "/.."))
52
msg_error("Spurious path, logfile not created",
53
evt_tag_str("path", name),
58
saved_caps = g_process_cap_save();
61
g_process_cap_modify(CAP_DAC_READ_SEARCH, TRUE);
62
g_process_cap_modify(CAP_SYSLOG, TRUE);
66
g_process_cap_modify(CAP_DAC_OVERRIDE, TRUE);
69
if (create_dirs && !create_containing_directory(name, dir_uid, dir_gid, dir_mode))
71
g_process_cap_restore(saved_caps);
76
if (stat(name, &st) >= 0)
78
if (is_pipe && !S_ISFIFO(st.st_mode))
80
msg_warning("WARNING: you are using the pipe driver, underlying file is not a FIFO, it should be used by file()",
81
evt_tag_str("filename", name),
84
else if (!is_pipe && S_ISFIFO(st.st_mode))
86
msg_warning("WARNING: you are using the file driver, underlying file is a FIFO, it should be used by pipe()",
87
evt_tag_str("filename", name),
91
*fd = open(name, flags, mode < 0 ? 0600 : mode);
92
if (is_pipe && *fd < 0 && errno == ENOENT)
94
if (mkfifo(name, 0666) >= 0)
95
*fd = open(name, flags, 0666);
100
g_fd_set_cloexec(*fd, TRUE);
102
g_process_cap_modify(CAP_CHOWN, TRUE);
103
g_process_cap_modify(CAP_FOWNER, TRUE);
104
set_permissions_fd(*fd, uid, gid, mode);
106
g_process_cap_restore(saved_caps);
107
msg_trace("affile_open_file",
108
evt_tag_str("path", name),
109
evt_tag_int("fd",*fd),
116
affile_sd_open_file(AFFileSourceDriver *self, gchar *name, gint *fd)
120
if (self->flags & AFFILE_PIPE)
121
flags = O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
123
flags = O_RDONLY | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
125
if (affile_open_file(name, flags, -1, -1, -1, 0, 0, 0, 0, !!(self->flags & AFFILE_PRIVILEGED), !!(self->flags & AFFILE_PIPE), fd))
130
static inline gchar *
131
affile_sd_format_persist_name(AFFileSourceDriver *self)
133
static gchar persist_name[1024];
135
g_snprintf(persist_name, sizeof(persist_name), "affile_sd_curpos(%s)", self->filename->str);
140
affile_sd_recover_state(LogPipe *s, GlobalConfig *cfg, LogProto *proto)
142
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
144
if ((self->flags & AFFILE_PIPE) || self->reader_options.follow_freq <= 0)
147
if (!log_proto_restart_with_state(proto, cfg->state, affile_sd_format_persist_name(self)))
149
msg_error("Error converting persistent state from on-disk format, losing file position information",
150
evt_tag_str("filename", self->filename->str),
157
affile_sd_construct_proto(AFFileSourceDriver *self, LogTransport *transport)
161
MsgFormatHandler *handler;
164
((self->reader_options.follow_freq > 0)
165
? LPBS_IGNORE_EOF | LPBS_POS_TRACKING
168
handler = self->reader_options.parse_options.format_handler;
169
if ((handler && handler->construct_proto))
170
proto = self->reader_options.parse_options.format_handler->construct_proto(&self->reader_options.parse_options, transport, flags);
171
else if (self->reader_options.padding)
172
proto = log_proto_record_server_new(transport, self->reader_options.padding, flags);
174
proto = log_proto_text_server_new(transport, self->reader_options.msg_size, flags);
179
/* NOTE: runs in the main thread */
181
affile_sd_notify(LogPipe *s, LogPipe *sender, gint notify_code, gpointer user_data)
183
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
184
GlobalConfig *cfg = log_pipe_get_config(s);
191
msg_verbose("Follow-mode file source moved, tracking of the new file is started",
192
evt_tag_str("filename", self->filename->str),
195
log_pipe_deinit(self->reader);
196
log_pipe_unref(self->reader);
198
if (affile_sd_open_file(self, self->filename->str, &fd))
200
LogTransport *transport;
203
transport = log_transport_plain_new(fd, 0);
204
transport->timeout = 10;
206
proto = affile_sd_construct_proto(self, transport);
208
self->reader = log_reader_new(proto);
210
log_reader_set_options(self->reader, s, &self->reader_options, 1, SCS_FILE, self->super.super.id, self->filename->str);
211
log_reader_set_follow_filename(self->reader, self->filename->str);
212
log_reader_set_immediate_check(self->reader);
214
log_pipe_append(self->reader, s);
215
if (!log_pipe_init(self->reader, cfg))
217
msg_error("Error initializing log_reader, closing fd",
218
evt_tag_int("fd", fd),
220
log_pipe_unref(self->reader);
224
affile_sd_recover_state(s, cfg, proto);
238
affile_sd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
240
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
241
static NVHandle filename_handle = 0;
243
if (!filename_handle)
244
filename_handle = log_msg_get_value_handle("FILE_NAME");
246
log_msg_set_value(msg, filename_handle, self->filename->str, self->filename->len);
248
log_pipe_forward_msg(s, msg, path_options);
252
affile_sd_init(LogPipe *s)
254
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
255
GlobalConfig *cfg = log_pipe_get_config(s);
257
gboolean file_opened, open_deferred = FALSE;
259
if (!log_src_driver_init_method(s))
262
log_reader_options_init(&self->reader_options, cfg, self->super.super.group);
264
file_opened = affile_sd_open_file(self, self->filename->str, &fd);
265
if (!file_opened && self->reader_options.follow_freq > 0)
267
msg_info("Follow-mode file source not found, deferring open",
268
evt_tag_str("filename", self->filename->str),
270
open_deferred = TRUE;
274
if (file_opened || open_deferred)
276
LogTransport *transport;
279
transport = log_transport_plain_new(fd, 0);
280
transport->timeout = 10;
282
proto = affile_sd_construct_proto(self, transport);
283
/* FIXME: we shouldn't use reader_options to store log protocol parameters */
284
self->reader = log_reader_new(proto);
286
log_reader_set_options(self->reader, s, &self->reader_options, 1, SCS_FILE, self->super.super.id, self->filename->str);
287
log_reader_set_follow_filename(self->reader, self->filename->str);
289
/* NOTE: if the file could not be opened, we ignore the last
290
* remembered file position, if the file is created in the future
291
* we're going to read from the start. */
293
log_pipe_append(self->reader, s);
295
if (!log_pipe_init(self->reader, NULL))
297
msg_error("Error initializing log_reader, closing fd",
298
evt_tag_int("fd", fd),
300
log_pipe_unref(self->reader);
305
affile_sd_recover_state(s, cfg, proto);
309
msg_error("Error opening file for reading",
310
evt_tag_str("filename", self->filename->str),
311
evt_tag_errno(EVT_TAG_OSERROR, errno),
313
return self->super.super.optional;
320
affile_sd_deinit(LogPipe *s)
322
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
326
log_pipe_deinit(self->reader);
327
log_pipe_unref(self->reader);
331
if (!log_src_driver_deinit_method(s))
338
affile_sd_free(LogPipe *s)
340
AFFileSourceDriver *self = (AFFileSourceDriver *) s;
342
g_string_free(self->filename, TRUE);
343
g_assert(!self->reader);
345
log_reader_options_destroy(&self->reader_options);
347
log_src_driver_free(s);
351
affile_sd_new(gchar *filename, guint32 flags)
353
AFFileSourceDriver *self = g_new0(AFFileSourceDriver, 1);
355
log_src_driver_init_instance(&self->super);
356
self->filename = g_string_new(filename);
358
self->super.super.super.init = affile_sd_init;
359
self->super.super.super.queue = affile_sd_queue;
360
self->super.super.super.deinit = affile_sd_deinit;
361
self->super.super.super.notify = affile_sd_notify;
362
self->super.super.super.free_fn = affile_sd_free;
363
log_reader_options_defaults(&self->reader_options);
364
self->reader_options.parse_options.flags |= LP_LOCAL;
366
if ((self->flags & AFFILE_PIPE))
368
static gboolean warned = FALSE;
370
if (configuration && configuration->version < 0x0302)
374
msg_warning("WARNING: the expected message format is being changed for pipe() to improve "
375
"syslogd compatibity with syslog-ng 3.2. If you are using custom "
376
"applications which bypass the syslog() API, you might "
377
"need the 'expect-hostname' flag to get the old behaviour back", NULL);
383
self->reader_options.parse_options.flags &= ~LP_EXPECT_HOSTNAME;
387
if (configuration && configuration->version < 0x0300)
389
static gboolean warned = FALSE;
393
msg_warning("WARNING: file source: default value of follow_freq in file sources is changing in 3.0 to '1' for all files except /proc/kmsg",
400
if ((self->flags & AFFILE_PIPE) == 0)
404
(strcmp(filename, "/proc/kmsg") == 0) ||
406
(strcmp(filename, "/dev/klog") == 0) ||
410
self->reader_options.follow_freq = 0;
414
self->reader_options.follow_freq = 1000;
419
if (strcmp(filename, "/proc/kmsg") == 0)
421
self->flags |= AFFILE_PRIVILEGED;
424
return &self->super.super;
430
* Apart from standard initialization/deinitialization (normally performed
431
* by the main thread when syslog-ng starts up) the following processes are
432
* performed in various threads.
434
* - queue runs in the thread of the source thread that generated the message
435
* - if the message is to be written to a not-yet-opened file, a new gets
436
* opened and stored in the writer_hash hashtable (initiated from queue,
437
* but performed in the main thread, but more on that later)
438
* - currently opened destination files are checked regularly and closed
439
* if they are idle for a given amount of time (time_reap) (this is done
440
* in the main thread)
442
* Some of these operations have to be performed in the main thread, others
443
* are done in the queue call.
448
* The AFFileDestDriver instance is registered into the current
449
* configuration, thus its presence is always given, it cannot go away while
450
* syslog-ng is running.
452
* AFFileDestWriter instances are created dynamically when a new file is
453
* opened. A reference is stored in the writer_hash hashtable. This is then:
454
* - looked up in _queue() (in the source thread)
455
* - cleaned up in reap callback (in the main thread)
457
* writer_hash is locked (currently a simple mutex) using
458
* AFFileDestDriver->lock. The "queue" method cannot hold the lock while
459
* forwarding it to the next pipe, thus a reference is taken under the
460
* protection of the lock, keeping a the next pipe alive, even if that would
461
* go away in a parallel reaper process.
464
struct _AFFileDestWriter
468
AFFileDestDriver *owner;
471
time_t last_msg_stamp;
472
time_t last_open_stamp;
474
struct iv_timer reap_timer;
475
gboolean reopen_pending, queue_pending;
478
static void affile_dd_reap_writer(AFFileDestDriver *self, AFFileDestWriter *dw);
481
affile_dw_arm_reaper(AFFileDestWriter *self)
483
/* not yet reaped, set up the next callback */
485
self->reap_timer.expires = iv_now;
486
timespec_add_msec(&self->reap_timer.expires, self->owner->time_reap * 1000 / 2);
487
iv_timer_register(&self->reap_timer);
491
affile_dw_reap(gpointer s)
493
AFFileDestWriter *self = (AFFileDestWriter *) s;
495
main_loop_assert_main_thread();
497
g_static_mutex_lock(&self->lock);
498
if (!log_writer_has_pending_writes((LogWriter *) self->writer) &&
499
!self->queue_pending &&
500
(cached_g_current_time_sec() - self->last_msg_stamp) >= self->owner->time_reap)
502
g_static_mutex_unlock(&self->lock);
503
msg_verbose("Destination timed out, reaping",
504
evt_tag_str("template", self->owner->filename_template->template),
505
evt_tag_str("filename", self->filename),
507
affile_dd_reap_writer(self->owner, self);
511
g_static_mutex_unlock(&self->lock);
512
affile_dw_arm_reaper(self);
517
affile_dw_reopen(AFFileDestWriter *self)
522
self->last_open_stamp = self->last_msg_stamp;
523
if (self->owner->overwrite_if_older > 0 &&
524
stat(self->filename, &st) == 0 &&
525
st.st_mtime < time(NULL) - self->owner->overwrite_if_older)
527
msg_info("Destination file is older than overwrite_if_older(), overwriting",
528
evt_tag_str("filename", self->filename),
529
evt_tag_int("overwrite_if_older", self->owner->overwrite_if_older),
531
unlink(self->filename);
534
if (self->owner->flags & AFFILE_PIPE)
535
flags = O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
537
flags = O_WRONLY | O_CREAT | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
540
if (affile_open_file(self->filename, flags,
541
self->owner->file_uid, self->owner->file_gid, self->owner->file_perm,
542
self->owner->dir_uid, self->owner->dir_gid, self->owner->dir_perm,
543
!!(self->owner->flags & AFFILE_CREATE_DIRS), FALSE, !!(self->owner->flags & AFFILE_PIPE), &fd))
548
((self->owner->flags & AFFILE_PIPE) ? LTF_PIPE : LTF_APPEND) |
549
((self->owner->flags & AFFILE_FSYNC) ? LTF_FSYNC : 0);
550
log_writer_reopen(self->writer,
551
self->owner->flags & AFFILE_PIPE
552
? log_proto_text_client_new(log_transport_plain_new(fd, write_flags))
553
: log_proto_file_writer_new(log_transport_plain_new(fd, write_flags), self->owner->writer_options.flush_lines));
555
main_loop_call((void * (*)(void *)) affile_dw_arm_reaper, self, TRUE);
559
msg_error("Error opening file for writing",
560
evt_tag_str("filename", self->filename),
561
evt_tag_errno(EVT_TAG_OSERROR, errno),
563
return self->owner->super.super.optional;
569
affile_dw_init(LogPipe *s)
571
AFFileDestWriter *self = (AFFileDestWriter *) s;
572
GlobalConfig *cfg = log_pipe_get_config(s);
575
self->time_reopen = cfg->time_reopen;
577
msg_verbose("Initializing destination file writer",
578
evt_tag_str("template", self->owner->filename_template->template),
579
evt_tag_str("filename", self->filename),
586
flags = LW_FORMAT_FILE |
587
((self->owner->flags & AFFILE_PIPE) ? 0 : LW_SOFT_FLOW_CONTROL);
589
self->writer = log_writer_new(flags);
591
log_writer_set_options((LogWriter *) self->writer, s, &self->owner->writer_options, 1,
592
self->owner->flags & AFFILE_PIPE ? SCS_PIPE : SCS_FILE,
593
self->owner->super.super.id, self->filename);
594
log_writer_set_queue(self->writer, log_dest_driver_acquire_queue(&self->owner->super, NULL));
596
if (!log_pipe_init(self->writer, NULL))
598
msg_error("Error initializing log writer", NULL);
599
log_pipe_unref(self->writer);
603
log_pipe_append(&self->super, self->writer);
605
return affile_dw_reopen(self);
609
affile_dw_deinit(LogPipe *s)
611
AFFileDestWriter *self = (AFFileDestWriter *) s;
613
main_loop_assert_main_thread();
616
log_pipe_deinit(self->writer);
618
if (iv_timer_registered(&self->reap_timer))
619
iv_timer_unregister(&self->reap_timer);
624
* NOTE: the caller (e.g. AFFileDestDriver) holds a reference to @self, thus
625
* @self may _never_ be freed, even if the reaper timer is elapsed in the
629
affile_dw_queue(LogPipe *s, LogMessage *lm, const LogPathOptions *path_options, gpointer user_data)
631
AFFileDestWriter *self = (AFFileDestWriter *) s;
633
g_static_mutex_lock(&self->lock);
634
self->last_msg_stamp = cached_g_current_time_sec();
635
if (self->last_open_stamp == 0)
636
self->last_open_stamp = self->last_msg_stamp;
638
if (!log_writer_opened((LogWriter *) self->writer) &&
639
!self->reopen_pending &&
640
(self->last_open_stamp < self->last_msg_stamp - self->time_reopen))
642
self->reopen_pending = TRUE;
643
/* if the file couldn't be opened, try it again every time_reopen seconds */
644
g_static_mutex_unlock(&self->lock);
645
affile_dw_reopen(self);
646
g_static_mutex_lock(&self->lock);
647
self->reopen_pending = FALSE;
649
g_static_mutex_unlock(&self->lock);
651
log_pipe_forward_msg(&self->super, lm, path_options);
655
affile_dw_set_owner(AFFileDestWriter *self, AFFileDestDriver *owner)
658
log_pipe_unref(&self->owner->super.super.super);
659
log_pipe_ref(&owner->super.super.super);
662
log_writer_set_options((LogWriter *) self->writer, &self->super, &owner->writer_options, 1, SCS_FILE, self->owner->super.super.id, self->filename);
667
affile_dw_free(LogPipe *s)
669
AFFileDestWriter *self = (AFFileDestWriter *) s;
671
log_pipe_unref(self->writer);
673
g_free(self->filename);
674
log_pipe_unref(&self->owner->super.super.super);
675
log_pipe_free_method(s);
678
static AFFileDestWriter *
679
affile_dw_new(AFFileDestDriver *owner, const gchar *filename)
681
AFFileDestWriter *self = g_new0(AFFileDestWriter, 1);
683
log_pipe_init_instance(&self->super);
685
self->super.init = affile_dw_init;
686
self->super.deinit = affile_dw_deinit;
687
self->super.free_fn = affile_dw_free;
688
self->super.queue = affile_dw_queue;
689
log_pipe_ref(&owner->super.super.super);
691
self->time_reopen = 60;
693
IV_TIMER_INIT(&self->reap_timer);
694
self->reap_timer.cookie = self;
695
self->reap_timer.handler = affile_dw_reap;
697
/* we have to take care about freeing filename later.
698
This avoids a move of the filename. */
699
self->filename = g_strdup(filename);
700
g_static_mutex_init(&self->lock);
705
affile_dd_set_file_uid(LogDriver *s, const gchar *file_uid)
707
AFFileDestDriver *self = (AFFileDestDriver *) s;
710
if (!resolve_user(file_uid, &self->file_uid))
712
msg_error("Error resolving user",
713
evt_tag_str("user", file_uid),
719
affile_dd_set_file_gid(LogDriver *s, const gchar *file_gid)
721
AFFileDestDriver *self = (AFFileDestDriver *) s;
724
if (!resolve_group(file_gid, &self->file_gid))
726
msg_error("Error resolving group",
727
evt_tag_str("group", file_gid),
733
affile_dd_set_file_perm(LogDriver *s, gint file_perm)
735
AFFileDestDriver *self = (AFFileDestDriver *) s;
737
self->file_perm = file_perm;
741
affile_dd_set_dir_uid(LogDriver *s, const gchar *dir_uid)
743
AFFileDestDriver *self = (AFFileDestDriver *) s;
746
if (!resolve_user(dir_uid, &self->dir_uid))
748
msg_error("Error resolving user",
749
evt_tag_str("user", dir_uid),
755
affile_dd_set_dir_gid(LogDriver *s, const gchar *dir_gid)
757
AFFileDestDriver *self = (AFFileDestDriver *) s;
760
if (!resolve_group(dir_gid, &self->dir_gid))
762
msg_error("Error resolving group",
763
evt_tag_str("group", dir_gid),
769
affile_dd_set_dir_perm(LogDriver *s, gint dir_perm)
771
AFFileDestDriver *self = (AFFileDestDriver *) s;
773
self->dir_perm = dir_perm;
777
affile_dd_set_create_dirs(LogDriver *s, gboolean create_dirs)
779
AFFileDestDriver *self = (AFFileDestDriver *) s;
782
self->flags |= AFFILE_CREATE_DIRS;
784
self->flags &= ~AFFILE_CREATE_DIRS;
788
affile_dd_set_overwrite_if_older(LogDriver *s, gint overwrite_if_older)
790
AFFileDestDriver *self = (AFFileDestDriver *) s;
792
self->overwrite_if_older = overwrite_if_older;
796
affile_dd_set_fsync(LogDriver *s, gboolean fsync)
798
AFFileDestDriver *self = (AFFileDestDriver *) s;
800
self->flags |= AFFILE_FSYNC;
802
self->flags &= ~AFFILE_FSYNC;
806
affile_dd_set_local_time_zone(LogDriver *s, const gchar *local_time_zone)
808
AFFileDestDriver *self = (AFFileDestDriver *) s;
810
self->local_time_zone = g_strdup(local_time_zone);
813
static inline gchar *
814
affile_dd_format_persist_name(AFFileDestDriver *self)
816
static gchar persist_name[1024];
818
g_snprintf(persist_name, sizeof(persist_name), "affile_dd_writers(%s)", self->filename_template->template);
823
affile_dd_reap_writer(AFFileDestDriver *self, AFFileDestWriter *dw)
825
main_loop_assert_main_thread();
827
if ((self->flags & AFFILE_NO_EXPAND) == 0)
829
g_static_mutex_lock(&self->lock);
830
/* remove from hash table */
831
g_hash_table_remove(self->writer_hash, dw->filename);
832
g_static_mutex_unlock(&self->lock);
836
g_static_mutex_lock(&self->lock);
837
g_assert(dw == self->single_writer);
838
self->single_writer = NULL;
839
g_static_mutex_unlock(&self->lock);
842
log_pipe_deinit(&dw->super);
843
log_pipe_unref(&dw->super);
848
* affile_dd_reuse_writer:
850
* This function is called as a g_hash_table_foreach() callback to set the
851
* owner of each writer, previously connected to an AFileDestDriver instance
852
* in an earlier configuration. This way AFFileDestWriter instances are
853
* remembered accross reloads.
857
affile_dd_reuse_writer(gpointer key, gpointer value, gpointer user_data)
859
AFFileDestDriver *self = (AFFileDestDriver *) user_data;
860
AFFileDestWriter *writer = (AFFileDestWriter *) value;
862
affile_dw_set_owner(writer, self);
863
log_pipe_init(&writer->super, NULL);
868
affile_dd_init(LogPipe *s)
870
AFFileDestDriver *self = (AFFileDestDriver *) s;
871
GlobalConfig *cfg = log_pipe_get_config(s);
873
if (!log_dest_driver_init_method(s))
876
if (cfg->create_dirs)
877
self->flags |= AFFILE_CREATE_DIRS;
878
if (self->file_uid == -1)
879
self->file_uid = cfg->file_uid;
880
if (self->file_gid == -1)
881
self->file_gid = cfg->file_gid;
882
if (self->file_perm == -1)
883
self->file_perm = cfg->file_perm;
884
if (self->dir_uid == -1)
885
self->dir_uid = cfg->dir_uid;
886
if (self->dir_gid == -1)
887
self->dir_gid = cfg->dir_gid;
888
if (self->dir_perm == -1)
889
self->dir_perm = cfg->dir_perm;
890
if (self->time_reap == -1)
891
self->time_reap = cfg->time_reap;
893
log_writer_options_init(&self->writer_options, cfg, 0);
894
log_template_options_init(&self->template_fname_options, cfg);
896
if ((self->flags & AFFILE_NO_EXPAND) == 0)
898
self->writer_hash = cfg_persist_config_fetch(cfg, affile_dd_format_persist_name(self));
899
if (self->writer_hash)
900
g_hash_table_foreach(self->writer_hash, affile_dd_reuse_writer, self);
904
self->single_writer = cfg_persist_config_fetch(cfg, affile_dd_format_persist_name(self));
905
if (self->single_writer)
907
affile_dw_set_owner(self->single_writer, self);
908
log_pipe_init(&self->single_writer->super, cfg);
918
* This is registered as a destroy-notify callback for an AFFileDestWriter
919
* instance. It destructs and frees the writer instance.
922
affile_dd_destroy_writer(gpointer value)
924
AFFileDestWriter *writer = (AFFileDestWriter *) value;
926
main_loop_assert_main_thread();
927
log_pipe_deinit(&writer->super);
928
log_pipe_unref(&writer->super);
932
* This function is called as a g_hash_table_foreach_remove() callback to
933
* free the specific AFFileDestWriter instance in the hashtable.
936
affile_dd_destroy_writer_hr(gpointer key, gpointer value, gpointer user_data)
938
affile_dd_destroy_writer(value);
943
* affile_dd_destroy_writer_hash:
944
* @value: GHashTable instance passed as a generic pointer
946
* Destroy notify callback for the GHashTable storing AFFileDestWriter instances.
949
affile_dd_destroy_writer_hash(gpointer value)
951
GHashTable *writer_hash = (GHashTable *) value;
953
g_hash_table_foreach_remove(writer_hash, affile_dd_destroy_writer_hr, NULL);
954
g_hash_table_destroy(writer_hash);
958
affile_dd_deinit_writer(gpointer key, gpointer value, gpointer user_data)
960
log_pipe_deinit((LogPipe *) value);
964
affile_dd_deinit(LogPipe *s)
966
AFFileDestDriver *self = (AFFileDestDriver *) s;
967
GlobalConfig *cfg = log_pipe_get_config(s);
968
/* NOTE: we free all AFFileDestWriter instances here as otherwise we'd
969
* have circular references between AFFileDestDriver and file writers */
970
if (self->single_writer)
972
g_assert(self->writer_hash == NULL);
974
log_pipe_deinit(&self->single_writer->super);
975
cfg_persist_config_add(cfg, affile_dd_format_persist_name(self), self->single_writer, affile_dd_destroy_writer, FALSE);
976
self->single_writer = NULL;
978
else if (self->writer_hash)
980
g_assert(self->single_writer == NULL);
982
g_hash_table_foreach(self->writer_hash, affile_dd_deinit_writer, NULL);
983
cfg_persist_config_add(cfg, affile_dd_format_persist_name(self), self->writer_hash, affile_dd_destroy_writer_hash, FALSE);
984
self->writer_hash = NULL;
987
if (!log_dest_driver_deinit_method(s))
994
* This function is ran in the main thread whenever a writer is not yet
995
* instantiated. Returns a reference to the newly constructed LogPipe
996
* instance where the caller needs to forward its message.
999
affile_dd_open_writer(gpointer args[])
1001
AFFileDestDriver *self = args[0];
1002
GlobalConfig *cfg = log_pipe_get_config(&self->super.super.super);
1003
AFFileDestWriter *next;
1005
main_loop_assert_main_thread();
1006
if (self->flags & AFFILE_NO_EXPAND)
1008
if (!self->single_writer)
1010
next = affile_dw_new(self, self->filename_template->template);
1011
if (next && log_pipe_init(&next->super, cfg))
1013
log_pipe_ref(&next->super);
1014
g_static_mutex_lock(&self->lock);
1015
self->single_writer = next;
1016
g_static_mutex_unlock(&self->lock);
1020
log_pipe_unref(&next->super);
1026
next = self->single_writer;
1027
log_pipe_ref(&next->super);
1032
GString *filename = args[1];
1034
/* hash table construction is serialized, as we only do that in the main thread. */
1035
if (!self->writer_hash)
1036
self->writer_hash = g_hash_table_new(g_str_hash, g_str_equal);
1038
/* we don't need to lock the hashtable as it is only written in
1039
* the main thread, which we're running right now. lookups in
1040
* other threads must be locked. writers must be locked even in
1041
* this thread to exclude lookups in other threads. */
1043
next = g_hash_table_lookup(self->writer_hash, filename->str);
1046
next = affile_dw_new(self, filename->str);
1047
if (!log_pipe_init(&next->super, cfg))
1049
log_pipe_unref(&next->super);
1054
log_pipe_ref(&next->super);
1055
g_static_mutex_lock(&self->lock);
1056
g_hash_table_insert(self->writer_hash, next->filename, next);
1057
g_static_mutex_unlock(&self->lock);
1062
log_pipe_ref(&next->super);
1068
next->queue_pending = TRUE;
1069
/* we're returning a reference */
1070
return &next->super;
1076
affile_dd_queue(LogPipe *s, LogMessage *msg, const LogPathOptions *path_options, gpointer user_data)
1078
AFFileDestDriver *self = (AFFileDestDriver *) s;
1079
AFFileDestWriter *next;
1080
gpointer args[2] = { self, NULL };
1082
if (self->flags & AFFILE_NO_EXPAND)
1084
/* no need to lock the check below, the worst case that happens is
1085
* that we go to the mainloop to return the same information, but this
1086
* is not fast path anyway */
1088
g_static_mutex_lock(&self->lock);
1089
if (!self->single_writer)
1091
g_static_mutex_unlock(&self->lock);
1092
next = main_loop_call((void *(*)(void *)) affile_dd_open_writer, args, TRUE);
1096
/* we need to lock single_writer in order to get a reference and
1097
* make sure it is not a stale pointer by the time we ref it */
1098
next = self->single_writer;
1099
next->queue_pending = TRUE;
1100
log_pipe_ref(&next->super);
1101
g_static_mutex_unlock(&self->lock);
1108
filename = g_string_sized_new(32);
1109
log_template_format(self->filename_template, msg, &self->template_fname_options, LTZ_LOCAL, 0, NULL, filename);
1111
g_static_mutex_lock(&self->lock);
1112
if (self->writer_hash)
1113
next = g_hash_table_lookup(self->writer_hash, filename->str);
1119
log_pipe_ref(&next->super);
1120
next->queue_pending = TRUE;
1121
g_static_mutex_unlock(&self->lock);
1125
g_static_mutex_unlock(&self->lock);
1127
next = main_loop_call((void *(*)(void *)) affile_dd_open_writer, args, TRUE);
1129
g_string_free(filename, TRUE);
1133
log_pipe_queue(&next->super, msg, path_options);
1134
next->queue_pending = FALSE;
1135
log_pipe_unref(&next->super);
1138
log_msg_drop(msg, path_options);
1142
affile_dd_free(LogPipe *s)
1144
AFFileDestDriver *self = (AFFileDestDriver *) s;
1146
/* NOTE: this must be NULL as deinit has freed it, otherwise we'd have circular references */
1147
g_assert(self->single_writer == NULL && self->writer_hash == NULL);
1149
log_template_options_destroy(&self->template_fname_options);
1150
log_template_unref(self->filename_template);
1151
log_writer_options_destroy(&self->writer_options);
1152
log_dest_driver_free(s);
1156
affile_dd_new(gchar *filename, guint32 flags)
1158
AFFileDestDriver *self = g_new0(AFFileDestDriver, 1);
1160
log_dest_driver_init_instance(&self->super);
1161
self->super.super.super.init = affile_dd_init;
1162
self->super.super.super.deinit = affile_dd_deinit;
1163
self->super.super.super.queue = affile_dd_queue;
1164
self->super.super.super.free_fn = affile_dd_free;
1165
self->filename_template = log_template_new(configuration, NULL);
1166
log_template_compile(self->filename_template, filename, NULL);
1167
self->flags = flags;
1168
self->file_uid = self->file_gid = -1;
1169
self->file_perm = -1;
1170
self->dir_uid = self->dir_gid = -1;
1171
self->dir_perm = -1;
1172
log_writer_options_defaults(&self->writer_options);
1173
if (strchr(filename, '$') == NULL)
1175
self->flags |= AFFILE_NO_EXPAND;
1177
self->time_reap = -1;
1178
log_template_options_defaults(&self->template_fname_options);
1179
g_static_mutex_init(&self->lock);
1180
return &self->super.super;