From: Simo Sorce Date: Wed, 15 Oct 2008 18:03:20 +0000 (-0400) Subject: Transform the sequence_number operation into a normal extended operation as it should... X-Git-Tag: samba-4.0.0alpha6~769^2~65^2~2 X-Git-Url: http://git.samba.org/samba.git/?p=ira%2Fwip.git;a=commitdiff_plain;h=2deeb99fff1a90c79ba1927e1a069362e250a63c 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. --- diff --git a/source4/dsdb/samdb/ldb_modules/objectguid.c b/source4/dsdb/samdb/ldb_modules/objectguid.c index 054905992de..3d725686e72 100644 --- a/source4/dsdb/samdb/ldb_modules/objectguid.c +++ b/source4/dsdb/samdb/ldb_modules/objectguid.c @@ -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) { diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index b452b66d569..b4a7a47a232 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -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; + res = talloc_zero(req, struct ldb_result); + if (res == NULL) { + return LDB_ERR_OPERATIONS_ERROR; } - 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; + 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); + ret = ldb_next_request(module, treq); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(treq->handle, LDB_WAIT_ALL); } - - /* gross hack part1 */ - ret = ldb_request_add_control(req, - DSDB_CONTROL_CURRENT_PARTITION_OID, - false, NULL); if (ret != LDB_SUCCESS) { + talloc_free(res); return ret; } + 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++) { - /* 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; - } + 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; } - ret = partition_request(data->partitions[i]->module, req); + ret = ldb_request_add_control(treq, + DSDB_CONTROL_CURRENT_PARTITION_OID, + false, data->partitions[i]); if (ret != LDB_SUCCESS) { + talloc_free(res); return ret; } - if (req->op.seq_num.flags & LDB_SEQ_TIMESTAMP_SEQUENCE) { - timestamp_sequence = MAX(timestamp_sequence, req->op.seq_num.seq_num); + + 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 = seq_number + req->op.seq_num.seq_num; + seq_number += tseqr->seq_num; } + talloc_free(res); } - /* fall though */ + /* fall through */ 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; - ret = ldb_next_request(module, date_req); + 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; } - timestamp = date_req->op.seq_num.seq_num; - /* Look at base DN */ - /* Figure out which partition it is under */ + 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++) { - 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 = 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; } - timestamp = MAX(timestamp, date_req->op.seq_num.seq_num); + 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; } + + 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 (req->op.seq_num.flags) { + 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, diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index d15e85ad41a..c353914e2cd 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -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 }; diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 75c8109042a..c013565da0b 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -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; } + 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; - 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); + ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res); + if (ret != LDB_SUCCESS) { + goto done; + } + talloc_steal(tmp_ctx, res); - if (ret == LDB_SUCCESS) { - *seq_num = req->op.seq_num.seq_num; + 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; - talloc_free(req); +done: + talloc_free(tmp_ctx); return ret; } - - /* return extended error information */ diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 5cc8de29b48..2b453bb0c37 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -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); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index b1ce3ef70b2..9bc5c183d84 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -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; diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i index 024ba1959a0..60134622251 100644 --- a/source4/lib/ldb/ldb.i +++ b/source4/lib/ldb/ldb.i @@ -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" diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index a220b4a6288..1c76411db29 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -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 diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 0087f6c44d4..2282f61d479 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -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 }; /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 223181ca0bd..61e90bccc69 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -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); diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c index cc8099f27f5..bc9266a306e 100644 --- a/source4/lib/ldb/ldb_wrap.c +++ b/source4/lib/ldb/ldb_wrap.c @@ -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))); diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 2c007395fb4..c27157d7137 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -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