2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 14:07:59 +00:00

isc_log_create now has three parameters, the additional one used to

return an isc_logconfig_t.  isc_log_cretechannel and isc_log_usechannel
now take an isc_logconfig_t instead of an isc_log_t; this is to address
reconfiguration in a multithreaded environment.

isc_logconfig_create, isc_logconfig_get, isc_logconfig_use and
isc_logconfig_destroy were added to work with the new isc_logconfig_t type.

isc_logregister_categories and dns_log_init are now both void rather than
returning isc_result_t.
This commit is contained in:
David Lawrence
2000-02-26 19:57:02 +00:00
parent 3dbea10f98
commit edcd1247ad
9 changed files with 396 additions and 247 deletions

View File

@@ -1028,6 +1028,7 @@ main(int argc, char *argv[]) {
signer_key_t *key; signer_key_t *key;
isc_result_t result; isc_result_t result;
isc_log_t *log = NULL; isc_log_t *log = NULL;
isc_logconfig_t *logconfig;
dns_result_register(); dns_result_register();
@@ -1107,11 +1108,11 @@ main(int argc, char *argv[]) {
} }
if (verbose > 0) { if (verbose > 0) {
RUNTIME_CHECK(isc_log_create(mctx, &log) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig)
RUNTIME_CHECK(dns_log_init(log) == ISC_R_SUCCESS); == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_log_usechannel(log, "default_stderr", dns_log_init(log);
RUNTIME_CHECK(isc_log_usechannel(logconfig, "default_stderr",
NULL, NULL) == ISC_R_SUCCESS); NULL, NULL) == ISC_R_SUCCESS);
dns_lctx = log;
} }
argc -= isc_commandline_index; argc -= isc_commandline_index;

View File

@@ -218,6 +218,7 @@ main(int argc, char **argv)
client_t *client; client_t *client;
isc_logdestination_t destination; isc_logdestination_t destination;
isc_log_t *lctx; isc_log_t *lctx;
isc_logconfig_t *lcfg;
UNUSED(argc); UNUSED(argc);
UNUSED(argv); UNUSED(argv);
@@ -235,21 +236,20 @@ main(int argc, char **argv)
* Set up logging. * Set up logging.
*/ */
lctx = NULL; lctx = NULL;
result = isc_log_create(mem, &lctx); result = isc_log_create(mem, &lctx, &lcfg);
INSIST(result == ISC_R_SUCCESS);
result = dns_log_init(lctx);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
dns_log_init(lctx);
destination.file.stream = stderr; destination.file.stream = stderr;
destination.file.name = NULL; destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0; destination.file.maximum_size = 0;
result = isc_log_createchannel(lctx, "_default", result = isc_log_createchannel(lcfg, "_default",
ISC_LOG_TOFILEDESC, ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC, ISC_LOG_DYNAMIC,
&destination, ISC_LOG_PRINTTIME); &destination, ISC_LOG_PRINTTIME);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
result = isc_log_usechannel(lctx, "_default", NULL, NULL); result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
INSIST(result == ISC_R_SUCCESS); INSIST(result == ISC_R_SUCCESS);
/* /*

View File

@@ -63,6 +63,7 @@ ns_log_init(void) {
isc_result_t result; isc_result_t result;
isc_logdestination_t destination; isc_logdestination_t destination;
unsigned int flags; unsigned int flags;
isc_logconfig_t *lcfg;
ns_g_categories = categories; ns_g_categories = categories;
ns_g_modules = modules; ns_g_modules = modules;
@@ -75,16 +76,13 @@ ns_log_init(void) {
/* /*
* Setup a logging context. * Setup a logging context.
*/ */
result = isc_log_create(ns_g_mctx, &ns_g_lctx); result = isc_log_create(ns_g_mctx, &ns_g_lctx, &lcfg);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
return (result); return (result);
result = isc_log_registercategories(ns_g_lctx, ns_g_categories);
if (result != ISC_R_SUCCESS) isc_log_registercategories(ns_g_lctx, ns_g_categories);
goto cleanup;
isc_log_registermodules(ns_g_lctx, ns_g_modules); isc_log_registermodules(ns_g_lctx, ns_g_modules);
result = dns_log_init(ns_g_lctx); dns_log_init(ns_g_lctx);
if (result != ISC_R_SUCCESS)
goto cleanup;
/* /*
* Create and install the default channel. * Create and install the default channel.
@@ -95,14 +93,14 @@ ns_log_init(void) {
destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0; destination.file.maximum_size = 0;
flags = ISC_LOG_PRINTTIME; flags = ISC_LOG_PRINTTIME;
result = isc_log_createchannel(ns_g_lctx, "_default", result = isc_log_createchannel(lcfg, "_default",
ISC_LOG_TOFILEDESC, ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC, ISC_LOG_DYNAMIC,
&destination, flags); &destination, flags);
} else { } else {
destination.facility = LOG_DAEMON; destination.facility = LOG_DAEMON;
flags = ISC_LOG_PRINTTIME; flags = ISC_LOG_PRINTTIME;
result = isc_log_createchannel(ns_g_lctx, "_default", result = isc_log_createchannel(lcfg, "_default",
ISC_LOG_TOSYSLOG, ISC_LOG_TOSYSLOG,
ISC_LOG_DYNAMIC, ISC_LOG_DYNAMIC,
&destination, flags); &destination, flags);
@@ -110,7 +108,7 @@ ns_log_init(void) {
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup; goto cleanup;
result = isc_log_usechannel(ns_g_lctx, "_default", NULL, NULL); result = isc_log_usechannel(lcfg, "_default", NULL, NULL);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
goto cleanup; goto cleanup;

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: log_test.c,v 1.7 2000/02/03 23:03:46 halley Exp $ */ /* $Id: log_test.c,v 1.8 2000/02/26 19:57:00 tale Exp $ */
/* Principal Authors: DCL */ /* Principal Authors: DCL */
@@ -44,19 +44,13 @@ char usage[] = "Usage: %s [-m] [-s syslog_logfile] [-r file_versions]\n";
progname, isc_result_totext(result)); \ progname, isc_result_totext(result)); \
} }
#define CHECK_DNS(expr) result = expr; \
if (result != DNS_R_SUCCESS) { \
fprintf(stderr, "%s: " #expr "%s: exiting\n", \
progname, dns_result_totext(result)); \
}
int int
main (int argc, char **argv) { main (int argc, char **argv) {
char *progname, *syslog_file, *message; char *progname, *syslog_file, *message;
int ch, i, file_versions; int ch, i, file_versions;
isc_boolean_t show_final_mem = ISC_FALSE; isc_boolean_t show_final_mem = ISC_FALSE;
isc_log_t *lctx; isc_log_t *lctx;
isc_logconfig_t *lcfg;
isc_mem_t *mctx; isc_mem_t *mctx;
isc_result_t result; isc_result_t result;
isc_logdestination_t destination; isc_logdestination_t destination;
@@ -113,8 +107,9 @@ main (int argc, char **argv) {
lctx = NULL; lctx = NULL;
CHECK_ISC(isc_mem_create(0, 0, &mctx)); CHECK_ISC(isc_mem_create(0, 0, &mctx));
CHECK_ISC(isc_log_create(mctx, &lctx)); CHECK_ISC(isc_log_create(mctx, &lctx, &lcfg));
CHECK_DNS(dns_log_init(lctx));
dns_log_init(lctx);
/* /*
* Create a file channel to test file opening, size limiting and * Create a file channel to test file opening, size limiting and
@@ -125,7 +120,7 @@ main (int argc, char **argv) {
destination.file.maximum_size = 1; destination.file.maximum_size = 1;
destination.file.versions = file_versions; destination.file.versions = file_versions;
CHECK_ISC(isc_log_createchannel(lctx, "file_test", ISC_LOG_TOFILE, CHECK_ISC(isc_log_createchannel(lcfg, "file_test", ISC_LOG_TOFILE,
ISC_LOG_INFO, &destination, ISC_LOG_INFO, &destination,
ISC_LOG_PRINTTIME| ISC_LOG_PRINTTIME|
ISC_LOG_PRINTLEVEL| ISC_LOG_PRINTLEVEL|
@@ -137,7 +132,7 @@ main (int argc, char **argv) {
*/ */
destination.file.stream = stderr; destination.file.stream = stderr;
CHECK_ISC(isc_log_createchannel(lctx, "debug_test", ISC_LOG_TOFILEDESC, CHECK_ISC(isc_log_createchannel(lcfg, "debug_test", ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC, &destination, ISC_LOG_DYNAMIC, &destination,
ISC_LOG_PRINTTIME| ISC_LOG_PRINTTIME|
ISC_LOG_PRINTLEVEL)); ISC_LOG_PRINTLEVEL));
@@ -145,27 +140,27 @@ main (int argc, char **argv) {
/* /*
* Test the usability of the four predefined logging channels. * Test the usability of the four predefined logging channels.
*/ */
CHECK_ISC(isc_log_usechannel(lctx, "default_syslog", CHECK_ISC(isc_log_usechannel(lcfg, "default_syslog",
DNS_LOGCATEGORY_DATABASE, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE)); DNS_LOGMODULE_CACHE));
CHECK_ISC(isc_log_usechannel(lctx, "default_stderr", CHECK_ISC(isc_log_usechannel(lcfg, "default_stderr",
DNS_LOGCATEGORY_DATABASE, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE)); DNS_LOGMODULE_CACHE));
CHECK_ISC(isc_log_usechannel(lctx, "default_debug", CHECK_ISC(isc_log_usechannel(lcfg, "default_debug",
DNS_LOGCATEGORY_DATABASE, DNS_LOGCATEGORY_DATABASE,
DNS_LOGMODULE_CACHE)); DNS_LOGMODULE_CACHE));
CHECK_ISC(isc_log_usechannel(lctx, "null", CHECK_ISC(isc_log_usechannel(lcfg, "null",
DNS_LOGCATEGORY_DATABASE, DNS_LOGCATEGORY_DATABASE,
NULL)); NULL));
/* /*
* Use the custom channels. * Use the custom channels.
*/ */
CHECK_ISC(isc_log_usechannel(lctx, "file_test", CHECK_ISC(isc_log_usechannel(lcfg, "file_test",
DNS_LOGCATEGORY_GENERAL, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_DB)); DNS_LOGMODULE_DB));
CHECK_ISC(isc_log_usechannel(lctx, "debug_test", CHECK_ISC(isc_log_usechannel(lcfg, "debug_test",
DNS_LOGCATEGORY_GENERAL, DNS_LOGCATEGORY_GENERAL,
DNS_LOGMODULE_RBTDB)); DNS_LOGMODULE_RBTDB));
@@ -199,7 +194,7 @@ main (int argc, char **argv) {
* Reset the internal default to use syslog instead of stderr, * Reset the internal default to use syslog instead of stderr,
* and test it. * and test it.
*/ */
CHECK_ISC(isc_log_usechannel(lctx, "default_syslog", CHECK_ISC(isc_log_usechannel(lcfg, "default_syslog",
ISC_LOGCATEGORY_DEFAULT, ISC_LOGCATEGORY_DEFAULT,
NULL)); NULL));
isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT, isc_log_write(lctx, DNS_LOGCATEGORY_SECURITY, DNS_LOGMODULE_RBT,
@@ -261,7 +256,7 @@ main (int argc, char **argv) {
/* /*
* Test out the duplicate filtering using the debug_test channel. * Test out the duplicate filtering using the debug_test channel.
*/ */
isc_log_setduplicateinterval(lctx, 10); isc_log_setduplicateinterval(lcfg, 10);
message = "This message should appear only once on stderr"; message = "This message should appear only once on stderr";
isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB, isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
@@ -269,7 +264,7 @@ main (int argc, char **argv) {
isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB, isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,
ISC_LOG_CRITICAL, message); ISC_LOG_CRITICAL, message);
isc_log_setduplicateinterval(lctx, 1); isc_log_setduplicateinterval(lcfg, 1);
message = "This message should appear twice on stderr"; message = "This message should appear twice on stderr";
isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB, isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB,

View File

@@ -1028,6 +1028,7 @@ main(int argc, char *argv[]) {
signer_key_t *key; signer_key_t *key;
isc_result_t result; isc_result_t result;
isc_log_t *log = NULL; isc_log_t *log = NULL;
isc_logconfig_t *logconfig;
dns_result_register(); dns_result_register();
@@ -1107,11 +1108,11 @@ main(int argc, char *argv[]) {
} }
if (verbose > 0) { if (verbose > 0) {
RUNTIME_CHECK(isc_log_create(mctx, &log) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig)
RUNTIME_CHECK(dns_log_init(log) == ISC_R_SUCCESS); == ISC_R_SUCCESS);
RUNTIME_CHECK(isc_log_usechannel(log, "default_stderr", dns_log_init(log);
RUNTIME_CHECK(isc_log_usechannel(logconfig, "default_stderr",
NULL, NULL) == ISC_R_SUCCESS); NULL, NULL) == ISC_R_SUCCESS);
dns_lctx = log;
} }
argc -= isc_commandline_index; argc -= isc_commandline_index;

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: log.h,v 1.11 2000/02/03 23:40:57 halley Exp $ */ /* $Id: log.h,v 1.12 2000/02/26 19:57:01 tale Exp $ */
/* Principal Authors: DCL */ /* Principal Authors: DCL */
@@ -58,7 +58,7 @@ extern isc_logmodule_t dns_modules[];
#define DNS_LOGMODULE_XFER_OUT (&dns_modules[14]) #define DNS_LOGMODULE_XFER_OUT (&dns_modules[14])
#define DNS_LOGMODULE_ACL (&dns_modules[15]) #define DNS_LOGMODULE_ACL (&dns_modules[15])
isc_result_t void
dns_log_init(isc_log_t *lctx); dns_log_init(isc_log_t *lctx);
/* /*
* Make the libdns.a categories and modules available for use with the * Make the libdns.a categories and modules available for use with the
@@ -70,20 +70,8 @@ dns_log_init(isc_log_t *lctx);
* dns_log_init() is called only once. * dns_log_init() is called only once.
* *
* Ensures: * Ensures:
* ISC_R_SUCCESS * The catgories and modules defined above are available for
* The catgories and modules defined above are available for * use by isc_log_usechannnel() and isc_log_write().
* use by isc_log_usechannnel() and isc_log_write().
*
* ISC_R_NOMEMORY
* The catgories and modules defined above are not available for
* use by isc_log_usechannnel() and isc_log_write(), and no
* additional memory is being used because of the call to
* dns_log_init().
*
*
* Returns:
* ISC_R_SUCCESS Success
* ISC_R_NOMEMORY Resource limit: Out of memory
*/ */
ISC_LANG_ENDDECLS ISC_LANG_ENDDECLS

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: log.c,v 1.13 2000/02/03 23:43:49 halley Exp $ */ /* $Id: log.c,v 1.14 2000/02/26 19:57:00 tale Exp $ */
/* Principal Authors: DCL */ /* Principal Authors: DCL */
@@ -68,18 +68,12 @@ isc_logmodule_t dns_modules[] = {
isc_log_t *dns_lctx; isc_log_t *dns_lctx;
isc_result_t void
dns_log_init(isc_log_t *lctx) { dns_log_init(isc_log_t *lctx) {
isc_result_t result;
REQUIRE(dns_lctx == NULL); REQUIRE(dns_lctx == NULL);
result = isc_log_registercategories(lctx, dns_categories); isc_log_registercategories(lctx, dns_categories);
isc_log_registermodules(lctx, dns_modules);
if (result == ISC_R_SUCCESS) { dns_lctx = lctx;
isc_log_registermodules(lctx, dns_modules);
dns_lctx = lctx;
}
return (result);
} }

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: log.h,v 1.8 2000/02/03 23:07:50 halley Exp $ */ /* $Id: log.h,v 1.9 2000/02/26 19:57:02 tale Exp $ */
#ifndef ISC_LOG_H #ifndef ISC_LOG_H
#define ISC_LOG_H 1 #define ISC_LOG_H 1
@@ -75,6 +75,11 @@ ISC_LANG_BEGINDECLS
*/ */
typedef struct isc_log isc_log_t; typedef struct isc_log isc_log_t;
/*
* Channel configuration. Details are internal to the implementation.
*/
typedef struct isc_logconfig isc_logconfig_t;
/* /*
* Used to name the categories used by a library. An array of isc_logcategory * Used to name the categories used by a library. An array of isc_logcategory
* structures names each category, and the id value is initialized by calling * structures names each category, and the id value is initialized by calling
@@ -138,7 +143,7 @@ extern isc_logcategory_t isc_categories[];
#define ISC_LOGCATEGORY_DEFAULT (&isc_categories[0]) #define ISC_LOGCATEGORY_DEFAULT (&isc_categories[0])
isc_result_t isc_result_t
isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp); isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp);
/* /*
* Establish a new logging context, with default channels. * Establish a new logging context, with default channels.
* *
@@ -167,6 +172,15 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp);
* ISC_R_UNEXPECTED The mutex lock could not be initialized. * ISC_R_UNEXPECTED The mutex lock could not be initialized.
*/ */
isc_result_t
isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp);
isc_logconfig_t *
isc_logconfig_get(isc_log_t *lctx);
isc_result_t
isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg);
void void
isc_log_destroy(isc_log_t **lctxp); isc_log_destroy(isc_log_t **lctxp);
/* /*
@@ -184,8 +198,10 @@ isc_log_destroy(isc_log_t **lctxp);
* The logging context is marked as invalid. * The logging context is marked as invalid.
*/ */
void
isc_logconfig_destroy(isc_logconfig_t **lcfgp);
isc_result_t void
isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]); isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]);
/* /*
* Identify logging categories a library will use. * Identify logging categories a library will use.
@@ -249,9 +265,9 @@ isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]);
*/ */
isc_result_t isc_result_t
isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
int level, isc_logdestination_t *destination, unsigned int type, int level,
unsigned int flags); isc_logdestination_t *destination, unsigned int flags);
/* /*
* Specify the parameters of a logging channel. * Specify the parameters of a logging channel.
* *
@@ -313,7 +329,7 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type,
*/ */
isc_result_t isc_result_t
isc_log_usechannel(isc_log_t *lctx, const char *name, isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
isc_logcategory_t *category, isc_logmodule_t *module); isc_logcategory_t *category, isc_logmodule_t *module);
/* /*
* Associate a named logging channel with a category and module that * Associate a named logging channel with a category and module that
@@ -502,7 +518,7 @@ isc_log_getdebuglevel(isc_log_t *lctx);
*/ */
void void
isc_log_setduplicateinterval(isc_log_t *lctx, unsigned int interval); isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval);
/* /*
* Set the interval over which duplicate log messages will be ignored * Set the interval over which duplicate log messages will be ignored
* by isc_log_[v]write1(), in seconds. * by isc_log_[v]write1(), in seconds.
@@ -525,7 +541,7 @@ isc_log_setduplicateinterval(isc_log_t *lctx, unsigned int interval);
*/ */
unsigned int unsigned int
isc_log_getduplicateinterval(isc_log_t *lctx); isc_log_getduplicateinterval(isc_logconfig_t *lcfg);
/* /*
* Get the current duplicate filtering interval. * Get the current duplicate filtering interval.
* *

View File

@@ -15,7 +15,7 @@
* SOFTWARE. * SOFTWARE.
*/ */
/* $Id: log.c,v 1.15 2000/02/03 23:08:25 halley Exp $ */ /* $Id: log.c,v 1.16 2000/02/26 19:57:01 tale Exp $ */
/* Principal Authors: DCL */ /* Principal Authors: DCL */
@@ -29,15 +29,19 @@
#include <isc/assertions.h> #include <isc/assertions.h>
#include <isc/boolean.h> #include <isc/boolean.h>
#include <isc/dir.h> #include <isc/dir.h>
#include <isc/error.h>
#include <isc/list.h> #include <isc/list.h>
#include <isc/log.h> #include <isc/log.h>
#include <isc/mem.h> #include <isc/mem.h>
#include <isc/mutex.h> #include <isc/mutex.h>
#include <isc/print.h> #include <isc/print.h>
#include <isc/time.h> #include <isc/time.h>
#include <isc/util.h>
#define LOG_MAGIC 0x494C4F47U /* ILOG. */ #define LCTX_MAGIC 0x4C637478U /* Lctx. */
#define VALID_CONTEXT(lctx) ((lctx) != NULL && (lctx)->magic == LOG_MAGIC) #define VALID_CONTEXT(lctx) ((lctx) != NULL && (lctx)->magic == LCTX_MAGIC)
#define LCFG_MAGIC 0x4C636667U /* Lcfg. */
#define VALID_CONFIG(lcfg) ((lcfg) != NULL && (lcfg)->magic == LCFG_MAGIC)
#define LOG_BUFFER_SIZE (8 * 1024) #define LOG_BUFFER_SIZE (8 * 1024)
@@ -58,6 +62,7 @@ struct isc_logchannel {
int level; int level;
unsigned int flags; unsigned int flags;
isc_logdestination_t destination; isc_logdestination_t destination;
/* XXXDCL should be an ISC_LINK, so this can be an ISC_LIST */
isc_logchannel_t * next; isc_logchannel_t * next;
}; };
@@ -74,6 +79,7 @@ typedef struct isc_logchannellist isc_logchannellist_t;
struct isc_logchannellist { struct isc_logchannellist {
isc_logmodule_t * module; isc_logmodule_t * module;
isc_logchannel_t * channel; isc_logchannel_t * channel;
/* XXXDCL should be an ISC_LINK, so this can be an ISC_LIST */
isc_logchannellist_t * next; isc_logchannellist_t * next;
}; };
@@ -84,14 +90,26 @@ struct isc_logchannellist {
typedef struct isc_logmessage isc_logmessage_t; typedef struct isc_logmessage isc_logmessage_t;
struct isc_logmessage { struct isc_logmessage {
char * text; char * text;
isc_time_t time; isc_time_t time;
isc_logmessage_t * next; ISC_LINK(isc_logmessage_t) link;
};
/*
* XXX describe
*/
struct isc_logconfig {
unsigned int magic;
isc_log_t * lctx;
isc_logchannel_t * channels;
isc_logchannellist_t ** channellists;
unsigned int channellist_count;
unsigned int duplicate_interval;
}; };
/* /*
* This isc_log structure provides the context for the isc_log functions. * This isc_log structure provides the context for the isc_log functions.
* The log context locks itself in isc_log_vwrite, the internal backend to * The log context locks itself in isc_log_doit, the internal backend to
* isc_log_write. The locking is necessary both to provide exclusive access * isc_log_write. The locking is necessary both to provide exclusive access
* to the the buffer into which the message is formatted and to guard against * to the the buffer into which the message is formatted and to guard against
* competing threads trying to write to the same syslog resource. (On * competing threads trying to write to the same syslog resource. (On
@@ -100,20 +118,24 @@ struct isc_logmessage {
* context in the same program competing for syslog's attention. Thus * context in the same program competing for syslog's attention. Thus
* There Can Be Only One, but this is not enforced. * There Can Be Only One, but this is not enforced.
* XXX enforce it? * XXX enforce it?
*
* Note that the category and module information is not locked.
* This is because in the usual case, only one isc_log_t is ever created
* in a program, and the category/module registration happens only once.
* XXX it might be wise to add more locking overall.
*/ */
struct isc_log { struct isc_log {
/* Not locked. */
unsigned int magic; unsigned int magic;
isc_mem_t * mctx; isc_mem_t * mctx;
isc_mutex_t lock;
char buffer[LOG_BUFFER_SIZE];
int debug_level;
unsigned int duplicate_interval;
isc_logchannel_t * channels;
isc_logchannellist_t ** categories;
unsigned int category_count; unsigned int category_count;
isc_logmodule_t ** modules;
unsigned int module_count; unsigned int module_count;
int debug_level;
char buffer[LOG_BUFFER_SIZE];
ISC_LIST(isc_logmessage_t) messages; ISC_LIST(isc_logmessage_t) messages;
isc_mutex_t lock;
/* Locked by isc_log lock. */
isc_logconfig_t * logconfig;
}; };
/* /*
@@ -133,9 +155,7 @@ static const int syslog_map[] = {
/* /*
* When adding new categories, a corresponding ISC_LOGCATEGORY_foo * When adding new categories, a corresponding ISC_LOGCATEGORY_foo
* definition needs to be added to <isc/log.h>. Each name string should * definition needs to be added to <isc/log.h>.
* end with a colon-space pair because they are used in the formatted
* log message when ISC_LOG_PRINTCATEGORY is enabled.
* *
* The default category is provided so that the internal default can * The default category is provided so that the internal default can
* be overridden. Since the default is always looked up as the first * be overridden. Since the default is always looked up as the first
@@ -156,9 +176,12 @@ isc_logchannellist_t default_channel;
* Forward declarations. * Forward declarations.
*/ */
static isc_result_t static isc_result_t
assignchannel(isc_log_t *lctx, unsigned int category_id, assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
isc_logmodule_t *module, isc_logchannel_t *channel); isc_logmodule_t *module, isc_logchannel_t *channel);
static isc_result_t
sync_channellist(isc_logconfig_t *lcfg);
static unsigned int static unsigned int
greatest_version(isc_logchannel_t *channel); greatest_version(isc_logchannel_t *channel);
@@ -188,37 +211,82 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
* Establish a new logging context, with default channels. * Establish a new logging context, with default channels.
*/ */
isc_result_t isc_result_t
isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) { isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp, isc_logconfig_t **lcfgp) {
isc_log_t *lctx; isc_log_t *lctx;
isc_logdestination_t destination; isc_logconfig_t *lcfg = NULL;
isc_result_t result; isc_result_t result = ISC_R_SUCCESS;
REQUIRE(mctx != NULL); REQUIRE(mctx != NULL);
REQUIRE(lctxp != NULL && *lctxp == NULL); REQUIRE(lctxp != NULL && *lctxp == NULL);
lctx = (isc_log_t *)isc_mem_get(mctx, sizeof(*lctx)); lctx = (isc_log_t *)isc_mem_get(mctx, sizeof(*lctx));
if (lctx == NULL) if (lctx != NULL) {
return (ISC_R_NOMEMORY); lctx->mctx = mctx;
lctx->category_count = 0;
lctx->module_count = 0;
lctx->debug_level = 0;
lctx->mctx = mctx; ISC_LIST_INIT(lctx->messages);
lctx->channels = NULL;
lctx->categories = NULL; RUNTIME_CHECK(isc_mutex_init(&lctx->lock) == ISC_R_SUCCESS);
lctx->category_count = 0;
lctx->debug_level = 0;
lctx->duplicate_interval = 0;
lctx->modules = NULL;
lctx->module_count = 0;
ISC_LIST_INIT(lctx->messages); /*
* Normally setting the magic number is the last step done
* in a creation function, but a valid log context is needed
* by isc_log_registercategories and isc_logconfig_create.
* If either fails, the lctx is destroyed and not returned
* to the caller.
*/
lctx->magic = LCTX_MAGIC;
result = isc_mutex_init(&lctx->lock); isc_log_registercategories(lctx, isc_categories);
result = isc_logconfig_create(lctx, &lcfg);
} else
result = ISC_R_NOMEMORY;
if (result == ISC_R_SUCCESS) {
lctx->logconfig = lcfg;
*lctxp = lctx;
if (lcfgp != NULL)
*lcfgp = lcfg;
/* } else
* Normally the magic number is the last thing set in the structure, if (lctx != NULL)
* but isc_log_createchannel() needs a valid context. If the channel isc_log_destroy(&lctx);
* creation fails, the lctx is not returned to the caller.
*/ return (result);
lctx->magic = LOG_MAGIC; }
isc_result_t
isc_logconfig_create(isc_log_t *lctx, isc_logconfig_t **lcfgp) {
isc_logconfig_t *lcfg;
isc_logdestination_t destination;
isc_result_t result = ISC_R_SUCCESS;
REQUIRE(lcfgp != NULL && *lcfgp == NULL);
REQUIRE(VALID_CONTEXT(lctx));
lcfg = (isc_logconfig_t *)isc_mem_get(lctx->mctx, sizeof(*lcfg));
if (lcfg != NULL) {
lcfg->lctx = lctx;
lcfg->channels = NULL;
lcfg->channellists = NULL;
lcfg->channellist_count = 0;
lcfg->duplicate_interval = 0;
/*
* Normally the magic number is the last thing set in the
* structure, but isc_log_createchannel() needs a valid
* config. If the channel creation fails, the lcfg is not
* returned to the caller.
*/
lcfg->magic = LCFG_MAGIC;
} else
result = ISC_R_NOMEMORY;
/* /*
* Create the default channels: * Create the default channels:
@@ -226,7 +294,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) {
*/ */
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
destination.facility = LOG_INFO; destination.facility = LOG_INFO;
result = isc_log_createchannel(lctx, "default_syslog", result = isc_log_createchannel(lcfg, "default_syslog",
ISC_LOG_TOSYSLOG, ISC_LOG_INFO, ISC_LOG_TOSYSLOG, ISC_LOG_INFO,
&destination, 0); &destination, 0);
} }
@@ -236,7 +304,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) {
destination.file.name = NULL; destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0; destination.file.maximum_size = 0;
result = isc_log_createchannel(lctx, "default_stderr", result = isc_log_createchannel(lcfg, "default_stderr",
ISC_LOG_TOFILEDESC, ISC_LOG_TOFILEDESC,
ISC_LOG_INFO, ISC_LOG_INFO,
&destination, &destination,
@@ -247,14 +315,14 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) {
* Set the default category's channel to default_stderr. * Set the default category's channel to default_stderr.
* XXX I find this odd. * XXX I find this odd.
*/ */
default_channel.channel = lctx->channels; default_channel.channel = lcfg->channels;
if (result == ISC_R_SUCCESS) { if (result == ISC_R_SUCCESS) {
destination.file.stream = stderr; destination.file.stream = stderr;
destination.file.name = NULL; destination.file.name = NULL;
destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.versions = ISC_LOG_ROLLNEVER;
destination.file.maximum_size = 0; destination.file.maximum_size = 0;
result = isc_log_createchannel(lctx, "default_debug", result = isc_log_createchannel(lcfg, "default_debug",
ISC_LOG_TOFILEDESC, ISC_LOG_TOFILEDESC,
ISC_LOG_DYNAMIC, ISC_LOG_DYNAMIC,
&destination, &destination,
@@ -262,20 +330,52 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) {
} }
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
result = isc_log_createchannel(lctx, "null", result = isc_log_createchannel(lcfg, "null",
ISC_LOG_TONULL, ISC_LOG_TONULL,
ISC_LOG_DYNAMIC, ISC_LOG_DYNAMIC,
NULL, 0); NULL, 0);
if (result == ISC_R_SUCCESS) if (result == ISC_R_SUCCESS)
result = isc_log_registercategories(lctx, isc_categories); *lcfgp = lcfg;
if (result != ISC_R_SUCCESS) { else
isc_mem_put(mctx, lctx, sizeof(*lctx)); if (lcfg != NULL)
isc_logconfig_destroy(&lcfg);
return (result);
}
isc_logconfig_t *
isc_logconfig_get(isc_log_t *lctx) {
return (lctx->logconfig);
}
isc_result_t
isc_logconfig_use(isc_log_t *lctx, isc_logconfig_t *lcfg) {
isc_logconfig_t *old_cfg;
isc_result_t result;
REQUIRE(VALID_CONTEXT(lctx));
REQUIRE(VALID_CONFIG(lcfg));
REQUIRE(lcfg->lctx == lctx);
/*
* Ensure that lcfg->channellist_count == lctx->category_count.
* They won't be equal if isc_log_usechannel has not been called
* since any call to isc_log_registercategories.
*/
result = sync_channellist(lcfg);
if (result != ISC_R_SUCCESS)
return (result); return (result);
}
*lctxp = lctx; LOCK(&lctx->lock);
old_cfg = lctx->logconfig;
lctx->logconfig = lcfg;
UNLOCK(&lctx->lock);
isc_logconfig_destroy(&old_cfg);
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
@@ -283,18 +383,63 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) {
void void
isc_log_destroy(isc_log_t **lctxp) { isc_log_destroy(isc_log_t **lctxp) {
isc_log_t *lctx; isc_log_t *lctx;
isc_logconfig_t *lcfg;
isc_mem_t *mctx; isc_mem_t *mctx;
isc_logchannel_t *channel, *next_channel; isc_logmessage_t *message;
isc_logchannellist_t *channellist, *next_channellist;
isc_logmessage_t *message, *next_message;
unsigned int i;
REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp)); REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp));
lctx = *lctxp; lctx = *lctxp;
mctx = lctx->mctx; mctx = lctx->mctx;
for (channel = lctx->channels; channel != NULL; if (lctx->logconfig != NULL) {
lcfg = lctx->logconfig;
lctx->logconfig = NULL;
isc_logconfig_destroy(&lcfg);
}
RUNTIME_CHECK(isc_mutex_destroy(&lctx->lock) == ISC_R_SUCCESS);
while ((message = ISC_LIST_HEAD(lctx->messages)) != NULL) {
ISC_LIST_UNLINK(lctx->messages, message, link);
isc_mem_put(mctx, message,
sizeof(*message) + strlen(message->text) + 1);
}
lctx->buffer[0] = '\0';
lctx->debug_level = 0;
lctx->category_count = 0;
lctx->module_count = 0;
lctx->mctx = NULL;
lctx->magic = 0;
isc_mem_put(mctx, lctx, sizeof(*lctx));
*lctxp = NULL;
}
void
isc_logconfig_destroy(isc_logconfig_t **lcfgp) {
isc_logconfig_t *lcfg;
isc_mem_t *mctx;
isc_logchannel_t *channel, *next_channel;
isc_logchannellist_t *item, *next_item;
unsigned int i;
REQUIRE(lcfgp != NULL && VALID_CONFIG(*lcfgp));
lcfg = *lcfgp;
/*
* This function cannot be called with a logconfig that is in
* use by a log context.
*/
REQUIRE(lcfg->lctx != NULL && lcfg->lctx->logconfig != lcfg);
mctx = lcfg->lctx->mctx;
for (channel = lcfg->channels; channel != NULL;
channel = next_channel) { channel = next_channel) {
next_channel = channel->next; next_channel = channel->next;
@@ -309,39 +454,28 @@ isc_log_destroy(isc_log_t **lctxp) {
isc_mem_put(mctx, channel, sizeof(*channel)); isc_mem_put(mctx, channel, sizeof(*channel));
} }
for (i = 0; i < lctx->category_count; i++) for (i = 0; i < lcfg->channellist_count; i++)
for (channellist = lctx->categories[i]; channellist != NULL; for (item = lcfg->channellists[i]; item != NULL;
channellist = next_channellist) { item = next_item) {
next_channellist = channellist->next; next_item = item->next;
isc_mem_put(mctx, channellist, sizeof(*channellist)); isc_mem_put(mctx, item, sizeof(*item));
} }
isc_mem_put(mctx, &lctx->categories[0], isc_mem_put(mctx, lcfg->channellists,
lctx->category_count * sizeof(isc_logchannellist_t **)); lcfg->channellist_count * sizeof(isc_logchannellist_t **));
for (message = ISC_LIST_HEAD(lctx->messages); message != NULL; lcfg->duplicate_interval = 0;
message = next_message) { lcfg->magic = 0;
next_message = message->next; isc_mem_put(mctx, lcfg, sizeof(*lcfg));
isc_mem_put(mctx, message,
sizeof(*message) + strlen(message->text) + 1);
}
ISC_LIST_INIT(lctx->messages);
isc_mutex_destroy(&lctx->lock); *lcfgp = NULL;
lctx->magic = 0;
isc_mem_put(mctx, lctx, sizeof(*lctx));
*lctxp = NULL;
} }
isc_result_t void
isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) { isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
isc_logchannellist_t **lists;
isc_logcategory_t *catp; isc_logcategory_t *catp;
unsigned int old_count, new_count, bytes; unsigned int old_count, new_count;
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONTEXT(lctx));
REQUIRE(categories != NULL); REQUIRE(categories != NULL);
@@ -355,23 +489,7 @@ isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) {
for (new_count = old_count, catp = categories; catp->name != NULL; ) for (new_count = old_count, catp = categories; catp->name != NULL; )
catp++->id = new_count++; catp++->id = new_count++;
lists = (isc_logchannellist_t **)isc_mem_get(lctx->mctx,
new_count * sizeof(isc_logchannellist_t *));
if (lists == NULL)
return (ISC_R_NOMEMORY);
memset(lists, 0, new_count * sizeof(isc_logchannellist_t *));
if (old_count != 0) {
bytes = old_count * sizeof(isc_logchannellist_t *);
memcpy(lists, lctx->categories, bytes);
isc_mem_put(lctx->mctx, lctx->categories, bytes);
}
lctx->categories = lists;
lctx->category_count = new_count; lctx->category_count = new_count;
return (ISC_R_SUCCESS);
} }
void void
@@ -395,13 +513,14 @@ isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) {
} }
isc_result_t isc_result_t
isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, isc_log_createchannel(isc_logconfig_t *lcfg, const char *name,
int level, isc_logdestination_t *destination, unsigned int type, int level,
unsigned int flags) isc_logdestination_t *destination, unsigned int flags)
{ {
isc_logchannel_t *channel; isc_logchannel_t *channel;
isc_mem_t *mctx;
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONFIG(lcfg));
REQUIRE(name != NULL); REQUIRE(name != NULL);
REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE || REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE ||
type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL); type == ISC_LOG_TOFILEDESC || type == ISC_LOG_TONULL);
@@ -409,16 +528,17 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type,
REQUIRE(level >= ISC_LOG_CRITICAL); REQUIRE(level >= ISC_LOG_CRITICAL);
REQUIRE((flags & ~ISC_LOG_PRINTALL) == 0); REQUIRE((flags & ~ISC_LOG_PRINTALL) == 0);
/* XXX DCL find duplicate names? */ /* XXXDCL find duplicate names? */
channel = (isc_logchannel_t *)isc_mem_get(lctx->mctx, mctx = lcfg->lctx->mctx;
sizeof(*channel));
channel = (isc_logchannel_t *)isc_mem_get(mctx, sizeof(*channel));
if (channel == NULL) if (channel == NULL)
return (ISC_R_NOMEMORY); return (ISC_R_NOMEMORY);
channel->name = isc_mem_strdup(lctx->mctx, name); channel->name = isc_mem_strdup(mctx, name);
if (channel->name == NULL) { if (channel->name == NULL) {
isc_mem_put(lctx->mctx, channel, sizeof(*channel)); isc_mem_put(mctx, channel, sizeof(*channel));
return (ISC_R_NOMEMORY); return (ISC_R_NOMEMORY);
} }
@@ -438,7 +558,7 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type,
* writable memory. * writable memory.
*/ */
FILE_NAME(channel) = FILE_NAME(channel) =
isc_mem_strdup(lctx->mctx, destination->file.name); isc_mem_strdup(mctx, destination->file.name);
FILE_STREAM(channel) = NULL; FILE_STREAM(channel) = NULL;
FILE_MAXSIZE(channel) = destination->file.maximum_size; FILE_MAXSIZE(channel) = destination->file.maximum_size;
FILE_VERSIONS(channel) = destination->file.versions; FILE_VERSIONS(channel) = destination->file.versions;
@@ -456,19 +576,17 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type,
break; break;
default: default:
isc_mem_put(lctx->mctx, channel->name, isc_mem_put(mctx, channel->name, strlen(channel->name) + 1);
strlen(channel->name) + 1); isc_mem_put(mctx, channel, sizeof(*channel));
isc_mem_put(lctx->mctx, channel, sizeof(*channel));
return (ISC_R_UNEXPECTED); return (ISC_R_UNEXPECTED);
} }
channel->next = lctx->channels; channel->next = lcfg->channels;
lctx->channels = channel; lcfg->channels = channel;
/* /*
* If default_stderr was redefined, make the default category * If default_stderr was redefined, make the default category
* point to the new default_stderr. * point to the new default_stderr.
* XXX I find this odd.
*/ */
if (strcmp(name, "default_stderr") == 0) if (strcmp(name, "default_stderr") == 0)
default_channel.channel = channel; default_channel.channel = channel;
@@ -477,19 +595,23 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type,
} }
isc_result_t isc_result_t
isc_log_usechannel(isc_log_t *lctx, const char *name, isc_log_usechannel(isc_logconfig_t *lcfg, const char *name,
isc_logcategory_t *category, isc_logmodule_t *module) isc_logcategory_t *category, isc_logmodule_t *module)
{ {
isc_log_t *lctx;
isc_logchannel_t *channel; isc_logchannel_t *channel;
isc_result_t result; isc_result_t result = ISC_R_SUCCESS;
unsigned int i; unsigned int i;
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONFIG(lcfg));
REQUIRE(name != NULL); REQUIRE(name != NULL);
lctx = lcfg->lctx;
REQUIRE(category == NULL || category->id < lctx->category_count); REQUIRE(category == NULL || category->id < lctx->category_count);
REQUIRE(module == NULL || module->id < lctx->module_count); REQUIRE(module == NULL || module->id < lctx->module_count);
for (channel = lctx->channels; channel != NULL; for (channel = lcfg->channels; channel != NULL;
channel = channel->next) channel = channel->next)
if (strcmp(name, channel->name) == 0) if (strcmp(name, channel->name) == 0)
break; break;
@@ -497,13 +619,8 @@ isc_log_usechannel(isc_log_t *lctx, const char *name,
if (channel == NULL) if (channel == NULL)
return (ISC_R_NOTFOUND); return (ISC_R_NOTFOUND);
/*
* Silence bogus GCC warning, "`result' might be used uninitialized".
*/
result = ISC_R_SUCCESS;
if (category != NULL) if (category != NULL)
result = assignchannel(lctx, category->id, module, channel); result = assignchannel(lcfg, category->id, module, channel);
else else
/* /*
@@ -511,7 +628,7 @@ isc_log_usechannel(isc_log_t *lctx, const char *name,
* the default channel. * the default channel.
*/ */
for (i = 0; i < lctx->category_count; i++) { for (i = 0; i < lctx->category_count; i++) {
result = assignchannel(lctx, i, module, channel); result = assignchannel(lcfg, i, module, channel);
if (result != ISC_R_SUCCESS) if (result != ISC_R_SUCCESS)
break; break;
} }
@@ -590,17 +707,17 @@ isc_log_getdebuglevel(isc_log_t *lctx) {
} }
void void
isc_log_setduplicateinterval(isc_log_t *lctx, unsigned int interval) { isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) {
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONFIG(lcfg));
lctx->duplicate_interval = interval; lcfg->duplicate_interval = interval;
} }
unsigned int unsigned int
isc_log_getduplicateinterval(isc_log_t *lctx) { isc_log_getduplicateinterval(isc_logconfig_t *lcfg) {
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONTEXT(lcfg));
return (lctx->duplicate_interval); return (lcfg->duplicate_interval);
} }
/* XXXDCL NT -- This interface will assuredly be changing. */ /* XXXDCL NT -- This interface will assuredly be changing. */
@@ -615,7 +732,9 @@ isc_log_closefilelogs(isc_log_t *lctx) {
REQUIRE(VALID_CONTEXT(lctx)); REQUIRE(VALID_CONTEXT(lctx));
for (channel = lctx->channels; channel != NULL; channel= channel->next) for (channel = lctx->logconfig->channels; channel != NULL;
channel = channel->next)
if (channel->type == ISC_LOG_TOFILE && if (channel->type == ISC_LOG_TOFILE &&
FILE_STREAM(channel) != NULL) { FILE_STREAM(channel) != NULL) {
(void)fclose(FILE_STREAM(channel)); (void)fclose(FILE_STREAM(channel));
@@ -628,16 +747,28 @@ isc_log_closefilelogs(isc_log_t *lctx) {
****/ ****/
static isc_result_t static isc_result_t
assignchannel(isc_log_t *lctx, unsigned int category_id, assignchannel(isc_logconfig_t *lcfg, unsigned int category_id,
isc_logmodule_t *module, isc_logchannel_t *channel) isc_logmodule_t *module, isc_logchannel_t *channel)
{ {
isc_logchannellist_t *new_item; isc_logchannellist_t *new_item;
isc_log_t *lctx;
isc_result_t result;
REQUIRE(VALID_CONFIG(lcfg));
lctx = lcfg->lctx;
REQUIRE(VALID_CONTEXT(lctx));
REQUIRE(category_id < lctx->category_count); REQUIRE(category_id < lctx->category_count);
REQUIRE(module == NULL || module->id < lctx->module_count); REQUIRE(module == NULL || module->id < lctx->module_count);
REQUIRE(channel != NULL); REQUIRE(channel != NULL);
/*
* Ensure lcfg->channellist_count == lctx->category_count.
*/
result = sync_channellist(lcfg);
if (result != ISC_R_SUCCESS)
return (result);
new_item = (isc_logchannellist_t *)isc_mem_get(lctx->mctx, new_item = (isc_logchannellist_t *)isc_mem_get(lctx->mctx,
sizeof(*new_item)); sizeof(*new_item));
if (new_item == NULL) if (new_item == NULL)
@@ -645,16 +776,52 @@ assignchannel(isc_log_t *lctx, unsigned int category_id,
new_item->channel = channel; new_item->channel = channel;
new_item->module = module; new_item->module = module;
new_item->next = lctx->categories[category_id]; new_item->next = lcfg->channellists[category_id];
lctx->categories[category_id] = new_item; lcfg->channellists[category_id] = new_item;
return (ISC_R_SUCCESS);
}
static isc_result_t
sync_channellist(isc_logconfig_t *lcfg) {
int bytes;
isc_log_t *lctx;
isc_logchannellist_t **lists;
REQUIRE(VALID_CONFIG(lcfg));
lctx = lcfg->lctx;
REQUIRE(lctx->category_count != 0);
if (lctx->category_count == lcfg->channellist_count)
return (ISC_R_SUCCESS);
bytes = lctx->category_count * sizeof(isc_logchannellist_t *);
lists = (isc_logchannellist_t **)isc_mem_get(lctx->mctx, bytes);
if (lists == NULL)
return (ISC_R_NOMEMORY);
memset(lists, 0, bytes);
if (lcfg->channellist_count != 0) {
bytes = lcfg->channellist_count *
sizeof(isc_logchannellist_t *);
memcpy(lists, lcfg->channellists, bytes);
isc_mem_put(lctx->mctx, lcfg->channellists, bytes);
}
lcfg->channellists = lists;
lcfg->channellist_count = lctx->category_count;
return (ISC_R_SUCCESS); return (ISC_R_SUCCESS);
} }
static unsigned int static unsigned int
greatest_version(isc_logchannel_t *channel) greatest_version(isc_logchannel_t *channel) {
{
/* XXXDCL HIGHLY NT */ /* XXXDCL HIGHLY NT */
char *dirname, *basename, *digit_end; char *dirname, *basename, *digit_end;
int version, greatest = -1; int version, greatest = -1;
@@ -836,6 +1003,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
struct tm *timeptr; struct tm *timeptr;
time_t now; time_t now;
isc_boolean_t matched = ISC_FALSE; isc_boolean_t matched = ISC_FALSE;
isc_logconfig_t *lcfg;
isc_logchannel_t *channel; isc_logchannel_t *channel;
isc_logchannellist_t *category_channels; isc_logchannellist_t *category_channels;
isc_result_t result; isc_result_t result;
@@ -859,10 +1027,11 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
level_string[0] = '\0'; level_string[0] = '\0';
lctx->buffer[0] = '\0'; lctx->buffer[0] = '\0';
category_channels = lctx->categories[category->id]; LOCK(&lctx->lock);
if (isc_mutex_lock(&lctx->lock) != ISC_R_SUCCESS) lcfg = lctx->logconfig;
return;
category_channels = lcfg->channellists[category->id];
/* /*
* XXX duplicate filtering (do not write multiple times to same source * XXX duplicate filtering (do not write multiple times to same source
@@ -877,12 +1046,12 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
break; break;
if (category_channels == NULL && ! matched && if (category_channels == NULL && ! matched &&
category_channels != lctx->categories[0]) category_channels != lcfg->channellists[0])
/* /*
* No category/module pair was explicitly configured. * No category/module pair was explicitly configured.
* Try the category named "default". * Try the category named "default".
*/ */
category_channels = lctx->categories[0]; category_channels = lcfg->channellists[0];
if (category_channels == NULL && ! matched) if (category_channels == NULL && ! matched)
/* /*
@@ -951,7 +1120,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
isc_interval_t interval; isc_interval_t interval;
isc_interval_set(&interval, isc_interval_set(&interval,
lctx->duplicate_interval, 0); lcfg->duplicate_interval, 0);
/* /*
* 'oldest' is the age of the oldest messages * 'oldest' is the age of the oldest messages
@@ -974,29 +1143,23 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
* so it should be dropped from * so it should be dropped from
* the history. * the history.
* *
* XXX Setting the interval * Setting the interval to be
* to be longer will obviously * to be longer will obviously
* not cause the expired * not cause the expired
* message to spring back into * message to spring back into
* existence. * existence.
*/ */
new = message->next; new = ISC_LIST_NEXT(message,
link);
ISC_LIST_UNLINK(lctx->messages,
message, link);
isc_mem_put(lctx->mctx, isc_mem_put(lctx->mctx,
message, message,
sizeof(*message) + 1 + sizeof(*message) + 1 +
strlen(message->text)); strlen(message->text));
lctx->messages.head = new;
if (new == NULL)
/*
* Last element of the
* list was removed, so
* the tail pointer
* is no longer valid.
*/
lctx->messages.tail =
NULL;
message = new; message = new;
continue; continue;
} }
@@ -1012,11 +1175,11 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
* Unlock the mutex and * Unlock the mutex and
* get the hell out of Dodge. * get the hell out of Dodge.
*/ */
isc_mutex_unlock(&lctx->lock); UNLOCK(&lctx->lock);
return; return;
} }
message = message->next; message = ISC_LIST_NEXT(message, link);
} }
/* /*
@@ -1040,20 +1203,13 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
* This will cause the message * This will cause the message
* to immediately expire on * to immediately expire on
* the next call to [v]write1. * the next call to [v]write1.
* XXX ok? * What's a fella to do if
* getting the time fails?
*/ */
isc_time_settoepoch(&new->time); isc_time_settoepoch(&new->time);
new->next = NULL; ISC_LIST_APPEND(lctx->messages,
new, link);
if (ISC_LIST_EMPTY(lctx->messages)) {
lctx->messages.head = new;
lctx->messages.tail = new;
} else {
lctx->messages.tail->next =
new;
lctx->messages.tail = new;
}
} }
} }
} }
@@ -1145,5 +1301,5 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category,
} while (1); } while (1);
isc_mutex_unlock(&lctx->lock); UNLOCK(&lctx->lock);
} }