Home | History | Annotate | Line # | Download | only in postscreen
      1 /*	$NetBSD: postscreen_dict.c,v 1.1.1.1 2011/03/02 19:32:26 tron Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	postscreen_dict 3
      6 /* SUMMARY
      7 /*	postscreen table access wrappers
      8 /* SYNOPSIS
      9 /*	#include <postscreen.h>
     10 /*
     11 /*	int	psc_addr_match_list_match(match_list, client_addr)
     12 /*	ADDR_MATCH_LIST *match_list;
     13 /*	const char *client_addr;
     14 /*
     15 /*	const char *psc_cache_lookup(DICT_CACHE *cache, const char *key)
     16 /*	DICT_CACHE *cache;
     17 /*	const char *key;
     18 /*
     19 /*	void	psc_cache_update(cache, key, value)
     20 /*	DICT_CACHE *cache;
     21 /*	const char *key;
     22 /*	const char *value;
     23 /*
     24 /*	void	psc_dict_get(dict, key)
     25 /*	DICT	*dict;
     26 /*	const char *key;
     27 /*
     28 /*	void	psc_maps_find(maps, key, flags)
     29 /*	MAPS	*maps;
     30 /*	const char *key;
     31 /*	int	flags;
     32 /* DESCRIPTION
     33 /*	This module implements wrappers around time-critical table
     34 /*	access functions.  The functions log a warning when table
     35 /*	access takes a non-trivial amount of time.
     36 /*
     37 /*	psc_addr_match_list_match() is a wrapper around
     38 /*	addr_match_list_match().
     39 /*
     40 /*	psc_cache_lookup() and psc_cache_update() are wrappers around
     41 /*	the corresponding dict_cache() methods.
     42 /*
     43 /*	psc_dict_get() and psc_maps_find() are wrappers around
     44 /*	dict_get() and maps_find(), respectively.
     45 /* LICENSE
     46 /* .ad
     47 /* .fi
     48 /*	The Secure Mailer license must be distributed with this software.
     49 /* AUTHOR(S)
     50 /*	Wietse Venema
     51 /*	IBM T.J. Watson Research
     52 /*	P.O. Box 704
     53 /*	Yorktown Heights, NY 10598, USA
     54 /*--*/
     55 
     56 /* System library. */
     57 
     58 #include <sys_defs.h>
     59 
     60 /* Utility library. */
     61 
     62 #include <msg.h>
     63 #include <dict.h>
     64 
     65 /* Global library. */
     66 
     67 #include <maps.h>
     68 
     69 /* Application-specific. */
     70 
     71 #include <postscreen.h>
     72 
     73  /*
     74   * Monitor time-critical operations.
     75   *
     76   * XXX Averaging support was added during a stable release candidate, so it
     77   * provides only the absolute minimum necessary. A complete implementation
     78   * should maintain separate statistics for each table, and it should not
     79   * complain when the access latency is less than the time between accesses.
     80   */
     81 #define PSC_GET_TIME_BEFORE_LOOKUP { \
     82     struct timeval _before, _after; \
     83     DELTA_TIME _delta; \
     84     double _new_delta_ms; \
     85     GETTIMEOFDAY(&_before);
     86 
     87 #define PSC_DELTA_MS(d) ((d).dt_sec * 1000.0 + (d).dt_usec / 1000.0)
     88 
     89 #define PSC_AVERAGE(new, old)	(0.1 * (new) + 0.9 * (old))
     90 
     91 #ifndef PSC_THRESHOLD_MS
     92 #define PSC_THRESHOLD_MS	100	/* nag if latency > 100ms */
     93 #endif
     94 
     95 #ifndef PSC_WARN_LOCKOUT_S
     96 #define PSC_WARN_LOCKOUT_S	60	/* don't nag for 60s */
     97 #endif
     98 
     99  /*
    100   * Shared warning lock, so that we don't spam the logfile when the system
    101   * becomes slow.
    102   */
    103 static time_t psc_last_warn = 0;
    104 
    105 #define PSC_CHECK_TIME_AFTER_LOOKUP(table, action, average) \
    106     GETTIMEOFDAY(&_after); \
    107     PSC_CALC_DELTA(_delta, _after, _before); \
    108     _new_delta_ms = PSC_DELTA_MS(_delta); \
    109     if ((average = PSC_AVERAGE(_new_delta_ms, average)) > PSC_THRESHOLD_MS \
    110 	&& psc_last_warn < _after.tv_sec - PSC_WARN_LOCKOUT_S) { \
    111         msg_warn("%s: %s %s average delay is %.0f ms", \
    112                  myname, (table), (action), average); \
    113 	psc_last_warn = _after.tv_sec; \
    114     } \
    115 }
    116 
    117 /* psc_addr_match_list_match - time-critical address list lookup */
    118 
    119 int     psc_addr_match_list_match(ADDR_MATCH_LIST *addr_list,
    120 				          const char *addr_str)
    121 {
    122     const char *myname = "psc_addr_match_list_match";
    123     int     result;
    124     static double latency_ms;
    125 
    126     PSC_GET_TIME_BEFORE_LOOKUP;
    127     result = addr_match_list_match(addr_list, addr_str);
    128     PSC_CHECK_TIME_AFTER_LOOKUP("address list", "lookup", latency_ms);
    129     return (result);
    130 }
    131 
    132 /* psc_cache_lookup - time-critical cache lookup */
    133 
    134 const char *psc_cache_lookup(DICT_CACHE *cache, const char *key)
    135 {
    136     const char *myname = "psc_cache_lookup";
    137     const char *result;
    138     static double latency_ms;
    139 
    140     PSC_GET_TIME_BEFORE_LOOKUP;
    141     result = dict_cache_lookup(cache, key);
    142     PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "lookup", latency_ms);
    143     return (result);
    144 }
    145 
    146 /* psc_cache_update - time-critical cache update */
    147 
    148 void    psc_cache_update(DICT_CACHE *cache, const char *key, const char *value)
    149 {
    150     const char *myname = "psc_cache_update";
    151     static double latency_ms;
    152 
    153     PSC_GET_TIME_BEFORE_LOOKUP;
    154     dict_cache_update(cache, key, value);
    155     PSC_CHECK_TIME_AFTER_LOOKUP(dict_cache_name(cache), "update", latency_ms);
    156 }
    157 
    158 /* psc_dict_get - time-critical table lookup */
    159 
    160 const char *psc_dict_get(DICT *dict, const char *key)
    161 {
    162     const char *myname = "psc_dict_get";
    163     const char *result;
    164     static double latency_ms;
    165 
    166     PSC_GET_TIME_BEFORE_LOOKUP;
    167     result = dict_get(dict, key);
    168     PSC_CHECK_TIME_AFTER_LOOKUP(dict->name, "lookup", latency_ms);
    169     return (result);
    170 }
    171 
    172 /* psc_maps_find - time-critical table lookup */
    173 
    174 const char *psc_maps_find(MAPS *maps, const char *key, int flags)
    175 {
    176     const char *myname = "psc_maps_find";
    177     const char *result;
    178     static double latency_ms;
    179 
    180     PSC_GET_TIME_BEFORE_LOOKUP;
    181     result = maps_find(maps, key, flags);
    182     PSC_CHECK_TIME_AFTER_LOOKUP(maps->title, "lookup", latency_ms);
    183     return (result);
    184 }
    185