1
0
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:
Simo Sorce 2008-10-15 14:03:20 -04:00
parent f0dcc1fad4
commit 2deeb99fff
12 changed files with 433 additions and 228 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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
}; };

View File

@ -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
*/ */

View File

@ -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);

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -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
}; };
/* /*

View File

@ -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);

View File

@ -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)));

View File

@ -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