diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/torture/nbt/winsreplication.c | 122 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_apply_records.c | 20 |
2 files changed, 141 insertions, 1 deletions
diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index 5b8aa0119a..cf6f3d4ed7 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -4623,6 +4623,128 @@ static BOOL test_conflict_different_owner(struct test_wrepl_conflict_conn *ctx) .apply_expected = True, } }, + + /* + * sgroup,active vs. sgroup,tombstone different no addresses, special + * => should be replaced + */ + { + .line = __location__, + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .comment= "A:B_3_4_X_3_4 vs. B:NULL => B:NULL", + .extra = True, + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4_X_3_4), + .ips = addresses_B_3_4_X_3_4, + .apply_expected = True, + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = 0, + .ips = NULL, + .apply_expected = True, + } + }, + /* + * sgroup,active vs. sgroup,tombstone different addresses + * => should be replaced + */ + { + .line = __location__, + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .comment= "A:B_3_4_X_3_4 vs. B:A_3_4 => B:A_3_4", + .extra = True, + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4_X_3_4), + .ips = addresses_B_3_4_X_3_4, + .apply_expected = True, + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_A_3_4), + .ips = addresses_A_3_4, + .apply_expected = True, + } + }, + /* + * sgroup,active vs. sgroup,tombstone subset addresses + * => should be replaced + */ + { + .line = __location__, + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .comment= "A:B_3_4_X_3_4 vs. B:B_3_4 => B:B_3_4", + .extra = True, + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4_X_3_4), + .ips = addresses_B_3_4_X_3_4, + .apply_expected = True, + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4), + .ips = addresses_B_3_4, + .apply_expected = True, + } + }, + /* + * sgroup,active vs. sgroup,active same addresses + * => should be replaced + */ + { + .line = __location__, + .name = _NBT_NAME("_DIFF_OWNER", 0x00, NULL), + .comment= "A:B_3_4_X_3_4 vs. B:B_3_4_X_3_4 => B:B_3_4_X_3_4", + .extra = True, + .r1 = { + .owner = &ctx->a, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_ACTIVE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4_X_3_4), + .ips = addresses_B_3_4_X_3_4, + .apply_expected = True, + }, + .r2 = { + .owner = &ctx->b, + .type = WREPL_TYPE_SGROUP, + .state = WREPL_STATE_TOMBSTONE, + .node = WREPL_NODE_B, + .is_static = False, + .num_ips = ARRAY_SIZE(addresses_B_3_4_X_3_4), + .ips = addresses_B_3_4_X_3_4, + .apply_expected = True, + } + }, + /* * This should be the last record in this array, * we need to make sure the we leave a tombstoned unique entry diff --git a/source4/wrepl_server/wrepl_apply_records.c b/source4/wrepl_server/wrepl_apply_records.c index 5d7958926c..1da9c03f36 100644 --- a/source4/wrepl_server/wrepl_apply_records.c +++ b/source4/wrepl_server/wrepl_apply_records.c @@ -265,6 +265,14 @@ SGROUP,ACTIVE vs. SGROUP,ACTIVE A:X_3_4 vs. B:A_3_4 => C:A_3_4_X_3_4 => SGROUP_M SGROUP,ACTIVE vs. SGROUP,ACTIVE A:A_3_4_X_3_4 vs. B:A_3_4_OWNER_B => B:A_3_4_OWNER_B_X_3_4 => SGROUP_MERGE SGROUP,ACTIVE vs. SGROUP,ACTIVE A:B_3_4_X_3_4 vs. B:B_3_4_X_1_2 => C:B_3_4_X_1_2_3_4 => SGROUP_MERGE SGROUP,ACTIVE vs. SGROUP,ACTIVE A:B_3_4_X_3_4 vs. B:NULL => B:X_3_4 => SGROUP_MERGE + + +this is a bit strange, incoming tombstone replicas always replace old replicas: + +SGROUP,ACTIVE vs. SGROUP,TOMBSTONE A:B_3_4_X_3_4 vs. B:NULL => B:NULL => REPLACE +SGROUP,ACTIVE vs. SGROUP,TOMBSTONE A:B_3_4_X_3_4 vs. B:A_3_4 => B:A_3_4 => REPLACE +SGROUP,ACTIVE vs. SGROUP,TOMBSTONE A:B_3_4_X_3_4 vs. B:B_3_4 => B:B_3_4 => REPLACE +SGROUP,ACTIVE vs. SGROUP,TOMBSTONE A:B_3_4_X_3_4 vs. B:B_3_4_X_3_4 => B:B_3_4_X_3_4 => REPLACE */ static enum _R_ACTION replace_sgroup_replica_vs_X_replica(struct winsdb_record *r1, struct wrepl_name *r2) { @@ -273,11 +281,21 @@ static enum _R_ACTION replace_sgroup_replica_vs_X_replica(struct winsdb_record * return R_DO_REPLACE; } - if (!R_IS_SGROUP(r2) || !R_IS_ACTIVE(r2)) { + if (!R_IS_SGROUP(r2)) { /* NOT REPLACE */ return R_NOT_REPLACE; } + /* + * this is strange, but correct + * the incoming tombstone replace the current active + * record + */ + if (!R_IS_ACTIVE(r2)) { + /* REPLACE */ + return R_DO_REPLACE; + } + if (r2->num_addresses == 0) { if (r_contains_addrs_from_owner(r1, r2->owner)) { /* not handled here: MERGE */ |