The branch, master has been updated via 349f7ba... s4-drs: added filtering by udv in getncchanges via b0090d0... s4-idl: give a enum for attribute cn and a 'NONE' attribute from 9e6eb22... s4-drs: fixed the NC in the getncchanges RID alloc reply
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 349f7ba09c4cda14eea4df69bd6dcb082fc23c8d Author: Andrew Tridgell <tri...@samba.org> Date: Sat Jan 9 13:11:27 2010 +1100 s4-drs: added filtering by udv in getncchanges When a client supplied an uptodateness_vector, we can use it to filter what objects we return. This greatly reduces the amount of replication traffic between DCs. commit b0090d01e061220d9b70a14e5a88b683949fe6a5 Author: Andrew Tridgell <tri...@samba.org> Date: Sat Jan 9 13:10:28 2010 +1100 s4-idl: give a enum for attribute cn and a 'NONE' attribute The 'NONE' attribute has value 0xFFFFFFFF. Adding this ensures the compiler will complain if it is set to use 16 bit enums. We rely on being able to store 32 bits in an attid enum. ----------------------------------------------------------------------- Summary of changes: librpc/gen_ndr/drsuapi.h | 6 ++- librpc/gen_ndr/ndr_drsuapi.c | 2 + librpc/idl/drsuapi.idl | 4 +- source4/dsdb/common/util.c | 6 +++ source4/rpc_server/drsuapi/getncchanges.c | 66 +++++++++++++++++++++++++---- 5 files changed, 73 insertions(+), 11 deletions(-) Changeset truncated at 500 lines: diff --git a/librpc/gen_ndr/drsuapi.h b/librpc/gen_ndr/drsuapi.h index 8596bf3..1f5960d 100644 --- a/librpc/gen_ndr/drsuapi.h +++ b/librpc/gen_ndr/drsuapi.h @@ -326,6 +326,7 @@ enum drsuapi_DsAttributeId #ifndef USE_UINT_ENUMS { DRSUAPI_ATTRIBUTE_objectClass=(int)(0x00000000), + DRSUAPI_ATTRIBUTE_cn=(int)(0x00000003), DRSUAPI_ATTRIBUTE_description=(int)(0x0000000d), DRSUAPI_ATTRIBUTE_member=(int)(0x0000001f), DRSUAPI_ATTRIBUTE_instanceType=(int)(0x00020001), @@ -396,11 +397,13 @@ enum drsuapi_DsAttributeId DRSUAPI_ATTRIBUTE_msDS_Behavior_Version=(int)(0x000905b3), DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber=(int)(0x000906f6), DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs=(int)(0x0009071c), - DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs=(int)(0x0009072c) + DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs=(int)(0x0009072c), + DRSUAPI_ATTRIBUTE_NONE=(int)(0xFFFFFFFF) } #else { __donnot_use_enum_drsuapi_DsAttributeId=0x7FFFFFFF} #define DRSUAPI_ATTRIBUTE_objectClass ( 0x00000000 ) +#define DRSUAPI_ATTRIBUTE_cn ( 0x00000003 ) #define DRSUAPI_ATTRIBUTE_description ( 0x0000000d ) #define DRSUAPI_ATTRIBUTE_member ( 0x0000001f ) #define DRSUAPI_ATTRIBUTE_instanceType ( 0x00020001 ) @@ -472,6 +475,7 @@ enum drsuapi_DsAttributeId #define DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber ( 0x000906f6 ) #define DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs ( 0x0009071c ) #define DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs ( 0x0009072c ) +#define DRSUAPI_ATTRIBUTE_NONE ( 0xFFFFFFFF ) #endif ; diff --git a/librpc/gen_ndr/ndr_drsuapi.c b/librpc/gen_ndr/ndr_drsuapi.c index 16388e7..5b31d1e 100644 --- a/librpc/gen_ndr/ndr_drsuapi.c +++ b/librpc/gen_ndr/ndr_drsuapi.c @@ -1379,6 +1379,7 @@ _PUBLIC_ void ndr_print_drsuapi_DsAttributeId(struct ndr_print *ndr, const char ndr_set_flags(&ndr->flags, LIBNDR_PRINT_ARRAY_HEX); switch (r) { case DRSUAPI_ATTRIBUTE_objectClass: val = "DRSUAPI_ATTRIBUTE_objectClass"; break; + case DRSUAPI_ATTRIBUTE_cn: val = "DRSUAPI_ATTRIBUTE_cn"; break; case DRSUAPI_ATTRIBUTE_description: val = "DRSUAPI_ATTRIBUTE_description"; break; case DRSUAPI_ATTRIBUTE_member: val = "DRSUAPI_ATTRIBUTE_member"; break; case DRSUAPI_ATTRIBUTE_instanceType: val = "DRSUAPI_ATTRIBUTE_instanceType"; break; @@ -1450,6 +1451,7 @@ _PUBLIC_ void ndr_print_drsuapi_DsAttributeId(struct ndr_print *ndr, const char case DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber: val = "DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber"; break; case DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs: val = "DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs"; break; case DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs: val = "DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs"; break; + case DRSUAPI_ATTRIBUTE_NONE: val = "DRSUAPI_ATTRIBUTE_NONE"; break; } ndr_print_enum(ndr, name, "ENUM", val, r); ndr->flags = _flags_save_ENUM; diff --git a/librpc/idl/drsuapi.idl b/librpc/idl/drsuapi.idl index 2994958..dadaeee 100644 --- a/librpc/idl/drsuapi.idl +++ b/librpc/idl/drsuapi.idl @@ -437,6 +437,7 @@ interface drsuapi typedef [flag(NDR_PAHEX),v1_enum,public] enum { DRSUAPI_ATTRIBUTE_objectClass = 0x00000000, + DRSUAPI_ATTRIBUTE_cn = 0x00000003, DRSUAPI_ATTRIBUTE_description = 0x0000000d, DRSUAPI_ATTRIBUTE_member = 0x0000001f, DRSUAPI_ATTRIBUTE_instanceType = 0x00020001, @@ -507,7 +508,8 @@ interface drsuapi DRSUAPI_ATTRIBUTE_msDS_Behavior_Version = 0x000905b3, DRSUAPI_ATTRIBUTE_msDS_KeyVersionNumber = 0x000906f6, DRSUAPI_ATTRIBUTE_msDS_HasDomainNCs = 0x0009071c, - DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs = 0x0009072c + DRSUAPI_ATTRIBUTE_msDS_hasMasterNCs = 0x0009072c, + DRSUAPI_ATTRIBUTE_NONE = 0xFFFFFFFF } drsuapi_DsAttributeId; typedef struct { diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 70750ca..632025d 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -2810,6 +2810,12 @@ int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1, return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id); } +int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1, + const struct drsuapi_DsReplicaCursor *c2) +{ + return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id); +} + /* see if we are a RODC diff --git a/source4/rpc_server/drsuapi/getncchanges.c b/source4/rpc_server/drsuapi/getncchanges.c index d0ce819..46996c7 100644 --- a/source4/rpc_server/drsuapi/getncchanges.c +++ b/source4/rpc_server/drsuapi/getncchanges.c @@ -30,6 +30,7 @@ #include "rpc_server/dcerpc_server_proto.h" #include "../libcli/drsuapi/drsuapi.h" #include "libcli/security/security.h" +#include "lib/util/binsearch.h" /* build a DsReplicaObjectIdentifier from a ldb msg @@ -57,6 +58,29 @@ static struct drsuapi_DsReplicaObjectIdentifier *get_object_identifier(TALLOC_CT return identifier; } +static int udv_compare(const struct GUID *guid1, struct GUID guid2) +{ + return GUID_compare(guid1, &guid2); +} + +/* + see if we can filter an attribute using the uptodateness_vector + */ +static bool udv_filter(const struct drsuapi_DsReplicaCursorCtrEx *udv, + const struct GUID *originating_invocation_id, + uint64_t originating_usn) +{ + const struct drsuapi_DsReplicaCursor *c; + if (udv == NULL) return false; + BINARY_ARRAY_SEARCH(udv->cursors, udv->count, source_dsa_invocation_id, + originating_invocation_id, udv_compare, c); + if (c && originating_usn <= c->highest_usn) { + return true; + } + return false; + +} + /* drsuapi_DsGetNCChanges for one object */ @@ -67,7 +91,8 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem struct dsdb_schema *schema, DATA_BLOB *session_key, uint64_t highest_usn, - uint32_t replica_flags) + uint32_t replica_flags, + struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector) { const struct ldb_val *md_value; int i, n; @@ -156,6 +181,14 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem } } + /* filter by uptodateness_vector */ + if (md.ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType && + udv_filter(uptodateness_vector, + &md.ctr.ctr1.array[i].originating_invocation_id, + md.ctr.ctr1.array[i].originating_usn)) { + continue; + } + obj->meta_data_ctr->meta_data[n].originating_change_time = md.ctr.ctr1.array[i].originating_change_time; obj->meta_data_ctr->meta_data[n].version = md.ctr.ctr1.array[i].version; obj->meta_data_ctr->meta_data[n].originating_invocation_id = md.ctr.ctr1.array[i].originating_invocation_id; @@ -164,11 +197,15 @@ static WERROR get_nc_changes_build_object(struct drsuapi_DsReplicaObjectListItem n++; } - /* - note that if n==0 we still need to send the change, as it - could be a rename, which changes the uSNChanged, but not any - of the replicated attributes - */ + /* ignore it if its an empty change. Note that renames always + * change the 'name' attribute, so they won't be ignored by + * this */ + if (n == 0 || + (n == 1 && attids[0] == DRSUAPI_ATTRIBUTE_instanceType)) { + talloc_free(obj->meta_data_ctr); + obj->meta_data_ctr = NULL; + return WERR_OK; + } obj->meta_data_ctr->count = n; @@ -302,7 +339,8 @@ static WERROR get_nc_changes_add_links(struct ldb_context *sam_ctx, uint32_t replica_flags, struct ldb_message *msg, struct drsuapi_DsReplicaLinkedAttribute **la_list, - uint32_t *la_count) + uint32_t *la_count, + struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector) { int i; TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); @@ -668,6 +706,7 @@ struct drsuapi_getncchanges_state { struct ldb_dn *last_dn; struct drsuapi_DsReplicaLinkedAttribute *la_list; uint32_t la_count; + struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector; }; /* @@ -880,6 +919,14 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ (comparison_fn_t)site_res_cmp_usn_order); } + getnc_state->uptodateness_vector = talloc_steal(getnc_state, req8->uptodateness_vector); + if (getnc_state->uptodateness_vector) { + /* make sure its sorted */ + qsort(getnc_state->uptodateness_vector->cursors, + getnc_state->uptodateness_vector->count, + sizeof(getnc_state->uptodateness_vector->cursors[0]), + (comparison_fn_t)drsuapi_DsReplicaCursor_compare); + } } /* Prefix mapping */ @@ -935,7 +982,7 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ werr = get_nc_changes_build_object(obj, msg, b_state->sam_ctx, getnc_state->ncRoot_dn, schema, &session_key, getnc_state->min_usn, - req8->replica_flags); + req8->replica_flags, getnc_state->uptodateness_vector); if (!W_ERROR_IS_OK(werr)) { return werr; } @@ -946,7 +993,8 @@ WERROR dcesrv_drsuapi_DsGetNCChanges(struct dcesrv_call_state *dce_call, TALLOC_ req8->replica_flags, msg, &getnc_state->la_list, - &getnc_state->la_count); + &getnc_state->la_count, + getnc_state->uptodateness_vector); if (!W_ERROR_IS_OK(werr)) { return werr; } -- Samba Shared Repository