The branch, master has been updated via b55a5ad... s4-ldb: ensure DNs pass validity tests in indexing via 2eca02a... s4-ldb: fixed string length handling on index records via c34e45a... s4-dsdb: ensure that new partitions inherit any transaction via d4c0e8f... tdb: detect tdb store of identical records and skip via dffb572... s4-ldb: don't allow modifies outside a transaction. via 5002cdd... s4-ldb: fixed re-index during a complex transaction via e7d9f5e... s4-python: fixed annoyance where control-C doesn't kill our python scripts from a07eb08... s4:dcesrv_samr: always use mem_ctx as initial parent for samr_*_state
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit b55a5adab99f535bb392662d54afbabed116a3b6 Author: Andrew Tridgell <tri...@samba.org> Date: Sun Oct 25 13:13:41 2009 +1100 s4-ldb: ensure DNs pass validity tests in indexing commit 2eca02a4080b68fbb2dacb659b1733224cfa462e Author: Andrew Tridgell <tri...@samba.org> Date: Sun Oct 25 13:12:32 2009 +1100 s4-ldb: fixed string length handling on index records commit c34e45a8e2880eb06be6425fa6be15246db03197 Author: Andrew Tridgell <tri...@samba.org> Date: Fri Oct 23 22:46:09 2009 +1100 s4-dsdb: ensure that new partitions inherit any transaction commit d4c0e8fdf063f88032c32de7ece60d502b322089 Author: Andrew Tridgell <tri...@samba.org> Date: Fri Oct 23 22:45:03 2009 +1100 tdb: detect tdb store of identical records and skip This can help with ldb where we rewrite the index records commit dffb572ce0b350bf42549c882275b627d9b36e59 Author: Andrew Tridgell <tri...@samba.org> Date: Fri Oct 23 22:43:24 2009 +1100 s4-ldb: don't allow modifies outside a transaction. commit 5002cddcb0d9e539ded949bcc805c035e038362d Author: Andrew Tridgell <tri...@samba.org> Date: Fri Oct 23 22:42:26 2009 +1100 s4-ldb: fixed re-index during a complex transaction We may have modified index objects in the in-memory index tdb commit e7d9f5eea52403f576b636a35fb9889ed82cbf0b Author: Andrew Tridgell <tri...@samba.org> Date: Fri Oct 23 17:12:48 2009 +1100 s4-python: fixed annoyance where control-C doesn't kill our python scripts We want our scripts to die immediately when a user hits control-C. Otherwise we not only annoy the hell out of the user, we also risk db corruption as the control-C could get delivered as an exception which gets mis-interpreted (eg. as a missing db object). We use transactions for all our databases, so the right thing to do in all our command line tools is to die immediately. ----------------------------------------------------------------------- Summary of changes: lib/tdb/common/tdb.c | 20 ++++++++++ source4/dsdb/samdb/ldb_modules/partition.c | 15 +++++++ source4/dsdb/samdb/ldb_modules/partition.h | 1 + source4/dsdb/samdb/ldb_modules/partition_init.c | 21 +++++----- source4/lib/ldb/ldb_tdb/ldb_index.c | 47 +++++++++++++++++----- source4/lib/ldb/ldb_tdb/ldb_tdb.c | 8 ++++ source4/scripting/python/pyglue.c | 10 +++++ 7 files changed, 100 insertions(+), 22 deletions(-) Changeset truncated at 500 lines: diff --git a/lib/tdb/common/tdb.c b/lib/tdb/common/tdb.c index 0389d3c..564c5fe 100644 --- a/lib/tdb/common/tdb.c +++ b/lib/tdb/common/tdb.c @@ -121,6 +121,7 @@ tdb_off_t tdb_find_lock_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t has return rec_ptr; } +static TDB_DATA _tdb_fetch(struct tdb_context *tdb, TDB_DATA key); /* update an entry in place - this only works if the new data size is <= the old data size and the key exists. @@ -135,6 +136,25 @@ static int tdb_update_hash(struct tdb_context *tdb, TDB_DATA key, uint32_t hash, if (!(rec_ptr = tdb_find(tdb, key, hash, &rec))) return -1; + /* it could be an exact duplicate of what is there - this is + * surprisingly common (eg. with a ldb re-index). */ + if (rec.key_len == key.dsize && + rec.data_len == dbuf.dsize && + rec.full_hash == hash) { + TDB_DATA data = _tdb_fetch(tdb, key); + if (data.dsize == dbuf.dsize && + memcmp(data.dptr, dbuf.dptr, data.dsize) == 0) { + if (data.dptr) { + free(data.dptr); + } + return 0; + } + if (data.dptr) { + free(data.dptr); + } + } + + /* must be long enough key, data and tailer */ if (rec.rec_len < key.dsize + dbuf.dsize + sizeof(tdb_off_t)) { tdb->ecode = TDB_SUCCESS; /* Not really an error */ diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 779b8b5..64015ed 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -690,6 +690,9 @@ static int partition_start_trans(struct ldb_module *module) return ret; } } + + data->in_transaction++; + return LDB_SUCCESS; } @@ -737,6 +740,12 @@ static int partition_end_trans(struct ldb_module *module) } } + if (data->in_transaction == 0) { + DEBUG(0,("partition end transaction mismatch\n")); + return LDB_ERR_OPERATIONS_ERROR; + } + data->in_transaction--; + return ldb_next_end_trans(module); } @@ -756,6 +765,12 @@ static int partition_del_trans(struct ldb_module *module) } } + if (data->in_transaction == 0) { + DEBUG(0,("partition del transaction mismatch\n")); + return LDB_ERR_OPERATIONS_ERROR; + } + data->in_transaction--; + ret = ldb_next_del_trans(module); if (ret != LDB_SUCCESS) { final_ret = ret; diff --git a/source4/dsdb/samdb/ldb_modules/partition.h b/source4/dsdb/samdb/ldb_modules/partition.h index 3572f17..dda0b86 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.h +++ b/source4/dsdb/samdb/ldb_modules/partition.h @@ -45,6 +45,7 @@ struct partition_private_data { const char *ldapBackend; uint64_t metadata_seq; + uint32_t in_transaction; }; #define PARTITION_FIND_OP_NOERROR(module, op) do { \ diff --git a/source4/dsdb/samdb/ldb_modules/partition_init.c b/source4/dsdb/samdb/ldb_modules/partition_init.c index 28eab9b..5967bc8 100644 --- a/source4/dsdb/samdb/ldb_modules/partition_init.c +++ b/source4/dsdb/samdb/ldb_modules/partition_init.c @@ -282,6 +282,16 @@ static int new_partition_from_dn(struct ldb_context *ldb, struct partition_priva talloc_steal((*partition), (*partition)->module); + /* if we were in a transaction then we need to start a + transaction on this new partition, otherwise we'll get a + transaction mismatch when we end the transaction */ + if (data->in_transaction) { + struct ldb_module *next = (*partition)->module; + PARTITION_FIND_OP(next, start_transaction); + + ret = next->ops->start_transaction(next); + } + return ret; } @@ -698,17 +708,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req) if (ret != LDB_SUCCESS) { return ret; } - - /* Start a transaction on the DB (as it won't be in one being brand new) */ - { - struct ldb_module *next = partition->module; - PARTITION_FIND_OP(next, start_transaction); - - ret = next->ops->start_transaction(next); - if (ret != LDB_SUCCESS) { - return ret; - } - } } ret = new_partition_set_replicated_metadata(ldb, module, last_req, data, partition); diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c index 0d560fe..252154f 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_index.c +++ b/source4/lib/ldb/ldb_tdb/ldb_index.c @@ -40,7 +40,6 @@ struct dn_list { struct ltdb_idxptr { struct tdb_context *itdb; - bool repack; int error; }; @@ -313,7 +312,7 @@ static int ltdb_index_traverse_store(struct tdb_context *tdb, TDB_DATA key, TDB_ } v.data = key.dptr; - v.length = key.dsize; + v.length = strnlen((char *)key.dptr, key.dsize); dn = ldb_dn_from_ldb_val(module, ldb, &v); if (dn == NULL) { @@ -402,6 +401,10 @@ static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb, if (ldb_should_b64_encode(ldb, &v)) { char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length); if (!vstr) return NULL; + /* remove trailing '=' to make it a valid DN */ + if (vstr[strlen(vstr)-1] == '=') { + vstr[strlen(vstr)-1] = 0; + } ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr); talloc_free(vstr); } else { @@ -1402,10 +1405,34 @@ int ltdb_index_delete(struct ldb_module *module, const struct ldb_message *msg) */ static int delete_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *state) { - const char *dn = "DN=" LTDB_INDEX ":"; - if (strncmp((char *)key.dptr, dn, strlen(dn)) == 0) { - return tdb_delete(tdb, key); + struct ldb_module *module = state; + struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); + const char *dnstr = "DN=" LTDB_INDEX ":"; + struct dn_list list; + struct ldb_dn *dn; + struct ldb_val v; + int ret; + + if (strncmp((char *)key.dptr, dnstr, strlen(dnstr)) != 0) { + return 0; + } + /* we need to put a empty list in the internal tdb for this + * index entry */ + list.dn = NULL; + list.count = 0; + v.data = key.dptr; + v.length = strnlen((char *)key.dptr, key.dsize); + + dn = ldb_dn_from_ldb_val(ltdb, ldb_module_get_ctx(module), &v); + ret = ltdb_dn_list_store(module, dn, &list); + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(ldb_module_get_ctx(module), + "Unable to store null index for %s\n", + ldb_dn_get_linearized(dn)); + talloc_free(dn); + return -1; } + talloc_free(dn); return 0; } @@ -1493,8 +1520,10 @@ int ltdb_reindex(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } - /* first traverse the database deleting any @INDEX records */ - ret = tdb_traverse(ltdb->tdb, delete_index, NULL); + /* first traverse the database deleting any @INDEX records by + * putting NULL entries in the in-memory tdb + */ + ret = tdb_traverse(ltdb->tdb, delete_index, module); if (ret == -1) { return LDB_ERR_OPERATIONS_ERROR; } @@ -1510,9 +1539,5 @@ int ltdb_reindex(struct ldb_module *module) return LDB_ERR_OPERATIONS_ERROR; } - if (ltdb->idxptr) { - ltdb->idxptr->repack = true; - } - return LDB_SUCCESS; } diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 01153fe..d617586 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -200,6 +200,14 @@ static int ltdb_check_special_dn(struct ldb_module *module, static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn) { int ret = LDB_SUCCESS; + struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private); + + /* only allow modifies inside a transaction, otherwise the + * ldb is unsafe */ + if (ltdb->in_transaction == 0) { + ldb_set_errstring(ldb_module_get_ctx(module), "ltdb modify without transaction"); + return LDB_ERR_OPERATIONS_ERROR; + } if (ldb_dn_is_special(dn) && (ldb_dn_check_special(dn, LTDB_INDEXLIST) || diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index 71203d3..2f7023e 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -549,5 +549,15 @@ void initglue(void) PyModule_AddObject(m, "DS_DC_FUNCTION_2003", PyInt_FromLong(DS_DC_FUNCTION_2003)); PyModule_AddObject(m, "DS_DC_FUNCTION_2008", PyInt_FromLong(DS_DC_FUNCTION_2008)); PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2", PyInt_FromLong(DS_DC_FUNCTION_2008_R2)); + + /* one of the most annoying things about python scripts is + that they don't die when you hit control-C. This fixes that + sillyness. As we do all database operations using + transactions, this is also safe. In fact, not dying + immediately is unsafe as we could end up treating the + control-C exception as a different error and try to modify + as database incorrectly + */ + signal(SIGINT, SIG_DFL); } -- Samba Shared Repository