[SCM] Samba Shared Repository - branch master updated
Andrew Tridgell
tridge at samba.org
Mon Feb 15 05:23:39 MST 2010
The branch, master has been updated
via aba7376... s4-kcc: remove C++ comment
via 0cf4e8a... s4-kcc: initial code for the topology algorithm
via 4edbb25... s4-dsdb: don't change replPropertyMetaData if the value hasn't changed
from 694ab7c... s4-heimdal: Fix typos in comment.
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit aba73767c05c16121ffc5cb3c9a997457222ece4
Author: Andrew Tridgell <tridge at samba.org>
Date: Mon Feb 15 23:05:33 2010 +1100
s4-kcc: remove C++ comment
commit 0cf4e8aae6a2d4155c067137e5e4a391031df930
Author: CrÃstian Deives <cristiandeives at gmail.com>
Date: Wed Feb 10 03:42:28 2010 -0200
s4-kcc: initial code for the topology algorithm
this patch contains the data structures declarations and the functions to
setup the graph.
Signed-off-by: Andrew Tridgell <tridge at samba.org>
commit 4edbb255998269f848636669c6d358f194c5eedd
Author: Andrew Tridgell <tridge at samba.org>
Date: Mon Feb 15 22:49:35 2010 +1100
s4-dsdb: don't change replPropertyMetaData if the value hasn't changed
When updating replPropertyMetaData, check if the value being stored is
the same as the current value, and skip the update if it is.
This is based on a patch by Fernando J V da Silva <fernandojvsilva at yahoo.com.br>
-----------------------------------------------------------------------
Summary of changes:
source4/dsdb/config.mk | 1 +
source4/dsdb/kcc/kcc_topology.c | 614 +++++++++++++++++++++++
source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 24 +-
3 files changed, 635 insertions(+), 4 deletions(-)
create mode 100644 source4/dsdb/kcc/kcc_topology.c
Changeset truncated at 500 lines:
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index b038b5e..94e6e39 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -84,6 +84,7 @@ PRIVATE_DEPENDENCIES = \
KCC_SRV_OBJ_FILES = $(addprefix $(dsdbsrcdir)/kcc/, \
kcc_service.o \
kcc_connection.o \
+ kcc_topology.o \
kcc_deleted.o \
kcc_periodic.o \
kcc_drs_replica_info.o)
diff --git a/source4/dsdb/kcc/kcc_topology.c b/source4/dsdb/kcc/kcc_topology.c
new file mode 100644
index 0000000..53de556
--- /dev/null
+++ b/source4/dsdb/kcc/kcc_topology.c
@@ -0,0 +1,614 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ KCC service
+
+ Copyright (C) CrÃstian Deives 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+
+#define NTDSTRANSPORT_OPT_IGNORE_SCHEDULES 0x00000001
+#define NTDSTRANSPORT_OPT_BRIDGES_REQUIRED 0x00000002
+
+/** replication parameters of a graph edge */
+struct kcctpl_repl_info {
+ int cost;
+ int interval;
+ int options;
+ uint8_t schedule[84];
+};
+
+/** color of a vertex */
+enum kcctpl_color { RED, BLACK, WHITE };
+
+/** a GUID array list */
+struct GUID_list {
+ struct GUID *data;
+ unsigned int count;
+};
+
+/** a vertex in the site graph */
+struct kcctpl_vertex {
+ struct GUID id;
+ struct GUID_list edge_ids;
+ enum kcctpl_color color;
+ struct GUID_list accept_red_red;
+ struct GUID_list accept_black;
+ struct kcctpl_repl_info repl_info;
+ int dist_to_red;
+
+ /* Dijkstra data */
+ struct GUID root_id;
+ bool demoted;
+
+ /* Kruskal data */
+ struct GUID component_id;
+ int component_index;
+};
+
+/** fully connected subgraph of vertices */
+struct kcctpl_multi_edge {
+ struct GUID id;
+ struct GUID_list vertex_ids;
+ struct GUID type;
+ struct kcctpl_repl_info repl_info;
+ bool directed;
+};
+
+/** set of transitively connected kcc_multi_edge's. all edges within the set
+ * have the same type. */
+struct kcctpl_multi_edge_set {
+ struct GUID id;
+ struct GUID_list edge_ids;
+};
+
+/** a vertices array list */
+struct kcctpl_vertex_list {
+ struct kcctpl_vertex *data;
+ unsigned int count;
+};
+
+/** an edges linked list */
+struct kcctpl_multi_edge_list {
+ struct kcctpl_multi_edge *data;
+ unsigned int count;
+};
+
+/** an edge sets linked list */
+struct kcctpl_multi_edge_set_list {
+ struct kcctpl_multi_edge_set *data;
+ unsigned int count;
+};
+
+/** a site graph */
+struct kcctpl_graph {
+ struct kcctpl_vertex_list vertices;
+ struct kcctpl_multi_edge_list edges;
+ struct kcctpl_multi_edge_set_list edge_sets;
+};
+
+/** path found in the graph between two non-white vertices */
+struct kcctpl_internal_edge {
+ struct GUID v1id, v2id;
+ bool red_red;
+ struct kcctpl_repl_info repl_info;
+ struct GUID type;
+};
+
+/**
+ * find a graph edge based on its GUID.
+ */
+static struct kcctpl_multi_edge *kcctpl_find_edge_by_guid(struct kcctpl_graph *graph,
+ struct GUID guid)
+{
+ unsigned int i;
+
+ for (i = 0; i < graph->edges.count; i++) {
+ if (GUID_compare(&graph->edges.data[i].id, &guid) == 0) {
+ return &graph->edges.data[i];
+ }
+ }
+ return NULL;
+}
+/**
+ * create a kcctpl_graph instance.
+ */
+static NTSTATUS kcctpl_create_graph(TALLOC_CTX *mem_ctx,
+ struct GUID_list *guids,
+ struct kcctpl_graph **_graph)
+{
+ struct kcctpl_graph *graph;
+ unsigned int i;
+
+ graph = talloc_zero(mem_ctx, struct kcctpl_graph);
+ NT_STATUS_HAVE_NO_MEMORY(graph);
+
+ graph->vertices.count = guids->count;
+ graph->vertices.data = talloc_zero_array(graph, struct kcctpl_vertex,
+ guids->count);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(graph->vertices.data, graph);
+
+ qsort(guids->data, guids->count, sizeof(struct GUID),
+ QSORT_CAST GUID_compare);
+
+ for (i = 0; i < guids->count; i++) {
+ graph->vertices.data[i].id = guids->data[i];
+ }
+
+ *_graph = graph;
+ return NT_STATUS_OK;
+}
+
+/**
+ * create a kcctpl_multi_edge instance.
+ */
+static NTSTATUS kcctpl_create_edge(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ struct GUID type,
+ struct ldb_message *site_link,
+ struct kcctpl_multi_edge **_edge)
+{
+ struct kcctpl_multi_edge *edge;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_result *res;
+ const char * const attrs[] = { "siteList", NULL };
+ int ret;
+ struct ldb_message_element *el;
+ unsigned int i;
+ struct ldb_val val;
+
+ edge = talloc(mem_ctx, struct kcctpl_multi_edge);
+ NT_STATUS_HAVE_NO_MEMORY(edge);
+
+ edge->id = samdb_result_guid(site_link, "objectGUID");
+
+ tmp_ctx = talloc_new(mem_ctx);
+ ret = ldb_search(ldb, tmp_ctx, &res, NULL, LDB_SCOPE_BASE, attrs,
+ "objectGUID=%s", GUID_string(tmp_ctx, &edge->id));
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("failed to find siteLink object %s: %s\n",
+ GUID_string(tmp_ctx, &edge->id), ldb_strerror(ret)));
+ talloc_free(edge);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ if (res->count == 0) {
+ DEBUG(0, ("failed to find siteLink object %s\n",
+ GUID_string(tmp_ctx, &edge->id)));
+ talloc_free(edge);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ el = ldb_msg_find_element(res->msgs[0], "siteList");
+ edge->vertex_ids.count = el->num_values;
+ edge->vertex_ids.data = talloc_array(edge, struct GUID, el->num_values);
+ if (!edge->vertex_ids.data) {
+ talloc_free(edge);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ for (i = 0; i < el->num_values; i++) {
+ struct ldb_dn *dn;
+ struct GUID guid;
+
+ val = el->values[i];
+ dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &val);
+ ret = dsdb_find_guid_by_dn(ldb, dn, &guid);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("failed to find objectGUID for object %s: "
+ "%s\n", ldb_dn_get_linearized(dn),
+ ldb_strerror(ret)));
+ talloc_free(edge);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ edge->vertex_ids.data = talloc_realloc(edge,
+ edge->vertex_ids.data,
+ struct GUID,
+ edge->vertex_ids.count + 1);
+ if (!edge->vertex_ids.data) {
+ talloc_free(edge);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ edge->vertex_ids.data[edge->vertex_ids.count] = guid;
+ edge->vertex_ids.count++;
+ }
+
+ edge->repl_info.cost = samdb_result_int64(site_link, "cost", 0);
+ edge->repl_info.options = samdb_result_int64(site_link, "options", 0);
+ edge->repl_info.interval = samdb_result_int64(site_link, "replInterval",
+ 0);
+ /* val = ldb_msg_find_ldb_val(site_link, "schedule");
+ edge->repl_info.schedule = val->data; */
+ edge->type = type;
+ edge->directed = false;
+
+ *_edge = edge;
+ talloc_free(tmp_ctx);
+ return NT_STATUS_OK;
+}
+
+/**
+ * create a kcctpl_multi_edge_set instance containing edges for all siteLink
+ * objects.
+ */
+static NTSTATUS kcctpl_create_auto_edge_set(struct kcctpl_graph *graph,
+ struct GUID type,
+ struct ldb_result *res_site_link,
+ struct kcctpl_multi_edge_set **_set)
+{
+ struct kcctpl_multi_edge_set *set;
+ unsigned int i;
+
+ set = talloc_zero(graph, struct kcctpl_multi_edge_set);
+ NT_STATUS_HAVE_NO_MEMORY(set);
+
+ for (i = 0; i < res_site_link->count; i++) {
+ struct GUID site_link_guid;
+ struct kcctpl_multi_edge *edge;
+
+ site_link_guid = samdb_result_guid(res_site_link->msgs[i],
+ "objectGUID");
+ edge = kcctpl_find_edge_by_guid(graph, site_link_guid);
+ if (!edge) {
+ TALLOC_CTX *tmp_ctx = talloc_new(graph);
+ DEBUG(0, ("failed to find a graph edge with ID=%s\n",
+ GUID_string(tmp_ctx, &site_link_guid)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ if (GUID_compare(&edge->type, &type) == 0) {
+ set->edge_ids.data = talloc_realloc(set,
+ set->edge_ids.data,
+ struct GUID,
+ set->edge_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set->edge_ids.data,
+ set);
+ set->edge_ids.data[set->edge_ids.count] = site_link_guid;
+ set->edge_ids.count++;
+ }
+ }
+
+ *_set = set;
+ return NT_STATUS_OK;
+}
+
+/**
+ * create a kcctpl_multi_edge_set instance.
+ */
+static NTSTATUS kcctpl_create_edge_set(struct ldb_context *ldb,
+ struct kcctpl_graph *graph,
+ struct GUID type,
+ struct ldb_message *bridge,
+ struct kcctpl_multi_edge_set **_set)
+{
+ struct kcctpl_multi_edge_set *set;
+ struct ldb_message_element *el;
+ unsigned int i;
+
+ set = talloc_zero(graph, struct kcctpl_multi_edge_set);
+ NT_STATUS_HAVE_NO_MEMORY(set);
+
+ set->id = samdb_result_guid(bridge, "objectGUID");
+
+ el = ldb_msg_find_element(bridge, "siteLinkList");
+ for (i = 0; i < el->num_values; i++) {
+ struct ldb_val val;
+ TALLOC_CTX *tmp_ctx;
+ struct ldb_dn *dn;
+ struct GUID site_link_guid;
+ int ret;
+ struct kcctpl_multi_edge *edge;
+
+ val = el->values[i];
+ tmp_ctx = talloc_new(graph);
+ dn = ldb_dn_from_ldb_val(tmp_ctx, ldb, &val);
+ if (!ldb_dn_validate(dn)) {
+ DEBUG(0, ("invalid DN in siteLinkList attr of %s\n",
+ GUID_string(tmp_ctx, &set->id)));
+ talloc_free(set);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ret = dsdb_find_guid_by_dn(ldb, dn, &site_link_guid);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("failed to find objectGUID for object %s: "
+ "%s\n", ldb_dn_get_linearized(dn),
+ ldb_strerror(ret)));
+ talloc_free(set);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ edge = kcctpl_find_edge_by_guid(graph, site_link_guid);
+ if (!edge) {
+ DEBUG(0, ("failed to find a graph edge with ID=%s\n",
+ GUID_string(tmp_ctx, &site_link_guid)));
+ talloc_free(set);
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ talloc_free(tmp_ctx);
+
+ if (GUID_compare(&edge->type, &type) == 0) {
+ set->edge_ids.data = talloc_realloc(set,
+ set->edge_ids.data,
+ struct GUID,
+ set->edge_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(set->edge_ids.data,
+ set);
+ set->edge_ids.data[set->edge_ids.count] = site_link_guid;
+ set->edge_ids.count++;
+ }
+ }
+
+ *_set = set;
+ return NT_STATUS_OK;
+}
+
+/**
+ * set up a kcctpl_graph, populated with a kcctpl_vertex for each site object, a
+ * kcctpl_multi_edge for each siteLink object, and a kcctpl_multi_edge_set for
+ * each siteLinkBridge object (or implied siteLinkBridge).
+ */
+static NTSTATUS kcctpl_setup_graph(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ struct kcctpl_graph **_graph)
+{
+ struct kcctpl_graph *graph;
+ struct ldb_dn *config_dn, *base_dn;
+ TALLOC_CTX *tmp_ctx;
+ bool ok;
+ struct ldb_result *res;
+ const char * const site_link_attrs[] = { "objectGUID", NULL };
+ const char * const inter_site_transport_attrs[] = { "objectGUID",
+ "distinguishedName",
+ NULL };
+ const char * const attrs[] = { "objectGUID", "cost", "options",
+ "replInterval", "schedule", NULL };
+ const char * const site_link_bridge_attrs[] = { "objectGUID",
+ "siteLinkList",
+ NULL };
+ int ret;
+ struct GUID_list vertex_ids;
+ unsigned int i;
+ NTSTATUS status;
+
+ config_dn = samdb_config_dn(ldb);
+ if (!config_dn) {
+ DEBUG(0, ("failed to find our own Config DN\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ tmp_ctx = talloc_new(mem_ctx);
+ base_dn = ldb_dn_copy(tmp_ctx, config_dn);
+ if (!base_dn) {
+ DEBUG(0, ("failed to copy Config DN %s\n",
+ ldb_dn_get_linearized(config_dn)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ok = ldb_dn_add_child_fmt(base_dn, "CN=Sites");
+ if (!ok) {
+ if (ldb_dn_validate(base_dn)) {
+ DEBUG(0, ("failed to format DN %s\n",
+ ldb_dn_get_linearized(base_dn)));
+ }
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
+ site_link_attrs, "objectClass=siteLink");
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("failed to find siteLink objects under %s: %s\n",
+ ldb_dn_get_linearized(base_dn), ldb_strerror(ret)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ ZERO_STRUCT(vertex_ids);
+ for (i = 0; i < res->count; i++) {
+ struct GUID guid;
+
+ guid = samdb_result_guid(res->msgs[i], "objectGUID");
+ vertex_ids.data = talloc_realloc(tmp_ctx, vertex_ids.data,
+ struct GUID,
+ vertex_ids.count + 1);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(vertex_ids.data, tmp_ctx);
+ vertex_ids.data[vertex_ids.count] = guid;
+ vertex_ids.count++;
+ }
+
+ status = kcctpl_create_graph(mem_ctx, &vertex_ids, &graph);
+ if (NT_STATUS_IS_ERR(status)) {
+ DEBUG(0, ("failed to create graph: %s\n", nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ /* get site of local DC */
+
+ ok = ldb_dn_add_child_fmt(base_dn, "CN=Inter-Site Transports");
+ if (!ok) {
+ if (ldb_dn_validate(base_dn)) {
+ DEBUG(0, ("failed to format DN %s\n",
+ ldb_dn_get_linearized(base_dn)));
+ }
+ talloc_free(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, base_dn, LDB_SCOPE_SUBTREE,
+ inter_site_transport_attrs,
+ "objectClass=interSiteTransport");
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, ("failed to find interSiteTransport objects under %s: "
+ "%s\n", ldb_dn_get_linearized(base_dn),
+ ldb_strerror(ret)));
+ talloc_free(tmp_ctx);
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ for (i = 0; i < res->count; i++) {
+ struct ldb_message *transport;
+ struct ldb_result *res_site_link;
+ struct GUID transport_guid;
+ unsigned int j;
+ int options;
--
Samba Shared Repository
More information about the samba-cvs
mailing list