fixed two 64bit warnings
[sahlberg/ctdb.git] / server / ctdb_logging.c
1 /* 
2    ctdb logging code
3
4    Copyright (C) Andrew Tridgell  2008
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "lib/events/events.h"
22 #include "../include/ctdb_private.h"
23 #include "system/syslog.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26
27 struct ctdb_log_state {
28         char *logfile;
29         int fd, pfd;
30         char buf[1024];
31         uint16_t buf_used;
32         bool use_syslog;
33 };
34
35 /* we need this global to eep the DEBUG() syntax */
36 static struct ctdb_log_state *log_state;
37
38 /*
39   syslog logging function
40  */
41 static void ctdb_syslog_log(const char *format, va_list ap)
42 {
43         vsyslog(LOG_NOTICE, format, ap);
44 }
45
46
47 /*
48   log file logging function
49  */
50 static void ctdb_logfile_log(const char *format, va_list ap)
51 {
52         struct timeval t;
53         char *s = NULL;
54         struct tm *tm;
55         char tbuf[100];
56
57         vasprintf(&s, format, ap);
58
59         t = timeval_current();
60         tm = localtime(&t.tv_sec);
61
62         strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);
63
64         dprintf(log_state->fd, "%s.%06u [%5u]: %s", 
65                 tbuf, (unsigned)t.tv_usec, (unsigned)getpid(), s);
66         free(s);        
67 }
68
69 /*
70   choose the logfile location
71 */
72 int ctdb_set_logfile(struct ctdb_context *ctdb, const char *logfile, bool use_syslog)
73 {
74         ctdb->log = talloc_zero(ctdb, struct ctdb_log_state);
75
76         log_state = ctdb->log;
77
78         if (use_syslog) {
79                 do_debug_v = ctdb_syslog_log;
80                 ctdb->log->use_syslog = true;
81         } else if (logfile == NULL || strcmp(logfile, "-") == 0) {
82                 do_debug_v = ctdb_logfile_log;
83                 ctdb->log->fd = 1;
84                 /* also catch stderr of subcommands to stdout */
85                 dup2(1, 2);
86         } else {
87                 do_debug_v = ctdb_logfile_log;
88                 ctdb->log->logfile = talloc_strdup(ctdb, logfile);
89
90                 ctdb->log->fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666);
91                 if (ctdb->log->fd == -1) {
92                         printf("Failed to open logfile %s\n", ctdb->logfile);
93                         abort();
94                 }
95         }
96
97         return 0;
98 }
99
100
101
102 /*
103   called when log data comes in from a child process
104  */
105 static void ctdb_log_handler(struct event_context *ev, struct fd_event *fde, 
106                              uint16_t flags, void *private)
107 {
108         struct ctdb_context *ctdb = talloc_get_type(private, struct ctdb_context);
109         ssize_t n;
110         char *p;
111
112         if (!(flags & EVENT_FD_READ)) {
113                 return;
114         }
115         
116         n = read(ctdb->log->pfd, &ctdb->log->buf[ctdb->log->buf_used],
117                  sizeof(ctdb->log->buf) - ctdb->log->buf_used);
118         if (n > 0) {
119                 ctdb->log->buf_used += n;
120         }
121
122         if (ctdb->log->buf_used == sizeof(ctdb->log->buf)) {
123                 do_debug("%*.*s\n", 
124                          (int)ctdb->log->buf_used, (int)ctdb->log->buf_used, ctdb->log->buf);
125                 ctdb->log->buf_used = 0;
126                 return;
127         }
128
129         p = memchr(ctdb->log->buf, '\n', ctdb->log->buf_used);
130         if (!p) {
131                 return;
132         }
133
134         n = (p - ctdb->log->buf)+1;
135         do_debug("%*.*s", (int)n, (int)n, ctdb->log->buf);
136         memmove(ctdb->log->buf, ctdb->log->buf+n, sizeof(ctdb->log->buf) - n);
137         ctdb->log->buf_used -= n;
138 }
139
140
141
142 /*
143   setup for logging of child process stdout
144 */
145 int ctdb_set_child_logging(struct ctdb_context *ctdb)
146 {
147         int p[2];
148
149         if (ctdb->log->fd == 1) {
150                 /* not needed for stdout logging */
151                 return 0;
152         }
153
154         /* setup a pipe to catch IO from subprocesses */
155         if (pipe(p) != 0) {
156                 DEBUG(0,(__location__ " Failed to setup for child logging pipe\n"));
157                 return -1;
158         }
159
160         event_add_fd(ctdb->ev, ctdb, p[0], EVENT_FD_READ, 
161                      ctdb_log_handler, ctdb);
162         set_close_on_exec(p[0]);
163         ctdb->log->pfd = p[0];
164
165         close(1);
166         close(2);
167         if (p[1] != 1) {
168                 dup2(p[1], 1);
169                 close(p[1]);
170         }
171         /* also catch stderr of subcommands to the log */
172         dup2(1, 2);
173
174         return 0;
175 }