summaryrefslogtreecommitdiffstats
path: root/ctdb/server/ctdb_logging_file.c
blob: 09367f34881bf0fa35b2eb6f18748d6387a11946 (plain)
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
/*
   ctdb logging code

   Copyright (C) Andrew Tridgell  2008

   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/>.
*/

#include "includes.h"
#include "../include/ctdb_client.h"
#include "../include/ctdb_private.h"
#include "system/time.h"
#include "system/filesys.h"

struct file_state {
	int fd;
};

/*
  log file logging function
 */
static void ctdb_log_to_file(void *private_ptr, int dbglevel, const char *s)
{
	struct file_state *state = talloc_get_type(
		private_ptr, struct file_state);
	struct timeval t;
	struct tm *tm;
	char tbuf[100];
	char *s2 = NULL;
	int ret;

	t = timeval_current();
	tm = localtime(&t.tv_sec);

	strftime(tbuf,sizeof(tbuf)-1,"%Y/%m/%d %H:%M:%S", tm);

	ret = asprintf(&s2, "%s.%06u [%s%5u]: %s\n",
		       tbuf, (unsigned)t.tv_usec,
		       debug_extra, (unsigned)getpid(), s);
	if (ret == -1) {
		const char *errstr = "asprintf failed\n";
		sys_write(state->fd, errstr, strlen(errstr));
		return;
	}
	if (s2) {
		sys_write(state->fd, s2, strlen(s2));
		free(s2);
	}
}

static int file_state_destructor(struct file_state *state)
{
       close(state->fd);
       state->fd = -1;
       return 0;
}

int ctdb_log_setup_file(TALLOC_CTX *mem_ctx, const char *logfile)
{
	struct file_state *state;

	state = talloc_zero(mem_ctx, struct file_state);
	if (state == NULL) {
		return ENOMEM;
	}

	if (logfile == NULL || strcmp(logfile, "-") == 0) {
		int ret;

		state->fd = 1;
		/* also catch stderr of subcommands to stdout */
		ret = dup2(1, 2);
		if (ret == -1) {
			return errno;
		}
	} else {
		state->fd = open(logfile, O_WRONLY|O_APPEND|O_CREAT, 0666);
		if (state->fd == -1) {
			return errno;
		}
	}

	talloc_set_destructor(state, file_state_destructor);
	debug_set_callback(state, ctdb_log_to_file);

	return 0;
}