xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/dict_debug.c (revision e89934bbf778a6d6d6894877c4da59d0c7835b0f)
1 /*	$NetBSD: dict_debug.c,v 1.2 2017/02/14 01:16:49 christos Exp $	*/
2 
3 /*++
4 /* NAME
5 /*	dict_debug 3
6 /* SUMMARY
7 /*	dictionary manager, logging proxy
8 /* SYNOPSIS
9 /*	#include <dict.h>
10 /*
11 /*	DICT	*dict_debug(dict_handle)
12 /*	DICT	*dict_handle;
13 /*
14 /*	DICT	*DICT_DEBUG(dict_handle)
15 /*	DICT	*dict_handle;
16 /* DESCRIPTION
17 /*	dict_debug() encapsulates the given dictionary object and returns
18 /*	a proxy object that logs all access to the encapsulated object.
19 /*	This is more convenient than having to add logging capability
20 /*	to each individual dictionary access method.
21 /*
22 /*	DICT_DEBUG() is an unsafe macro that returns the original object if
23 /*	the object's debugging flag is not set, and that otherwise encapsulates
24 /*	the object with dict_debug(). This macro simplifies usage by avoiding
25 /*	clumsy expressions. The macro evaluates its argument multiple times.
26 /* DIAGNOSTICS
27 /*	Fatal errors: out of memory.
28 /* LICENSE
29 /* .ad
30 /* .fi
31 /*	The Secure Mailer license must be distributed with this software.
32 /* AUTHOR(S)
33 /*	Wietse Venema
34 /*	IBM T.J. Watson Research
35 /*	P.O. Box 704
36 /*	Yorktown Heights, NY 10598, USA
37 /*--*/
38 
39 /* System libraries. */
40 
41 #include <sys_defs.h>
42 
43 /* Utility library. */
44 
45 #include <msg.h>
46 #include <mymalloc.h>
47 #include <dict.h>
48 
49 /* Application-specific. */
50 
51 typedef struct {
52     DICT    dict;			/* the proxy service */
53     DICT   *real_dict;			/* encapsulated object */
54 } DICT_DEBUG;
55 
56 /* dict_debug_lookup - log lookup operation */
57 
dict_debug_lookup(DICT * dict,const char * key)58 static const char *dict_debug_lookup(DICT *dict, const char *key)
59 {
60     DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
61     DICT   *real_dict = dict_debug->real_dict;
62     const char *result;
63 
64     real_dict->flags = dict->flags;
65     result = dict_get(real_dict, key);
66     dict->flags = real_dict->flags;
67     msg_info("%s:%s lookup: \"%s\" = \"%s\"", dict->type, dict->name, key,
68 	     result ? result : real_dict->error ? "error" : "not_found");
69     DICT_ERR_VAL_RETURN(dict, real_dict->error, result);
70 }
71 
72 /* dict_debug_update - log update operation */
73 
dict_debug_update(DICT * dict,const char * key,const char * value)74 static int dict_debug_update(DICT *dict, const char *key, const char *value)
75 {
76     DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
77     DICT   *real_dict = dict_debug->real_dict;
78     int     result;
79 
80     real_dict->flags = dict->flags;
81     result = dict_put(real_dict, key, value);
82     dict->flags = real_dict->flags;
83     msg_info("%s:%s update: \"%s\" = \"%s\": %s", dict->type, dict->name,
84 	     key, value, result == 0 ? "success" : real_dict->error ?
85 	     "error" : "failed");
86     DICT_ERR_VAL_RETURN(dict, real_dict->error, result);
87 }
88 
89 /* dict_debug_delete - log delete operation */
90 
dict_debug_delete(DICT * dict,const char * key)91 static int dict_debug_delete(DICT *dict, const char *key)
92 {
93     DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
94     DICT   *real_dict = dict_debug->real_dict;
95     int     result;
96 
97     real_dict->flags = dict->flags;
98     result = dict_del(real_dict, key);
99     dict->flags = real_dict->flags;
100     msg_info("%s:%s delete: \"%s\": %s", dict->type, dict->name, key,
101 	     result == 0 ? "success" : real_dict->error ?
102 	     "error" : "failed");
103     DICT_ERR_VAL_RETURN(dict, real_dict->error, result);
104 }
105 
106 /* dict_debug_sequence - log sequence operation */
107 
dict_debug_sequence(DICT * dict,int function,const char ** key,const char ** value)108 static int dict_debug_sequence(DICT *dict, int function,
109 			               const char **key, const char **value)
110 {
111     DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
112     DICT   *real_dict = dict_debug->real_dict;
113     int     result;
114 
115     real_dict->flags = dict->flags;
116     result = dict_seq(real_dict, function, key, value);
117     dict->flags = real_dict->flags;
118     if (result == 0)
119 	msg_info("%s:%s sequence: \"%s\" = \"%s\"", dict->type, dict->name,
120 		 *key, *value);
121     else
122 	msg_info("%s:%s sequence: found EOF", dict->type, dict->name);
123     DICT_ERR_VAL_RETURN(dict, real_dict->error, result);
124 }
125 
126 /* dict_debug_close - log operation */
127 
dict_debug_close(DICT * dict)128 static void dict_debug_close(DICT *dict)
129 {
130     DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
131 
132     dict_close(dict_debug->real_dict);
133     dict_free(dict);
134 }
135 
136 /* dict_debug - encapsulate dictionary object and install proxies */
137 
dict_debug(DICT * real_dict)138 DICT   *dict_debug(DICT *real_dict)
139 {
140     DICT_DEBUG *dict_debug;
141 
142     dict_debug = (DICT_DEBUG *) dict_alloc(real_dict->type,
143 				      real_dict->name, sizeof(*dict_debug));
144     dict_debug->dict.flags = real_dict->flags;	/* XXX not synchronized */
145     dict_debug->dict.lookup = dict_debug_lookup;
146     dict_debug->dict.update = dict_debug_update;
147     dict_debug->dict.delete = dict_debug_delete;
148     dict_debug->dict.sequence = dict_debug_sequence;
149     dict_debug->dict.close = dict_debug_close;
150     dict_debug->real_dict = real_dict;
151     return (&dict_debug->dict);
152 }
153