1/* -*- c-basic-offset: 2 -*- */
2/*
3 Copyright(C) 2009-2017 Brazil
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License version 2.1 as published by the Free Software Foundation.
8
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.
13
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 Street, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "grn_logger.h"
20#include "grn_ctx.h"
21#include "grn_ctx_impl.h"
22
23#include <stdio.h>
24#include <string.h>
25#include <sys/stat.h>
26
27#ifdef WIN32
28# include <share.h>
29#endif /* WIN32 */
30
31static const char *log_level_names[] = {
32 "none",
33 "emergency",
34 "alert",
35 "critical",
36 "error",
37 "warning",
38 "notice",
39 "info",
40 "debug",
41 "dump"
42};
43
44#define GRN_LOG_LAST GRN_LOG_DUMP
45
46const char *
47grn_log_level_to_string(grn_log_level level)
48{
49 if (level <= GRN_LOG_LAST) {
50 return log_level_names[level];
51 } else {
52 return "unknown";
53 }
54}
55
56grn_bool
57grn_log_level_parse(const char *string, grn_log_level *level)
58{
59 if (strcmp(string, " ") == 0 ||
60 grn_strcasecmp(string, "none") == 0) {
61 *level = GRN_LOG_NONE;
62 return GRN_TRUE;
63 } else if (strcmp(string, "E") == 0 ||
64 grn_strcasecmp(string, "emerg") == 0 ||
65 grn_strcasecmp(string, "emergency") == 0) {
66 *level = GRN_LOG_EMERG;
67 return GRN_TRUE;
68 } else if (strcmp(string, "A") == 0 ||
69 grn_strcasecmp(string, "alert") == 0) {
70 *level = GRN_LOG_ALERT;
71 return GRN_TRUE;
72 } else if (strcmp(string, "C") == 0 ||
73 grn_strcasecmp(string, "crit") == 0 ||
74 grn_strcasecmp(string, "critical") == 0) {
75 *level = GRN_LOG_CRIT;
76 return GRN_TRUE;
77 } else if (strcmp(string, "e") == 0 ||
78 grn_strcasecmp(string, "error") == 0) {
79 *level = GRN_LOG_ERROR;
80 return GRN_TRUE;
81 } else if (strcmp(string, "w") == 0 ||
82 grn_strcasecmp(string, "warn") == 0 ||
83 grn_strcasecmp(string, "warning") == 0) {
84 *level = GRN_LOG_WARNING;
85 return GRN_TRUE;
86 } else if (strcmp(string, "n") == 0 ||
87 grn_strcasecmp(string, "notice") == 0) {
88 *level = GRN_LOG_NOTICE;
89 return GRN_TRUE;
90 } else if (strcmp(string, "i") == 0 ||
91 grn_strcasecmp(string, "info") == 0) {
92 *level = GRN_LOG_INFO;
93 return GRN_TRUE;
94 } else if (strcmp(string, "d") == 0 ||
95 grn_strcasecmp(string, "debug") == 0) {
96 *level = GRN_LOG_DEBUG;
97 return GRN_TRUE;
98 } else if (strcmp(string, "-") == 0 ||
99 grn_strcasecmp(string, "dump") == 0) {
100 *level = GRN_LOG_DUMP;
101 return GRN_TRUE;
102 } else {
103 return GRN_FALSE;
104 }
105}
106
107static void
108rotate_log_file(grn_ctx *ctx, const char *current_path)
109{
110 char rotated_path[PATH_MAX];
111 grn_timeval now;
112 struct tm tm_buffer;
113 struct tm *tm;
114
115 grn_timeval_now(ctx, &now);
116 tm = grn_timeval2tm(ctx, &now, &tm_buffer);
117 grn_snprintf(rotated_path, PATH_MAX, PATH_MAX,
118 "%s.%04d-%02d-%02d-%02d-%02d-%02d-%06d",
119 current_path,
120 tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
121 tm->tm_hour, tm->tm_min, tm->tm_sec,
122 (int)(GRN_TIME_NSEC_TO_USEC(now.tv_nsec)));
123 rename(current_path, rotated_path);
124}
125
126static grn_bool logger_inited = GRN_FALSE;
127static char *default_logger_path = NULL;
128static FILE *default_logger_file = NULL;
129static grn_critical_section default_logger_lock;
130static off_t default_logger_size = 0;
131static off_t default_logger_rotate_threshold_size = 0;
132
133#define LOGGER_NEED_ROTATE(size, threshold) \
134 ((threshold) > 0 && (size) >= (threshold))
135
136static void
137default_logger_log(grn_ctx *ctx, grn_log_level level,
138 const char *timestamp, const char *title,
139 const char *message, const char *location, void *user_data)
140{
141 const char slev[] = " EACewnid-";
142 if (default_logger_path) {
143 CRITICAL_SECTION_ENTER(default_logger_lock);
144 if (!default_logger_file) {
145 default_logger_file = grn_fopen(default_logger_path, "a");
146 default_logger_size = 0;
147 if (default_logger_file) {
148 struct stat stat;
149 if (fstat(grn_fileno(default_logger_file), &stat) != -1) {
150 default_logger_size = stat.st_size;
151 }
152 }
153 }
154 if (default_logger_file) {
155 char label = *(slev + level);
156 int written;
157 if (location && *location) {
158 if (title && *title) {
159 written = fprintf(default_logger_file, "%s|%c|%s: %s %s\n",
160 timestamp, label, location, title, message);
161 } else {
162 written = fprintf(default_logger_file, "%s|%c|%s: %s\n",
163 timestamp, label, location, message);
164 }
165 } else {
166 written = fprintf(default_logger_file, "%s|%c|%s %s\n",
167 timestamp, label, title, message);
168 }
169 if (written > 0) {
170 default_logger_size += written;
171 if (LOGGER_NEED_ROTATE(default_logger_size,
172 default_logger_rotate_threshold_size)) {
173 fclose(default_logger_file);
174 default_logger_file = NULL;
175 rotate_log_file(ctx, default_logger_path);
176 } else {
177 fflush(default_logger_file);
178 }
179 }
180 }
181 CRITICAL_SECTION_LEAVE(default_logger_lock);
182 }
183}
184
185static void
186default_logger_reopen(grn_ctx *ctx, void *user_data)
187{
188 GRN_LOG(ctx, GRN_LOG_NOTICE, "log will be closed.");
189 CRITICAL_SECTION_ENTER(default_logger_lock);
190 if (default_logger_file) {
191 fclose(default_logger_file);
192 default_logger_file = NULL;
193 }
194 CRITICAL_SECTION_LEAVE(default_logger_lock);
195 GRN_LOG(ctx, GRN_LOG_NOTICE, "log opened.");
196}
197
198static void
199default_logger_fin(grn_ctx *ctx, void *user_data)
200{
201 CRITICAL_SECTION_ENTER(default_logger_lock);
202 if (default_logger_file) {
203 fclose(default_logger_file);
204 default_logger_file = NULL;
205 }
206 CRITICAL_SECTION_LEAVE(default_logger_lock);
207}
208
209static grn_logger default_logger = {
210 GRN_LOG_DEFAULT_LEVEL,
211 GRN_LOG_TIME|GRN_LOG_MESSAGE,
212 NULL,
213 default_logger_log,
214 default_logger_reopen,
215 default_logger_fin
216};
217
218#define INITIAL_LOGGER { \
219 GRN_LOG_DEFAULT_LEVEL, \
220 GRN_LOG_TIME|GRN_LOG_MESSAGE, \
221 NULL, \
222 NULL, \
223 NULL, \
224 NULL \
225}
226
227static grn_logger current_logger = INITIAL_LOGGER;
228
229void
230grn_default_logger_set_max_level(grn_log_level max_level)
231{
232 default_logger.max_level = max_level;
233 if (current_logger.log == default_logger_log) {
234 current_logger.max_level = max_level;
235 }
236}
237
238grn_log_level
239grn_default_logger_get_max_level(void)
240{
241 return default_logger.max_level;
242}
243
244void
245grn_default_logger_set_flags(int flags)
246{
247 default_logger.flags = flags;
248 if (current_logger.log == default_logger_log) {
249 current_logger.flags = flags;
250 }
251}
252
253int
254grn_default_logger_get_flags(void)
255{
256 return default_logger.flags;
257}
258
259void
260grn_default_logger_set_path(const char *path)
261{
262 if (logger_inited) {
263 CRITICAL_SECTION_ENTER(default_logger_lock);
264 }
265
266 if (default_logger_path) {
267 free(default_logger_path);
268 }
269
270 if (path) {
271 default_logger_path = grn_strdup_raw(path);
272 } else {
273 default_logger_path = NULL;
274 }
275
276 if (logger_inited) {
277 CRITICAL_SECTION_LEAVE(default_logger_lock);
278 }
279}
280
281const char *
282grn_default_logger_get_path(void)
283{
284 return default_logger_path;
285}
286
287void
288grn_default_logger_set_rotate_threshold_size(off_t threshold)
289{
290 default_logger_rotate_threshold_size = threshold;
291}
292
293off_t
294grn_default_logger_get_rotate_threshold_size(void)
295{
296 return default_logger_rotate_threshold_size;
297}
298
299void
300grn_logger_reopen(grn_ctx *ctx)
301{
302 if (current_logger.reopen) {
303 current_logger.reopen(ctx, current_logger.user_data);
304 }
305}
306
307static void
308current_logger_fin(grn_ctx *ctx)
309{
310 if (current_logger.fin) {
311 current_logger.fin(ctx, current_logger.user_data);
312 }
313 {
314 grn_logger initial_logger = INITIAL_LOGGER;
315 current_logger = initial_logger;
316 }
317}
318
319static void
320logger_info_func_wrapper(grn_ctx *ctx, grn_log_level level,
321 const char *timestamp, const char *title,
322 const char *message, const char *location,
323 void *user_data)
324{
325 grn_logger_info *info = user_data;
326 info->func(level, timestamp, title, message, location, info->func_arg);
327}
328
329/* Deprecated since 2.1.2. */
330grn_rc
331grn_logger_info_set(grn_ctx *ctx, const grn_logger_info *info)
332{
333 if (info) {
334 grn_logger logger;
335
336 memset(&logger, 0, sizeof(grn_logger));
337 logger.max_level = info->max_level;
338 logger.flags = info->flags;
339 if (info->func) {
340 logger.log = logger_info_func_wrapper;
341 logger.user_data = (grn_logger_info *)info;
342 } else {
343 logger.log = default_logger_log;
344 logger.reopen = default_logger_reopen;
345 logger.fin = default_logger_fin;
346 }
347 return grn_logger_set(ctx, &logger);
348 } else {
349 return grn_logger_set(ctx, NULL);
350 }
351}
352
353grn_rc
354grn_logger_set(grn_ctx *ctx, const grn_logger *logger)
355{
356 current_logger_fin(ctx);
357 if (logger) {
358 current_logger = *logger;
359 } else {
360 current_logger = default_logger;
361 }
362 return GRN_SUCCESS;
363}
364
365void
366grn_logger_set_max_level(grn_ctx *ctx, grn_log_level max_level)
367{
368 current_logger.max_level = max_level;
369}
370
371grn_log_level
372grn_logger_get_max_level(grn_ctx *ctx)
373{
374 return current_logger.max_level;
375}
376
377grn_bool
378grn_logger_pass(grn_ctx *ctx, grn_log_level level)
379{
380 return level <= current_logger.max_level;
381}
382
383#define TBUFSIZE GRN_TIMEVAL_STR_SIZE
384#define MBUFSIZE 0x1000
385#define LBUFSIZE 0x400
386
387void
388grn_logger_put(grn_ctx *ctx,
389 grn_log_level level,
390 const char *file,
391 int line,
392 const char *func,
393 const char *fmt,
394 ...)
395{
396 va_list ap;
397 va_start(ap, fmt);
398 grn_logger_putv(ctx, level, file, line, func, fmt, ap);
399 va_end(ap);
400}
401
402void
403grn_logger_putv(grn_ctx *ctx,
404 grn_log_level level,
405 const char *file,
406 int line,
407 const char *func,
408 const char *fmt,
409 va_list ap)
410{
411 if (level <= current_logger.max_level && current_logger.log) {
412 char tbuf[TBUFSIZE];
413 char mbuf[MBUFSIZE];
414 char lbuf[LBUFSIZE];
415 tbuf[0] = '\0';
416 if (current_logger.flags & GRN_LOG_TIME) {
417 grn_timeval tv;
418 grn_timeval_now(ctx, &tv);
419 grn_timeval2str(ctx, &tv, tbuf, TBUFSIZE);
420 }
421 if (current_logger.flags & GRN_LOG_MESSAGE) {
422 grn_vsnprintf(mbuf, MBUFSIZE, fmt, ap);
423 } else {
424 mbuf[0] = '\0';
425 }
426 if (current_logger.flags & GRN_LOG_LOCATION) {
427 grn_snprintf(lbuf, LBUFSIZE, LBUFSIZE,
428 "%d %s:%d %s()", grn_getpid(), file, line, func);
429 } else if (current_logger.flags & GRN_LOG_PID) {
430 grn_snprintf(lbuf, LBUFSIZE, LBUFSIZE,
431 "%d", grn_getpid());
432 } else {
433 lbuf[0] = '\0';
434 }
435 current_logger.log(ctx, level, tbuf, "", mbuf, lbuf,
436 current_logger.user_data);
437 }
438}
439
440void
441grn_logger_init(void)
442{
443 CRITICAL_SECTION_INIT(default_logger_lock);
444 if (!current_logger.log) {
445 current_logger = default_logger;
446 }
447
448 logger_inited = GRN_TRUE;
449}
450
451void
452grn_logger_fin(grn_ctx *ctx)
453{
454 current_logger_fin(ctx);
455 if (default_logger_path) {
456 free(default_logger_path);
457 default_logger_path = NULL;
458 }
459 CRITICAL_SECTION_FIN(default_logger_lock);
460
461 logger_inited = GRN_FALSE;
462}
463
464
465static grn_bool query_logger_inited = GRN_FALSE;
466static char *default_query_logger_path = NULL;
467static FILE *default_query_logger_file = NULL;
468static grn_critical_section default_query_logger_lock;
469static off_t default_query_logger_size = 0;
470static off_t default_query_logger_rotate_threshold_size = 0;
471
472grn_bool
473grn_query_log_flags_parse(const char *string,
474 int string_size,
475 unsigned int *flags)
476{
477 const char *string_end;
478
479 *flags = GRN_QUERY_LOG_NONE;
480
481 if (!string) {
482 return GRN_TRUE;
483 }
484
485 if (string_size < 0) {
486 string_size = strlen(string);
487 }
488
489 string_end = string + string_size;
490
491 while (string < string_end) {
492 if (*string == '|' || *string == ' ') {
493 string += 1;
494 continue;
495 }
496
497#define CHECK_FLAG(name) \
498 if (((string_end - string) >= (sizeof(#name) - 1)) && \
499 (memcmp(string, #name, sizeof(#name) - 1) == 0) && \
500 (((string_end - string) == (sizeof(#name) - 1)) || \
501 (string[sizeof(#name) - 1] == '|') || \
502 (string[sizeof(#name) - 1] == ' '))) { \
503 *flags |= GRN_QUERY_LOG_ ## name; \
504 string += sizeof(#name) - 1; \
505 continue; \
506 }
507
508 CHECK_FLAG(NONE);
509 CHECK_FLAG(COMMAND);
510 CHECK_FLAG(RESULT_CODE);
511 CHECK_FLAG(DESTINATION);
512 CHECK_FLAG(CACHE);
513 CHECK_FLAG(SIZE);
514 CHECK_FLAG(SCORE);
515 CHECK_FLAG(ALL);
516 CHECK_FLAG(DEFAULT);
517
518#undef CHECK_FLAG
519
520 return GRN_FALSE;
521 }
522
523 return GRN_TRUE;
524}
525
526static void
527default_query_logger_log(grn_ctx *ctx, unsigned int flag,
528 const char *timestamp, const char *info,
529 const char *message, void *user_data)
530{
531 if (default_query_logger_path) {
532 CRITICAL_SECTION_ENTER(default_query_logger_lock);
533 if (!default_query_logger_file) {
534 default_query_logger_file = grn_fopen(default_query_logger_path, "a");
535 default_query_logger_size = 0;
536 if (default_query_logger_file) {
537 struct stat stat;
538 if (fstat(grn_fileno(default_query_logger_file), &stat) != -1) {
539 default_query_logger_size = stat.st_size;
540 }
541 }
542 }
543 if (default_query_logger_file) {
544 int written;
545 written = fprintf(default_query_logger_file, "%s|%s%s\n",
546 timestamp, info, message);
547 if (written > 0) {
548 default_query_logger_size += written;
549 if (LOGGER_NEED_ROTATE(default_query_logger_size,
550 default_query_logger_rotate_threshold_size)) {
551 fclose(default_query_logger_file);
552 default_query_logger_file = NULL;
553 rotate_log_file(ctx, default_query_logger_path);
554 } else {
555 fflush(default_query_logger_file);
556 }
557 }
558 }
559 CRITICAL_SECTION_LEAVE(default_query_logger_lock);
560 }
561}
562
563static void
564default_query_logger_close(grn_ctx *ctx, void *user_data)
565{
566 GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_DESTINATION, " ",
567 "query log will be closed: <%s>", default_query_logger_path);
568 CRITICAL_SECTION_ENTER(default_query_logger_lock);
569 if (default_query_logger_file) {
570 fclose(default_query_logger_file);
571 default_query_logger_file = NULL;
572 }
573 CRITICAL_SECTION_LEAVE(default_query_logger_lock);
574}
575
576static void
577default_query_logger_reopen(grn_ctx *ctx, void *user_data)
578{
579 default_query_logger_close(ctx, user_data);
580 if (default_query_logger_path) {
581 GRN_QUERY_LOG(ctx, GRN_QUERY_LOG_DESTINATION, " ",
582 "query log is opened: <%s>", default_query_logger_path);
583 }
584}
585
586static void
587default_query_logger_fin(grn_ctx *ctx, void *user_data)
588{
589 if (default_query_logger_file) {
590 default_query_logger_close(ctx, user_data);
591 }
592}
593
594static grn_query_logger default_query_logger = {
595 GRN_QUERY_LOG_DEFAULT,
596 NULL,
597 default_query_logger_log,
598 default_query_logger_reopen,
599 default_query_logger_fin
600};
601
602#define INITIAL_QUERY_LOGGER { \
603 GRN_QUERY_LOG_DEFAULT, \
604 NULL, \
605 NULL, \
606 NULL, \
607 NULL \
608}
609
610static grn_query_logger current_query_logger = INITIAL_QUERY_LOGGER;
611
612void
613grn_default_query_logger_set_flags(unsigned int flags)
614{
615 default_query_logger.flags = flags;
616 if (current_query_logger.log == default_query_logger_log) {
617 current_query_logger.flags = flags;
618 }
619}
620
621unsigned int
622grn_default_query_logger_get_flags(void)
623{
624 return default_query_logger.flags;
625}
626
627void
628grn_default_query_logger_set_path(const char *path)
629{
630 if (query_logger_inited) {
631 CRITICAL_SECTION_ENTER(default_query_logger_lock);
632 }
633
634 if (default_query_logger_path) {
635 free(default_query_logger_path);
636 }
637
638 if (path) {
639 default_query_logger_path = grn_strdup_raw(path);
640 } else {
641 default_query_logger_path = NULL;
642 }
643
644 if (query_logger_inited) {
645 CRITICAL_SECTION_LEAVE(default_query_logger_lock);
646 }
647}
648
649const char *
650grn_default_query_logger_get_path(void)
651{
652 return default_query_logger_path;
653}
654
655void
656grn_default_query_logger_set_rotate_threshold_size(off_t threshold)
657{
658 default_query_logger_rotate_threshold_size = threshold;
659}
660
661off_t
662grn_default_query_logger_get_rotate_threshold_size(void)
663{
664 return default_query_logger_rotate_threshold_size;
665}
666
667void
668grn_query_logger_reopen(grn_ctx *ctx)
669{
670 if (current_query_logger.reopen) {
671 current_query_logger.reopen(ctx, current_query_logger.user_data);
672 }
673}
674
675static void
676current_query_logger_fin(grn_ctx *ctx)
677{
678 if (current_query_logger.fin) {
679 current_query_logger.fin(ctx, current_query_logger.user_data);
680 }
681 {
682 grn_query_logger initial_query_logger = INITIAL_QUERY_LOGGER;
683 current_query_logger = initial_query_logger;
684 }
685}
686
687grn_rc
688grn_query_logger_set(grn_ctx *ctx, const grn_query_logger *logger)
689{
690 current_query_logger_fin(ctx);
691 if (logger) {
692 current_query_logger = *logger;
693 } else {
694 current_query_logger = default_query_logger;
695 }
696 return GRN_SUCCESS;
697}
698
699void
700grn_query_logger_set_flags(grn_ctx *ctx, unsigned int flags)
701{
702 current_query_logger.flags = flags;
703}
704
705void
706grn_query_logger_add_flags(grn_ctx *ctx, unsigned int flags)
707{
708 current_query_logger.flags |= flags;
709}
710
711void
712grn_query_logger_remove_flags(grn_ctx *ctx, unsigned int flags)
713{
714 current_query_logger.flags &= ~flags;
715}
716
717unsigned int
718grn_query_logger_get_flags(grn_ctx *ctx)
719{
720 return current_query_logger.flags;
721}
722
723grn_bool
724grn_query_logger_pass(grn_ctx *ctx, unsigned int flag)
725{
726 return current_query_logger.flags & flag;
727}
728
729#define TIMESTAMP_BUFFER_SIZE TBUFSIZE
730/* 8+a(%p) + 1(|) + 1(mark) + 15(elapsed time) = 25+a */
731#define INFO_BUFFER_SIZE 40
732
733void
734grn_query_logger_put(grn_ctx *ctx, unsigned int flag, const char *mark,
735 const char *format, ...)
736{
737 char timestamp[TIMESTAMP_BUFFER_SIZE];
738 char info[INFO_BUFFER_SIZE];
739 grn_obj *message = &ctx->impl->query_log_buf;
740
741 if (!current_query_logger.log) {
742 return;
743 }
744
745 {
746 grn_timeval tv;
747 timestamp[0] = '\0';
748 grn_timeval_now(ctx, &tv);
749 grn_timeval2str(ctx, &tv, timestamp, TIMESTAMP_BUFFER_SIZE);
750 }
751
752 if (flag & (GRN_QUERY_LOG_COMMAND | GRN_QUERY_LOG_DESTINATION)) {
753 grn_snprintf(info, INFO_BUFFER_SIZE, INFO_BUFFER_SIZE,
754 "%p|%s", ctx, mark);
755 info[INFO_BUFFER_SIZE - 1] = '\0';
756 } else {
757 grn_timeval tv;
758 uint64_t elapsed_time;
759 grn_timeval_now(ctx, &tv);
760 elapsed_time =
761 (uint64_t)(tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_NSEC_PER_SEC +
762 (tv.tv_nsec - ctx->impl->tv.tv_nsec);
763
764 grn_snprintf(info, INFO_BUFFER_SIZE, INFO_BUFFER_SIZE,
765 "%p|%s%015" GRN_FMT_INT64U " ", ctx, mark, elapsed_time);
766 info[INFO_BUFFER_SIZE - 1] = '\0';
767 }
768
769 {
770 va_list args;
771
772 va_start(args, format);
773 GRN_BULK_REWIND(message);
774 grn_text_vprintf(ctx, message, format, args);
775 va_end(args);
776 GRN_TEXT_PUTC(ctx, message, '\0');
777 }
778
779 current_query_logger.log(ctx, flag, timestamp, info, GRN_TEXT_VALUE(message),
780 current_query_logger.user_data);
781}
782
783void
784grn_query_logger_init(void)
785{
786 current_query_logger = default_query_logger;
787 CRITICAL_SECTION_INIT(default_query_logger_lock);
788
789 query_logger_inited = GRN_TRUE;
790}
791
792void
793grn_query_logger_fin(grn_ctx *ctx)
794{
795 current_query_logger_fin(ctx);
796 if (default_query_logger_path) {
797 free(default_query_logger_path);
798 default_query_logger_path = NULL;
799 }
800 CRITICAL_SECTION_FIN(default_query_logger_lock);
801
802 query_logger_inited = GRN_FALSE;
803}
804
805void
806grn_log_reopen(grn_ctx *ctx)
807{
808 grn_logger_reopen(ctx);
809 grn_query_logger_reopen(ctx);
810}
811