diff options
-rw-r--r-- | source4/rpc_server/drsuapi/getncchanges.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index 819a4a3a85..efd2e638f2 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -119,7 +119,8 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem uint32_t replica_flags, struct drsuapi_DsPartialAttributeSet *partial_attribute_set, struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector, - enum drsuapi_DsExtendedOperation extended_op) + enum drsuapi_DsExtendedOperation extended_op, + bool force_object_return) { const struct ldb_val *md_value; uint32_t i, n; @@ -260,9 +261,17 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem /* ignore it if its an empty change. Note that renames always * change the 'name' attribute, so they won't be ignored by - * this */ + * this + + * the force_object_return check is used to force an empty + * object return when we timeout in the getncchanges loop. + * This allows us to return an empty object, which keeps the + * client happy while preventing timeouts + */ if (n == 0 || - (n == 1 && attids[0] == DRSUAPI_ATTID_instanceType)) { + (n == 1 && + attids[0] == DRSUAPI_ATTID_instanceType && + !force_object_return)) { talloc_free(obj->meta_data_ctr); obj->meta_data_ctr = NULL; return WERR_OK; @@ -328,7 +337,6 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem return WERR_OK; } - /* add one linked attribute from an object to the list of linked attributes in a getncchanges request @@ -1426,6 +1434,9 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ bool is_secret_request; bool is_gc_pas_request; struct drsuapi_changed_objects *changes; + time_t max_wait; + time_t start = time(NULL); + bool max_wait_reached = false; DCESRV_PULL_HANDLE_WERR(h, r->in.bind_handle, DRSUAPI_BIND_HANDLE); b_state = h->data; @@ -1753,10 +1764,17 @@ allowed: */ max_links = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max link sync", 1500); + /* + * Maximum time that we can spend in a getncchanges + * in order to avoid timeout of the other part. + * 10 seconds by default. + */ + max_wait = lpcfg_parm_int(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "max work time", 10); for (i=getnc_state->num_processed; i<getnc_state->num_records && !null_scope && - (r->out.ctr->ctr6.object_count < max_objects); + (r->out.ctr->ctr6.object_count < max_objects) + && !max_wait_reached; i++) { int uSN; struct drsuapi_DsReplicaObjectListItemEx *obj; @@ -1795,6 +1813,8 @@ allowed: msg = msg_res->msgs[0]; + max_wait_reached = (time(NULL) - start > max_wait); + werr = get_nc_changes_build_object(obj, msg, sam_ctx, getnc_state->ncRoot_dn, getnc_state->is_schema_nc, @@ -1802,7 +1822,8 @@ allowed: req10->replica_flags, req10->partial_attribute_set, getnc_state->uptodateness_vector, - req10->extended_op); + req10->extended_op, + max_wait_reached); if (!W_ERROR_IS_OK(werr)) { return werr; } |