diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index 2183b1dcac..65f7cd1c21 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -1028,6 +1028,7 @@ main(int argc, char *argv[]) { signer_key_t *key; isc_result_t result; isc_log_t *log = NULL; + isc_logconfig_t *logconfig; dns_result_register(); @@ -1107,11 +1108,11 @@ main(int argc, char *argv[]) { } if (verbose > 0) { - RUNTIME_CHECK(isc_log_create(mctx, &log) == ISC_R_SUCCESS); - RUNTIME_CHECK(dns_log_init(log) == ISC_R_SUCCESS); - RUNTIME_CHECK(isc_log_usechannel(log, "default_stderr", + RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) + == ISC_R_SUCCESS); + dns_log_init(log); + RUNTIME_CHECK(isc_log_usechannel(logconfig, "default_stderr", NULL, NULL) == ISC_R_SUCCESS); - dns_lctx = log; } argc -= isc_commandline_index; diff --git a/bin/lwresd/main.c b/bin/lwresd/main.c index e2d97d6e84..babafd5f9f 100644 --- a/bin/lwresd/main.c +++ b/bin/lwresd/main.c @@ -218,6 +218,7 @@ main(int argc, char **argv) client_t *client; isc_logdestination_t destination; isc_log_t *lctx; + isc_logconfig_t *lcfg; UNUSED(argc); UNUSED(argv); @@ -235,21 +236,20 @@ main(int argc, char **argv) * Set up logging. */ lctx = NULL; - result = isc_log_create(mem, &lctx); - INSIST(result == ISC_R_SUCCESS); - result = dns_log_init(lctx); + result = isc_log_create(mem, &lctx, &lcfg); INSIST(result == ISC_R_SUCCESS); + dns_log_init(lctx); destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; - result = isc_log_createchannel(lctx, "_default", + result = isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, ISC_LOG_PRINTTIME); 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); /* diff --git a/bin/named/log.c b/bin/named/log.c index fdfd61d224..edf1fcc05e 100644 --- a/bin/named/log.c +++ b/bin/named/log.c @@ -63,6 +63,7 @@ ns_log_init(void) { isc_result_t result; isc_logdestination_t destination; unsigned int flags; + isc_logconfig_t *lcfg; ns_g_categories = categories; ns_g_modules = modules; @@ -75,16 +76,13 @@ ns_log_init(void) { /* * 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) return (result); - result = isc_log_registercategories(ns_g_lctx, ns_g_categories); - if (result != ISC_R_SUCCESS) - goto cleanup; + + isc_log_registercategories(ns_g_lctx, ns_g_categories); isc_log_registermodules(ns_g_lctx, ns_g_modules); - result = dns_log_init(ns_g_lctx); - if (result != ISC_R_SUCCESS) - goto cleanup; + dns_log_init(ns_g_lctx); /* * Create and install the default channel. @@ -95,14 +93,14 @@ ns_log_init(void) { destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; flags = ISC_LOG_PRINTTIME; - result = isc_log_createchannel(ns_g_lctx, "_default", + result = isc_log_createchannel(lcfg, "_default", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, flags); } else { destination.facility = LOG_DAEMON; flags = ISC_LOG_PRINTTIME; - result = isc_log_createchannel(ns_g_lctx, "_default", + result = isc_log_createchannel(lcfg, "_default", ISC_LOG_TOSYSLOG, ISC_LOG_DYNAMIC, &destination, flags); @@ -110,7 +108,7 @@ ns_log_init(void) { if (result != ISC_R_SUCCESS) 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) goto cleanup; diff --git a/bin/tests/log_test.c b/bin/tests/log_test.c index abc5defee4..da4166b745 100644 --- a/bin/tests/log_test.c +++ b/bin/tests/log_test.c @@ -15,7 +15,7 @@ * 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 */ @@ -44,19 +44,13 @@ char usage[] = "Usage: %s [-m] [-s syslog_logfile] [-r file_versions]\n"; 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 main (int argc, char **argv) { char *progname, *syslog_file, *message; int ch, i, file_versions; isc_boolean_t show_final_mem = ISC_FALSE; isc_log_t *lctx; + isc_logconfig_t *lcfg; isc_mem_t *mctx; isc_result_t result; isc_logdestination_t destination; @@ -113,8 +107,9 @@ main (int argc, char **argv) { lctx = NULL; CHECK_ISC(isc_mem_create(0, 0, &mctx)); - CHECK_ISC(isc_log_create(mctx, &lctx)); - CHECK_DNS(dns_log_init(lctx)); + CHECK_ISC(isc_log_create(mctx, &lctx, &lcfg)); + + dns_log_init(lctx); /* * 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.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_PRINTTIME| ISC_LOG_PRINTLEVEL| @@ -137,7 +132,7 @@ main (int argc, char **argv) { */ 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_PRINTTIME| ISC_LOG_PRINTLEVEL)); @@ -145,27 +140,27 @@ main (int argc, char **argv) { /* * 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_LOGMODULE_CACHE)); - CHECK_ISC(isc_log_usechannel(lctx, "default_stderr", + CHECK_ISC(isc_log_usechannel(lcfg, "default_stderr", DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE)); - CHECK_ISC(isc_log_usechannel(lctx, "default_debug", + CHECK_ISC(isc_log_usechannel(lcfg, "default_debug", DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_CACHE)); - CHECK_ISC(isc_log_usechannel(lctx, "null", + CHECK_ISC(isc_log_usechannel(lcfg, "null", DNS_LOGCATEGORY_DATABASE, NULL)); /* * Use the custom channels. */ - CHECK_ISC(isc_log_usechannel(lctx, "file_test", + CHECK_ISC(isc_log_usechannel(lcfg, "file_test", DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_DB)); - CHECK_ISC(isc_log_usechannel(lctx, "debug_test", + CHECK_ISC(isc_log_usechannel(lcfg, "debug_test", DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB)); @@ -199,7 +194,7 @@ main (int argc, char **argv) { * Reset the internal default to use syslog instead of stderr, * and test it. */ - CHECK_ISC(isc_log_usechannel(lctx, "default_syslog", + CHECK_ISC(isc_log_usechannel(lcfg, "default_syslog", ISC_LOGCATEGORY_DEFAULT, NULL)); 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. */ - isc_log_setduplicateinterval(lctx, 10); + isc_log_setduplicateinterval(lcfg, 10); message = "This message should appear only once on stderr"; 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_CRITICAL, message); - isc_log_setduplicateinterval(lctx, 1); + isc_log_setduplicateinterval(lcfg, 1); message = "This message should appear twice on stderr"; isc_log_write1(lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_RBTDB, diff --git a/bin/tests/signer.c b/bin/tests/signer.c index 2183b1dcac..65f7cd1c21 100644 --- a/bin/tests/signer.c +++ b/bin/tests/signer.c @@ -1028,6 +1028,7 @@ main(int argc, char *argv[]) { signer_key_t *key; isc_result_t result; isc_log_t *log = NULL; + isc_logconfig_t *logconfig; dns_result_register(); @@ -1107,11 +1108,11 @@ main(int argc, char *argv[]) { } if (verbose > 0) { - RUNTIME_CHECK(isc_log_create(mctx, &log) == ISC_R_SUCCESS); - RUNTIME_CHECK(dns_log_init(log) == ISC_R_SUCCESS); - RUNTIME_CHECK(isc_log_usechannel(log, "default_stderr", + RUNTIME_CHECK(isc_log_create(mctx, &log, &logconfig) + == ISC_R_SUCCESS); + dns_log_init(log); + RUNTIME_CHECK(isc_log_usechannel(logconfig, "default_stderr", NULL, NULL) == ISC_R_SUCCESS); - dns_lctx = log; } argc -= isc_commandline_index; diff --git a/lib/dns/include/dns/log.h b/lib/dns/include/dns/log.h index 8af09f38aa..e6354a2b57 100644 --- a/lib/dns/include/dns/log.h +++ b/lib/dns/include/dns/log.h @@ -15,7 +15,7 @@ * 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 */ @@ -58,7 +58,7 @@ extern isc_logmodule_t dns_modules[]; #define DNS_LOGMODULE_XFER_OUT (&dns_modules[14]) #define DNS_LOGMODULE_ACL (&dns_modules[15]) -isc_result_t +void dns_log_init(isc_log_t *lctx); /* * 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. * * Ensures: - * ISC_R_SUCCESS - * The catgories and modules defined above are available for - * 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 + * The catgories and modules defined above are available for + * use by isc_log_usechannnel() and isc_log_write(). */ ISC_LANG_ENDDECLS diff --git a/lib/dns/log.c b/lib/dns/log.c index 7516aaa66f..72f9f32597 100644 --- a/lib/dns/log.c +++ b/lib/dns/log.c @@ -15,7 +15,7 @@ * 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 */ @@ -68,18 +68,12 @@ isc_logmodule_t dns_modules[] = { isc_log_t *dns_lctx; -isc_result_t +void dns_log_init(isc_log_t *lctx) { - isc_result_t result; - 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) { - isc_log_registermodules(lctx, dns_modules); - dns_lctx = lctx; - } - - return (result); + dns_lctx = lctx; } diff --git a/lib/isc/include/isc/log.h b/lib/isc/include/isc/log.h index 4f1affbfc5..e71c91b2aa 100644 --- a/lib/isc/include/isc/log.h +++ b/lib/isc/include/isc/log.h @@ -15,7 +15,7 @@ * 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 #define ISC_LOG_H 1 @@ -75,6 +75,11 @@ ISC_LANG_BEGINDECLS */ 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 * 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]) 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. * @@ -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_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 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. */ +void +isc_logconfig_destroy(isc_logconfig_t **lcfgp); -isc_result_t +void isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]); /* * 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_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, - int level, isc_logdestination_t *destination, - unsigned int flags); +isc_log_createchannel(isc_logconfig_t *lcfg, const char *name, + unsigned int type, int level, + isc_logdestination_t *destination, unsigned int flags); /* * 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_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); /* * Associate a named logging channel with a category and module that @@ -502,7 +518,7 @@ isc_log_getdebuglevel(isc_log_t *lctx); */ 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 * by isc_log_[v]write1(), in seconds. @@ -525,7 +541,7 @@ isc_log_setduplicateinterval(isc_log_t *lctx, unsigned int interval); */ unsigned int -isc_log_getduplicateinterval(isc_log_t *lctx); +isc_log_getduplicateinterval(isc_logconfig_t *lcfg); /* * Get the current duplicate filtering interval. * diff --git a/lib/isc/log.c b/lib/isc/log.c index 16a8192d45..1803e05bf2 100644 --- a/lib/isc/log.c +++ b/lib/isc/log.c @@ -15,7 +15,7 @@ * 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 */ @@ -29,15 +29,19 @@ #include #include #include +#include #include #include #include #include #include #include +#include -#define LOG_MAGIC 0x494C4F47U /* ILOG. */ -#define VALID_CONTEXT(lctx) ((lctx) != NULL && (lctx)->magic == LOG_MAGIC) +#define LCTX_MAGIC 0x4C637478U /* Lctx. */ +#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) @@ -58,6 +62,7 @@ struct isc_logchannel { int level; unsigned int flags; isc_logdestination_t destination; + /* XXXDCL should be an ISC_LINK, so this can be an ISC_LIST */ isc_logchannel_t * next; }; @@ -74,6 +79,7 @@ typedef struct isc_logchannellist isc_logchannellist_t; struct isc_logchannellist { isc_logmodule_t * module; isc_logchannel_t * channel; + /* XXXDCL should be an ISC_LINK, so this can be an ISC_LIST */ isc_logchannellist_t * next; }; @@ -84,14 +90,26 @@ struct isc_logchannellist { typedef struct isc_logmessage isc_logmessage_t; struct isc_logmessage { - char * text; - isc_time_t time; - isc_logmessage_t * next; + char * text; + isc_time_t time; + 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. - * 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 * 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 @@ -100,20 +118,24 @@ struct isc_logmessage { * context in the same program competing for syslog's attention. Thus * There Can Be Only One, but this is not enforced. * 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 { + /* Not locked. */ unsigned int magic; 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; - isc_logmodule_t ** modules; unsigned int module_count; + int debug_level; + char buffer[LOG_BUFFER_SIZE]; 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 - * definition needs to be added to . Each name string should - * end with a colon-space pair because they are used in the formatted - * log message when ISC_LOG_PRINTCATEGORY is enabled. + * definition needs to be added to . * * The default category is provided so that the internal default can * be overridden. Since the default is always looked up as the first @@ -156,9 +176,12 @@ isc_logchannellist_t default_channel; * Forward declarations. */ 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); +static isc_result_t +sync_channellist(isc_logconfig_t *lcfg); + static unsigned int 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. */ 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_logdestination_t destination; - isc_result_t result; + isc_logconfig_t *lcfg = NULL; + isc_result_t result = ISC_R_SUCCESS; REQUIRE(mctx != NULL); REQUIRE(lctxp != NULL && *lctxp == NULL); lctx = (isc_log_t *)isc_mem_get(mctx, sizeof(*lctx)); - if (lctx == NULL) - return (ISC_R_NOMEMORY); + if (lctx != NULL) { + lctx->mctx = mctx; + lctx->category_count = 0; + lctx->module_count = 0; + lctx->debug_level = 0; - lctx->mctx = mctx; - lctx->channels = NULL; - lctx->categories = NULL; - lctx->category_count = 0; - lctx->debug_level = 0; - lctx->duplicate_interval = 0; - lctx->modules = NULL; - lctx->module_count = 0; + ISC_LIST_INIT(lctx->messages); + + RUNTIME_CHECK(isc_mutex_init(&lctx->lock) == ISC_R_SUCCESS); - 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; - /* - * Normally the magic number is the last thing set in the structure, - * but isc_log_createchannel() needs a valid context. If the channel - * creation fails, the lctx is not returned to the caller. - */ - lctx->magic = LOG_MAGIC; + } else + if (lctx != NULL) + isc_log_destroy(&lctx); + + return (result); +} + +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: @@ -226,7 +294,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) { */ if (result == ISC_R_SUCCESS) { destination.facility = LOG_INFO; - result = isc_log_createchannel(lctx, "default_syslog", + result = isc_log_createchannel(lcfg, "default_syslog", ISC_LOG_TOSYSLOG, ISC_LOG_INFO, &destination, 0); } @@ -236,7 +304,7 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) { destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; - result = isc_log_createchannel(lctx, "default_stderr", + result = isc_log_createchannel(lcfg, "default_stderr", ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &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. * XXX I find this odd. */ - default_channel.channel = lctx->channels; + default_channel.channel = lcfg->channels; if (result == ISC_R_SUCCESS) { destination.file.stream = stderr; destination.file.name = NULL; destination.file.versions = ISC_LOG_ROLLNEVER; destination.file.maximum_size = 0; - result = isc_log_createchannel(lctx, "default_debug", + result = isc_log_createchannel(lcfg, "default_debug", ISC_LOG_TOFILEDESC, ISC_LOG_DYNAMIC, &destination, @@ -262,20 +330,52 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) { } if (result == ISC_R_SUCCESS) - result = isc_log_createchannel(lctx, "null", + result = isc_log_createchannel(lcfg, "null", ISC_LOG_TONULL, ISC_LOG_DYNAMIC, NULL, 0); if (result == ISC_R_SUCCESS) - result = isc_log_registercategories(lctx, isc_categories); + *lcfgp = lcfg; - if (result != ISC_R_SUCCESS) { - isc_mem_put(mctx, lctx, sizeof(*lctx)); + else + 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); - } - *lctxp = lctx; + LOCK(&lctx->lock); + + old_cfg = lctx->logconfig; + lctx->logconfig = lcfg; + + UNLOCK(&lctx->lock); + + isc_logconfig_destroy(&old_cfg); return (ISC_R_SUCCESS); } @@ -283,18 +383,63 @@ isc_log_create(isc_mem_t *mctx, isc_log_t **lctxp) { void isc_log_destroy(isc_log_t **lctxp) { isc_log_t *lctx; + isc_logconfig_t *lcfg; isc_mem_t *mctx; - isc_logchannel_t *channel, *next_channel; - isc_logchannellist_t *channellist, *next_channellist; - isc_logmessage_t *message, *next_message; - unsigned int i; + isc_logmessage_t *message; REQUIRE(lctxp != NULL && VALID_CONTEXT(*lctxp)); lctx = *lctxp; 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) { next_channel = channel->next; @@ -309,39 +454,28 @@ isc_log_destroy(isc_log_t **lctxp) { isc_mem_put(mctx, channel, sizeof(*channel)); } - for (i = 0; i < lctx->category_count; i++) - for (channellist = lctx->categories[i]; channellist != NULL; - channellist = next_channellist) { - next_channellist = channellist->next; - isc_mem_put(mctx, channellist, sizeof(*channellist)); + for (i = 0; i < lcfg->channellist_count; i++) + for (item = lcfg->channellists[i]; item != NULL; + item = next_item) { + next_item = item->next; + isc_mem_put(mctx, item, sizeof(*item)); } - isc_mem_put(mctx, &lctx->categories[0], - lctx->category_count * sizeof(isc_logchannellist_t **)); + isc_mem_put(mctx, lcfg->channellists, + lcfg->channellist_count * sizeof(isc_logchannellist_t **)); - for (message = ISC_LIST_HEAD(lctx->messages); message != NULL; - message = next_message) { + lcfg->duplicate_interval = 0; + lcfg->magic = 0; - next_message = message->next; - isc_mem_put(mctx, message, - sizeof(*message) + strlen(message->text) + 1); - } - ISC_LIST_INIT(lctx->messages); + isc_mem_put(mctx, lcfg, sizeof(*lcfg)); - isc_mutex_destroy(&lctx->lock); - - lctx->magic = 0; - - isc_mem_put(mctx, lctx, sizeof(*lctx)); - - *lctxp = NULL; + *lcfgp = NULL; } -isc_result_t +void isc_log_registercategories(isc_log_t *lctx, isc_logcategory_t categories[]) { - isc_logchannellist_t **lists; isc_logcategory_t *catp; - unsigned int old_count, new_count, bytes; + unsigned int old_count, new_count; REQUIRE(VALID_CONTEXT(lctx)); 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; ) 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; - - return (ISC_R_SUCCESS); } void @@ -395,13 +513,14 @@ isc_log_registermodules(isc_log_t *lctx, isc_logmodule_t modules[]) { } isc_result_t -isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, - int level, isc_logdestination_t *destination, - unsigned int flags) +isc_log_createchannel(isc_logconfig_t *lcfg, const char *name, + unsigned int type, int level, + isc_logdestination_t *destination, unsigned int flags) { isc_logchannel_t *channel; + isc_mem_t *mctx; - REQUIRE(VALID_CONTEXT(lctx)); + REQUIRE(VALID_CONFIG(lcfg)); REQUIRE(name != NULL); REQUIRE(type == ISC_LOG_TOSYSLOG || type == ISC_LOG_TOFILE || 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((flags & ~ISC_LOG_PRINTALL) == 0); - /* XXX DCL find duplicate names? */ + /* XXXDCL find duplicate names? */ - channel = (isc_logchannel_t *)isc_mem_get(lctx->mctx, - sizeof(*channel)); + mctx = lcfg->lctx->mctx; + + channel = (isc_logchannel_t *)isc_mem_get(mctx, sizeof(*channel)); if (channel == NULL) return (ISC_R_NOMEMORY); - channel->name = isc_mem_strdup(lctx->mctx, name); + channel->name = isc_mem_strdup(mctx, name); if (channel->name == NULL) { - isc_mem_put(lctx->mctx, channel, sizeof(*channel)); + isc_mem_put(mctx, channel, sizeof(*channel)); return (ISC_R_NOMEMORY); } @@ -438,7 +558,7 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, * writable memory. */ FILE_NAME(channel) = - isc_mem_strdup(lctx->mctx, destination->file.name); + isc_mem_strdup(mctx, destination->file.name); FILE_STREAM(channel) = NULL; FILE_MAXSIZE(channel) = destination->file.maximum_size; FILE_VERSIONS(channel) = destination->file.versions; @@ -456,19 +576,17 @@ isc_log_createchannel(isc_log_t *lctx, const char *name, unsigned int type, break; default: - isc_mem_put(lctx->mctx, channel->name, - strlen(channel->name) + 1); - isc_mem_put(lctx->mctx, channel, sizeof(*channel)); + isc_mem_put(mctx, channel->name, strlen(channel->name) + 1); + isc_mem_put(mctx, channel, sizeof(*channel)); return (ISC_R_UNEXPECTED); } - channel->next = lctx->channels; - lctx->channels = channel; + channel->next = lcfg->channels; + lcfg->channels = channel; /* * If default_stderr was redefined, make the default category * point to the new default_stderr. - * XXX I find this odd. */ if (strcmp(name, "default_stderr") == 0) 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_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_log_t *lctx; isc_logchannel_t *channel; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; unsigned int i; - REQUIRE(VALID_CONTEXT(lctx)); + REQUIRE(VALID_CONFIG(lcfg)); REQUIRE(name != NULL); + + lctx = lcfg->lctx; + REQUIRE(category == NULL || category->id < lctx->category_count); REQUIRE(module == NULL || module->id < lctx->module_count); - for (channel = lctx->channels; channel != NULL; + for (channel = lcfg->channels; channel != NULL; channel = channel->next) if (strcmp(name, channel->name) == 0) break; @@ -497,13 +619,8 @@ isc_log_usechannel(isc_log_t *lctx, const char *name, if (channel == NULL) return (ISC_R_NOTFOUND); - /* - * Silence bogus GCC warning, "`result' might be used uninitialized". - */ - result = ISC_R_SUCCESS; - if (category != NULL) - result = assignchannel(lctx, category->id, module, channel); + result = assignchannel(lcfg, category->id, module, channel); else /* @@ -511,7 +628,7 @@ isc_log_usechannel(isc_log_t *lctx, const char *name, * the default channel. */ 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) break; } @@ -590,17 +707,17 @@ isc_log_getdebuglevel(isc_log_t *lctx) { } void -isc_log_setduplicateinterval(isc_log_t *lctx, unsigned int interval) { - REQUIRE(VALID_CONTEXT(lctx)); +isc_log_setduplicateinterval(isc_logconfig_t *lcfg, unsigned int interval) { + REQUIRE(VALID_CONFIG(lcfg)); - lctx->duplicate_interval = interval; + lcfg->duplicate_interval = interval; } unsigned int -isc_log_getduplicateinterval(isc_log_t *lctx) { - REQUIRE(VALID_CONTEXT(lctx)); +isc_log_getduplicateinterval(isc_logconfig_t *lcfg) { + REQUIRE(VALID_CONTEXT(lcfg)); - return (lctx->duplicate_interval); + return (lcfg->duplicate_interval); } /* XXXDCL NT -- This interface will assuredly be changing. */ @@ -615,7 +732,9 @@ isc_log_closefilelogs(isc_log_t *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 && FILE_STREAM(channel) != NULL) { (void)fclose(FILE_STREAM(channel)); @@ -628,16 +747,28 @@ isc_log_closefilelogs(isc_log_t *lctx) { ****/ 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_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(module == NULL || module->id < lctx->module_count); 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, sizeof(*new_item)); if (new_item == NULL) @@ -645,16 +776,52 @@ assignchannel(isc_log_t *lctx, unsigned int category_id, new_item->channel = channel; 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); } static unsigned int -greatest_version(isc_logchannel_t *channel) -{ +greatest_version(isc_logchannel_t *channel) { /* XXXDCL HIGHLY NT */ char *dirname, *basename, *digit_end; int version, greatest = -1; @@ -836,6 +1003,7 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, struct tm *timeptr; time_t now; isc_boolean_t matched = ISC_FALSE; + isc_logconfig_t *lcfg; isc_logchannel_t *channel; isc_logchannellist_t *category_channels; isc_result_t result; @@ -859,10 +1027,11 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, level_string[0] = '\0'; lctx->buffer[0] = '\0'; - category_channels = lctx->categories[category->id]; + LOCK(&lctx->lock); - if (isc_mutex_lock(&lctx->lock) != ISC_R_SUCCESS) - return; + lcfg = lctx->logconfig; + + category_channels = lcfg->channellists[category->id]; /* * 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; if (category_channels == NULL && ! matched && - category_channels != lctx->categories[0]) + category_channels != lcfg->channellists[0]) /* * No category/module pair was explicitly configured. * Try the category named "default". */ - category_channels = lctx->categories[0]; + category_channels = lcfg->channellists[0]; 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_set(&interval, - lctx->duplicate_interval, 0); + lcfg->duplicate_interval, 0); /* * '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 * the history. * - * XXX Setting the interval + * Setting the interval to be * to be longer will obviously * not cause the expired * message to spring back into * existence. */ - new = message->next; + new = ISC_LIST_NEXT(message, + link); + + ISC_LIST_UNLINK(lctx->messages, + message, link); + isc_mem_put(lctx->mctx, message, sizeof(*message) + 1 + 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; continue; } @@ -1012,11 +1175,11 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, * Unlock the mutex and * get the hell out of Dodge. */ - isc_mutex_unlock(&lctx->lock); + UNLOCK(&lctx->lock); 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 * to immediately expire on * the next call to [v]write1. - * XXX ok? + * What's a fella to do if + * getting the time fails? */ isc_time_settoepoch(&new->time); - new->next = NULL; - - if (ISC_LIST_EMPTY(lctx->messages)) { - lctx->messages.head = new; - lctx->messages.tail = new; - } else { - lctx->messages.tail->next = - new; - lctx->messages.tail = new; - } + ISC_LIST_APPEND(lctx->messages, + new, link); } } } @@ -1145,5 +1301,5 @@ isc_log_doit(isc_log_t *lctx, isc_logcategory_t *category, } while (1); - isc_mutex_unlock(&lctx->lock); + UNLOCK(&lctx->lock); }