aboutsummaryrefslogtreecommitdiff
path: root/mfd
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-05-03 13:16:34 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-05-03 13:16:34 +0300
commit9503ac3090f1013ab501e863d56277cccf301a86 (patch)
tree9d1f46fb3f3657953c34f66092629454b47f9c1f /mfd
parent4f617bee9e4bba6753bf6b88f693eb45df19a055 (diff)
downloadmailfromd-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.m417
-rw-r--r--mfd/mailfromd.h9
-rw-r--r--mfd/rate.c44
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);
diff --git a/mfd/rate.c b/mfd/rate.c
index 2e0c125b..881bae06 100644
--- a/mfd/rate.c
+++ b/mfd/rate.c
@@ -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);

Return to:

Send suggestions and report system problems to the System administrator.