[dovecot-cvs] dovecot/src/lib-dict Makefile.am, 1.4, 1.5 dict-client.c, 1.12, 1.13 dict-client.h, 1.3, 1.4 dict-db.c, NONE, 1.1 dict-private.h, 1.5, 1.6 dict-sql.c, 1.11, 1.12 dict.c, 1.9, 1.10 dict.h, 1.6, 1.7
tss-movial at dovecot.org
tss-movial at dovecot.org
Sun Jul 30 21:49:43 EEST 2006
Update of /var/lib/cvs/dovecot/src/lib-dict
In directory talvi:/tmp/cvs-serv14402/lib-dict
Modified Files:
Makefile.am dict-client.c dict-client.h dict-private.h
dict-sql.c dict.c dict.h
Added Files:
dict-db.c
Log Message:
Dictionary changes: Added support for defining value's type. Key is still always a string. Added support for sorting the iteration replies. Added dict_unset(). Added Berkeley DB support. Most of the code written by Tianyan Liu.
Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Makefile.am 14 Jan 2006 14:01:40 -0000 1.4
+++ Makefile.am 30 Jul 2006 18:49:38 -0000 1.5
@@ -9,10 +9,12 @@
libdict_a_SOURCES = \
dict.c \
dict-client.c \
+ dict-db.c \
dict-sql.c
noinst_HEADERS = \
dict.h \
dict-client.h \
dict-private.h \
+ dict-db.h \
dict-sql.h
Index: dict-client.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict-client.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -r1.12 -r1.13
--- dict-client.c 30 Jul 2006 18:13:03 -0000 1.12
+++ dict-client.c 30 Jul 2006 18:49:38 -0000 1.13
@@ -19,6 +19,7 @@
const char *uri;
const char *username;
const char *path;
+ enum dict_data_type value_type;
struct istream *input;
struct ostream *output;
@@ -247,10 +248,11 @@
dict->transaction_id_counter = 0;
t_push();
- query = t_strdup_printf("%c%u\t%u\t%s\t%s\n", DICT_PROTOCOL_CMD_HELLO,
+ query = t_strdup_printf("%c%u\t%u\t%d\t%s\t%s\n",
+ DICT_PROTOCOL_CMD_HELLO,
DICT_CLIENT_PROTOCOL_MAJOR_VERSION,
DICT_CLIENT_PROTOCOL_MINOR_VERSION,
- dict->username, dict->uri);
+ dict->value_type, dict->username, dict->uri);
if (client_dict_send_query(dict, query) < 0) {
client_dict_disconnect(dict);
t_pop();
@@ -279,8 +281,9 @@
}
}
-static struct dict *client_dict_init(struct dict *dict_class, const char *uri,
- const char *username)
+static struct dict *
+client_dict_init(struct dict *dict_class, const char *uri,
+ enum dict_data_type value_type, const char *username)
{
struct client_dict *dict;
const char *dest_uri;
@@ -297,6 +300,7 @@
dict = p_new(pool, struct client_dict, 1);
dict->pool = pool;
dict->dict = *dict_class;
+ dict->value_type = value_type;
dict->username = p_strdup(pool, username);
dict->fd = -1;
@@ -354,7 +358,8 @@
}
static struct dict_iterate_context *
-client_dict_iterate_init(struct dict *_dict, const char *path, bool recurse)
+client_dict_iterate_init(struct dict *_dict, const char *path,
+ enum dict_iterate_flags flags)
{
struct client_dict *dict = (struct client_dict *)_dict;
struct client_dict_iterate_context *ctx;
@@ -370,7 +375,7 @@
t_push();
query = t_strdup_printf("%c%d\t%s\n", DICT_PROTOCOL_CMD_ITERATE,
- recurse, dict_client_escape(path));
+ flags, dict_client_escape(path));
if (client_dict_send_query(dict, query) < 0)
ctx->failed = TRUE;
t_pop();
@@ -501,6 +506,21 @@
t_pop();
}
+static void client_dict_unset(struct dict_transaction_context *_ctx,
+ const char *key)
+{
+ struct client_dict_transaction_context *ctx =
+ (struct client_dict_transaction_context *)_ctx;
+ const char *query;
+
+ t_push();
+ query = t_strdup_printf("%c%u\t%s\n",
+ DICT_PROTOCOL_CMD_UNSET, ctx->id,
+ dict_client_escape(key));
+ (void)client_dict_send_transaction_query(ctx, query);
+ t_pop();
+}
+
static void client_dict_atomic_inc(struct dict_transaction_context *_ctx,
const char *key, long long diff)
{
@@ -530,6 +550,7 @@
client_dict_transaction_commit,
client_dict_transaction_rollback,
client_dict_set,
+ client_dict_unset,
client_dict_atomic_inc
}
};
Index: dict-client.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict-client.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- dict-client.h 17 Jun 2006 12:25:07 -0000 1.3
+++ dict-client.h 30 Jul 2006 18:49:38 -0000 1.4
@@ -3,23 +3,24 @@
#define DEFAULT_DICT_SERVER_SOCKET_PATH PKG_RUNDIR"/dict-server"
-#define DICT_CLIENT_PROTOCOL_MAJOR_VERSION 1
+#define DICT_CLIENT_PROTOCOL_MAJOR_VERSION 2
#define DICT_CLIENT_PROTOCOL_MINOR_VERSION 0
#define DICT_CLIENT_MAX_LINE_LENGTH (64*1024)
enum {
- /* <major-version> <minor-version> <user> <dict name> */
+ /* <major-version> <minor-version> <value type> <user> <dict name> */
DICT_PROTOCOL_CMD_HELLO = 'H',
DICT_PROTOCOL_CMD_LOOKUP = 'L', /* <key> */
- DICT_PROTOCOL_CMD_ITERATE = 'I', /* <recurse> <path> */
+ DICT_PROTOCOL_CMD_ITERATE = 'I', /* <flags> <path> */
DICT_PROTOCOL_CMD_BEGIN = 'B', /* <id> */
DICT_PROTOCOL_CMD_COMMIT = 'C', /* <id> */
DICT_PROTOCOL_CMD_ROLLBACK = 'R', /* <id> */
DICT_PROTOCOL_CMD_SET = 'S', /* <id> <key> <value> */
+ DICT_PROTOCOL_CMD_UNSET = 'U', /* <id> <key> */
DICT_PROTOCOL_CMD_ATOMIC_INC = 'A' /* <id> <key> <diff> */
};
--- NEW FILE: dict-db.c ---
/* Copyright (C) 2006 PT.COM / SAPO. Code by Tianyan Liu */
#include "lib.h"
#include "dict-private.h"
#include "dict-db.h"
#include <stdlib.h>
#include <db.h>
struct db_dict {
struct dict dict;
enum dict_data_type value_type;
pool_t pool;
DB_ENV *db_env;
DB *pdb;
DB *sdb;
};
struct db_dict_iterate_context {
struct dict_iterate_context ctx;
pool_t pool;
DBC *cursor;
char *path;
DBT pkey, pdata;
int (*iterate_next)(struct db_dict_iterate_context *ctx,
const char **key_r, const char **value_r);
enum dict_iterate_flags flags;
};
struct db_dict_transaction_context {
struct dict_transaction_context ctx;
DB_TXN *tid;
};
static void db_dict_deinit(struct dict *_dict);
static int associate_key(DB *pdb __attr_unused__,
const DBT *pkey __attr_unused__,
const DBT *pdata, DBT *skey)
{
memset(skey, 0, sizeof(*skey));
skey->data = pdata->data;
skey->size = pdata->size;
return 0;
}
static int uint32_t_compare(DB *db __attr_unused__,
const DBT *keya, const DBT *keyb)
{
const uint32_t *ua = keya->data, *ub = keyb->data;
return *ua > *ub ? 1 :
(*ua < *ub ? -1 : 0);
}
static struct dict *db_dict_init(struct dict *dict_class, const char *uri,
enum dict_data_type value_type,
const char *username __attr_unused__)
{
struct db_dict *dict;
const char *hdir;
DB_TXN *tid = NULL;
pool_t pool;
int ret;
pool = pool_alloconly_create("db dict", 1024);
dict = p_new(pool, struct db_dict, 1);
dict->pool = pool;
dict->dict = *dict_class;
/* prepare the environment */
ret = db_env_create(&dict->db_env, 0);
if (ret != 0) {
i_error("db_env:%s\n", db_strerror(ret));
pool_unref(pool);
return NULL;
}
dict->db_env->set_errfile(dict->db_env, stderr);
dict->db_env->set_errpfx(dict->db_env, "db_env");
hdir = strrchr(uri, '/');
if (hdir != NULL)
hdir = t_strndup(uri, hdir - uri);
ret = dict->db_env->open(dict->db_env, hdir, DB_CREATE |
DB_INIT_MPOOL | DB_INIT_TXN, 0);
if (ret != 0) {
pool_unref(pool);
return NULL;
}
ret = dict->db_env->txn_begin(dict->db_env, NULL, &tid, 0);
if (ret != 0) {
pool_unref(pool);
return NULL;
}
/* create both primary and secondary databases */
ret = db_create(&dict->pdb, dict->db_env, 0);
if (ret != 0) {
i_error("primary db:%s\n", db_strerror(ret));
db_dict_deinit(&dict->dict);
return NULL;
}
dict->pdb->set_errfile(dict->pdb, stderr);
dict->pdb->set_errpfx(dict->pdb, "primary db");
ret = db_create(&dict->sdb, dict->db_env, 0);
if (ret != 0) {
i_error("secondary db:%s\n", db_strerror(ret));
db_dict_deinit(&dict->dict);
return NULL;
}
dict->pdb->set_errfile(dict->pdb, stderr);
dict->pdb->set_errpfx(dict->pdb, "secondary db");
if (dict->pdb->open(dict->pdb, tid, uri, NULL,
DB_BTREE, DB_CREATE, 0) != 0) {
db_dict_deinit(&dict->dict);
return NULL;
}
if (dict->sdb->set_flags(dict->sdb, DB_DUP) != 0) {
db_dict_deinit(&dict->dict);
return NULL;
}
/* by default db compare keys as if they are strings.
if we store uint32_t, then we need a customized
compare function */
dict->value_type = value_type;
if (value_type == DICT_DATA_TYPE_UINT32) {
if (dict->sdb->set_bt_compare(dict->sdb,
uint32_t_compare) != 0) {
db_dict_deinit(&dict->dict);
return NULL;
}
}
if (dict->sdb->open(dict->sdb, tid, NULL, NULL,
DB_BTREE, DB_CREATE, 0) != 0) {
db_dict_deinit(&dict->dict);
return NULL;
}
if (dict->pdb->associate(dict->pdb, tid, dict->sdb,
associate_key, DB_CREATE) != 0) {
db_dict_deinit(&dict->dict);
return NULL;
}
return &dict->dict;
}
static void db_dict_deinit(struct dict *_dict)
{
struct db_dict *dict = (struct db_dict *)_dict;
if (dict->pdb != NULL)
dict->pdb->close(dict->pdb, 0);
if (dict->sdb != NULL)
dict->sdb->close(dict->sdb, 0);
pool_unref(dict->pool);
}
static int db_dict_iterate_set(struct db_dict_iterate_context *ctx, int ret,
const char **key_r, const char **value_r)
{
struct db_dict *dict = (struct db_dict *)ctx->ctx.dict;
if (ret == DB_NOTFOUND)
return 0;
else if (ret != 0)
return -1;
p_clear(ctx->pool);
*key_r = p_strndup(ctx->pool, ctx->pkey.data, ctx->pkey.size);
switch (dict->value_type) {
case DICT_DATA_TYPE_UINT32:
i_assert(ctx->pdata.size == sizeof(uint32_t));
*value_r = p_strdup(ctx->pool,
dec2str(*((uint32_t *)ctx->pdata.data)));
break;
case DICT_DATA_TYPE_STRING:
*value_r = p_strndup(ctx->pool,
ctx->pdata.data, ctx->pdata.size);
break;
}
return 1;
}
static int db_dict_lookup(struct dict *_dict, pool_t pool,
const char *key, const char **value_r)
{
struct db_dict *dict = (struct db_dict *)_dict;
DBT pkey, pdata;
int ret;
memset(&pkey, 0, sizeof(DBT));
memset(&pdata, 0, sizeof(DBT));
pkey.data = (char *)key;
pkey.size = strlen(key);
ret = dict->pdb->get(dict->pdb, NULL, &pkey, &pdata, 0);
if (ret == DB_NOTFOUND)
return 0;
else if (ret != 0)
return -1;
switch (dict->value_type) {
case DICT_DATA_TYPE_UINT32:
i_assert(pdata.size == sizeof(uint32_t));
*value_r = p_strdup(pool, dec2str(*((uint32_t *)pdata.data)));
break;
case DICT_DATA_TYPE_STRING:
*value_r = p_strndup(pool, pdata.data, pdata.size);
break;
}
return 1;
}
static int db_dict_iterate_next(struct db_dict_iterate_context *ctx,
const char **key_r, const char **value_r)
{
DBT pkey, pdata, skey;
int ret;
memset(&pkey, 0, sizeof(pkey));
memset(&pdata, 0, sizeof(pdata));
memset(&skey, 0, sizeof(skey));
if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_VALUE) != 0) {
while ((ret = ctx->cursor->c_pget(ctx->cursor, &skey,
&ctx->pkey, &ctx->pdata,
DB_NEXT)) == 0) {
/* make sure the path matches */
if (ctx->path == NULL ||
strncmp(ctx->path, ctx->pkey.data,
ctx->pkey.size) == 0)
break;
}
} else {
ret = ctx->cursor->c_get(ctx->cursor, &ctx->pkey, &ctx->pdata,
DB_NEXT);
if (ctx->path != NULL && ret == 0 &&
strncmp(ctx->path, ctx->pkey.data, ctx->pkey.size) != 0) {
/* there are no more matches */
return 0;
}
}
return db_dict_iterate_set(ctx, ret, key_r, value_r);
}
static int db_dict_iterate_first(struct db_dict_iterate_context *ctx,
const char **key_r, const char **value_r)
{
struct db_dict *dict = (struct db_dict *)ctx->ctx.dict;
int ret;
ctx->iterate_next = db_dict_iterate_next;
if ((ctx->flags & DICT_ITERATE_FLAG_SORT_BY_VALUE) != 0) {
/* iterating through secondary database returns values sorted */
ret = dict->sdb->cursor(dict->sdb, NULL, &ctx->cursor, 0);
} else {
ret = dict->pdb->cursor(dict->pdb, NULL, &ctx->cursor, 0);
if (ret == 0 && ctx->path != NULL) {
ctx->pkey.data = ctx->path;
ctx->pkey.size = strlen(ctx->path);
ret = ctx->cursor->c_get(ctx->cursor, &ctx->pkey,
&ctx->pdata, DB_SET_RANGE);
if (ret == 0 && strncmp(ctx->path, ctx->pkey.data,
ctx->pkey.size) != 0)
return 0;
return db_dict_iterate_set(ctx, ret, key_r, value_r);
}
}
return db_dict_iterate_next(ctx, key_r, value_r);
}
static struct dict_iterate_context *
db_dict_iterate_init(struct dict *_dict, const char *path,
enum dict_iterate_flags flags)
{
struct db_dict_iterate_context *ctx;
ctx = i_new(struct db_dict_iterate_context, 1);
ctx->pool = pool_alloconly_create("db iter", 1024);
ctx->cursor = NULL;
ctx->ctx.dict = _dict;
ctx->flags = flags;
ctx->path = i_strdup_empty(path);
ctx->iterate_next = db_dict_iterate_first;
return &ctx->ctx;
}
static int db_dict_iterate(struct dict_iterate_context *_ctx,
const char **key_r, const char **value_r)
{
struct db_dict_iterate_context *ctx =
(struct db_dict_iterate_context *)_ctx;
return ctx->iterate_next(ctx, key_r, value_r);
}
static void db_dict_iterate_deinit(struct dict_iterate_context *_ctx)
{
struct db_dict_iterate_context *ctx =
(struct db_dict_iterate_context *)_ctx;
ctx->cursor->c_close(ctx->cursor);
pool_unref(ctx->pool);
i_free(ctx->path);
i_free(ctx);
}
static struct dict_transaction_context *
db_dict_transaction_init(struct dict *_dict)
{
struct db_dict *dict = (struct db_dict *)_dict;
struct db_dict_transaction_context *ctx;
ctx = i_new(struct db_dict_transaction_context, 1);
ctx->ctx.dict = _dict;
dict->db_env->txn_begin(dict->db_env, NULL, &ctx->tid, 0);
return &ctx->ctx;
}
static int db_dict_transaction_commit(struct dict_transaction_context *_ctx)
{
struct db_dict_transaction_context *ctx =
(struct db_dict_transaction_context *)_ctx;
int ret;
ret = ctx->tid->commit(ctx->tid, 0);
i_free(ctx);
return ret == 0 ? 0 : -1;
}
static void db_dict_transaction_rollback(struct dict_transaction_context *_ctx)
{
struct db_dict_transaction_context *ctx =
(struct db_dict_transaction_context *)_ctx;
ctx->tid->discard(ctx->tid, 0);
i_free(ctx);
}
static void db_dict_set(struct dict_transaction_context *_ctx,
const char *key, const char *value)
{
struct db_dict_transaction_context *ctx =
(struct db_dict_transaction_context *)_ctx;
struct db_dict *dict = (struct db_dict *)_ctx->dict;
DBT dkey, ddata;
memset(&dkey, 0, sizeof(dkey));
memset(&ddata, 0, sizeof(ddata));
dkey.data = (char *)key;
dkey.size = strlen(key);
if (dict->value_type == DICT_DATA_TYPE_UINT32) {
uint32_t ivalue = (uint32_t)strtoul(value, NULL, 10);
ddata.data = &ivalue;
ddata.size = sizeof(ivalue);
} else {
ddata.data = (char *)value;
ddata.size = strlen(value);
}
dict->pdb->put(dict->pdb, ctx->tid, &dkey, &ddata, 0);
}
static void db_dict_unset(struct dict_transaction_context *_ctx,
const char *key)
{
struct db_dict_transaction_context *ctx =
(struct db_dict_transaction_context *)_ctx;
struct db_dict *dict = (struct db_dict *)_ctx->dict;
DBT dkey;
memset(&dkey, 0, sizeof(dkey));
dkey.data = (char *)key;
dkey.size = strlen(key);
dict->pdb->del(dict->pdb, ctx->tid, &dkey, 0);
}
static void db_dict_atomic_inc(struct dict_transaction_context *_ctx,
const char *key, long long diff)
{
/* FIXME */
}
static struct dict dict_db_class = {
MEMBER(name) "db",
{
db_dict_init,
db_dict_deinit,
db_dict_lookup,
db_dict_iterate_init,
db_dict_iterate,
db_dict_iterate_deinit,
db_dict_transaction_init,
db_dict_transaction_commit,
db_dict_transaction_rollback,
db_dict_set,
db_dict_unset,
db_dict_atomic_inc
}
};
void dict_db_register(void)
{
dict_class_register(&dict_db_class);
}
void dict_db_unregister(void)
{
dict_class_unregister(&dict_db_class);
}
Index: dict-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict-private.h,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- dict-private.h 30 Jul 2006 18:06:09 -0000 1.5
+++ dict-private.h 30 Jul 2006 18:49:38 -0000 1.6
@@ -5,6 +5,7 @@
struct dict_vfuncs {
struct dict *(*init)(struct dict *dict_class, const char *uri,
+ enum dict_data_type value_type,
const char *username);
void (*deinit)(struct dict *dict);
@@ -13,7 +14,7 @@
struct dict_iterate_context *
(*iterate_init)(struct dict *dict, const char *path,
- bool recurse);
+ enum dict_iterate_flags flags);
int (*iterate)(struct dict_iterate_context *ctx,
const char **key_r, const char **value_r);
void (*iterate_deinit)(struct dict_iterate_context *ctx);
@@ -24,6 +25,8 @@
void (*set)(struct dict_transaction_context *ctx,
const char *key, const char *value);
+ void (*unset)(struct dict_transaction_context *ctx,
+ const char *key);
void (*atomic_inc)(struct dict_transaction_context *ctx,
const char *key, long long diff);
};
Index: dict-sql.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict-sql.c,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- dict-sql.c 30 Jul 2006 18:06:09 -0000 1.11
+++ dict-sql.c 30 Jul 2006 18:49:38 -0000 1.12
@@ -101,8 +101,10 @@
return 0;
}
-static struct dict *sql_dict_init(struct dict *dict_class, const char *uri,
- const char *username)
+static struct dict *
+sql_dict_init(struct dict *dict_class, const char *uri,
+ enum dict_data_type value_type __attr_unused__,
+ const char *username)
{
struct sql_dict *dict;
pool_t pool;
@@ -193,7 +195,8 @@
}
static struct dict_iterate_context *
-sql_dict_iterate_init(struct dict *_dict, const char *path, bool recurse)
+sql_dict_iterate_init(struct dict *_dict, const char *path,
+ enum dict_iterate_flags flags)
{
struct sql_dict *dict = (struct sql_dict *)_dict;
struct sql_dict_iterate_context *ctx;
@@ -219,11 +222,15 @@
sql_escape_string(dict->db,
dict->username));
}
- if (!recurse) {
+ if ((flags & DICT_ITERATE_FLAG_RECURSE) == 0) {
str_printfa(query, " AND %s NOT LIKE '%s/%%/%%'",
dict->where_field,
sql_escape_string(dict->db, path));
}
+ if ((flags & DICT_ITERATE_FLAG_SORT_BY_KEY) != 0)
+ str_printfa(query, " ORDER BY %s", dict->where_field);
+ else if ((flags & DICT_ITERATE_FLAG_SORT_BY_VALUE) != 0)
+ str_printfa(query, " ORDER BY %s", dict->select_field);
ctx->result = sql_query_s(dict->db, str_c(query));
t_pop();
}
@@ -344,6 +351,39 @@
t_pop();
}
+static void sql_dict_unset(struct dict_transaction_context *_ctx,
+ const char *key)
+{
+ struct sql_dict_transaction_context *ctx =
+ (struct sql_dict_transaction_context *)_ctx;
+ struct sql_dict *dict = (struct sql_dict *)_ctx->dict;
+ const char *query;
+ bool priv;
+
+ if (sql_path_fix(&key, &priv) < 0) {
+ i_error("sql dict: Invalid key: %s", key);
+ ctx->failed = TRUE;
+ return;
+ }
+
+ t_push();
+ if (priv) {
+ query = t_strdup_printf(
+ "DELETE FROM %s WHERE %s = '%s' AND %s = '%s'",
+ dict->table, dict->where_field,
+ sql_escape_string(dict->db, key),
+ dict->username_field,
+ sql_escape_string(dict->db, dict->username));
+ } else {
+ query = t_strdup_printf(
+ "DELETE FROM %s WHERE %s = '%s'",
+ dict->table, dict->where_field,
+ sql_escape_string(dict->db, key));
+ }
+ sql_update(ctx->sql_ctx, query);
+ t_pop();
+}
+
static void sql_dict_atomic_inc(struct dict_transaction_context *_ctx,
const char *key, long long diff)
{
@@ -395,6 +435,7 @@
sql_dict_transaction_commit,
sql_dict_transaction_rollback,
sql_dict_set,
+ sql_dict_unset,
sql_dict_atomic_inc
}
};
Index: dict.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- dict.c 30 Jul 2006 18:06:09 -0000 1.9
+++ dict.c 30 Jul 2006 18:49:38 -0000 1.10
@@ -51,7 +51,8 @@
array_free(&dict_classes);
}
-struct dict *dict_init(const char *uri, const char *username)
+struct dict *dict_init(const char *uri, enum dict_data_type value_type,
+ const char *username)
{
struct dict *dict;
const char *p, *name;
@@ -72,7 +73,7 @@
}
t_pop();
- return dict->v.init(dict, p+1, username);
+ return dict->v.init(dict, p+1, value_type, username);
}
void dict_deinit(struct dict **_dict)
@@ -90,9 +91,10 @@
}
struct dict_iterate_context *
-dict_iterate_init(struct dict *dict, const char *path, bool recurse)
+dict_iterate_init(struct dict *dict, const char *path,
+ enum dict_iterate_flags flags)
{
- return dict->v.iterate_init(dict, path, recurse);
+ return dict->v.iterate_init(dict, path, flags);
}
int dict_iterate(struct dict_iterate_context *ctx,
@@ -128,6 +130,13 @@
ctx->changed = TRUE;
}
+void dict_unset(struct dict_transaction_context *ctx,
+ const char *key)
+{
+ ctx->dict->v.unset(ctx, key);
+ ctx->changed = TRUE;
+}
+
void dict_atomic_inc(struct dict_transaction_context *ctx,
const char *key, long long diff)
{
Index: dict.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-dict/dict.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- dict.h 31 Jan 2006 06:05:22 -0000 1.6
+++ dict.h 30 Jul 2006 18:49:38 -0000 1.7
@@ -6,12 +6,24 @@
struct dict;
+enum dict_iterate_flags {
+ DICT_ITERATE_FLAG_RECURSE = 0x01,
+ DICT_ITERATE_FLAG_SORT_BY_KEY = 0x02,
+ DICT_ITERATE_FLAG_SORT_BY_VALUE = 0x04
+};
+
+enum dict_data_type {
+ DICT_DATA_TYPE_STRING,
+ DICT_DATA_TYPE_UINT32
+};
+
void dict_class_register(struct dict *dict_class);
void dict_class_unregister(struct dict *dict_class);
/* Open dictionary with given URI (type:data).
If URI is invalid, returns NULL. */
-struct dict *dict_init(const char *uri, const char *username);
+struct dict *dict_init(const char *uri, enum dict_data_type value_type,
+ const char *username);
/* Close dictionary. */
void dict_deinit(struct dict **dict);
@@ -20,10 +32,11 @@
int dict_lookup(struct dict *dict, pool_t pool,
const char *key, const char **value_r);
-/* Iterate through all values in a path. If recurse is FALSE, keys in
- the given path are returned, but not their children. */
+/* Iterate through all values in a path. flag indicates how iteration
+ is carried out */
struct dict_iterate_context *
-dict_iterate_init(struct dict *dict, const char *path, bool recurse);
+dict_iterate_init(struct dict *dict, const char *path,
+ enum dict_iterate_flags flags);
/* Returns -1 = error, 0 = finished, 1 = key/value set */
int dict_iterate(struct dict_iterate_context *ctx,
const char **key_r, const char **value_r);
@@ -39,6 +52,9 @@
/* Set key=value in dictionary. */
void dict_set(struct dict_transaction_context *ctx,
const char *key, const char *value);
+/* Unset a record in dictionary, identified by key*/
+void dict_unset(struct dict_transaction_context *ctx,
+ const char *key);
/* Increase/decrease a numeric value in dictionary. Note that the value is
changed when transaction is being committed, so you can't know beforehand
what the value will become. */
More information about the dovecot-cvs
mailing list