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"
26 int LogLevel
= DEBUG_NOTICE
;
27 int this_log_level
= 0;
31 #define MAX_LOG_SIZE 128
33 static int first_entry
= 0;
34 static int ringbuf_count
= 0;
36 struct ctdb_log_entry
{
39 char message
[MAX_LOG_SIZE
];
43 static struct ctdb_log_entry
*log_entries
;
46 * this function logs all messages for all levels to a ringbuffer
48 static void log_ringbuffer_v(const char *format
, va_list ap
)
53 if (log_entries
== NULL
&& log_ringbuf_size
!= 0) {
54 /* Hope this works. We cant log anything if it doesnt anyway */
55 log_entries
= malloc(sizeof(struct ctdb_log_entry
) * log_ringbuf_size
);
57 if (log_entries
== NULL
) {
61 next_entry
= (first_entry
+ ringbuf_count
) % log_ringbuf_size
;
63 if (ringbuf_count
> 0 && first_entry
== next_entry
) {
64 first_entry
= (first_entry
+ 1) % log_ringbuf_size
;
67 log_entries
[next_entry
].message
[0] = '\0';
69 ret
= vsnprintf(&log_entries
[next_entry
].message
[0], MAX_LOG_SIZE
, format
, ap
);
73 /* Log messages longer than MAX_LOG_SIZE are truncated to MAX_LOG_SIZE-1
74 * bytes. In that case, add a newline.
76 if (ret
>= MAX_LOG_SIZE
) {
77 log_entries
[next_entry
].message
[MAX_LOG_SIZE
-2] = '\n';
80 log_entries
[next_entry
].level
= this_log_level
;
81 log_entries
[next_entry
].t
= timeval_current();
83 if (ringbuf_count
< log_ringbuf_size
) {
88 void log_ringbuffer(const char *format
, ...)
93 log_ringbuffer_v(format
, ap
);
97 void ctdb_log_ringbuffer_free(void)
99 if (log_entries
!= NULL
) {
103 log_ringbuf_size
= 0;
106 TDB_DATA
ctdb_log_ringbuffer_collect_log(TALLOC_CTX
*mem_ctx
,
107 enum debug_level max_level
)
117 DEBUG(DEBUG_ERR
,("Marshalling %d log entries\n", ringbuf_count
));
119 /* dump to a file, then send the file as a blob */
122 DEBUG(DEBUG_ERR
,(__location__
" Unable to open tmpfile - %s\n",
127 for (i
=0; i
<ringbuf_count
; i
++) {
128 tmp_entry
= (first_entry
+ i
) % log_ringbuf_size
;
130 if (log_entries
[tmp_entry
].level
> max_level
) {
134 tm
= localtime(&log_entries
[tmp_entry
].t
.tv_sec
);
135 strftime(tbuf
, sizeof(tbuf
)-1,"%Y/%m/%d %H:%M:%S", tm
);
137 if (log_entries
[tmp_entry
].message
[0] != '\0') {
138 fprintf(f
, "%s:%s %s", tbuf
,
139 get_debug_by_level(log_entries
[tmp_entry
].level
),
140 log_entries
[tmp_entry
].message
);
147 DEBUG(DEBUG_ERR
, ("Cannot get file size for log entries\n"));
151 data
.dptr
= talloc_size(NULL
, fsize
);
152 if (data
.dptr
== NULL
) {
154 DEBUG(DEBUG_ERR
, (__location__
" Memory allocation error\n"));
157 data
.dsize
= fread(data
.dptr
, 1, fsize
, f
);
160 DEBUG(DEBUG_ERR
,("Marshalling log entries into a blob of %d bytes\n", (int)data
.dsize
));
165 void ctdb_clear_log(struct ctdb_context
*ctdb
)
171 int32_t ctdb_control_clear_log(struct ctdb_context
*ctdb
)
173 ctdb_clear_log(ctdb
);
178 struct debug_levels debug_levels
[] = {
179 {DEBUG_EMERG
, "EMERG"},
180 {DEBUG_ALERT
, "ALERT"},
181 {DEBUG_CRIT
, "CRIT"},
183 {DEBUG_WARNING
, "WARNING"},
184 {DEBUG_NOTICE
, "NOTICE"},
185 {DEBUG_INFO
, "INFO"},
186 {DEBUG_DEBUG
, "DEBUG"},
190 const char *get_debug_by_level(int32_t level
)
194 for (i
=0; debug_levels
[i
].description
!= NULL
; i
++) {
195 if (debug_levels
[i
].level
== level
) {
196 return debug_levels
[i
].description
;
202 int32_t get_debug_by_desc(const char *desc
)
206 for (i
=0; debug_levels
[i
].description
!= NULL
; i
++) {
207 if (!strcasecmp(debug_levels
[i
].description
, desc
)) {
208 return debug_levels
[i
].level
;