mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
Transform the sequence_number operation into a normal extended operation as it should always have been. Make it also async so that it is not a special case.
This commit is contained in:
parent
f0dcc1fad4
commit
2deeb99fff
@ -194,7 +194,7 @@ static int objectguid_add(struct ldb_module *module, struct ldb_request *req)
|
||||
}
|
||||
|
||||
/* Get a sequence number from the backend */
|
||||
/* FIXME: ldb_sequence_number is still SYNC now, when this changes,
|
||||
/* FIXME: ldb_sequence_number is a semi-async call,
|
||||
* make sure this function is split and a callback is used */
|
||||
ret = ldb_sequence_number(module->ldb, LDB_SEQ_NEXT, &seq_num);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
|
@ -115,10 +115,6 @@ int partition_request(struct ldb_module *module, struct ldb_request *request)
|
||||
PARTITION_FIND_OP(module, extended);
|
||||
ret = module->ops->extended(module, request);
|
||||
break;
|
||||
case LDB_SEQUENCE_NUMBER:
|
||||
PARTITION_FIND_OP(module, sequence_number);
|
||||
ret = module->ops->sequence_number(module, request);
|
||||
break;
|
||||
default:
|
||||
PARTITION_FIND_OP(module, request);
|
||||
ret = module->ops->request(module, request);
|
||||
@ -716,9 +712,8 @@ static int partition_del_trans(struct ldb_module *module)
|
||||
return ret2;
|
||||
}
|
||||
|
||||
/* NOTE: ldb_sequence_number is still a completely SYNCHRONOUS call
|
||||
* implemented only in ldb_rdb. It does not require ldb_wait() to be
|
||||
* called after a request is made */
|
||||
|
||||
/* FIXME: This function is still semi-async */
|
||||
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
|
||||
{
|
||||
int i, ret;
|
||||
@ -727,113 +722,241 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
|
||||
uint64_t timestamp = 0;
|
||||
struct partition_private_data *data = talloc_get_type(module->private_data,
|
||||
struct partition_private_data);
|
||||
struct ldb_seqnum_request *seq;
|
||||
struct ldb_seqnum_result *seqr;
|
||||
struct ldb_request *treq;
|
||||
struct ldb_seqnum_request *tseq;
|
||||
struct ldb_seqnum_result *tseqr;
|
||||
struct ldb_extended *ext;
|
||||
struct ldb_result *res;
|
||||
|
||||
switch (req->op.seq_num.type) {
|
||||
seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request);
|
||||
|
||||
switch (seq->type) {
|
||||
case LDB_SEQ_NEXT:
|
||||
case LDB_SEQ_HIGHEST_SEQ:
|
||||
ret = ldb_next_request(module, req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if (req->op.seq_num.flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
|
||||
timestamp_sequence = req->op.seq_num.seq_num;
|
||||
} else {
|
||||
seq_number = seq_number + req->op.seq_num.seq_num;
|
||||
}
|
||||
|
||||
/* gross hack part1 */
|
||||
ret = ldb_request_add_control(req,
|
||||
DSDB_CONTROL_CURRENT_PARTITION_OID,
|
||||
false, NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Look at base DN */
|
||||
/* Figure out which partition it is under */
|
||||
/* Skip the lot if 'data' isn't here yet (initialistion) */
|
||||
for (i=0; data && data->partitions && data->partitions[i]; i++) {
|
||||
|
||||
/* gross hack part2 */
|
||||
int j;
|
||||
for (j=0; req->controls[j]; j++) {
|
||||
if (strcmp(req->controls[j]->oid, DSDB_CONTROL_CURRENT_PARTITION_OID) == 0) {
|
||||
req->controls[j]->data = data->partitions[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = partition_request(data->partitions[i]->module, req);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
if (req->op.seq_num.flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
|
||||
timestamp_sequence = MAX(timestamp_sequence, req->op.seq_num.seq_num);
|
||||
} else {
|
||||
seq_number = seq_number + req->op.seq_num.seq_num;
|
||||
}
|
||||
}
|
||||
/* fall though */
|
||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||
{
|
||||
struct ldb_request *date_req = talloc(req, struct ldb_request);
|
||||
if (!date_req) {
|
||||
res = talloc_zero(req, struct ldb_result);
|
||||
if (res == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
*date_req = *req;
|
||||
date_req->op.seq_num.flags = LDB_SEQ_HIGHEST_TIMESTAMP;
|
||||
tseq = talloc_zero(res, struct ldb_seqnum_request);
|
||||
if (tseq == NULL) {
|
||||
talloc_free(res);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
tseq->type = seq->type;
|
||||
|
||||
ret = ldb_next_request(module, date_req);
|
||||
ret = ldb_build_extended_req(&treq, module->ldb, res,
|
||||
LDB_EXTENDED_SEQUENCE_NUMBER,
|
||||
tseq,
|
||||
NULL,
|
||||
res,
|
||||
ldb_extended_default_callback,
|
||||
NULL);
|
||||
ret = ldb_next_request(module, treq);
|
||||
if (ret == LDB_SUCCESS) {
|
||||
ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
|
||||
}
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
timestamp = date_req->op.seq_num.seq_num;
|
||||
seqr = talloc_get_type(res->extended->data,
|
||||
struct ldb_seqnum_result);
|
||||
if (seqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
|
||||
timestamp_sequence = seqr->seq_num;
|
||||
} else {
|
||||
seq_number += seqr->seq_num;
|
||||
}
|
||||
talloc_free(res);
|
||||
|
||||
/* Look at base DN */
|
||||
/* Figure out which partition it is under */
|
||||
/* Skip the lot if 'data' isn't here yet (initialistion) */
|
||||
for (i=0; data && data->partitions && data->partitions[i]; i++) {
|
||||
|
||||
ret = partition_request(data->partitions[i]->module, req);
|
||||
res = talloc_zero(req, struct ldb_result);
|
||||
if (res == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
tseq = talloc_zero(res, struct ldb_seqnum_request);
|
||||
if (tseq == NULL) {
|
||||
talloc_free(res);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
tseq->type = seq->type;
|
||||
|
||||
ret = ldb_build_extended_req(&treq, module->ldb, res,
|
||||
LDB_EXTENDED_SEQUENCE_NUMBER,
|
||||
tseq,
|
||||
NULL,
|
||||
res,
|
||||
ldb_extended_default_callback,
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
timestamp = MAX(timestamp, date_req->op.seq_num.seq_num);
|
||||
|
||||
ret = ldb_request_add_control(treq,
|
||||
DSDB_CONTROL_CURRENT_PARTITION_OID,
|
||||
false, data->partitions[i]);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = partition_request(data->partitions[i]->module, treq);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
tseqr = talloc_get_type(res->extended->data,
|
||||
struct ldb_seqnum_result);
|
||||
if (tseqr->flags & LDB_SEQ_TIMESTAMP_SEQUENCE) {
|
||||
timestamp_sequence = MAX(timestamp_sequence,
|
||||
tseqr->seq_num);
|
||||
} else {
|
||||
seq_number += tseqr->seq_num;
|
||||
}
|
||||
talloc_free(res);
|
||||
}
|
||||
/* fall through */
|
||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||
|
||||
res = talloc_zero(req, struct ldb_result);
|
||||
if (res == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
tseq = talloc_zero(res, struct ldb_seqnum_request);
|
||||
if (tseq == NULL) {
|
||||
talloc_free(res);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP;
|
||||
|
||||
ret = ldb_build_extended_req(&treq, module->ldb, res,
|
||||
LDB_EXTENDED_SEQUENCE_NUMBER,
|
||||
tseq,
|
||||
NULL,
|
||||
res,
|
||||
ldb_extended_default_callback,
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ldb_next_request(module, treq);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tseqr = talloc_get_type(res->extended->data,
|
||||
struct ldb_seqnum_result);
|
||||
timestamp = tseqr->seq_num;
|
||||
|
||||
talloc_free(res);
|
||||
|
||||
/* Skip the lot if 'data' isn't here yet (initialistion) */
|
||||
for (i=0; data && data->partitions && data->partitions[i]; i++) {
|
||||
|
||||
res = talloc_zero(req, struct ldb_result);
|
||||
if (res == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
tseq = talloc_zero(res, struct ldb_seqnum_request);
|
||||
if (tseq == NULL) {
|
||||
talloc_free(res);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
tseq->type = LDB_SEQ_HIGHEST_TIMESTAMP;
|
||||
|
||||
ret = ldb_build_extended_req(&treq, module->ldb, res,
|
||||
LDB_EXTENDED_SEQUENCE_NUMBER,
|
||||
tseq,
|
||||
NULL,
|
||||
res,
|
||||
ldb_extended_default_callback,
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = partition_request(data->partitions[i]->module, treq);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
ret = ldb_wait(treq->handle, LDB_WAIT_ALL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
talloc_free(res);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tseqr = talloc_get_type(res->extended->data,
|
||||
struct ldb_seqnum_result);
|
||||
timestamp = MAX(timestamp, tseqr->seq_num);
|
||||
|
||||
talloc_free(res);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (req->op.seq_num.flags) {
|
||||
ext = talloc_zero(req, struct ldb_extended);
|
||||
if (!ext) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
seqr = talloc_zero(ext, struct ldb_seqnum_result);
|
||||
if (seqr == NULL) {
|
||||
talloc_free(ext);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
|
||||
ext->data = seqr;
|
||||
|
||||
switch (seq->type) {
|
||||
case LDB_SEQ_NEXT:
|
||||
case LDB_SEQ_HIGHEST_SEQ:
|
||||
|
||||
req->op.seq_num.flags = 0;
|
||||
|
||||
/* Has someone above set a timebase sequence? */
|
||||
if (timestamp_sequence) {
|
||||
req->op.seq_num.seq_num = (((unsigned long long)timestamp << 24) | (seq_number & 0xFFFFFF));
|
||||
seqr->seq_num = (((unsigned long long)timestamp << 24) | (seq_number & 0xFFFFFF));
|
||||
} else {
|
||||
req->op.seq_num.seq_num = seq_number;
|
||||
seqr->seq_num = seq_number;
|
||||
}
|
||||
|
||||
if (timestamp_sequence > req->op.seq_num.seq_num) {
|
||||
req->op.seq_num.seq_num = timestamp_sequence;
|
||||
req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||
if (timestamp_sequence > seqr->seq_num) {
|
||||
seqr->seq_num = timestamp_sequence;
|
||||
seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||
}
|
||||
|
||||
req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||
seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||
break;
|
||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||
req->op.seq_num.seq_num = timestamp;
|
||||
seqr->seq_num = timestamp;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (req->op.seq_num.flags) {
|
||||
case LDB_SEQ_NEXT:
|
||||
req->op.seq_num.seq_num++;
|
||||
if (seq->type == LDB_SEQ_NEXT) {
|
||||
seqr->seq_num++;
|
||||
}
|
||||
return LDB_SUCCESS;
|
||||
|
||||
/* send request done */
|
||||
return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
|
||||
}
|
||||
|
||||
static int partition_extended_replicated_objects(struct ldb_module *module, struct ldb_request *req)
|
||||
@ -906,6 +1029,10 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
|
||||
return partition_sequence_number(module, req);
|
||||
}
|
||||
|
||||
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) {
|
||||
return partition_extended_replicated_objects(module, req);
|
||||
}
|
||||
@ -1204,7 +1331,6 @@ _PUBLIC_ const struct ldb_module_ops ldb_partition_module_ops = {
|
||||
.del = partition_delete,
|
||||
.rename = partition_rename,
|
||||
.extended = partition_extended,
|
||||
.sequence_number = partition_sequence_number,
|
||||
.start_transaction = partition_start_trans,
|
||||
.end_transaction = partition_end_trans,
|
||||
.del_transaction = partition_del_trans,
|
||||
|
@ -603,10 +603,18 @@ static int nsuniqueid_init(struct ldb_module *module)
|
||||
return ldb_next_init(module);
|
||||
}
|
||||
|
||||
static int get_seq(struct ldb_request *req,
|
||||
struct ldb_reply *ares)
|
||||
static int get_seq_callback(struct ldb_request *req,
|
||||
struct ldb_reply *ares)
|
||||
{
|
||||
unsigned long long *seq = (unsigned long long *)req->context;
|
||||
|
||||
if (!ares) {
|
||||
return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
|
||||
}
|
||||
if (ares->error != LDB_SUCCESS) {
|
||||
return ldb_request_done(req, ares->error);
|
||||
}
|
||||
|
||||
if (ares->type == LDB_REPLY_ENTRY) {
|
||||
struct ldb_message_element *el = ldb_msg_find_element(ares->message, "contextCSN");
|
||||
if (el) {
|
||||
@ -618,6 +626,7 @@ static int get_seq(struct ldb_request *req,
|
||||
return ldb_request_done(req, LDB_SUCCESS);
|
||||
}
|
||||
|
||||
talloc_free(ares);
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
@ -626,7 +635,7 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
||||
int ret;
|
||||
struct map_private *map_private;
|
||||
struct entryuuid_private *entryuuid_private;
|
||||
unsigned long long seq = 0;
|
||||
unsigned long long seq_num = 0;
|
||||
struct ldb_request *search_req;
|
||||
|
||||
const struct ldb_control *partition_ctrl;
|
||||
@ -636,6 +645,12 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
||||
"contextCSN", NULL
|
||||
};
|
||||
|
||||
struct ldb_seqnum_request *seq;
|
||||
struct ldb_seqnum_result *seqr;
|
||||
struct ldb_extended *ext;
|
||||
|
||||
seq = talloc_get_type(req->op.extended.data, struct ldb_seqnum_request);
|
||||
|
||||
map_private = talloc_get_type(module->private_data, struct map_private);
|
||||
|
||||
entryuuid_private = talloc_get_type(map_private->caller_private, struct entryuuid_private);
|
||||
@ -655,7 +670,7 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
||||
ret = ldb_build_search_req(&search_req, module->ldb, req,
|
||||
partition->dn, LDB_SCOPE_BASE,
|
||||
NULL, contextCSN_attr, NULL,
|
||||
&seq, get_seq,
|
||||
&seq_num, get_seq_callback,
|
||||
NULL);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
return ret;
|
||||
@ -672,36 +687,59 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (req->op.seq_num.type) {
|
||||
ext = talloc_zero(req, struct ldb_extended);
|
||||
if (!ext) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
seqr = talloc_zero(req, struct ldb_seqnum_result);
|
||||
if (seqr == NULL) {
|
||||
talloc_free(ext);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
ext->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
|
||||
ext->data = seqr;
|
||||
|
||||
switch (seq->type) {
|
||||
case LDB_SEQ_HIGHEST_SEQ:
|
||||
req->op.seq_num.seq_num = seq;
|
||||
seqr->seq_num = seq_num;
|
||||
break;
|
||||
case LDB_SEQ_NEXT:
|
||||
req->op.seq_num.seq_num = seq;
|
||||
req->op.seq_num.seq_num++;
|
||||
seqr->seq_num = seq_num;
|
||||
seqr->seq_num++;
|
||||
break;
|
||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||
{
|
||||
req->op.seq_num.seq_num = (seq >> 24);
|
||||
seqr->seq_num = (seq_num >> 24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
req->op.seq_num.flags = 0;
|
||||
req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||
req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||
return LDB_SUCCESS;
|
||||
seqr->flags = 0;
|
||||
seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||
seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||
|
||||
/* send request done */
|
||||
return ldb_module_done(req, NULL, ext, LDB_SUCCESS);
|
||||
}
|
||||
|
||||
static int entryuuid_extended(struct ldb_module *module, struct ldb_request *req)
|
||||
{
|
||||
if (strcmp(req->op.extended.oid, LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
|
||||
return entryuuid_sequence_number(module, req);
|
||||
}
|
||||
|
||||
return ldb_next_request(module, req);
|
||||
}
|
||||
|
||||
_PUBLIC_ const struct ldb_module_ops ldb_entryuuid_module_ops = {
|
||||
.name = "entryuuid",
|
||||
.init_context = entryuuid_init,
|
||||
.sequence_number = entryuuid_sequence_number,
|
||||
.extended = entryuuid_extended,
|
||||
LDB_MAP_OPS
|
||||
};
|
||||
|
||||
_PUBLIC_ const struct ldb_module_ops ldb_nsuniqueid_module_ops = {
|
||||
.name = "nsuniqueid",
|
||||
.init_context = nsuniqueid_init,
|
||||
.sequence_number = entryuuid_sequence_number,
|
||||
.extended = entryuuid_extended,
|
||||
LDB_MAP_OPS
|
||||
};
|
||||
|
@ -527,10 +527,6 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
|
||||
FIRST_OP(ldb, extended);
|
||||
ret = module->ops->extended(module, req);
|
||||
break;
|
||||
case LDB_SEQUENCE_NUMBER:
|
||||
FIRST_OP(ldb, sequence_number);
|
||||
ret = module->ops->sequence_number(module, req);
|
||||
break;
|
||||
default:
|
||||
FIRST_OP(ldb, request);
|
||||
ret = module->ops->request(module, req);
|
||||
@ -1172,35 +1168,47 @@ int ldb_rename(struct ldb_context *ldb,
|
||||
int ldb_sequence_number(struct ldb_context *ldb,
|
||||
enum ldb_sequence_type type, uint64_t *seq_num)
|
||||
{
|
||||
struct ldb_request *req;
|
||||
struct ldb_seqnum_request *seq;
|
||||
struct ldb_seqnum_result *seqr;
|
||||
struct ldb_result *res;
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
int ret;
|
||||
|
||||
req = talloc_zero(ldb, struct ldb_request);
|
||||
if (req == NULL) {
|
||||
*seq_num = 0;
|
||||
|
||||
tmp_ctx = talloc_zero(ldb, struct ldb_request);
|
||||
if (tmp_ctx == NULL) {
|
||||
ldb_set_errstring(ldb, "Out of Memory");
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
req->operation = LDB_SEQUENCE_NUMBER;
|
||||
req->controls = NULL;
|
||||
req->context = NULL;
|
||||
req->callback = ldb_op_default_callback;
|
||||
ldb_set_timeout(ldb, req, 0); /* use default timeout */
|
||||
|
||||
req->op.seq_num.type = type;
|
||||
/* do request and autostart a transaction */
|
||||
ret = ldb_request(ldb, req);
|
||||
|
||||
if (ret == LDB_SUCCESS) {
|
||||
*seq_num = req->op.seq_num.seq_num;
|
||||
seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request);
|
||||
if (seq == NULL) {
|
||||
ldb_set_errstring(ldb, "Out of Memory");
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
seq->type = type;
|
||||
|
||||
talloc_free(req);
|
||||
ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
talloc_steal(tmp_ctx, res);
|
||||
|
||||
if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) {
|
||||
ldb_set_errstring(ldb, "Invalid OID in reply");
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
seqr = talloc_get_type(res->extended->data,
|
||||
struct ldb_seqnum_result);
|
||||
*seq_num = seqr->seq_num;
|
||||
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
return extended error information
|
||||
*/
|
||||
|
@ -517,10 +517,6 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
|
||||
FIND_OP(module, extended);
|
||||
ret = module->ops->extended(module, request);
|
||||
break;
|
||||
case LDB_SEQUENCE_NUMBER:
|
||||
FIND_OP(module, sequence_number);
|
||||
ret = module->ops->sequence_number(module, request);
|
||||
break;
|
||||
default:
|
||||
FIND_OP(module, request);
|
||||
ret = module->ops->request(module, request);
|
||||
|
@ -652,7 +652,6 @@ enum ldb_request_type {
|
||||
LDB_DELETE,
|
||||
LDB_RENAME,
|
||||
LDB_EXTENDED,
|
||||
LDB_SEQUENCE_NUMBER,
|
||||
LDB_REQ_REGISTER_CONTROL,
|
||||
LDB_REQ_REGISTER_PARTITION
|
||||
};
|
||||
@ -679,21 +678,38 @@ struct ldb_extended {
|
||||
void *data; /* NULL or a valid talloc pointer! talloc_get_type() will be used on it */
|
||||
};
|
||||
|
||||
#define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3"
|
||||
|
||||
enum ldb_sequence_type {
|
||||
LDB_SEQ_HIGHEST_SEQ,
|
||||
LDB_SEQ_HIGHEST_TIMESTAMP,
|
||||
LDB_SEQ_NEXT
|
||||
};
|
||||
|
||||
struct ldb_seqnum_request {
|
||||
enum ldb_sequence_type type;
|
||||
};
|
||||
|
||||
struct ldb_seqnum_result {
|
||||
uint64_t seq_num;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
struct ldb_result {
|
||||
unsigned int count;
|
||||
struct ldb_message **msgs;
|
||||
char **refs;
|
||||
struct ldb_extended *extended;
|
||||
struct ldb_control **controls;
|
||||
char **refs;
|
||||
};
|
||||
|
||||
struct ldb_reply {
|
||||
int error;
|
||||
enum ldb_reply_type type;
|
||||
struct ldb_message *message;
|
||||
struct ldb_extended *response;
|
||||
char *referral;
|
||||
struct ldb_control **controls;
|
||||
int error;
|
||||
char *referral;
|
||||
};
|
||||
|
||||
struct ldb_request;
|
||||
@ -732,18 +748,6 @@ struct ldb_register_partition {
|
||||
struct ldb_dn *dn;
|
||||
};
|
||||
|
||||
enum ldb_sequence_type {
|
||||
LDB_SEQ_HIGHEST_SEQ,
|
||||
LDB_SEQ_HIGHEST_TIMESTAMP,
|
||||
LDB_SEQ_NEXT
|
||||
};
|
||||
|
||||
struct ldb_sequence_number {
|
||||
enum ldb_sequence_type type;
|
||||
uint64_t seq_num;
|
||||
uint32_t flags;
|
||||
};
|
||||
|
||||
typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *);
|
||||
|
||||
struct ldb_request {
|
||||
@ -757,7 +761,6 @@ struct ldb_request {
|
||||
struct ldb_delete del;
|
||||
struct ldb_rename rename;
|
||||
struct ldb_extended extended;
|
||||
struct ldb_sequence_number seq_num;
|
||||
struct ldb_register_control reg_control;
|
||||
struct ldb_register_partition reg_partition;
|
||||
} op;
|
||||
|
@ -1219,25 +1219,6 @@ int py_module_del_transaction(struct ldb_module *mod)
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req)
|
||||
{
|
||||
PyObject *py_ldb = mod->private_data;
|
||||
PyObject *py_result;
|
||||
int ret;
|
||||
|
||||
py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags);
|
||||
|
||||
if (py_result == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ret = PyInt_AsLong(py_result);
|
||||
|
||||
Py_DECREF(py_result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int py_module_destructor(void *_mod)
|
||||
{
|
||||
struct ldb_module *mod = _mod;
|
||||
@ -1292,7 +1273,6 @@ int py_module_init (struct ldb_module *mod)
|
||||
$1->start_transaction = py_module_start_transaction;
|
||||
$1->end_transaction = py_module_end_transaction;
|
||||
$1->del_transaction = py_module_del_transaction;
|
||||
$1->sequence_number = py_module_sequence_number;
|
||||
}
|
||||
|
||||
%feature("docstring") ldb_register_module "S.register_module(module) -> None\n"
|
||||
|
@ -276,30 +276,6 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
lock the database for read - use by ltdb_search
|
||||
*/
|
||||
static int ltdb_lock_read(struct ldb_module *module)
|
||||
{
|
||||
struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
|
||||
if (ltdb->in_transaction == 0) {
|
||||
return tdb_lockall_read(ltdb->tdb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
unlock the database after a ltdb_lock_read()
|
||||
*/
|
||||
static int ltdb_unlock_read(struct ldb_module *module)
|
||||
{
|
||||
struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
|
||||
if (ltdb->in_transaction == 0) {
|
||||
return tdb_unlockall_read(ltdb->tdb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
add a set of attributes from a record to a set of results
|
||||
return 0 on success, -1 on failure
|
||||
|
@ -79,6 +79,30 @@ static int ltdb_err_map(enum TDB_ERROR tdb_code)
|
||||
return LDB_ERR_OTHER;
|
||||
}
|
||||
|
||||
/*
|
||||
lock the database for read - use by ltdb_search and ltdb_sequence_number
|
||||
*/
|
||||
int ltdb_lock_read(struct ldb_module *module)
|
||||
{
|
||||
struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
|
||||
if (ltdb->in_transaction == 0) {
|
||||
return tdb_lockall_read(ltdb->tdb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
unlock the database after a ltdb_lock_read()
|
||||
*/
|
||||
int ltdb_unlock_read(struct ldb_module *module)
|
||||
{
|
||||
struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data;
|
||||
if (ltdb->in_transaction == 0) {
|
||||
return tdb_unlockall_read(ltdb->tdb);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
form a TDB_DATA for a record key
|
||||
@ -860,61 +884,88 @@ static int ltdb_del_trans(struct ldb_module *module)
|
||||
/*
|
||||
return sequenceNumber from @BASEINFO
|
||||
*/
|
||||
static int ltdb_sequence_number(struct ldb_module *module,
|
||||
struct ldb_request *req)
|
||||
static int ltdb_sequence_number(struct ltdb_context *ctx,
|
||||
struct ldb_extended **ext)
|
||||
{
|
||||
struct ldb_module *module = ctx->module;
|
||||
struct ldb_request *req = ctx->req;
|
||||
TALLOC_CTX *tmp_ctx;
|
||||
struct ldb_seqnum_request *seq;
|
||||
struct ldb_seqnum_result *res;
|
||||
struct ldb_message *msg = NULL;
|
||||
struct ldb_dn *dn;
|
||||
const char *date;
|
||||
int tret;
|
||||
int ret;
|
||||
|
||||
seq = talloc_get_type(req->op.extended.data,
|
||||
struct ldb_seqnum_request);
|
||||
if (seq == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
req->handle->state = LDB_ASYNC_PENDING;
|
||||
|
||||
if (ltdb_lock_read(module) != 0) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
res = talloc_zero(req, struct ldb_seqnum_result);
|
||||
if (res == NULL) {
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
tmp_ctx = talloc_new(req);
|
||||
if (tmp_ctx == NULL) {
|
||||
talloc_free(tmp_ctx);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
|
||||
|
||||
msg = talloc(tmp_ctx, struct ldb_message);
|
||||
if (msg == NULL) {
|
||||
talloc_free(tmp_ctx);
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
||||
req->op.seq_num.flags = 0;
|
||||
|
||||
tret = ltdb_search_dn1(module, dn, msg);
|
||||
if (tret != LDB_SUCCESS) {
|
||||
talloc_free(tmp_ctx);
|
||||
/* zero is as good as anything when we don't know */
|
||||
req->op.seq_num.seq_num = 0;
|
||||
return tret;
|
||||
ret = ltdb_search_dn1(module, dn, msg);
|
||||
if (ret != LDB_SUCCESS) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (req->op.seq_num.type) {
|
||||
switch (seq->type) {
|
||||
case LDB_SEQ_HIGHEST_SEQ:
|
||||
req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
|
||||
res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
|
||||
break;
|
||||
case LDB_SEQ_NEXT:
|
||||
req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
|
||||
req->op.seq_num.seq_num++;
|
||||
res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0);
|
||||
res->seq_num++;
|
||||
break;
|
||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||
date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
|
||||
if (date) {
|
||||
req->op.seq_num.seq_num = ldb_string_to_time(date);
|
||||
res->seq_num = ldb_string_to_time(date);
|
||||
} else {
|
||||
req->op.seq_num.seq_num = 0;
|
||||
res->seq_num = 0;
|
||||
/* zero is as good as anything when we don't know */
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
talloc_free(tmp_ctx);
|
||||
*ext = talloc_zero(req, struct ldb_extended);
|
||||
if (*ext == NULL) {
|
||||
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||
goto done;
|
||||
}
|
||||
(*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER;
|
||||
(*ext)->data = talloc_steal(*ext, res);
|
||||
|
||||
return LDB_SUCCESS;
|
||||
ret = LDB_SUCCESS;
|
||||
|
||||
done:
|
||||
talloc_free(tmp_ctx);
|
||||
ltdb_unlock_read(module);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ltdb_request_done(struct ldb_request *req, int error)
|
||||
@ -949,6 +1000,47 @@ static void ltdb_timeout(struct event_context *ev,
|
||||
ltdb_request_done(ctx->req, LDB_ERR_TIME_LIMIT_EXCEEDED);
|
||||
}
|
||||
|
||||
static void ltdb_request_extended_done(struct ldb_request *req,
|
||||
struct ldb_extended *ext,
|
||||
int error)
|
||||
{
|
||||
struct ldb_reply *ares;
|
||||
|
||||
/* if we already returned an error just return */
|
||||
if (req->handle->status != LDB_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
ares = talloc_zero(req, struct ldb_reply);
|
||||
if (!ares) {
|
||||
ldb_oom(req->handle->ldb);
|
||||
req->callback(req, NULL);
|
||||
return;
|
||||
}
|
||||
ares->type = LDB_REPLY_DONE;
|
||||
ares->response = ext;
|
||||
ares->error = error;
|
||||
|
||||
req->callback(req, ares);
|
||||
}
|
||||
|
||||
static void ltdb_handle_extended(struct ltdb_context *ctx)
|
||||
{
|
||||
struct ldb_extended *ext = NULL;
|
||||
int ret;
|
||||
|
||||
if (strcmp(ctx->req->op.extended.oid,
|
||||
LDB_EXTENDED_SEQUENCE_NUMBER) == 0) {
|
||||
/* get sequence number */
|
||||
ret = ltdb_sequence_number(ctx, &ext);
|
||||
} else {
|
||||
/* not recognized */
|
||||
ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
|
||||
}
|
||||
|
||||
ltdb_request_extended_done(ctx->req, ext, ret);
|
||||
}
|
||||
|
||||
static void ltdb_callback(struct event_context *ev,
|
||||
struct timed_event *te,
|
||||
struct timeval t,
|
||||
@ -975,6 +1067,9 @@ static void ltdb_callback(struct event_context *ev,
|
||||
case LDB_RENAME:
|
||||
ret = ltdb_rename(ctx);
|
||||
break;
|
||||
case LDB_EXTENDED:
|
||||
ltdb_handle_extended(ctx);
|
||||
return;
|
||||
default:
|
||||
/* no other op supported */
|
||||
ret = LDB_ERR_UNWILLING_TO_PERFORM;
|
||||
@ -1037,11 +1132,10 @@ static const struct ldb_module_ops ltdb_ops = {
|
||||
.modify = ltdb_handle_request,
|
||||
.del = ltdb_handle_request,
|
||||
.rename = ltdb_handle_request,
|
||||
/* .request = ltdb_handle_request, */
|
||||
.extended = ltdb_handle_request,
|
||||
.start_transaction = ltdb_start_trans,
|
||||
.end_transaction = ltdb_end_trans,
|
||||
.del_transaction = ltdb_del_trans,
|
||||
.sequence_number = ltdb_sequence_number
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -112,6 +112,8 @@ int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs);
|
||||
int ltdb_search(struct ltdb_context *ctx);
|
||||
|
||||
/* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */
|
||||
int ltdb_lock_read(struct ldb_module *module);
|
||||
int ltdb_unlock_read(struct ldb_module *module);
|
||||
struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn);
|
||||
int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs);
|
||||
int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn);
|
||||
|
@ -3505,25 +3505,6 @@ int py_module_del_transaction(struct ldb_module *mod)
|
||||
return LDB_SUCCESS;
|
||||
}
|
||||
|
||||
int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req)
|
||||
{
|
||||
PyObject *py_ldb = mod->private_data;
|
||||
PyObject *py_result;
|
||||
int ret;
|
||||
|
||||
py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags);
|
||||
|
||||
if (py_result == NULL) {
|
||||
return LDB_ERR_OPERATIONS_ERROR;
|
||||
}
|
||||
|
||||
ret = PyInt_AsLong(py_result);
|
||||
|
||||
Py_DECREF(py_result);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int py_module_destructor(void *_mod)
|
||||
{
|
||||
struct ldb_module *mod = _mod;
|
||||
@ -6648,7 +6629,6 @@ SWIGINTERN PyObject *_wrap_register_module(PyObject *SWIGUNUSEDPARM(self), PyObj
|
||||
arg1->start_transaction = py_module_start_transaction;
|
||||
arg1->end_transaction = py_module_end_transaction;
|
||||
arg1->del_transaction = py_module_del_transaction;
|
||||
arg1->sequence_number = py_module_sequence_number;
|
||||
result = ldb_register_module((struct ldb_module_ops const *)arg1);
|
||||
if (result != 0) {
|
||||
PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_strerror(result)));
|
||||
|
@ -177,6 +177,8 @@ oMSyntax: 20
|
||||
#Allocated: DSDB_CONTROL_REPLICATED_UPDATE_OID 1.3.6.1.4.1.7165.4.3.3
|
||||
|
||||
#Allocated: DSDB_EXTENDED_REPLICATED_OBJECTS_OID 1.3.6.1.4.1.7165.4.4.1
|
||||
#Allocated: DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID 1.3.6.1.4.1.7165.4.4.2
|
||||
#Allocated: LDB_EXTENDED_SEQUENCE_NUMBER 1.3.6.1.4.1.7165.4.4.3
|
||||
|
||||
#Allocated: (middleName) attributeID: 1.3.6.1.4.1.7165.4.255.1
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user