summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org.ua>2013-08-01 16:20:54 (GMT)
committer Sergey Poznyakoff <gray@gnu.org.ua>2013-08-02 07:48:54 (GMT)
commit73f605f76d82aec40a7f1bbd309e2097d9abfd42 (patch) (side-by-side diff)
tree5820713d17efcb482a8801f4f805b0ae121903f7
parentd78a58be5fa2385987a3141ccbe942107332e677 (diff)
downloadvmod-tbf-73f605f76d82aec40a7f1bbd309e2097d9abfd42.tar.gz
vmod-tbf-73f605f76d82aec40a7f1bbd309e2097d9abfd42.tar.bz2
Switch to CDB environment.
* configure.ac: Version 0.99.91 * src/tbf.c (dbdir): New static. (tbf_set_db_name): Remove. (tbf_set_db_dir): New function. (tbf_open): Rename the parameter and related variables. Create a CDB environment and the database in it. (vmod_open): Change semantics of the first argument. * src/vmod-tbf.3: Update. * tests/Makefile.am (distclean-local): New rule, instead of DISTCLEANFILES. * tests/test00.vtc: Update call to tbf.open. * tests/test01.vtc: Likewise. * tests/test02.vtc: Likewise. * tests/test03.vtc: Likewise.
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac2
-rw-r--r--src/tbf.c212
-rw-r--r--src/vmod-tbf.332
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/test00.vtc2
-rw-r--r--tests/test01.vtc2
-rw-r--r--tests/test02.vtc2
-rw-r--r--tests/test03.vtc2
8 files changed, 175 insertions, 83 deletions
diff --git a/configure.ac b/configure.ac
index 9c228f6..4ca4e6f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -16,3 +16,3 @@
AC_PREREQ(2.69)
-AC_INIT([vmod-tbf], 0.99.90, [gray@gnu.org])
+AC_INIT([vmod-tbf], 0.99.91, [gray@gnu.org])
AC_CONFIG_AUX_DIR([build-aux])
diff --git a/src/tbf.c b/src/tbf.c
index 1dfb6c6..7050fc7 100644
--- a/src/tbf.c
+++ b/src/tbf.c
@@ -22,2 +22,3 @@
#include <inttypes.h>
+#include <sys/stat.h>
#include <db.h>
@@ -43,3 +44,9 @@ debugprt(const char *fmt, ...)
+#define DEFDBNAME "tbf.bdb"
+#define DEFOPENPARAMS "truncate"
+#define DBFILEMODE 0640
+
+static char *dbdir;
static char *dbname;
+static DB_ENV *dbenv;
static DB *db;
@@ -50,3 +57,2 @@ static int tbf_disabled;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
-#define DBFILEMODE 0640
@@ -124,15 +130,14 @@ keylock_remove_safe(struct keylock *kp)
static void
-tbf_set_db_name(const char *file_name)
+tbf_set_db_dir(const char *dir)
{
- if (dbname)
- free(dbname);
- dbname = strdup(file_name);
- if (!dbname)
- abort();
+ if (dbdir)
+ free(dbdir);
+ dbdir = strdup(dir);
+ AN(dbdir);
}
-struct mode_kw {
- char *mkw_str;
- int mkw_len;
- int mkw_tok;
+struct param_kw {
+ char *pkw_str;
+ int pkw_len;
+ int pkw_tok;
};
@@ -140,15 +145,17 @@ struct mode_kw {
enum {
- MKW_TRUNCATE,
- MKW_MODE,
- MKW_SYNC,
- MKW_DEBUG,
+ PKW_TRUNCATE,
+ PKW_MODE,
+ PKW_SYNC,
+ PKW_DEBUG,
+ PKW_DBNAME
};
-static struct mode_kw mode_kw_tab[] = {
+static struct param_kw param_kw_tab[] = {
#define S(s) #s, sizeof(#s)-1
- { S(truncate), MKW_TRUNCATE },
- { S(trunc), MKW_TRUNCATE },
- { S(mode=), MKW_MODE },
- { S(sync=), MKW_SYNC },
- { S(debug=), MKW_DEBUG },
+ { S(truncate), PKW_TRUNCATE },
+ { S(trunc), PKW_TRUNCATE },
+ { S(mode=), PKW_MODE },
+ { S(sync=), PKW_SYNC },
+ { S(debug=), PKW_DEBUG },
+ { S(dbname=), PKW_DBNAME },
{ NULL }
@@ -158,6 +165,5 @@ static struct mode_kw mode_kw_tab[] = {
static void
-tbf_open(const char *mode)
+tbf_open(const char *params)
{
int rc;
- int flags = DB_CREATE|DB_THREAD;
int filemode = DBFILEMODE;
@@ -165,17 +171,19 @@ tbf_open(const char *mode)
char *p;
+ struct stat st;
+ int truncate = 0;
- if (!dbname)
- tbf_set_db_name(LOCALSTATEDIR "/tbf.db");
-
- rc = db_create(&db, NULL, 0);
- if (rc) {
- syslog(LOG_DAEMON|LOG_ERR, "cannot create db struct");
- return;
+ if (!dbdir) {
+ dbdir = strdup(LOCALSTATEDIR "/vmod-tbf");
+ AN(dbdir);
}
-
- while (*mode) {
- struct mode_kw *mkw;
+ if (!dbname) {
+ dbname = strdup(DEFDBNAME);
+ AN(dbname);
+ }
+
+ while (*params) {
+ struct param_kw *pkw;
- for (mkw = mode_kw_tab; mkw->mkw_str; mkw++) {
- if (strncmp(mode, mkw->mkw_str, mkw->mkw_len) == 0)
+ for (pkw = param_kw_tab; pkw->pkw_str; pkw++) {
+ if (strncmp(params, pkw->pkw_str, pkw->pkw_len) == 0)
break;
@@ -183,4 +191,4 @@ tbf_open(const char *mode)
- if (!mkw->mkw_str) {
- syslog(LOG_DAEMON|LOG_ERR, "invalid keyword %s", mode);
+ if (!pkw->pkw_str) {
+ syslog(LOG_DAEMON|LOG_ERR, "invalid keyword %s", params);
break;
@@ -188,12 +196,12 @@ tbf_open(const char *mode)
- mode += mkw->mkw_len;
+ params += pkw->pkw_len;
- switch (mkw->mkw_tok) {
- case MKW_TRUNCATE:
- flags |= DB_TRUNCATE;
+ switch (pkw->pkw_tok) {
+ case PKW_TRUNCATE:
+ truncate = 1;
break;
- case MKW_MODE:
+ case PKW_MODE:
errno = 0;
- n = strtoul(mode, &p, 8);
+ n = strtoul(params, &p, 8);
if (errno || (n & ~0777) || !(*p == 0 || *p == ';')) {
@@ -201,6 +209,6 @@ tbf_open(const char *mode)
"invalid file mode near %s", p);
- mode += strlen(mode);
+ params += strlen(params);
} else {
filemode = n;
- mode = p;
+ params = p;
}
@@ -208,5 +216,5 @@ tbf_open(const char *mode)
- case MKW_SYNC:
+ case PKW_SYNC:
errno = 0;
- n = strtoul(mode, &p, 10);
+ n = strtoul(params, &p, 10);
if (errno || !(*p == 0 || *p == ';')) {
@@ -214,3 +222,3 @@ tbf_open(const char *mode)
"invalid count near %s", p);
- mode += strlen(mode);
+ params += strlen(params);
} else {
@@ -218,3 +226,3 @@ tbf_open(const char *mode)
autosync_count = 0;
- mode = p;
+ params = p;
}
@@ -222,5 +230,5 @@ tbf_open(const char *mode)
- case MKW_DEBUG:
+ case PKW_DEBUG:
errno = 0;
- n = strtoul(mode, &p, 10);
+ n = strtoul(params, &p, 10);
if (errno || !(*p == 0 || *p == ';')) {
@@ -228,16 +236,28 @@ tbf_open(const char *mode)
"invalid debug level near %s", p);
- mode += strlen(mode);
+ params += strlen(params);
} else {
debug_level = n;
- mode = p;
- }
+ params = p;
+ }
+ break;
+
+ case PKW_DBNAME:
+ if (dbname)
+ free(dbname);
+ n = strcspn(params, ";");
+ dbname = malloc(n + 1);
+ AN(dbname);
+ memcpy(dbname, params, n);
+ dbname[n] = 0;
+ params += n;
+ break;
}
- if (*mode == 0)
+ if (*params == 0)
break;
- else if (*mode == ';')
- mode++;
+ else if (*params == ';')
+ params++;
else {
syslog(LOG_DAEMON|LOG_ERR,
- "expected ';' near %s", mode);
+ "expected ';' near %s", params);
break;
@@ -246,6 +266,52 @@ tbf_open(const char *mode)
- debug(1, ("opening database %s", dbname));
- rc = db->open(db, NULL, dbname, NULL, DB_HASH, flags, filemode);
+ debug(1, ("opening database %s/%s", dbdir, dbname));
+
+ if (rc = db_env_create(&dbenv, 0)) {
+ syslog(LOG_DAEMON|LOG_ERR, "cannot create db environment: %s",
+ db_strerror(rc));
+ return;
+ }
+
+ if (stat(dbdir, &st)) {
+ if (errno == ENOENT) {
+ if (mkdir(dbdir,
+ filemode | 0100 |
+ ((filemode & 0060) ? 0010 : 0) |
+ ((filemode & 0006) ? 0001 : 0))) {
+ syslog(LOG_DAEMON|LOG_ERR,
+ "cannot create db environment directory %s: %m",
+ dbdir);
+ }
+ } else {
+ syslog(LOG_DAEMON|LOG_ERR,
+ "cannot stat db environment directory %s: %m",
+ dbdir);
+ return;
+ }
+ } else if (!S_ISDIR(st.st_mode)) {
+ syslog(LOG_DAEMON|LOG_ERR, "%s is not a directory",
+ dbdir);
+ return;
+ }
+
+ rc = dbenv->open(dbenv, dbdir,
+ DB_THREAD | DB_CREATE | DB_INIT_MPOOL | DB_INIT_CDB,
+ 0);
if (rc) {
- syslog(LOG_DAEMON|LOG_ERR, "cannot open %s: %s",
+ syslog(LOG_DAEMON|LOG_ERR, "cannot open db environment %s: %s",
+ dbdir, db_strerror(rc));
+ tbf_disabled = 1;
+ return;
+ }
+
+ rc = db_create(&db, dbenv, 0);
+ if (rc) {
+ syslog(LOG_DAEMON|LOG_ERR, "cannot create db struct");
+ return;
+ }
+
+ rc = db->open(db, NULL, dbname, NULL, DB_HASH,
+ DB_THREAD | DB_CREATE, filemode);
+ if (rc) {
+ syslog(LOG_DAEMON|LOG_ERR, "cannot open database %s: %s",
dbname, db_strerror (rc));
@@ -253,4 +319,14 @@ tbf_open(const char *mode)
db = NULL;
+ dbenv->close(dbenv, 0);
+ dbenv = NULL;
tbf_disabled = 1;
}
+
+ if (truncate) {
+ rc = db->truncate(db, NULL, NULL, 0);
+ if (rc)
+ syslog(LOG_DAEMON|LOG_WARNING,
+ "failed to truncate database %s: %s",
+ dbname, db_strerror(rc));
+ }
}
@@ -258,3 +334,3 @@ tbf_open(const char *mode)
static DB *
-tbf_open_safe(const char *mode)
+tbf_open_safe(const char *params)
{
@@ -264,3 +340,3 @@ tbf_open_safe(const char *mode)
if (!db)
- tbf_open(mode ? mode : "truncate");
+ tbf_open(params ? params : DEFOPENPARAMS);
pthread_mutex_unlock(&mutex);
@@ -277,3 +353,3 @@ tbf_init(struct vmod_priv *priv, const struct VCL_conf *vclconf)
void
-vmod_open(struct sess *sp, const char *file_name, const char *mode)
+vmod_open(struct sess *sp, const char *dir, const char *params)
{
@@ -283,4 +359,4 @@ vmod_open(struct sess *sp, const char *file_name, const char *mode)
}
- tbf_set_db_name(file_name);
- tbf_open_safe(mode);
+ tbf_set_db_dir(dir);
+ tbf_open_safe(params);
}
@@ -290,2 +366,3 @@ vmod_close(struct sess *sp)
{
+ pthread_mutex_lock(&mutex);
if (db) {
@@ -294,4 +371,7 @@ vmod_close(struct sess *sp)
db = NULL;
+ dbenv->close(dbenv, 0);
+ dbenv = NULL;
tbf_disabled = 0;
}
+ pthread_mutex_unlock(&mutex);
}
diff --git a/src/vmod-tbf.3 b/src/vmod-tbf.3
index cf12ea7..bd7b233 100644
--- a/src/vmod-tbf.3
+++ b/src/vmod-tbf.3
@@ -15,3 +15,3 @@
.\" along with vmod-tbf. If not, see <http://www.gnu.org/licenses/>.
-.TH VMOD-TBF 1 "July 23, 2013" "VMOD-TBF" "User Reference"
+.TH VMOD-TBF 1 "August 2, 2013" "VMOD-TBF" "User Reference"
.SH NAME
@@ -21,3 +21,3 @@ vmod-tbf \- token bucket filtering for Varnish
-.BI "VOID tbf.open(STRING " dbfile ", STRING " params ");"
+.BI "VOID tbf.open(STRING " dbdir ", STRING " params ");"
@@ -110,9 +110,13 @@ sub vcl_recv {
.PP
-Buckets are kept in a Berkeley DB file. The \fBtbf.open\fR function
-controls its location and permissions. The \fBdbfile\fR argument
-supplies the full pathname to the file. The \fBparams\fR argument is
-a semicolon separated list of the following parameters:
+Buckets are kept in a Berkeley database file. The \fBtbf.open\fR function
+controls its location and permissions. The \fBdbdir\fR argument
+supplies the full pathname to the directory where the database is
+located. The \fBparams\fR argument is a semicolon separated list of
+the following parameters:
+.TP
+.BI dbname= NAME
+Sets the name of the database file. Default is \fBtbf.bdb\fR.
.TP
.BR truncate " or " trunc
-Truncate the file if it already exists.
+Truncate the database if it already exists.
.TP
@@ -143,6 +147,12 @@ writable for the user \fBVarnish\fR runs as.
Unless the \fBtbf.open\fR function was called, both \fBtbf.rate\fR and
-\fBtbf.check\fR will attempt to use the file \fIlocalstatedir\fB/tbf.db\fR,
-where \fIlocalstatedir\fR is the directory for modifiable
-single-machine data, which is set when configuring the package
-(e.g. \fB/var/run/tbf\fR or the like).
+\fBtbf.check\fR will attempt to use the database located in
+\fIlocalstatedir\fB/vmod-tbf\fR, where \fIlocalstatedir\fR is the
+directory for modifiable single-machine data, which is set when
+configuring the package (e.g. \fB/var/run\fR or the like).
+.PP
+If the database directory does not exist, \fBtbf.open\fR will attempt
+to create it, deducing its mode from the database file mode (see the
+\fBmode=\fR parameter above) by setting executable
+bit in each triplet that has read or write bit set (e.g. \fB640\fR
+will become \fB750\fR).
.PP
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 383f18a..4790115 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -8,3 +8,5 @@ VMOD_TESTS = \
EXTRA_DIST=$(VMOD_TESTS)
-DISTCLEANFILES=tbf.db
+distclean-local:
+ rm -fr tbf
+
check:
diff --git a/tests/test00.vtc b/tests/test00.vtc
index 10f99ca..f69f5ed 100644
--- a/tests/test00.vtc
+++ b/tests/test00.vtc
@@ -10,3 +10,3 @@ varnish v1 -vcl+backend {
sub vcl_init {
- tbf.open("${vmod_topbuild}/tests/tbf.db", "truncate");
+ tbf.open("${vmod_topbuild}/tests/tbf", "truncate");
}
diff --git a/tests/test01.vtc b/tests/test01.vtc
index ad6f7d1..39eb4c3 100644
--- a/tests/test01.vtc
+++ b/tests/test01.vtc
@@ -10,3 +10,3 @@ varnish v1 -vcl+backend {
sub vcl_init {
- tbf.open("${vmod_topbuild}/tests/tbf.db", "trunc");
+ tbf.open("${vmod_topbuild}/tests/tbf", "trunc");
}
diff --git a/tests/test02.vtc b/tests/test02.vtc
index b957181..8df6730 100644
--- a/tests/test02.vtc
+++ b/tests/test02.vtc
@@ -10,3 +10,3 @@ varnish v1 -vcl+backend {
sub vcl_init {
- tbf.open("${vmod_topbuild}/tests/tbf.db", "truncate");
+ tbf.open("${vmod_topbuild}/tests/tbf", "truncate");
}
diff --git a/tests/test03.vtc b/tests/test03.vtc
index 5ffba9a..aa23da4 100644
--- a/tests/test03.vtc
+++ b/tests/test03.vtc
@@ -10,3 +10,3 @@ varnish v1 -vcl+backend {
sub vcl_init {
- tbf.open("${vmod_topbuild}/tests/tbf.db", "trunc");
+ tbf.open("${vmod_topbuild}/tests/tbf", "trunc");
}

Return to:

Send suggestions and report system problems to the System administrator.