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 */
|
/* 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 */
|
* make sure this function is split and a callback is used */
|
||||||
ret = ldb_sequence_number(module->ldb, LDB_SEQ_NEXT, &seq_num);
|
ret = ldb_sequence_number(module->ldb, LDB_SEQ_NEXT, &seq_num);
|
||||||
if (ret == LDB_SUCCESS) {
|
if (ret == LDB_SUCCESS) {
|
||||||
|
@ -115,10 +115,6 @@ int partition_request(struct ldb_module *module, struct ldb_request *request)
|
|||||||
PARTITION_FIND_OP(module, extended);
|
PARTITION_FIND_OP(module, extended);
|
||||||
ret = module->ops->extended(module, request);
|
ret = module->ops->extended(module, request);
|
||||||
break;
|
break;
|
||||||
case LDB_SEQUENCE_NUMBER:
|
|
||||||
PARTITION_FIND_OP(module, sequence_number);
|
|
||||||
ret = module->ops->sequence_number(module, request);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
PARTITION_FIND_OP(module, request);
|
PARTITION_FIND_OP(module, request);
|
||||||
ret = module->ops->request(module, request);
|
ret = module->ops->request(module, request);
|
||||||
@ -716,9 +712,8 @@ static int partition_del_trans(struct ldb_module *module)
|
|||||||
return ret2;
|
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
|
/* FIXME: This function is still semi-async */
|
||||||
* called after a request is made */
|
|
||||||
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
|
static int partition_sequence_number(struct ldb_module *module, struct ldb_request *req)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
@ -727,113 +722,241 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque
|
|||||||
uint64_t timestamp = 0;
|
uint64_t timestamp = 0;
|
||||||
struct partition_private_data *data = talloc_get_type(module->private_data,
|
struct partition_private_data *data = talloc_get_type(module->private_data,
|
||||||
struct partition_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_NEXT:
|
||||||
case LDB_SEQ_HIGHEST_SEQ:
|
case LDB_SEQ_HIGHEST_SEQ:
|
||||||
ret = ldb_next_request(module, req);
|
res = talloc_zero(req, struct ldb_result);
|
||||||
if (ret != LDB_SUCCESS) {
|
if (res == NULL) {
|
||||||
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) {
|
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
return LDB_ERR_OPERATIONS_ERROR;
|
||||||
}
|
}
|
||||||
*date_req = *req;
|
tseq = talloc_zero(res, struct ldb_seqnum_request);
|
||||||
date_req->op.seq_num.flags = LDB_SEQ_HIGHEST_TIMESTAMP;
|
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) {
|
if (ret != LDB_SUCCESS) {
|
||||||
|
talloc_free(res);
|
||||||
return ret;
|
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) */
|
/* Skip the lot if 'data' isn't here yet (initialistion) */
|
||||||
for (i=0; data && data->partitions && data->partitions[i]; i++) {
|
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) {
|
if (ret != LDB_SUCCESS) {
|
||||||
|
talloc_free(res);
|
||||||
return ret;
|
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;
|
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_NEXT:
|
||||||
case LDB_SEQ_HIGHEST_SEQ:
|
case LDB_SEQ_HIGHEST_SEQ:
|
||||||
|
|
||||||
req->op.seq_num.flags = 0;
|
|
||||||
|
|
||||||
/* Has someone above set a timebase sequence? */
|
/* Has someone above set a timebase sequence? */
|
||||||
if (timestamp_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 {
|
} else {
|
||||||
req->op.seq_num.seq_num = seq_number;
|
seqr->seq_num = seq_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timestamp_sequence > req->op.seq_num.seq_num) {
|
if (timestamp_sequence > seqr->seq_num) {
|
||||||
req->op.seq_num.seq_num = timestamp_sequence;
|
seqr->seq_num = timestamp_sequence;
|
||||||
req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||||
break;
|
break;
|
||||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||||
req->op.seq_num.seq_num = timestamp;
|
seqr->seq_num = timestamp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (req->op.seq_num.flags) {
|
if (seq->type == LDB_SEQ_NEXT) {
|
||||||
case LDB_SEQ_NEXT:
|
seqr->seq_num++;
|
||||||
req->op.seq_num.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)
|
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);
|
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) {
|
if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) {
|
||||||
return partition_extended_replicated_objects(module, req);
|
return partition_extended_replicated_objects(module, req);
|
||||||
}
|
}
|
||||||
@ -1204,7 +1331,6 @@ _PUBLIC_ const struct ldb_module_ops ldb_partition_module_ops = {
|
|||||||
.del = partition_delete,
|
.del = partition_delete,
|
||||||
.rename = partition_rename,
|
.rename = partition_rename,
|
||||||
.extended = partition_extended,
|
.extended = partition_extended,
|
||||||
.sequence_number = partition_sequence_number,
|
|
||||||
.start_transaction = partition_start_trans,
|
.start_transaction = partition_start_trans,
|
||||||
.end_transaction = partition_end_trans,
|
.end_transaction = partition_end_trans,
|
||||||
.del_transaction = partition_del_trans,
|
.del_transaction = partition_del_trans,
|
||||||
|
@ -603,10 +603,18 @@ static int nsuniqueid_init(struct ldb_module *module)
|
|||||||
return ldb_next_init(module);
|
return ldb_next_init(module);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_seq(struct ldb_request *req,
|
static int get_seq_callback(struct ldb_request *req,
|
||||||
struct ldb_reply *ares)
|
struct ldb_reply *ares)
|
||||||
{
|
{
|
||||||
unsigned long long *seq = (unsigned long long *)req->context;
|
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) {
|
if (ares->type == LDB_REPLY_ENTRY) {
|
||||||
struct ldb_message_element *el = ldb_msg_find_element(ares->message, "contextCSN");
|
struct ldb_message_element *el = ldb_msg_find_element(ares->message, "contextCSN");
|
||||||
if (el) {
|
if (el) {
|
||||||
@ -618,6 +626,7 @@ static int get_seq(struct ldb_request *req,
|
|||||||
return ldb_request_done(req, LDB_SUCCESS);
|
return ldb_request_done(req, LDB_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
talloc_free(ares);
|
||||||
return LDB_SUCCESS;
|
return LDB_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -626,7 +635,7 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
|||||||
int ret;
|
int ret;
|
||||||
struct map_private *map_private;
|
struct map_private *map_private;
|
||||||
struct entryuuid_private *entryuuid_private;
|
struct entryuuid_private *entryuuid_private;
|
||||||
unsigned long long seq = 0;
|
unsigned long long seq_num = 0;
|
||||||
struct ldb_request *search_req;
|
struct ldb_request *search_req;
|
||||||
|
|
||||||
const struct ldb_control *partition_ctrl;
|
const struct ldb_control *partition_ctrl;
|
||||||
@ -636,6 +645,12 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
|||||||
"contextCSN", NULL
|
"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);
|
map_private = talloc_get_type(module->private_data, struct map_private);
|
||||||
|
|
||||||
entryuuid_private = talloc_get_type(map_private->caller_private, struct entryuuid_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,
|
ret = ldb_build_search_req(&search_req, module->ldb, req,
|
||||||
partition->dn, LDB_SCOPE_BASE,
|
partition->dn, LDB_SCOPE_BASE,
|
||||||
NULL, contextCSN_attr, NULL,
|
NULL, contextCSN_attr, NULL,
|
||||||
&seq, get_seq,
|
&seq_num, get_seq_callback,
|
||||||
NULL);
|
NULL);
|
||||||
if (ret != LDB_SUCCESS) {
|
if (ret != LDB_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
@ -672,36 +687,59 @@ static int entryuuid_sequence_number(struct ldb_module *module, struct ldb_reque
|
|||||||
return ret;
|
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:
|
case LDB_SEQ_HIGHEST_SEQ:
|
||||||
req->op.seq_num.seq_num = seq;
|
seqr->seq_num = seq_num;
|
||||||
break;
|
break;
|
||||||
case LDB_SEQ_NEXT:
|
case LDB_SEQ_NEXT:
|
||||||
req->op.seq_num.seq_num = seq;
|
seqr->seq_num = seq_num;
|
||||||
req->op.seq_num.seq_num++;
|
seqr->seq_num++;
|
||||||
break;
|
break;
|
||||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||||
{
|
{
|
||||||
req->op.seq_num.seq_num = (seq >> 24);
|
seqr->seq_num = (seq_num >> 24);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
req->op.seq_num.flags = 0;
|
seqr->flags = 0;
|
||||||
req->op.seq_num.flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
seqr->flags |= LDB_SEQ_TIMESTAMP_SEQUENCE;
|
||||||
req->op.seq_num.flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
seqr->flags |= LDB_SEQ_GLOBAL_SEQUENCE;
|
||||||
return LDB_SUCCESS;
|
|
||||||
|
/* 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 = {
|
_PUBLIC_ const struct ldb_module_ops ldb_entryuuid_module_ops = {
|
||||||
.name = "entryuuid",
|
.name = "entryuuid",
|
||||||
.init_context = entryuuid_init,
|
.init_context = entryuuid_init,
|
||||||
.sequence_number = entryuuid_sequence_number,
|
.extended = entryuuid_extended,
|
||||||
LDB_MAP_OPS
|
LDB_MAP_OPS
|
||||||
};
|
};
|
||||||
|
|
||||||
_PUBLIC_ const struct ldb_module_ops ldb_nsuniqueid_module_ops = {
|
_PUBLIC_ const struct ldb_module_ops ldb_nsuniqueid_module_ops = {
|
||||||
.name = "nsuniqueid",
|
.name = "nsuniqueid",
|
||||||
.init_context = nsuniqueid_init,
|
.init_context = nsuniqueid_init,
|
||||||
.sequence_number = entryuuid_sequence_number,
|
.extended = entryuuid_extended,
|
||||||
LDB_MAP_OPS
|
LDB_MAP_OPS
|
||||||
};
|
};
|
||||||
|
@ -527,10 +527,6 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
|
|||||||
FIRST_OP(ldb, extended);
|
FIRST_OP(ldb, extended);
|
||||||
ret = module->ops->extended(module, req);
|
ret = module->ops->extended(module, req);
|
||||||
break;
|
break;
|
||||||
case LDB_SEQUENCE_NUMBER:
|
|
||||||
FIRST_OP(ldb, sequence_number);
|
|
||||||
ret = module->ops->sequence_number(module, req);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
FIRST_OP(ldb, request);
|
FIRST_OP(ldb, request);
|
||||||
ret = module->ops->request(module, req);
|
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,
|
int ldb_sequence_number(struct ldb_context *ldb,
|
||||||
enum ldb_sequence_type type, uint64_t *seq_num)
|
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;
|
int ret;
|
||||||
|
|
||||||
req = talloc_zero(ldb, struct ldb_request);
|
*seq_num = 0;
|
||||||
if (req == NULL) {
|
|
||||||
|
tmp_ctx = talloc_zero(ldb, struct ldb_request);
|
||||||
|
if (tmp_ctx == NULL) {
|
||||||
ldb_set_errstring(ldb, "Out of Memory");
|
ldb_set_errstring(ldb, "Out of Memory");
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
return LDB_ERR_OPERATIONS_ERROR;
|
||||||
}
|
}
|
||||||
|
seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request);
|
||||||
req->operation = LDB_SEQUENCE_NUMBER;
|
if (seq == NULL) {
|
||||||
req->controls = NULL;
|
ldb_set_errstring(ldb, "Out of Memory");
|
||||||
req->context = NULL;
|
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||||
req->callback = ldb_op_default_callback;
|
goto done;
|
||||||
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->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 ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
return extended error information
|
return extended error information
|
||||||
*/
|
*/
|
||||||
|
@ -517,10 +517,6 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
|
|||||||
FIND_OP(module, extended);
|
FIND_OP(module, extended);
|
||||||
ret = module->ops->extended(module, request);
|
ret = module->ops->extended(module, request);
|
||||||
break;
|
break;
|
||||||
case LDB_SEQUENCE_NUMBER:
|
|
||||||
FIND_OP(module, sequence_number);
|
|
||||||
ret = module->ops->sequence_number(module, request);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
FIND_OP(module, request);
|
FIND_OP(module, request);
|
||||||
ret = module->ops->request(module, request);
|
ret = module->ops->request(module, request);
|
||||||
|
@ -652,7 +652,6 @@ enum ldb_request_type {
|
|||||||
LDB_DELETE,
|
LDB_DELETE,
|
||||||
LDB_RENAME,
|
LDB_RENAME,
|
||||||
LDB_EXTENDED,
|
LDB_EXTENDED,
|
||||||
LDB_SEQUENCE_NUMBER,
|
|
||||||
LDB_REQ_REGISTER_CONTROL,
|
LDB_REQ_REGISTER_CONTROL,
|
||||||
LDB_REQ_REGISTER_PARTITION
|
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 */
|
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 {
|
struct ldb_result {
|
||||||
unsigned int count;
|
unsigned int count;
|
||||||
struct ldb_message **msgs;
|
struct ldb_message **msgs;
|
||||||
char **refs;
|
|
||||||
struct ldb_extended *extended;
|
struct ldb_extended *extended;
|
||||||
struct ldb_control **controls;
|
struct ldb_control **controls;
|
||||||
|
char **refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ldb_reply {
|
struct ldb_reply {
|
||||||
|
int error;
|
||||||
enum ldb_reply_type type;
|
enum ldb_reply_type type;
|
||||||
struct ldb_message *message;
|
struct ldb_message *message;
|
||||||
struct ldb_extended *response;
|
struct ldb_extended *response;
|
||||||
char *referral;
|
|
||||||
struct ldb_control **controls;
|
struct ldb_control **controls;
|
||||||
int error;
|
char *referral;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ldb_request;
|
struct ldb_request;
|
||||||
@ -732,18 +748,6 @@ struct ldb_register_partition {
|
|||||||
struct ldb_dn *dn;
|
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 *);
|
typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *);
|
||||||
|
|
||||||
struct ldb_request {
|
struct ldb_request {
|
||||||
@ -757,7 +761,6 @@ struct ldb_request {
|
|||||||
struct ldb_delete del;
|
struct ldb_delete del;
|
||||||
struct ldb_rename rename;
|
struct ldb_rename rename;
|
||||||
struct ldb_extended extended;
|
struct ldb_extended extended;
|
||||||
struct ldb_sequence_number seq_num;
|
|
||||||
struct ldb_register_control reg_control;
|
struct ldb_register_control reg_control;
|
||||||
struct ldb_register_partition reg_partition;
|
struct ldb_register_partition reg_partition;
|
||||||
} op;
|
} op;
|
||||||
|
@ -1219,25 +1219,6 @@ int py_module_del_transaction(struct ldb_module *mod)
|
|||||||
return LDB_SUCCESS;
|
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)
|
static int py_module_destructor(void *_mod)
|
||||||
{
|
{
|
||||||
struct ldb_module *mod = _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->start_transaction = py_module_start_transaction;
|
||||||
$1->end_transaction = py_module_end_transaction;
|
$1->end_transaction = py_module_end_transaction;
|
||||||
$1->del_transaction = py_module_del_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"
|
%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;
|
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
|
add a set of attributes from a record to a set of results
|
||||||
return 0 on success, -1 on failure
|
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;
|
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
|
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
|
return sequenceNumber from @BASEINFO
|
||||||
*/
|
*/
|
||||||
static int ltdb_sequence_number(struct ldb_module *module,
|
static int ltdb_sequence_number(struct ltdb_context *ctx,
|
||||||
struct ldb_request *req)
|
struct ldb_extended **ext)
|
||||||
{
|
{
|
||||||
|
struct ldb_module *module = ctx->module;
|
||||||
|
struct ldb_request *req = ctx->req;
|
||||||
TALLOC_CTX *tmp_ctx;
|
TALLOC_CTX *tmp_ctx;
|
||||||
|
struct ldb_seqnum_request *seq;
|
||||||
|
struct ldb_seqnum_result *res;
|
||||||
struct ldb_message *msg = NULL;
|
struct ldb_message *msg = NULL;
|
||||||
struct ldb_dn *dn;
|
struct ldb_dn *dn;
|
||||||
const char *date;
|
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);
|
tmp_ctx = talloc_new(req);
|
||||||
if (tmp_ctx == NULL) {
|
if (tmp_ctx == NULL) {
|
||||||
talloc_free(tmp_ctx);
|
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
|
dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO);
|
||||||
|
|
||||||
msg = talloc(tmp_ctx, struct ldb_message);
|
msg = talloc(tmp_ctx, struct ldb_message);
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
talloc_free(tmp_ctx);
|
ret = LDB_ERR_OPERATIONS_ERROR;
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
req->op.seq_num.flags = 0;
|
ret = ltdb_search_dn1(module, dn, msg);
|
||||||
|
if (ret != LDB_SUCCESS) {
|
||||||
tret = ltdb_search_dn1(module, dn, msg);
|
goto done;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (req->op.seq_num.type) {
|
switch (seq->type) {
|
||||||
case LDB_SEQ_HIGHEST_SEQ:
|
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;
|
break;
|
||||||
case LDB_SEQ_NEXT:
|
case LDB_SEQ_NEXT:
|
||||||
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);
|
||||||
req->op.seq_num.seq_num++;
|
res->seq_num++;
|
||||||
break;
|
break;
|
||||||
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
case LDB_SEQ_HIGHEST_TIMESTAMP:
|
||||||
date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
|
date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL);
|
||||||
if (date) {
|
if (date) {
|
||||||
req->op.seq_num.seq_num = ldb_string_to_time(date);
|
res->seq_num = ldb_string_to_time(date);
|
||||||
} else {
|
} else {
|
||||||
req->op.seq_num.seq_num = 0;
|
res->seq_num = 0;
|
||||||
/* zero is as good as anything when we don't know */
|
/* zero is as good as anything when we don't know */
|
||||||
}
|
}
|
||||||
break;
|
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)
|
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);
|
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,
|
static void ltdb_callback(struct event_context *ev,
|
||||||
struct timed_event *te,
|
struct timed_event *te,
|
||||||
struct timeval t,
|
struct timeval t,
|
||||||
@ -975,6 +1067,9 @@ static void ltdb_callback(struct event_context *ev,
|
|||||||
case LDB_RENAME:
|
case LDB_RENAME:
|
||||||
ret = ltdb_rename(ctx);
|
ret = ltdb_rename(ctx);
|
||||||
break;
|
break;
|
||||||
|
case LDB_EXTENDED:
|
||||||
|
ltdb_handle_extended(ctx);
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
/* no other op supported */
|
/* no other op supported */
|
||||||
ret = LDB_ERR_UNWILLING_TO_PERFORM;
|
ret = LDB_ERR_UNWILLING_TO_PERFORM;
|
||||||
@ -1037,11 +1132,10 @@ static const struct ldb_module_ops ltdb_ops = {
|
|||||||
.modify = ltdb_handle_request,
|
.modify = ltdb_handle_request,
|
||||||
.del = ltdb_handle_request,
|
.del = ltdb_handle_request,
|
||||||
.rename = ltdb_handle_request,
|
.rename = ltdb_handle_request,
|
||||||
/* .request = ltdb_handle_request, */
|
.extended = ltdb_handle_request,
|
||||||
.start_transaction = ltdb_start_trans,
|
.start_transaction = ltdb_start_trans,
|
||||||
.end_transaction = ltdb_end_trans,
|
.end_transaction = ltdb_end_trans,
|
||||||
.del_transaction = ltdb_del_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);
|
int ltdb_search(struct ltdb_context *ctx);
|
||||||
|
|
||||||
/* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */
|
/* 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);
|
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_store(struct ldb_module *module, const struct ldb_message *msg, int flgs);
|
||||||
int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn);
|
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;
|
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)
|
static int py_module_destructor(void *_mod)
|
||||||
{
|
{
|
||||||
struct ldb_module *mod = _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->start_transaction = py_module_start_transaction;
|
||||||
arg1->end_transaction = py_module_end_transaction;
|
arg1->end_transaction = py_module_end_transaction;
|
||||||
arg1->del_transaction = py_module_del_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);
|
result = ldb_register_module((struct ldb_module_ops const *)arg1);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_strerror(result)));
|
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_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_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
|
#Allocated: (middleName) attributeID: 1.3.6.1.4.1.7165.4.255.1
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user