1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-24 13:57:43 +03:00

lib/dbwrap: make it possible to delete/store the current record during traverse

metze

Autobuild-User: Stefan Metzmacher <metze@samba.org>
Autobuild-Date: Thu May 31 02:50:09 CEST 2012 on sn-devel-104
This commit is contained in:
Stefan Metzmacher 2012-05-30 15:06:12 +02:00
parent 39ac9457a3
commit 5e5f5692b8

View File

@ -206,6 +206,17 @@ static NTSTATUS db_rbt_delete(struct db_record *rec)
return NT_STATUS_OK;
}
static NTSTATUS db_rbt_store_deny(struct db_record *rec, TDB_DATA data, int flag)
{
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
static NTSTATUS db_rbt_delete_deny(struct db_record *rec)
{
return NT_STATUS_MEDIA_WRITE_PROTECTED;
}
struct db_rbt_search_result {
TDB_DATA key;
TDB_DATA val;
@ -346,27 +357,47 @@ static NTSTATUS db_rbt_parse_record(struct db_context *db, TDB_DATA key,
return NT_STATUS_OK;
}
static int db_rbt_traverse_internal(struct rb_node *n,
static int db_rbt_traverse_internal(struct db_context *db,
struct rb_node *n,
int (*f)(struct db_record *db,
void *private_data),
void *private_data, uint32_t* count)
void *private_data, uint32_t* count,
bool rw)
{
struct db_rbt_node *r;
struct rb_node *rb_right;
struct rb_node *rb_left;
struct db_record rec;
struct db_rbt_rec rec_priv;
int ret;
if (n == NULL) {
return 0;
}
ret = db_rbt_traverse_internal(n->rb_left, f, private_data, count);
rb_left = n->rb_left;
rb_right = n->rb_right;
ret = db_rbt_traverse_internal(db, rb_left, f, private_data, count, rw);
if (ret != 0) {
return ret;
}
r = db_rbt2node(n);
ZERO_STRUCT(rec_priv);
rec_priv.node = db_rbt2node(n);
/* n might be altered by the callback function */
n = NULL;
ZERO_STRUCT(rec);
db_rbt_parse_node(r, &rec.key, &rec.value);
rec.db = db;
rec.private_data = &rec_priv;
if (rw) {
rec.store = db_rbt_store;
rec.delete_rec = db_rbt_delete;
} else {
rec.store = db_rbt_store_deny;
rec.delete_rec = db_rbt_delete_deny;
}
db_rbt_parse_node(rec_priv.node, &rec.key, &rec.value);
ret = f(&rec, private_data);
(*count) ++;
@ -374,7 +405,15 @@ static int db_rbt_traverse_internal(struct rb_node *n,
return ret;
}
return db_rbt_traverse_internal(n->rb_right, f, private_data, count);
if (rec_priv.node != NULL) {
/*
* If the current record is still there
* we should take the current rb_right.
*/
rb_right = rec_priv.node->rb_node.rb_right;
}
return db_rbt_traverse_internal(db, rb_right, f, private_data, count, rw);
}
static int db_rbt_traverse(struct db_context *db,
@ -386,7 +425,30 @@ static int db_rbt_traverse(struct db_context *db,
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
int ret = db_rbt_traverse_internal(ctx->tree.rb_node, f, private_data, &count);
int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
f, private_data, &count,
true /* rw */);
if (ret != 0) {
return -1;
}
if (count > INT_MAX) {
return -1;
}
return count;
}
static int db_rbt_traverse_read(struct db_context *db,
int (*f)(struct db_record *db,
void *private_data),
void *private_data)
{
struct db_rbt_ctx *ctx = talloc_get_type_abort(
db->private_data, struct db_rbt_ctx);
uint32_t count = 0;
int ret = db_rbt_traverse_internal(db, ctx->tree.rb_node,
f, private_data, &count,
false /* rw */);
if (ret != 0) {
return -1;
}
@ -435,7 +497,7 @@ struct db_context *db_open_rbt(TALLOC_CTX *mem_ctx)
result->fetch_locked = db_rbt_fetch_locked;
result->try_fetch_locked = NULL;
result->traverse = db_rbt_traverse;
result->traverse_read = db_rbt_traverse;
result->traverse_read = db_rbt_traverse_read;
result->get_seqnum = db_rbt_get_seqnum;
result->transaction_start = db_rbt_trans_dummy;
result->transaction_commit = db_rbt_trans_dummy;