diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-03 13:16:34 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-05-03 13:16:34 +0300 |
commit | 9503ac3090f1013ab501e863d56277cccf301a86 (patch) | |
tree | 9d1f46fb3f3657953c34f66092629454b47f9c1f /mfd | |
parent | 4f617bee9e4bba6753bf6b88f693eb45df19a055 (diff) | |
download | mailfromd-9503ac3090f1013ab501e863d56277cccf301a86.tar.gz mailfromd-9503ac3090f1013ab501e863d56277cccf301a86.tar.bz2 |
Improve the rate function.
* mfd/bi_other.m4 (rate): Add second optional
parameter: a threshold.
* mfd/mailfromd.h (get_rate): Change prototype.
* mfd/rate.c (get_rate): Take two more parameters:
threshold and interval. Return rate as long.
Do not increment the hit counters if the observed
rate is higher than the threshold.
Expire the record if no mails were sent during a
time longer than `interval' seconds.
* mflib/rateok.mf: New file.
* mflib/Makefile.am (inc_DATA): Add rateok.
* NEWS: Update
Diffstat (limited to 'mfd')
-rw-r--r-- | mfd/bi_other.m4 | 17 | ||||
-rw-r--r-- | mfd/mailfromd.h | 9 | ||||
-rw-r--r-- | mfd/rate.c | 44 |
3 files changed, 37 insertions, 33 deletions
diff --git a/mfd/bi_other.m4 b/mfd/bi_other.m4 index 3e7224b3..2a0b76be 100644 --- a/mfd/bi_other.m4 +++ b/mfd/bi_other.m4 @@ -72,17 +72,18 @@ MF_DEFUN(interval, NUMBER, STRING str) } END -MF_DEFUN(rate, NUMBER, STRING key, NUMBER interval, OPTIONAL, NUMBER mincnt) +MF_DEFUN(rate, NUMBER, STRING key, NUMBER interval, OPTIONAL, NUMBER mincnt, + NUMBER threshold) { - double rate; - long lrate; - - MF_ASSERT(get_rate(key, &rate, MF_OPTVAL(mincnt)) == mf_success, + long ret; + + MF_ASSERT(get_rate(key, &ret, interval, + MF_OPTVAL(mincnt), + MF_OPTVAL(threshold)) == mf_success, mfe_dbfailure, _("Cannot get rate for %s"), key); - lrate = rate * interval; - - MF_RETURN(lrate); + + MF_RETURN(ret); } END diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h index 4493a517..4e2a7628 100644 --- a/mfd/mailfromd.h +++ b/mfd/mailfromd.h @@ -336,11 +336,6 @@ struct header_node { NODE *value; /* Header value */ }; -struct rate_node { /* Rate test */ - NODE *email; /* Originator email */ - double limit; /* Sending rate limit */ -}; - struct builtin_node { /* Call to a built-in function */ const struct builtin *builtin; /* Buit-in function */ NODE *args; /* Actual arguments */ @@ -471,7 +466,6 @@ struct node { struct un_node un; struct return_node ret; struct header_node hdr; - struct rate_node rate; struct builtin_node builtin; NODE *node; struct concat_node concat; @@ -900,7 +894,8 @@ mf_status dns_cache_get(int type, const char *keystr, char **rbuf, void dns_cache_put(int type, const char *keystr, time_t ttl, char **rbuf, size_t rcnt); -mf_status get_rate(char *email, double *ret, size_t mincount); +mf_status get_rate(char *email, long *ret, unsigned long interval, + size_t mincount, size_t threshold); int db_list_item(char *dbname, char *key, db_item_printer_t fun); int db_list(char *dbname, db_item_printer_t fun); @@ -30,16 +30,18 @@ struct rate_result { }; mf_status -get_rate(char *email, double *ret, size_t mincount) +get_rate(char *email, long *ret, unsigned long interval, size_t mincount, + size_t threshold) { DBM_FILE db; DBM_DATUM key; DBM_DATUM contents; int local_contents = 0; struct rate_result *rp, rate; - double result; + long result; time_t t; int res; + int obsolete; debug1(50, "getting rate info for %s", email); if (mu_dbm_open(rate_format->dbname, &db, MU_STREAM_RDWR, 0600, NULL)) { @@ -74,31 +76,37 @@ get_rate(char *email, double *ret, size_t mincount) } /* Update the structure */ - rp->interval = t - rp->timestamp + rp->interval; + obsolete = t - rp->timestamp > interval; + rp->interval += t - rp->timestamp; rp->timestamp = t; rp->count++; if (rp->interval == 0 || rp->count < mincount) result = 0; else - result = (double) rp->count / rp->interval; - debug2(50, "rate for %s is %g", email, result); + result = ((double) rp->count / rp->interval) * interval; + debug3(50, "rate for %s is %ld/%lu", email, result, interval); /* Update the db */ - if (rate_format->expire_interval - && rp->interval > rate_format->expire_interval) { - debug1(50, "expiring %s rates", email); - rp->interval = 0; - rp->count = 1; - } else - debug1(50, "updating %s rates", email); + if (threshold && result > threshold) + debug1(50, "not updating %s rates", email); + else { + if (obsolete + || (rate_format->expire_interval + && rp->interval > rate_format->expire_interval)) { + debug1(50, "expiring %s rates", email); + rp->interval = 0; + rp->count = 1; + } else + debug1(50, "updating %s rates", email); + + MU_DATUM_PTR(contents) = (void*)rp; + MU_DATUM_SIZE(contents) = sizeof(*rp); + if (mu_dbm_insert(&db, key, contents, 1)) + mu_error (_("Cannot insert datum `%s' into `%s': %s"), + email, db.name, mu_dbm_strerror()); + } - MU_DATUM_PTR(contents) = (void*)rp; - MU_DATUM_SIZE(contents) = sizeof(*rp); - if (mu_dbm_insert(&db, key, contents, 1)) - mu_error (_("Cannot insert datum `%s' into `%s': %s"), - email, db.name, mu_dbm_strerror()); - if (!local_contents) mu_dbm_datum_free(&contents); |