4 Copyright (C) Ronnie Sahlberg 2009
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.
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.
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/>.
22 #include "system/time.h"
23 #include "../include/ctdb_private.h"
24 #include "../include/ctdb_client.h"
28 #define MAX_LOG_SIZE 128
30 static int first_entry
= 0;
31 static int ringbuf_count
= 0;
33 struct ctdb_log_entry
{
36 char message
[MAX_LOG_SIZE
];
40 static struct ctdb_log_entry
*log_entries
;
43 * this function logs all messages for all levels to a ringbuffer
45 static void log_ringbuffer_v(const char *format
, va_list ap
)
50 if (log_entries
== NULL
&& log_ringbuf_size
!= 0) {
51 /* Hope this works. We cant log anything if it doesnt anyway */
52 log_entries
= malloc(sizeof(struct ctdb_log_entry
) * log_ringbuf_size
);
54 if (log_entries
== NULL
) {
58 next_entry
= (first_entry
+ ringbuf_count
) % log_ringbuf_size
;
60 if (ringbuf_count
> 0 && first_entry
== next_entry
) {
61 first_entry
= (first_entry
+ 1) % log_ringbuf_size
;
64 log_entries
[next_entry
].message
[0] = '\0';
66 ret
= vsnprintf(&log_entries
[next_entry
].message
[0], MAX_LOG_SIZE
, format
, ap
);
70 /* Log messages longer than MAX_LOG_SIZE are truncated to MAX_LOG_SIZE-1
71 * bytes. In that case, add a newline.
73 if (ret
>= MAX_LOG_SIZE
) {
74 log_entries
[next_entry
].message
[MAX_LOG_SIZE
-2] = '\n';
77 log_entries
[next_entry
].level
= this_log_level
;
78 log_entries
[next_entry
].t
= timeval_current();
80 if (ringbuf_count
< log_ringbuf_size
) {
85 void log_ringbuffer(const char *format
, ...)
90 log_ringbuffer_v(format
, ap
);
94 void ctdb_log_ringbuffer_free(void)
96 if (log_entries
!= NULL
) {
100 log_ringbuf_size
= 0;
103 void ctdb_collect_log(struct ctdb_context
*ctdb
, struct ctdb_get_log_addr
*log_addr
)
113 DEBUG(DEBUG_ERR
,("Marshalling %d log entries\n", ringbuf_count
));
115 /* dump to a file, then send the file as a blob */
118 DEBUG(DEBUG_ERR
,(__location__
" Unable to open tmpfile - %s\n", strerror(errno
)));
122 for (i
=0; i
<ringbuf_count
; i
++) {
123 tmp_entry
= (first_entry
+ i
) % log_ringbuf_size
;
125 if (log_entries
[tmp_entry
].level
> log_addr
->level
) {
129 tm
= localtime(&log_entries
[tmp_entry
].t
.tv_sec
);
130 strftime(tbuf
, sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
132 if (log_entries
[tmp_entry
].message
[0] != '\0') {
133 fprintf(f
, "%s:%s %s", tbuf
,
134 get_debug_by_level(log_entries
[tmp_entry
].level
),
135 log_entries
[tmp_entry
].message
);
142 DEBUG(DEBUG_ERR
, ("Cannot get file size for log entries\n"));
146 data
.dptr
= talloc_size(NULL
, fsize
);
147 if (data
.dptr
== NULL
) {
149 CTDB_NO_MEMORY_VOID(ctdb
, data
.dptr
);
151 data
.dsize
= fread(data
.dptr
, 1, fsize
, f
);
154 DEBUG(DEBUG_ERR
,("Marshalling log entries into a blob of %d bytes\n", (int)data
.dsize
));
156 DEBUG(DEBUG_ERR
,("Send log to %d:%d\n", (int)log_addr
->pnn
, (int)log_addr
->srvid
));
157 ctdb_client_send_message(ctdb
, log_addr
->pnn
, log_addr
->srvid
, data
);
159 talloc_free(data
.dptr
);
162 int32_t ctdb_control_get_log(struct ctdb_context
*ctdb
, TDB_DATA addr
)
164 struct ctdb_get_log_addr
*log_addr
= (struct ctdb_get_log_addr
*)addr
.dptr
;
167 /* spawn a child process to marshall the huge log blob and send it back
168 to the ctdb tool using a MESSAGE
170 child
= ctdb_fork_no_free_ringbuffer(ctdb
);
171 if (child
== (pid_t
)-1) {
172 DEBUG(DEBUG_ERR
,("Failed to fork a log collector child\n"));
177 ctdb_set_process_name("ctdb_log_collector");
178 if (switch_from_server_to_client(ctdb
, "log-collector") != 0) {
179 DEBUG(DEBUG_CRIT
, (__location__
"ERROR: failed to switch log collector child into client mode.\n"));
182 ctdb_collect_log(ctdb
, log_addr
);
189 void ctdb_clear_log(struct ctdb_context
*ctdb
)
195 int32_t ctdb_control_clear_log(struct ctdb_context
*ctdb
)
197 ctdb_clear_log(ctdb
);