diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/repl/drepl_out_helpers.c | 3 | ||||
-rw-r--r-- | source4/dsdb/repl/replicated_objects.c | 35 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb.c | 78 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_parse.c | 3 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 5 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_private.h | 2 |
6 files changed, 102 insertions, 24 deletions
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c index 168aacdde9..5c63c111f3 100644 --- a/source4/dsdb/repl/drepl_out_helpers.c +++ b/source4/dsdb/repl/drepl_out_helpers.c @@ -414,7 +414,8 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s &rf1, uptodateness_vector, &drsuapi->gensec_skey, - st, NULL); + st, NULL, + &st->op->source_dsa->notify_uSN); if (!W_ERROR_IS_OK(status)) { DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status))); composite_error(c, werror_to_ntstatus(status)); diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c index 2f4efc0fee..5ae622eeaa 100644 --- a/source4/dsdb/repl/replicated_objects.c +++ b/source4/dsdb/repl/replicated_objects.c @@ -212,7 +212,8 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, const struct drsuapi_DsReplicaCursor2CtrEx *uptodateness_vector, const DATA_BLOB *gensec_skey, TALLOC_CTX *mem_ctx, - struct dsdb_extended_replicated_objects **_out) + struct dsdb_extended_replicated_objects **_out, + uint64_t *notify_uSN) { WERROR status; const struct dsdb_schema *schema; @@ -221,6 +222,7 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, const struct drsuapi_DsReplicaObjectListItemEx *cur; uint32_t i; int ret; + uint64_t seq_num1, seq_num2; schema = dsdb_get_schema(ldb); if (!schema) { @@ -280,6 +282,14 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, return WERR_FOOBAR; } + ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num1); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ " Failed to load partition uSN\n")); + talloc_free(out); + ldb_transaction_cancel(ldb); + return WERR_FOOBAR; + } + ret = ldb_extended(ldb, DSDB_EXTENDED_REPLICATED_OBJECTS_OID, out, &ext_res); if (ret != LDB_SUCCESS) { DEBUG(0,("Failed to apply records: %s: %s\n", @@ -290,6 +300,28 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, } talloc_free(ext_res); + ret = ldb_transaction_prepare_commit(ldb); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ " Failed to prepare commit of transaction\n")); + talloc_free(out); + return WERR_FOOBAR; + } + + ret = dsdb_load_partition_usn(ldb, out->partition_dn, &seq_num2); + if (ret != LDB_SUCCESS) { + DEBUG(0,(__location__ " Failed to load partition uSN\n")); + talloc_free(out); + ldb_transaction_cancel(ldb); + return WERR_FOOBAR; + } + + /* if this replication partner didn't need to be notified + before this transaction then it still doesn't need to be + notified, as the changes came from this server */ + if (seq_num2 > seq_num1 && seq_num1 <= *notify_uSN) { + *notify_uSN = seq_num2; + } + ret = ldb_transaction_commit(ldb); if (ret != LDB_SUCCESS) { DEBUG(0,(__location__ " Failed to commit transaction\n")); @@ -297,6 +329,7 @@ WERROR dsdb_extended_replicated_objects_commit(struct ldb_context *ldb, return WERR_FOOBAR; } + DEBUG(2,("Replicated %u objects (%u linked attributes) for %s\n", out->num_objects, out->linked_attributes_count, ldb_dn_get_linearized(out->partition_dn))); diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 6939cefb59..613451a7c2 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -316,6 +316,7 @@ int ldb_transaction_start(struct ldb_context *ldb) /* start a new transaction */ ldb->transaction_active++; + ldb->prepare_commit_done = false; FIRST_OP(ldb, start_transaction); @@ -335,6 +336,57 @@ int ldb_transaction_start(struct ldb_context *ldb) } /* + prepare for transaction commit (first phase of two phase commit) +*/ +int ldb_transaction_prepare_commit(struct ldb_context *ldb) +{ + struct ldb_module *module; + int status; + + if (ldb->prepare_commit_done) { + return LDB_SUCCESS; + } + + /* commit only when all nested transactions are complete */ + if (ldb->transaction_active > 1) { + return LDB_SUCCESS; + } + + ldb->prepare_commit_done = true; + + if (ldb->transaction_active < 0) { + ldb_debug(ldb, LDB_DEBUG_FATAL, + "prepare commit called but no ldb transactions are active!"); + ldb->transaction_active = 0; + return LDB_ERR_OPERATIONS_ERROR; + } + + /* call prepare transaction if available */ + FIRST_OP_NOERR(ldb, prepare_commit); + if (module == NULL) { + return LDB_SUCCESS; + } + + status = module->ops->prepare_commit(module); + if (status != LDB_SUCCESS) { + /* if a module fails the prepare then we need + to call the end transaction for everyone */ + FIRST_OP(ldb, end_transaction); + module->ops->end_transaction(module); + if (ldb->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb, + "ldb transaction prepare commit: %s (%d)", + ldb_strerror(status), + status); + } + } + + return status; +} + + +/* commit a transaction */ int ldb_transaction_commit(struct ldb_context *ldb) @@ -342,6 +394,10 @@ int ldb_transaction_commit(struct ldb_context *ldb) struct ldb_module *module; int status; + status = ldb_transaction_prepare_commit(ldb); + if (status != LDB_SUCCESS) { + return status; + } ldb->transaction_active--; @@ -361,27 +417,6 @@ int ldb_transaction_commit(struct ldb_context *ldb) return LDB_ERR_OPERATIONS_ERROR; } - /* call prepare transaction if available */ - FIRST_OP_NOERR(ldb, prepare_commit); - if (module != NULL) { - status = module->ops->prepare_commit(module); - if (status != LDB_SUCCESS) { - /* if a module fails the prepare then we need - to call the end transaction for everyone */ - /* preserve err string */ - FIRST_OP(ldb, end_transaction); - module->ops->end_transaction(module); - if (ldb->err_string == NULL) { - /* no error string was setup by the backend */ - ldb_asprintf_errstring(ldb, - "ldb transaction prepare commit: %s (%d)", - ldb_strerror(status), - status); - } - return status; - } - } - ldb_reset_err_string(ldb); FIRST_OP(ldb, end_transaction); @@ -401,6 +436,7 @@ int ldb_transaction_commit(struct ldb_context *ldb) return status; } + /* cancel a transaction */ diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c index 654a635abf..0fab0026f3 100644 --- a/source4/lib/ldb/common/ldb_parse.c +++ b/source4/lib/ldb/common/ldb_parse.c @@ -267,7 +267,8 @@ static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char * p++; } - while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */ + while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) { + /* attribute names can only be alphanums */ p++; } diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 04b0a22fc1..2c89031919 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -1284,6 +1284,11 @@ int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, ui int ldb_transaction_start(struct ldb_context *ldb); /** + first phase of two phase commit + */ +int ldb_transaction_prepare_commit(struct ldb_context *ldb); + +/** commit a transaction */ int ldb_transaction_commit(struct ldb_context *ldb); diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index c12f33495b..1fb3109b1b 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -114,6 +114,8 @@ struct ldb_context { char *modules_dir; struct tevent_context *ev_ctx; + + bool prepare_commit_done; }; /* The following definitions come from lib/ldb/common/ldb.c */ |