mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
r13700: added highestCommittedUSN, uSNChanged and uSNCreated support, using
the @BASEINFO sequenceNumber (simo, I changed the function pointer to a structure element as you preferred)
This commit is contained in:
parent
71eb159f9c
commit
68c9ac38c7
@ -43,6 +43,7 @@ static int do_attribute(const char * const *attrs, const char *name)
|
||||
ldb_attr_in_list(attrs, "*");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
add dynamically generated attributes to rootDSE result
|
||||
*/
|
||||
@ -106,6 +107,14 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_request *re
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (do_attribute(s->attrs, "highestCommittedUSN")) {
|
||||
if (module->ldb->sequence_number != NULL &&
|
||||
ldb_msg_add_fmt(msg, "highestCommittedUSN",
|
||||
"%llu", module->ldb->sequence_number(module->ldb)) != 0) {
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: lots more dynamic attributes should be added here */
|
||||
|
||||
|
@ -107,6 +107,9 @@ struct ldb_context {
|
||||
int transaction_active;
|
||||
|
||||
int (*async_wait)(struct ldb_async_handle *, enum ldb_async_wait_type);
|
||||
|
||||
/* a backend supplied highestCommittedUSN function */
|
||||
uint64_t (*sequence_number)(struct ldb_context *);
|
||||
};
|
||||
|
||||
/* the modules init function */
|
||||
|
@ -772,6 +772,31 @@ static int ltdb_request(struct ldb_module *module, struct ldb_request *req)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
return sequenceNumber from @BASEINFO
|
||||
*/
|
||||
static uint64_t ltdb_sequence_number(struct ldb_context *ldb)
|
||||
{
|
||||
TALLOC_CTX *tmp_ctx = talloc_new(ldb);
|
||||
const char *attrs[] = { "sequenceNumber", NULL };
|
||||
struct ldb_result *res = NULL;
|
||||
struct ldb_dn *dn = ldb_dn_explode(tmp_ctx, "@BASEINFO");
|
||||
int ret;
|
||||
uint64_t seq_num;
|
||||
|
||||
ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, NULL, attrs, &res);
|
||||
talloc_steal(tmp_ctx, res);
|
||||
if (ret != LDB_SUCCESS || res->count != 1) {
|
||||
talloc_free(tmp_ctx);
|
||||
/* zero is as good as anything when we don't know */
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_num = ldb_msg_find_uint64(res->msgs[0], "sequenceNumber", 0);
|
||||
talloc_free(tmp_ctx);
|
||||
return seq_num;
|
||||
}
|
||||
|
||||
static int ltdb_init_2(struct ldb_module *module)
|
||||
{
|
||||
return LDB_SUCCESS;
|
||||
@ -847,6 +872,7 @@ int ltdb_connect(struct ldb_context *ldb, const char *url,
|
||||
ldb->modules->prev = ldb->modules->next = NULL;
|
||||
ldb->modules->private_data = ltdb;
|
||||
ldb->modules->ops = <db_ops;
|
||||
ldb->sequence_number = ltdb_sequence_number;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -267,6 +267,29 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
add a uint64_t element to a record
|
||||
*/
|
||||
static int add_uint64_element(struct ldb_message *msg, const char *attr, uint64_t v)
|
||||
{
|
||||
struct ldb_message_element *el;
|
||||
|
||||
if (ldb_msg_find_element(msg, attr) != NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ldb_msg_add_fmt(msg, attr, "%llu", v) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
el = ldb_msg_find_element(msg, attr);
|
||||
/* always set as replace. This works because on add ops, the flag
|
||||
is ignored */
|
||||
el->flags = LDB_FLAG_MOD_REPLACE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
hook add record ops
|
||||
@ -292,6 +315,17 @@ static int operational_add(struct ldb_module *module, struct ldb_request *req)
|
||||
talloc_free(msg2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* see if the backend can give us the USN */
|
||||
if (module->ldb->sequence_number != NULL) {
|
||||
uint64_t seq_num = module->ldb->sequence_number(module->ldb);
|
||||
if (add_uint64_element(msg2, "uSNCreated", seq_num) != 0 ||
|
||||
add_uint64_element(msg2, "uSNChanged", seq_num) != 0) {
|
||||
talloc_free(msg2);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* use the new structure for the call chain below this point */
|
||||
req->op.add.message = msg2;
|
||||
/* go on with the call chain */
|
||||
@ -326,6 +360,15 @@ static int operational_modify(struct ldb_module *module, struct ldb_request *req
|
||||
talloc_free(msg2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* update the records USN if possible */
|
||||
if (module->ldb->sequence_number != NULL &&
|
||||
add_uint64_element(msg2, "uSNChanged",
|
||||
module->ldb->sequence_number(module->ldb)) != 0) {
|
||||
talloc_free(msg2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* use the new structure for the call chain below this point */
|
||||
req->op.mod.message = msg2;
|
||||
/* go on with the call chain */
|
||||
|
Loading…
Reference in New Issue
Block a user