Import 1.9b4 NSS tag from cvs
[mozilla-nss.git] / security / nss / lib / libpkix / pkix / util / pkix_logger.c
blob433a9c32f3b456c5d17be8588c0c642aa45541d3
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
21 * Contributor(s):
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 * pkix_logger.c
40 * Logger Object Functions
44 #include "pkix_logger.h"
46 /* Global variable to keep PKIX_Logger List */
47 PKIX_List *pkixLoggers = NULL;
50 * Once the Logger has been set, for any logging related operations, we have
51 * to go through the List to find a match, and if found, issue the
52 * corresponding callback. The overhead to check for DEBUG and TRACE in each
53 * PKIX function entering and exiting is very expensive (400X), and redundant
54 * if they are not the interest of the Logger. Therefore, the PKIX_Logger List
55 * pkixLoggers is separated into two lists based on its Loggers' trace level.
57 * Whenever the pkixLoggers List is updated by PKIX_Logger_AddLogger() or
58 * PKIX_Logger_SetLoggers(), we destroy and reconstruct pkixLoggersErrors
59 * and pkixLoggersDebugTrace Logger Lists. The ERROR, FATAL_ERROR and
60 * WARNING goes to pkixLoggersErrors and the DEBUG and TRACE goes to
61 * pkixLoggersDebugTrace.
63 * Currently we provide five logging levels and the default setting are by:
65 * PKIX_FATAL_ERROR() macro invokes pkix_Logger_Check of FATAL_ERROR level
66 * PKIX_ERROR() macro invokes pkix_Logger_Check of ERROR level
67 * WARNING is not invoked as default
68 * PKIX_DEBUG() macro invokes pkix_Logger_Check of DEBUG level. This needs
69 * compilation -DPKIX_<component>DEBUG flag to turn on
70 * PKIX_ENTER() and PKIX_RETURN() macros invoke pkix_Logger_Check of TRACE
71 * level. TRACE provides duplicate information of DEBUG, but needs no
72 * recompilation and cannot choose component. To allow application
73 * to use DEBUG level, TRACE is put as last.
76 PKIX_List *pkixLoggersErrors = NULL;
77 PKIX_List *pkixLoggersDebugTrace = NULL;
79 /* To ensure atomic update on pkixLoggers lists */
80 PKIX_PL_MonitorLock *pkixLoggerLock = NULL;
82 /* --Private-Functions-------------------------------------------- */
85 * FUNCTION: pkix_Logger_CheckErrors
86 * DESCRIPTION:
88 * This function goes through each PKIX_Logger at "pkixLoggersList" and
89 * checks if "maxLevel" and "logComponent" satisfies what is specified in the
90 * PKIX_Logger. If satisfies, it invokes the callback in PKIX_Logger and
91 * passes a PKIX_PL_String that is the concatenation of "message" and
92 * "message2" to the application for processing.
93 * Since this call is inserted into a handful of PKIX macros, no macros are
94 * applied in this function, to avoid infinite recursion.
95 * If an error occurs, this call is aborted.
97 * PARAMETERS:
98 * "pkixLoggersList"
99 * A list of PKIX_Loggers to be examined for invoking callback. Must be
100 * non-NULL.
101 * "message"
102 * Address of "message" to be logged. Must be non-NULL.
103 * "message2"
104 * Address of "message2" to be concatenated and logged. May be NULL.
105 * "logComponent"
106 * A PKIX_UInt32 that indicates the component the message is from.
107 * "maxLevel"
108 * A PKIX_UInt32 that represents the level of severity of the message.
109 * "plContext"
110 * Platform-specific context pointer.
111 * THREAD SAFETY:
112 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
113 * RETURNS:
114 * Returns NULL if the function succeeds
115 * Returns a Fatal Error if the function fails in an unrecoverable way
117 PKIX_Error *
118 pkix_Logger_Check(
119 PKIX_List *pkixLoggersList,
120 const char *message,
121 const char *message2,
122 PKIX_ERRORCLASS logComponent,
123 PKIX_UInt32 currentLevel,
124 void *plContext)
126 PKIX_Logger *logger = NULL;
127 PKIX_List *savedPkixLoggersErrors = NULL;
128 PKIX_List *savedPkixLoggersDebugTrace = NULL;
129 PKIX_PL_String *formatString = NULL;
130 PKIX_PL_String *messageString = NULL;
131 PKIX_PL_String *message2String = NULL;
132 PKIX_PL_String *msgString = NULL;
133 PKIX_Error *error = NULL;
134 PKIX_Boolean needLogging = PKIX_FALSE;
135 PKIX_UInt32 i, length;
138 * We cannot use any the PKIX_ macros here, since this function is
139 * called from some of these macros. It can create infinite recursion.
142 if ((pkixLoggersList == NULL) || (message == NULL)) {
143 return(NULL);
147 * Disable all subsequent loggings to avoid recursion. The result is
148 * if other thread is calling this function at the same time, there
149 * won't be any logging because the pkixLoggersErrors and
150 * pkixLoggersDebugTrace are set to null.
151 * It would be nice if we provide control per thread (e.g. make
152 * plContext threadable) then we can avoid the recursion by setting
153 * flag at plContext. Then other thread's logging won't be affected.
155 * Also we need to use a reentrant Lock. Although we avoid recursion
156 * for TRACE. When there is an ERROR occurs in subsequent call, this
157 * function will be called.
160 error = PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext);
161 if (error) { return(NULL); }
163 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
164 pkixLoggersDebugTrace = NULL;
165 savedPkixLoggersErrors = pkixLoggersErrors;
166 pkixLoggersErrors = NULL;
168 /* Convert message and message2 to String */
169 error = PKIX_PL_String_Create
170 (PKIX_ESCASCII, message, 0, &messageString, plContext);
171 if (error) { goto cleanup; }
173 if (message2) {
174 error = PKIX_PL_String_Create
175 (PKIX_ESCASCII, message2, 0, &message2String, plContext);
176 if (error) { goto cleanup; }
177 error = PKIX_PL_String_Create
178 (PKIX_ESCASCII, "%s %s", 0, &formatString, plContext);
179 if (error) { goto cleanup; }
181 } else {
182 error = PKIX_PL_String_Create
183 (PKIX_ESCASCII, "%s", 0, &formatString, plContext);
184 if (error) { goto cleanup; }
188 error = PKIX_PL_Sprintf
189 (&msgString,
190 plContext,
191 formatString,
192 messageString,
193 message2String);
194 if (error) { goto cleanup; }
196 /* Go through the Logger list */
198 error = PKIX_List_GetLength(pkixLoggersList, &length, plContext);
199 if (error) { goto cleanup; }
201 for (i = 0; i < length; i++) {
203 error = PKIX_List_GetItem
204 (pkixLoggersList,
206 (PKIX_PL_Object **) &logger,
207 plContext);
208 if (error) { goto cleanup; }
210 /* Intended logging level less or equal than the max */
211 needLogging = (currentLevel <= logger->maxLevel);
213 if (needLogging && (logger->callback)) {
216 * We separate Logger into two lists based on log level
217 * but log level is not modified. We need to check here to
218 * avoid logging the higher log level (lower value) twice.
220 if (pkixLoggersList == pkixLoggersErrors) {
221 needLogging = needLogging &&
222 (currentLevel <= PKIX_LOGGER_LEVEL_WARNING);
223 } else if (pkixLoggersList == pkixLoggersDebugTrace) {
224 needLogging = needLogging &&
225 (currentLevel > PKIX_LOGGER_LEVEL_WARNING);
228 if (needLogging) {
229 if (logComponent == logger->logComponent) {
230 needLogging = PKIX_TRUE;
231 } else {
232 needLogging = PKIX_FALSE;
236 if (needLogging) {
237 error = logger->callback
238 (logger,
239 msgString,
240 currentLevel,
241 logComponent,
242 plContext);
243 if (error) { goto cleanup; }
247 error = PKIX_PL_Object_DecRef
248 ((PKIX_PL_Object *)logger, plContext);
249 logger = NULL;
250 if (error) { goto cleanup; }
254 cleanup:
256 if (formatString) {
257 error = PKIX_PL_Object_DecRef
258 ((PKIX_PL_Object *)formatString, plContext);
261 if (messageString) {
262 error = PKIX_PL_Object_DecRef
263 ((PKIX_PL_Object *)messageString, plContext);
266 if (message2String) {
267 error = PKIX_PL_Object_DecRef
268 ((PKIX_PL_Object *)message2String, plContext);
271 if (msgString) {
272 error = PKIX_PL_Object_DecRef
273 ((PKIX_PL_Object *)msgString, plContext);
276 if (logger) {
277 error = PKIX_PL_Object_DecRef
278 ((PKIX_PL_Object *)logger, plContext);
281 if (pkixLoggersErrors == NULL && savedPkixLoggersErrors != NULL) {
282 pkixLoggersErrors = savedPkixLoggersErrors;
285 if (pkixLoggersDebugTrace == NULL &&
286 savedPkixLoggersDebugTrace != NULL) {
287 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
290 error = PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext);
291 if (error) { return(NULL); }
293 return(NULL);
297 * FUNCTION: pkix_Logger_Destroy
298 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
300 static PKIX_Error *
301 pkix_Logger_Destroy(
302 PKIX_PL_Object *object,
303 void *plContext)
305 PKIX_Logger *logger = NULL;
307 PKIX_ENTER(LOGGER, "pkix_Logger_Destroy");
308 PKIX_NULLCHECK_ONE(object);
310 /* Check that this object is a logger */
311 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
312 PKIX_OBJECTNOTLOGGER);
314 logger = (PKIX_Logger *)object;
316 /* We have a valid logger. DecRef its item and recurse on next */
318 logger->callback = NULL;
319 PKIX_DECREF(logger->context);
320 logger->logComponent = (PKIX_ERRORCLASS)NULL;
322 cleanup:
324 PKIX_RETURN(LOGGER);
328 * FUNCTION: pkix_Logger_ToString
329 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
331 static PKIX_Error *
332 pkix_Logger_ToString(
333 PKIX_PL_Object *object,
334 PKIX_PL_String **pString,
335 void *plContext)
337 PKIX_Logger *logger = NULL;
338 char *asciiFormat = NULL;
339 PKIX_PL_String *formatString = NULL;
340 PKIX_PL_String *contextString = NULL;
341 PKIX_PL_String *componentString = NULL;
342 PKIX_PL_String *loggerString = NULL;
344 PKIX_ENTER(LOGGER, "pkix_Logger_ToString_Helper");
345 PKIX_NULLCHECK_TWO(object, pString);
347 /* Check that this object is a logger */
348 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
349 PKIX_OBJECTNOTLOGGER);
351 logger = (PKIX_Logger *)object;
353 asciiFormat =
354 "[\n"
355 "\tLogger: \n"
356 "\tContext: %s\n"
357 "\tMaximum Level: %d\n"
358 "\tComponent Name: %s\n"
359 "]\n";
361 PKIX_CHECK(PKIX_PL_String_Create
362 (PKIX_ESCASCII,
363 asciiFormat,
365 &formatString,
366 plContext),
367 PKIX_STRINGCREATEFAILED);
369 PKIX_TOSTRING(logger->context, &contextString, plContext,
370 PKIX_OBJECTTOSTRINGFAILED);
372 PKIX_CHECK(PKIX_PL_String_Create
373 (PKIX_ESCASCII,
374 (void *)PKIX_ERRORCLASSNAMES[logger->logComponent],
376 &componentString,
377 plContext),
378 PKIX_STRINGCREATEFAILED);
380 PKIX_CHECK(PKIX_PL_Sprintf
381 (&loggerString,
382 plContext,
383 formatString,
384 contextString,
385 logger->maxLevel,
386 componentString),
387 PKIX_SPRINTFFAILED);
389 *pString = loggerString;
391 cleanup:
393 PKIX_DECREF(formatString);
394 PKIX_DECREF(contextString);
395 PKIX_RETURN(LOGGER);
399 * FUNCTION: pkix_Logger_Equals
400 * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
402 static PKIX_Error *
403 pkix_Logger_Equals(
404 PKIX_PL_Object *first,
405 PKIX_PL_Object *second,
406 PKIX_Boolean *pResult,
407 void *plContext)
409 PKIX_UInt32 secondType;
410 PKIX_Boolean cmpResult;
411 PKIX_Logger *firstLogger = NULL;
412 PKIX_Logger *secondLogger = NULL;
413 PKIX_UInt32 i = 0;
415 PKIX_ENTER(LOGGER, "pkix_Logger_Equals");
416 PKIX_NULLCHECK_THREE(first, second, pResult);
418 /* test that first is a Logger */
419 PKIX_CHECK(pkix_CheckType(first, PKIX_LOGGER_TYPE, plContext),
420 PKIX_FIRSTOBJECTNOTLOGGER);
423 * Since we know first is a Logger, if both references are
424 * identical, they must be equal
426 if (first == second){
427 *pResult = PKIX_TRUE;
428 goto cleanup;
432 * If second isn't a Logger, we don't throw an error.
433 * We simply return a Boolean result of FALSE
435 *pResult = PKIX_FALSE;
436 PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
437 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
438 if (secondType != PKIX_LOGGER_TYPE) goto cleanup;
440 firstLogger = (PKIX_Logger *)first;
441 secondLogger = (PKIX_Logger *)second;
443 cmpResult = PKIX_FALSE;
445 if (firstLogger->callback != secondLogger->callback) {
446 goto cleanup;
449 if (firstLogger->logComponent != secondLogger->logComponent) {
450 goto cleanup;
453 PKIX_EQUALS
454 (firstLogger->context,
455 secondLogger->context,
456 &cmpResult,
457 plContext,
458 PKIX_OBJECTEQUALSFAILED);
460 if (cmpResult == PKIX_FALSE) {
461 goto cleanup;
464 if (firstLogger->maxLevel != secondLogger->maxLevel) {
465 goto cleanup;
468 *pResult = cmpResult;
470 cleanup:
472 PKIX_RETURN(LOGGER);
476 * FUNCTION: pkix_Logger_Hashcode
477 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
479 static PKIX_Error *
480 pkix_Logger_Hashcode(
481 PKIX_PL_Object *object,
482 PKIX_UInt32 *pHashcode,
483 void *plContext)
485 PKIX_Logger *logger = NULL;
486 PKIX_UInt32 hash = 0;
487 PKIX_UInt32 tempHash = 0;
489 PKIX_ENTER(LOGGER, "pkix_Logger_Hashcode");
490 PKIX_NULLCHECK_TWO(object, pHashcode);
492 PKIX_CHECK(pkix_CheckType(object, PKIX_LOGGER_TYPE, plContext),
493 PKIX_OBJECTNOTLOGGER);
495 logger = (PKIX_Logger *)object;
497 PKIX_HASHCODE(logger->context, &tempHash, plContext,
498 PKIX_OBJECTHASHCODEFAILED);
500 hash = (((((PKIX_UInt32) logger->callback + tempHash) << 7) +
501 logger->maxLevel) << 7) + (PKIX_UInt32)logger->logComponent;
503 *pHashcode = hash;
505 cleanup:
507 PKIX_RETURN(LOGGER);
512 * FUNCTION: pkix_Logger_Duplicate
513 * (see comments for PKIX_PL_DuplicateCallback in pkix_pl_system.h)
515 static PKIX_Error *
516 pkix_Logger_Duplicate(
517 PKIX_PL_Object *object,
518 PKIX_PL_Object **pNewObject,
519 void *plContext)
521 PKIX_Logger *logger = NULL;
522 PKIX_Logger *dupLogger = NULL;
524 PKIX_ENTER(LOGGER, "pkix_Logger_Duplicate");
525 PKIX_NULLCHECK_TWO(object, pNewObject);
527 PKIX_CHECK(pkix_CheckType
528 ((PKIX_PL_Object *)object, PKIX_LOGGER_TYPE, plContext),
529 PKIX_OBJECTNOTLOGGER);
531 logger = (PKIX_Logger *) object;
533 PKIX_CHECK(PKIX_PL_Object_Alloc
534 (PKIX_LOGGER_TYPE,
535 sizeof (PKIX_Logger),
536 (PKIX_PL_Object **)&dupLogger,
537 plContext),
538 PKIX_COULDNOTCREATELOGGEROBJECT);
540 dupLogger->callback = logger->callback;
541 dupLogger->maxLevel = logger->maxLevel;
543 PKIX_DUPLICATE
544 (logger->context,
545 &dupLogger->context,
546 plContext,
547 PKIX_OBJECTDUPLICATEFAILED);
549 dupLogger->logComponent = logger->logComponent;
551 *pNewObject = (PKIX_PL_Object *) dupLogger;
553 cleanup:
555 if (PKIX_ERROR_RECEIVED){
556 PKIX_DECREF(dupLogger);
559 PKIX_RETURN(LOGGER);
563 * FUNCTION: pkix_Logger_RegisterSelf
564 * DESCRIPTION:
565 * Registers PKIX_LOGGER_TYPE and its related functions with systemClasses[]
566 * THREAD SAFETY:
567 * Not Thread Safe - for performance and complexity reasons
569 * Since this function is only called by PKIX_PL_Initialize, which should
570 * only be called once, it is acceptable that this function is not
571 * thread-safe.
573 PKIX_Error *
574 pkix_Logger_RegisterSelf(void *plContext)
576 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
577 pkix_ClassTable_Entry entry;
579 PKIX_ENTER(LOGGER, "pkix_Logger_RegisterSelf");
581 entry.description = "Logger";
582 entry.objCounter = 0;
583 entry.typeObjectSize = sizeof(PKIX_Logger);
584 entry.destructor = pkix_Logger_Destroy;
585 entry.equalsFunction = pkix_Logger_Equals;
586 entry.hashcodeFunction = pkix_Logger_Hashcode;
587 entry.toStringFunction = pkix_Logger_ToString;
588 entry.comparator = NULL;
589 entry.duplicateFunction = pkix_Logger_Duplicate;
591 systemClasses[PKIX_LOGGER_TYPE] = entry;
593 PKIX_RETURN(LOGGER);
596 /* --Public-Logger-Functions--------------------------------------------- */
599 * FUNCTION: PKIX_Logger_Create (see comments in pkix_util.h)
601 PKIX_Error *
602 PKIX_Logger_Create(
603 PKIX_Logger_LogCallback callback,
604 PKIX_PL_Object *loggerContext,
605 PKIX_Logger **pLogger,
606 void *plContext)
608 PKIX_Logger *logger = NULL;
610 PKIX_ENTER(LOGGER, "PKIX_Logger_Create");
611 PKIX_NULLCHECK_ONE(pLogger);
613 PKIX_CHECK(PKIX_PL_Object_Alloc
614 (PKIX_LOGGER_TYPE,
615 sizeof (PKIX_Logger),
616 (PKIX_PL_Object **)&logger,
617 plContext),
618 PKIX_COULDNOTCREATELOGGEROBJECT);
620 logger->callback = callback;
621 logger->maxLevel = 0;
622 logger->logComponent = (PKIX_ERRORCLASS)NULL;
624 PKIX_INCREF(loggerContext);
625 logger->context = loggerContext;
627 *pLogger = logger;
628 logger = NULL;
630 cleanup:
632 PKIX_DECREF(logger);
634 PKIX_RETURN(LOGGER);
638 * FUNCTION: PKIX_Logger_GetLogCallback (see comments in pkix_util.h)
640 PKIX_Error *
641 PKIX_Logger_GetLogCallback(
642 PKIX_Logger *logger,
643 PKIX_Logger_LogCallback *pCallback,
644 void *plContext)
646 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLogCallback");
647 PKIX_NULLCHECK_TWO(logger, pCallback);
649 *pCallback = logger->callback;
651 PKIX_RETURN(LOGGER);
655 * FUNCTION: PKIX_Logger_GetLoggerContext (see comments in pkix_util.h)
657 PKIX_Error *
658 PKIX_Logger_GetLoggerContext(
659 PKIX_Logger *logger,
660 PKIX_PL_Object **pLoggerContext,
661 void *plContext)
663 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggerContex");
664 PKIX_NULLCHECK_TWO(logger, pLoggerContext);
666 PKIX_INCREF(logger->context);
667 *pLoggerContext = logger->context;
669 cleanup:
670 PKIX_RETURN(LOGGER);
674 * FUNCTION: PKIX_Logger_GetMaxLoggingLevel (see comments in pkix_util.h)
676 PKIX_Error *
677 PKIX_Logger_GetMaxLoggingLevel(
678 PKIX_Logger *logger,
679 PKIX_UInt32 *pLevel,
680 void *plContext)
682 PKIX_ENTER(LOGGER, "PKIX_Logger_GetMaxLoggingLevel");
683 PKIX_NULLCHECK_TWO(logger, pLevel);
685 *pLevel = logger->maxLevel;
687 PKIX_RETURN(LOGGER);
691 * FUNCTION: PKIX_Logger_SetMaxLoggingLevel (see comments in pkix_util.h)
693 PKIX_Error *
694 PKIX_Logger_SetMaxLoggingLevel(
695 PKIX_Logger *logger,
696 PKIX_UInt32 level,
697 void *plContext)
699 PKIX_ENTER(LOGGER, "PKIX_Logger_SetMaxLoggingLevel");
700 PKIX_NULLCHECK_ONE(logger);
702 if (level > PKIX_LOGGER_LEVEL_MAX) {
703 PKIX_ERROR(PKIX_LOGGINGLEVELEXCEEDSMAXIMUM);
704 } else {
705 logger->maxLevel = level;
708 cleanup:
710 PKIX_RETURN(LOGGER);
714 * FUNCTION: PKIX_Logger_GetLoggingComponent (see comments in pkix_util.h)
716 PKIX_Error *
717 PKIX_Logger_GetLoggingComponent(
718 PKIX_Logger *logger,
719 PKIX_ERRORCLASS *pComponent,
720 void *plContext)
722 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggingComponent");
723 PKIX_NULLCHECK_TWO(logger, pComponent);
725 *pComponent = logger->logComponent;
727 PKIX_RETURN(LOGGER);
731 * FUNCTION: PKIX_Logger_SetLoggingComponent (see comments in pkix_util.h)
733 PKIX_Error *
734 PKIX_Logger_SetLoggingComponent(
735 PKIX_Logger *logger,
736 PKIX_ERRORCLASS component,
737 void *plContext)
739 PKIX_ENTER(LOGGER, "PKIX_Logger_SetLoggingComponent");
740 PKIX_NULLCHECK_ONE(logger);
742 logger->logComponent = component;
744 PKIX_RETURN(LOGGER);
749 * Following PKIX_GetLoggers(), PKIX_SetLoggers() and PKIX_AddLogger() are
750 * documented as not thread-safe. However they are thread-safe now. We need
751 * the lock when accessing the logger lists.
755 * FUNCTION: PKIX_Logger_GetLoggers (see comments in pkix_util.h)
757 PKIX_Error *
758 PKIX_GetLoggers(
759 PKIX_List **pLoggers, /* list of PKIX_Logger */
760 void *plContext)
762 PKIX_List *list = NULL;
763 PKIX_List *savedPkixLoggersDebugTrace = NULL;
764 PKIX_List *savedPkixLoggersErrors = NULL;
765 PKIX_Logger *logger = NULL;
766 PKIX_Logger *dupLogger = NULL;
767 PKIX_UInt32 i, length;
768 PKIX_Boolean locked = PKIX_FALSE;
770 PKIX_ENTER(LOGGER, "PKIX_Logger_GetLoggers");
771 PKIX_NULLCHECK_ONE(pLoggers);
773 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
774 PKIX_MONITORLOCKENTERFAILED);
775 locked = PKIX_TRUE;
778 * Temporarily disable DEBUG/TRACE Logging to avoid possible
779 * deadlock:
780 * When the Logger List is being accessed, e.g. by PKIX_ENTER or
781 * PKIX_DECREF, pkix_Logger_Check may check whether logging
782 * is requested, creating a deadlock situation.
784 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
785 pkixLoggersDebugTrace = NULL;
786 savedPkixLoggersErrors = pkixLoggersErrors;
787 pkixLoggersErrors = NULL;
789 if (pkixLoggers == NULL) {
790 length = 0;
791 } else {
792 PKIX_CHECK(PKIX_List_GetLength
793 (pkixLoggers, &length, plContext),
794 PKIX_LISTGETLENGTHFAILED);
797 /* Create a list and copy the pkixLoggers item to the list */
798 PKIX_CHECK(PKIX_List_Create(&list, plContext),
799 PKIX_LISTCREATEFAILED);
801 for (i = 0; i < length; i++) {
803 PKIX_CHECK(PKIX_List_GetItem
804 (pkixLoggers,
806 (PKIX_PL_Object **) &logger,
807 plContext),
808 PKIX_LISTGETITEMFAILED);
810 PKIX_CHECK(pkix_Logger_Duplicate
811 ((PKIX_PL_Object *)logger,
812 (PKIX_PL_Object **)&dupLogger,
813 plContext),
814 PKIX_LOGGERDUPLICATEFAILED);
816 PKIX_CHECK(PKIX_List_AppendItem
817 (list,
818 (PKIX_PL_Object *) dupLogger,
819 plContext),
820 PKIX_LISTAPPENDITEMFAILED);
822 PKIX_DECREF(logger);
823 PKIX_DECREF(dupLogger);
826 /* Set the list to be immutable */
827 PKIX_CHECK(PKIX_List_SetImmutable(list, plContext),
828 PKIX_LISTSETIMMUTABLEFAILED);
830 *pLoggers = list;
832 cleanup:
834 PKIX_DECREF(logger);
836 /* Restore logging capability */
837 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
838 pkixLoggersErrors = savedPkixLoggersErrors;
840 if (locked) {
841 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
842 PKIX_MONITORLOCKEXITFAILED);
845 PKIX_RETURN(LOGGER);
849 * FUNCTION: PKIX_Logger_SetLoggers (see comments in pkix_util.h)
851 PKIX_Error *
852 PKIX_SetLoggers(
853 PKIX_List *loggers, /* list of PKIX_Logger */
854 void *plContext)
856 PKIX_List *list = NULL;
857 PKIX_List *savedPkixLoggersErrors = NULL;
858 PKIX_List *savedPkixLoggersDebugTrace = NULL;
859 PKIX_Logger *logger = NULL;
860 PKIX_Logger *dupLogger = NULL;
861 PKIX_Boolean locked = PKIX_FALSE;
862 PKIX_UInt32 i, length;
864 PKIX_ENTER(LOGGER, "PKIX_SetLoggers");
866 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
867 PKIX_MONITORLOCKENTERFAILED);
868 locked = PKIX_TRUE;
870 /* Disable tracing, etc. to avoid recursion and deadlock */
871 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
872 pkixLoggersDebugTrace = NULL;
873 savedPkixLoggersErrors = pkixLoggersErrors;
874 pkixLoggersErrors = NULL;
876 /* discard any prior loggers */
877 PKIX_DECREF(pkixLoggers);
878 PKIX_DECREF(savedPkixLoggersErrors);
879 PKIX_DECREF(savedPkixLoggersDebugTrace);
881 if (loggers != NULL) {
883 PKIX_CHECK(PKIX_List_Create(&list, plContext),
884 PKIX_LISTCREATEFAILED);
886 PKIX_CHECK(PKIX_List_GetLength(loggers, &length, plContext),
887 PKIX_LISTGETLENGTHFAILED);
889 for (i = 0; i < length; i++) {
891 PKIX_CHECK(PKIX_List_GetItem
892 (loggers,
894 (PKIX_PL_Object **) &logger,
895 plContext),
896 PKIX_LISTGETITEMFAILED);
898 PKIX_CHECK(pkix_Logger_Duplicate
899 ((PKIX_PL_Object *)logger,
900 (PKIX_PL_Object **)&dupLogger,
901 plContext),
902 PKIX_LOGGERDUPLICATEFAILED);
904 PKIX_CHECK(PKIX_List_AppendItem
905 (list,
906 (PKIX_PL_Object *) dupLogger,
907 plContext),
908 PKIX_LISTAPPENDITEMFAILED);
910 /* Make two lists */
912 /* Put in pkixLoggersErrors in any case*/
914 if (savedPkixLoggersErrors == NULL) {
916 PKIX_CHECK(PKIX_List_Create
917 (&savedPkixLoggersErrors,
918 plContext),
919 PKIX_LISTCREATEFAILED);
922 PKIX_CHECK(PKIX_List_AppendItem
923 (savedPkixLoggersErrors,
924 (PKIX_PL_Object *) dupLogger,
925 plContext),
926 PKIX_LISTAPPENDITEMFAILED);
928 if (logger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
930 /* Put in pkixLoggersDebugTrace */
932 if (savedPkixLoggersDebugTrace == NULL) {
934 PKIX_CHECK(PKIX_List_Create
935 (&savedPkixLoggersDebugTrace,
936 plContext),
937 PKIX_LISTCREATEFAILED);
940 PKIX_CHECK(PKIX_List_AppendItem
941 (savedPkixLoggersDebugTrace,
942 (PKIX_PL_Object *) dupLogger,
943 plContext),
944 PKIX_LISTAPPENDITEMFAILED);
946 PKIX_DECREF(logger);
947 PKIX_DECREF(dupLogger);
951 pkixLoggers = list;
954 cleanup:
956 if (PKIX_ERROR_RECEIVED){
957 PKIX_DECREF(list);
958 PKIX_DECREF(savedPkixLoggersErrors);
959 PKIX_DECREF(savedPkixLoggersDebugTrace);
960 pkixLoggers = NULL;
963 PKIX_DECREF(logger);
965 /* Reenable logging capability with new lists */
966 pkixLoggersErrors = savedPkixLoggersErrors;
967 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
969 if (locked) {
970 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
971 PKIX_MONITORLOCKEXITFAILED);
974 PKIX_RETURN(LOGGER);
978 * FUNCTION: PKIX_Logger_AddLogger (see comments in pkix_util.h)
980 PKIX_Error *
981 PKIX_AddLogger(
982 PKIX_Logger *logger,
983 void *plContext)
985 PKIX_Logger *dupLogger = NULL;
986 PKIX_Logger *addLogger = NULL;
987 PKIX_List *savedPkixLoggersErrors = NULL;
988 PKIX_List *savedPkixLoggersDebugTrace = NULL;
989 PKIX_Boolean locked = PKIX_FALSE;
990 PKIX_UInt32 i, length;
992 PKIX_ENTER(LOGGER, "PKIX_Logger_AddLogger");
993 PKIX_NULLCHECK_ONE(logger);
995 PKIX_CHECK(PKIX_PL_MonitorLock_Enter(pkixLoggerLock, plContext),
996 PKIX_MONITORLOCKENTERFAILED);
997 locked = PKIX_TRUE;
999 savedPkixLoggersDebugTrace = pkixLoggersDebugTrace;
1000 pkixLoggersDebugTrace = NULL;
1001 savedPkixLoggersErrors = pkixLoggersErrors;
1002 pkixLoggersErrors = NULL;
1004 PKIX_DECREF(savedPkixLoggersErrors);
1005 PKIX_DECREF(savedPkixLoggersDebugTrace);
1007 if (pkixLoggers == NULL) {
1009 PKIX_CHECK(PKIX_List_Create(&pkixLoggers, plContext),
1010 PKIX_LISTCREATEFAILED);
1013 PKIX_CHECK(pkix_Logger_Duplicate
1014 ((PKIX_PL_Object *)logger,
1015 (PKIX_PL_Object **)&dupLogger,
1016 plContext),
1017 PKIX_LOGGERDUPLICATEFAILED);
1019 PKIX_CHECK(PKIX_List_AppendItem
1020 (pkixLoggers,
1021 (PKIX_PL_Object *) dupLogger,
1022 plContext),
1023 PKIX_LISTAPPENDITEMFAILED);
1025 PKIX_CHECK(PKIX_List_GetLength(pkixLoggers, &length, plContext),
1026 PKIX_LISTGETLENGTHFAILED);
1028 /* Reconstruct pkixLoggersErrors and pkixLoggersDebugTrace */
1029 for (i = 0; i < length; i++) {
1031 PKIX_CHECK(PKIX_List_GetItem
1032 (pkixLoggers,
1034 (PKIX_PL_Object **) &addLogger,
1035 plContext),
1036 PKIX_LISTGETITEMFAILED);
1039 /* Put in pkixLoggersErrors */
1041 if (savedPkixLoggersErrors == NULL) {
1043 PKIX_CHECK(PKIX_List_Create
1044 (&savedPkixLoggersErrors,
1045 plContext),
1046 PKIX_LISTCREATEFAILED);
1049 PKIX_CHECK(PKIX_List_AppendItem
1050 (savedPkixLoggersErrors,
1051 (PKIX_PL_Object *) addLogger,
1052 plContext),
1053 PKIX_LISTAPPENDITEMFAILED);
1055 if (addLogger->maxLevel > PKIX_LOGGER_LEVEL_WARNING) {
1057 /* Put in pkixLoggersDebugTrace */
1059 if (savedPkixLoggersDebugTrace == NULL) {
1061 PKIX_CHECK(PKIX_List_Create
1062 (&savedPkixLoggersDebugTrace,
1063 plContext),
1064 PKIX_LISTCREATEFAILED);
1067 PKIX_CHECK(PKIX_List_AppendItem
1068 (savedPkixLoggersDebugTrace,
1069 (PKIX_PL_Object *) addLogger,
1070 plContext),
1071 PKIX_LISTAPPENDITEMFAILED);
1074 PKIX_DECREF(addLogger);
1078 cleanup:
1080 PKIX_DECREF(dupLogger);
1081 PKIX_DECREF(addLogger);
1083 /* Restore logging capability */
1084 pkixLoggersErrors = savedPkixLoggersErrors;
1085 pkixLoggersDebugTrace = savedPkixLoggersDebugTrace;
1087 if (locked) {
1088 PKIX_CHECK(PKIX_PL_MonitorLock_Exit(pkixLoggerLock, plContext),
1089 PKIX_MONITORLOCKEXITFAILED);
1092 PKIX_RETURN(LOGGER);