From 1b29f765bdfe3705c1b88fcdbb4fa923682e9678 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Mon, 23 Apr 2007 13:38:48 +0000
Subject: [PATCH] This integrates the multi-master synchronization with the new admin framework (issue 1477) and makes possible to dynamically add or remove changelog server and synchronization domains in a running server (issue 639).
---
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java | 11
opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java | 136 ++
opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml | 14
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java | 14
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java | 18
opends/src/server/org/opends/server/synchronization/common/LogMessages.java | 18
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java | 59
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java | 21
opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml | 33
opends/src/server/org/opends/server/api/SynchronizationProvider.java | 15
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java | 11
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java | 54
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java | 17
opends/resource/schema/02-config.ldif | 4
opends/resource/config/synchronization.ldif | 16
opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java | 448 +------
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java | 1
opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml | 211 +++
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java | 10
opends/src/server/org/opends/server/synchronization/changelog/Changelog.java | 299 +---
opends/src/server/org/opends/server/core/DirectoryServer.java | 16
opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java | 1061 ++++++------------
opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java | 3
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java | 190 +++
opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java | 40
opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java | 240 +--
opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml | 56 +
opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml | 172 +++
opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java | 141 +-
29 files changed, 1,588 insertions(+), 1,741 deletions(-)
diff --git a/opends/resource/config/synchronization.ldif b/opends/resource/config/synchronization.ldif
index 8924b3c..c2944fd 100644
--- a/opends/resource/config/synchronization.ldif
+++ b/opends/resource/config/synchronization.ldif
@@ -13,16 +13,22 @@
dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider
+objectClass: ds-cfg-multimaster-synchronization-provider
ds-cfg-synchronization-provider-enabled: true
ds-cfg-synchronization-provider-class: org.opends.server.synchronization.plugin.MultimasterSynchronization
-dn: cn=example, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+dn: cn=domains, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+objectClass: top
+objectClass: ds-cfg-branch
+cn: domains
+
+dn: cn=example, cn=domains, cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
objectClass: top
objectClass: ds-cfg-synchronization-provider-config
cn: example
ds-cfg-synchronization-dn: dc=example,dc=com
-ds-cfg-changelog-server: host1:8989
-ds-cfg-changelog-server: host2:8989
+ds-cfg-changelog-server: localhost:8989
+ds-cfg-changelog-server: localhost:8990
ds-cfg-directory-server-id: 1
ds-cfg-receive-status: true
@@ -31,7 +37,7 @@
objectClass: ds-cfg-synchronization-changelog-server-config
cn: Changelog Server
ds-cfg-changelog-port: 8989
-ds-cfg-changelog-server: host1:8989
-ds-cfg-changelog-server: host2:8989
+ds-cfg-changelog-server: localhost:8989
+ds-cfg-changelog-server: localhost:8990
ds-cfg-changelog-server-id: 1
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index c5b4b8b..e0ee545 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -1634,6 +1634,10 @@
MUST ( ds-task-initialize-domain-dn $ ds-task-initialize-replica-server-id )
MAY ( ds-task-processed-entry-count $ ds-task-unprocessed-entry-count )
X-ORIGIN 'OpenDS Directory Server' )
+objectClasses: ( 1.3.6.1.4.1.26027.1.2.94
+ NAME 'ds-cfg-multimaster-synchronization-provider'
+ SUP ds-cfg-synchronization-provider STRUCTURAL
+ X-ORIGIN 'OpenDS Directory Server' )
objectClasses: ( 1.3.6.1.4.1.26027.1.2.95
NAME 'ds-cfg-dictionary-password-validator' SUP ds-cfg-password-validator
STRUCTURAL MUST ( ds-cfg-dictionary-file $ ds-cfg-case-sensitive-validation $
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml
new file mode 100644
index 0000000..a6e8aae
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/ChangelogServerConfiguration.xml
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="changelog-server"
+ plural-name="changelog-servers" package="org.opends.server.admin.std"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ is the server to which Multimaster Domain connects to publish and
+ receive changes to or from other Multimaster Domains.
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.65</ldap:oid>
+ <ldap:name>
+ ds-cfg-synchronization-changelog-server-config
+ </ldap:name>
+ <ldap:superior>top</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property name="changelog-server" multi-valued="true"
+ mandatory="false">
+ <adm:synopsis>
+ Specifies the addresses of the changelog server to which this
+ <adm:user-friendly-name />
+ should try to connect at startup time.
+ </adm:synopsis>
+ <adm:description>
+ Adresses must be specified using the syntax: hostname:port
+ </adm:description>
+ <adm:requires-admin-action>
+ <adm:none />
+ </adm:requires-admin-action>
+ <adm:default-behavior>
+ <adm:undefined />
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string></adm:string>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.160</ldap:oid>
+ <ldap:name>ds-cfg-changelog-server</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="changelog-server-id" multi-valued="false"
+ mandatory="true" read-only="true">
+ <adm:synopsis>
+ Specifies the server ID of this Changelog Server
+ </adm:synopsis>
+ <adm:description>
+ Each Changelog Server must have a different server ID.
+ </adm:description>
+ <adm:requires-admin-action>
+ <adm:none />
+ </adm:requires-admin-action>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.278</ldap:oid>
+ <ldap:name>ds-cfg-changelog-server-id</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="window-size" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the window size that will this Domain must use when
+ communicating with changelog servers.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>100</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.288</ldap:oid>
+ <ldap:name>ds-cfg-window-size</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="queue-size" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the number of changes that will be kept in memory for
+ each LDAP server in the topology.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>10000</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.290</ldap:oid>
+ <ldap:name>ds-cfg-changelog-max-queue-size</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="changelog-db-directory" mandatory="false"
+ hidden="false" multi-valued="false" read-only="true">
+ <adm:synopsis>
+ The path where the
+ <adm:user-friendly-name />
+ will store all persistent information.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:undefined />
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:string></adm:string>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.306</ldap:oid>
+ <ldap:name>ds-cfg-changelog-db-directory</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="changelog-purge-delay" multi-valued="false">
+ <adm:synopsis>
+ The time (in seconds) after which the
+ <adm:user-friendly-name />
+ will erase all persistent information.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>86400s</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:duration base-unit="s" allow-unlimited="false" />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.319</ldap:oid>
+ <ldap:name>ds-cfg-changelog-purge-delay</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="changelog-port" mandatory="true"
+ multi-valued="false">
+ <adm:synopsis>
+ The port on which this
+ <adm:user-friendly-name></adm:user-friendly-name>
+ will wait for connections from other Changelog Servers or LDAP
+ Servers or from LDAP servers.
+ </adm:synopsis>
+ <adm:requires-admin-action>
+ <adm:none />
+ </adm:requires-admin-action>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.158</ldap:oid>
+ <ldap:name>ds-cfg-changelog-port</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
new file mode 100644
index 0000000..feb79e7
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterDomainConfiguration.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="multimaster-domain"
+ plural-name="multimaster-domains"
+ package="org.opends.server.admin.std"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ is used to provide Multimaster Replication of several OpenDS copies
+ of the same data
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.58</ldap:oid>
+ <ldap:name>ds-cfg-synchronization-provider-config</ldap:name>
+ <ldap:superior>top</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property name="changelog-server" multi-valued="true"
+ mandatory="true">
+ <adm:synopsis>
+ Specifies the addresses of the changelog server to which this
+ <adm:user-friendly-name />
+ should try to connect at startup time.
+ </adm:synopsis>
+ <adm:description>
+ Adresses must be specified using the syntax: hostname:port
+ </adm:description>
+ <adm:requires-admin-action>
+ <adm:none />
+ </adm:requires-admin-action>
+ <adm:syntax>
+ <adm:string></adm:string>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.160</ldap:oid>
+ <ldap:name>ds-cfg-changelog-server</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="server-id" multi-valued="false" mandatory="true"
+ read-only="true">
+ <adm:synopsis>
+ Specifies the server ID of this multimaster provider.
+ </adm:synopsis>
+ <adm:description>
+ Each multimaster provider must have a different server ID.
+ </adm:description>
+ <adm:requires-admin-action>
+ <adm:none />
+ </adm:requires-admin-action>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.279</ldap:oid>
+ <ldap:name>ds-cfg-directory-server-id</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="synchronization-dn" mandatory="true"
+ multi-valued="false" read-only="true">
+ <adm:synopsis>
+ Specifies the base dn of the Multimaster Domain
+ </adm:synopsis>
+ <adm:syntax>
+ <adm:dn></adm:dn>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.226</ldap:oid>
+ <ldap:name>ds-cfg-synchronization-dn</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="max-receive-queue" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the maximum length of the receive queue on the changelog
+ server before flow control must be activated.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>0</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.164</ldap:oid>
+ <ldap:name>ds-cfg-max-receive-queue</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="max-receive-delay" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the maximum delay on the changelog server before flow
+ control must be activated.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>0s</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:duration base-unit="s" allow-unlimited="false"
+ upper-limit="2147483647" lower-limit="0" />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.165</ldap:oid>
+ <ldap:name>ds-cfg-max-receive-delay</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="max-send-queue" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the maximum length of the send queue on the changelog
+ server before flow control must be activated.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>0</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.166</ldap:oid>
+ <ldap:name>ds-cfg-max-send-queue</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="max-send-delay" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the maximum send delay on the changelog server before
+ flow control must be activated.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>0s</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:duration upper-limit="2147483647" allow-unlimited="false"
+ lower-limit="0" base-unit="s" />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.167</ldap:oid>
+ <ldap:name>ds-cfg-max-send-delay</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="window-size" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the window size that will this Domain must use when
+ communicating with changelog servers.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>100</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:integer></adm:integer>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.288</ldap:oid>
+ <ldap:name>ds-cfg-window-size</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="heartbeat-interval" mandatory="false"
+ multi-valued="false">
+ <adm:synopsis>
+ Specifies the heartbeat interval that this Domain must use when
+ communicating with changelog servers. The Domain will expect
+ regular heatbeat coming from the changelog server with this
+ interval if they are not received it will close its connection and
+ connect to another changelog server.
+ </adm:synopsis>
+ <adm:default-behavior>
+ <adm:defined>
+ <adm:value>1000s</adm:value>
+ </adm:defined>
+ </adm:default-behavior>
+ <adm:syntax>
+ <adm:duration base-unit="ms" allow-unlimited="false"
+ lower-limit="100" />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.305</ldap:oid>
+ <ldap:name>ds-cfg-heartbeat-interval</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml
new file mode 100644
index 0000000..efc764a
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/MultimasterSynchronizationProviderConfiguration.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="multimaster-synchronization-provider"
+ plural-name="multimaster-synchronization-providers"
+ package="org.opends.server.admin.std"
+ extends="synchronization-provider"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap" abstract="false">
+ <adm:synopsis>
+ The
+ <adm:user-friendly-name />
+ is used to provide Multimaster Replication of several OpenDS copies
+ of the same data
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.91</ldap:oid>
+ <ldap:name>ds-cfg-multimaster-synchronization-provider</ldap:name>
+ <ldap:superior>ds-cfg-synchronization-provider</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:relation name="multimaster-domain">
+ <adm:one-to-many />
+ <adm:profile name="ldap">
+ <ldap:rdn-sequence>cn=domains</ldap:rdn-sequence>
+ </adm:profile>
+ </adm:relation>
+ <adm:relation name="changelog-server">
+ <adm:one-to-zero-or-one />
+ <adm:profile name="ldap">
+ <ldap:rdn-sequence>cn=changelog server</ldap:rdn-sequence>
+ </adm:profile>
+ </adm:relation>
+</adm:managed-object>
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
index 01da02b..9f68116 100644
--- a/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
+++ b/opends/src/admin/defn/org/opends/server/admin/std/RootConfiguration.xml
@@ -21,7 +21,15 @@
</ldap:rdn-sequence>
</adm:profile>
</adm:relation>
- <adm:relation name="access-control-handler">
+ <adm:relation name="synchronization-provider">
+ <adm:one-to-many />
+ <adm:profile name="ldap">
+ <ldap:rdn-sequence>
+ cn=Synchronization Providers, cn=config
+ </ldap:rdn-sequence>
+ </adm:profile>
+ </adm:relation>
+ <adm:relation name="access-control-handler">
<adm:one-to-one />
<adm:profile name="ldap">
<ldap:rdn-sequence>
@@ -72,9 +80,7 @@
<adm:relation name="plugin">
<adm:one-to-many />
<adm:profile name="ldap">
- <ldap:rdn-sequence>
- cn=Plugins,cn=config
- </ldap:rdn-sequence>
+ <ldap:rdn-sequence>cn=Plugins,cn=config</ldap:rdn-sequence>
</adm:profile>
</adm:relation>
<adm:relation name="virtual-attribute">
diff --git a/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml b/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml
new file mode 100644
index 0000000..f532aab
--- /dev/null
+++ b/opends/src/admin/defn/org/opends/server/admin/std/SynchronizationProviderConfiguration.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<adm:managed-object name="synchronization-provider"
+ plural-name="synchronization-providers"
+ package="org.opends.server.admin.std" abstract="true"
+ xmlns:adm="http://www.opends.org/admin"
+ xmlns:ldap="http://www.opends.org/admin-ldap">
+ <adm:synopsis>
+ <adm:user-friendly-plural-name />
+ are responsible for handling Synchronization of the Directory Server
+ datas with other OpenDS instances or other data repositories.
+ </adm:synopsis>
+ <adm:profile name="ldap">
+ <ldap:object-class>
+ <ldap:oid>1.3.6.1.4.1.26027.1.2.57</ldap:oid>
+ <ldap:name>ds-cfg-synchronization-provider</ldap:name>
+ <ldap:superior>top</ldap:superior>
+ </ldap:object-class>
+ </adm:profile>
+ <adm:property name="enabled" mandatory="true">
+ <adm:synopsis>
+ Indicate whether the
+ <adm:user-friendly-name />
+ is enabled for use.
+ </adm:synopsis>
+ <adm:syntax>
+ <adm:boolean />
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.155</ldap:oid>
+ <ldap:name>ds-cfg-synchronization-provider-enabled</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+ <adm:property name="java-implementation-class" mandatory="true"
+ multi-valued="false">
+ <adm:synopsis>
+ The fully-qualified name of the Java class that provides the
+ <adm:user-friendly-name />
+ implementation.
+ </adm:synopsis>
+ <adm:syntax>
+ <adm:java-class>
+ <adm:instance-of>
+ org.opends.server.api.SynchronizationProvider
+ </adm:instance-of>
+ </adm:java-class>
+ </adm:syntax>
+ <adm:profile name="ldap">
+ <ldap:attribute>
+ <ldap:oid>1.3.6.1.4.1.26027.1.1.154</ldap:oid>
+ <ldap:name>ds-cfg-synchronization-provider-class</ldap:name>
+ </ldap:attribute>
+ </adm:profile>
+ </adm:property>
+</adm:managed-object>
diff --git a/opends/src/server/org/opends/server/api/SynchronizationProvider.java b/opends/src/server/org/opends/server/api/SynchronizationProvider.java
index 3305807..063857f 100644
--- a/opends/src/server/org/opends/server/api/SynchronizationProvider.java
+++ b/opends/src/server/org/opends/server/api/SynchronizationProvider.java
@@ -30,7 +30,7 @@
import java.util.List;
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
@@ -51,8 +51,11 @@
* the Directory Server are properly communicated to other instances,
* and potentially to other kinds of applications, so that they can be
* updated accordingly.
+ *
+ * @param <T> the configuration for the synchronization provider.
*/
-public abstract class SynchronizationProvider
+public abstract class
+ SynchronizationProvider<T extends SynchronizationProviderCfg>
{
@@ -61,9 +64,8 @@
* Performs any initialization that might be necessary for this
* synchronization provider.
*
- * @param configEntry The entry containing the configuration
- * information for this synchronization
- * provider.
+ * @param config The configuration information for this
+ * synchronization provider.
*
* @throws ConfigException If the provided entry does not contain
* a valid configuration for this
@@ -75,8 +77,7 @@
* is not related to the server
* configuration.
*/
- public abstract void initializeSynchronizationProvider(
- ConfigEntry configEntry)
+ public abstract void initializeSynchronizationProvider(T config)
throws ConfigException, InitializationException;
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 2472675..64dd31c 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -49,6 +49,7 @@
import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.std.server.PasswordValidatorCfg;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
import org.opends.server.api.*;
import org.opends.server.api.plugin.PluginType;
import org.opends.server.api.plugin.StartupPluginResult;
@@ -334,7 +335,8 @@
// The set of synchronization providers that have been registered with the
// Directory Server.
- private CopyOnWriteArrayList<SynchronizationProvider>
+ private
+ CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
synchronizationProviders;
// The set of virtual attributes defined in the server.
@@ -630,7 +632,8 @@
directoryServer.shutdownListeners =
new CopyOnWriteArrayList<ServerShutdownListener>();
directoryServer.synchronizationProviders =
- new CopyOnWriteArrayList<SynchronizationProvider>();
+ new CopyOnWriteArrayList<SynchronizationProvider
+ <SynchronizationProviderCfg>>();
directoryServer.supportedControls = new TreeSet<String>();
directoryServer.supportedFeatures = new TreeSet<String>();
directoryServer.virtualAttributes =
@@ -7187,8 +7190,9 @@
* @return The set of synchronization providers that have been registered
* with the Directory Server.
*/
- public static CopyOnWriteArrayList<SynchronizationProvider>
- getSynchronizationProviders()
+ public static
+ CopyOnWriteArrayList<SynchronizationProvider<SynchronizationProviderCfg>>
+ getSynchronizationProviders()
{
return directoryServer.synchronizationProviders;
}
@@ -7200,8 +7204,8 @@
*
* @param provider The synchronization provider to register.
*/
- public static void registerSynchronizationProvider(SynchronizationProvider
- provider)
+ public static void registerSynchronizationProvider(
+ SynchronizationProvider<SynchronizationProviderCfg> provider)
{
directoryServer.synchronizationProviders.add(provider);
}
diff --git a/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java b/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
index d8186e9..659b148 100644
--- a/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
+++ b/opends/src/server/org/opends/server/core/SynchronizationProviderConfigManager.java
@@ -28,33 +28,31 @@
-import java.util.ArrayList;
-import java.util.concurrent.ConcurrentHashMap;
-
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.config.BooleanConfigAttribute;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
-import org.opends.server.config.StringConfigAttribute;
-import org.opends.server.types.ConfigChangeResult;
-import org.opends.server.types.DN;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.InitializationException;
-import org.opends.server.types.ResultCode;
-import org.opends.server.types.SearchFilter;
-
-import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.debug.DebugLogger.debugCaught;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.Error.*;
import static org.opends.server.messages.ConfigMessages.*;
-import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.StaticUtils.*;
+import static org.opends.server.messages.MessageHandler.getMessage;
+import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.opends.server.admin.ClassPropertyDefinition;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.server.ServerManagementContext;
+import org.opends.server.admin.std.meta.SynchronizationProviderCfgDefn;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
+import org.opends.server.api.SynchronizationProvider;
+import org.opends.server.config.ConfigException;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DebugLogLevel;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.ResultCode;
@@ -66,17 +64,20 @@
* to them while the server is running.
*/
public class SynchronizationProviderConfigManager
- implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener
+ implements ConfigurationChangeListener<SynchronizationProviderCfg>,
+ ConfigurationAddListener<SynchronizationProviderCfg>,
+ ConfigurationDeleteListener<SynchronizationProviderCfg>
{
// The mapping between configuration entry DNs and their corresponding
// synchronization provider implementations.
- private ConcurrentHashMap<DN,SynchronizationProvider> registeredProviders;
+ private ConcurrentHashMap<DN,
+ SynchronizationProvider<SynchronizationProviderCfg>> registeredProviders =
+ new ConcurrentHashMap<DN,
+ SynchronizationProvider<SynchronizationProviderCfg>>();
- // The DN of the associated configuration entry.
- private DN configEntryDN;
@@ -107,765 +108,407 @@
public void initializeSynchronizationProviders()
throws ConfigException, InitializationException
{
- registeredProviders = new ConcurrentHashMap<DN,SynchronizationProvider>();
+ // Create an internal server management context and retrieve
+ // the root configuration which has the synchronization provider relation.
+ ServerManagementContext context = ServerManagementContext.getInstance();
+ RootCfg root = context.getRootConfiguration();
+ // Register as an add and delete listener so that we can
+ // be notified when new synchronization providers are added or existing
+ // sycnhronization providers are removed.
+ root.addSynchronizationProviderAddListener(this);
+ root.addSynchronizationProviderDeleteListener(this);
- // Get the configuration entry that is the parent for all synchronization
- // providers in the server.
- ConfigEntry providerRoot;
- try
+ // Initialize existing synchronization providers.
+ for (String name : root.listSynchronizationProviders())
{
- configEntryDN = DN.decode(DN_SYNCHRONIZATION_PROVIDER_BASE);
- providerRoot = DirectoryServer.getConfigEntry(configEntryDN);
- }
- catch (Exception e)
- {
- if (debugEnabled())
+ // Get the synchronization provider's configuration.
+ // This will automatically decode and validate its properties.
+ SynchronizationProviderCfg config = root.getSynchronizationProvider(name);
+
+ // Register as a change listener for this synchronization provider
+ // entry so that we can be notified when it is disabled or enabled.
+ config.addChangeListener(this);
+
+ // Ignore this synchronization provider if it is disabled.
+ if (config.isEnabled())
{
- debugCaught(DebugLogLevel.ERROR, e);
+ // Perform initialization, load the synchronization provider's
+ // implementation class and initialize it.
+ SynchronizationProvider<SynchronizationProviderCfg> provider =
+ getSynchronizationProvider(config);
+
+ // Register the synchronization provider with the Directory Server.
+ DirectoryServer.registerSynchronizationProvider(provider);
+
+ // Put this synchronization provider in the hash map so that we will be
+ // able to find it if it is deleted or disabled.
+ registeredProviders.put(config.dn(), provider);
}
-
- int msgID = MSGID_CONFIG_SYNCH_CANNOT_GET_CONFIG_BASE;
- String message = getMessage(msgID, stackTraceToSingleLineString(e));
- throw new ConfigException(msgID, message, e);
- }
-
-
- // If the configuration root entry is null, then assume it doesn't exist.
- // In that case, then fail. At least that entry must exist in the
- // configuration, even if there are no synchronization providers defined
- // below it.
- if (providerRoot == null)
- {
- int msgID = MSGID_CONFIG_SYNCH_BASE_DOES_NOT_EXIST;
- String message = getMessage(msgID);
- throw new ConfigException(msgID, message);
- }
-
-
- // Register as an add and delete listener for the base entry so that we can
- // be notified if new providers are added or existing providers are removed.
- providerRoot.registerAddListener(this);
- providerRoot.registerDeleteListener(this);
-
-
- // Iterate through the set of immediate children below the provider root
- // entry and register those providers.
- for (ConfigEntry providerEntry : providerRoot.getChildren().values())
- {
- DN providerDN = providerEntry.getDN();
-
-
- // Register as a change listener for this provider entry so that we will
- // be notified of any changes that may be made to it.
- providerEntry.registerChangeListener(this);
-
-
- // Check to see if this entry appears to contain a synchronization
- // provider configuration. If not, then fail.
- try
- {
- SearchFilter providerFilter =
- SearchFilter.createFilterFromString("(objectClass=" +
- OC_SYNCHRONIZATION_PROVIDER +
- ")");
-
- if (! providerFilter.matchesEntry(providerEntry.getEntry()))
- {
- int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
- String message = getMessage(msgID, String.valueOf(providerDN));
- throw new ConfigException(msgID, message);
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
- String message = getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new InitializationException(msgID, message, e);
- }
-
-
- // See if the entry contains an attribute that indicates whether the
- // synchronization provider should be enabled. If it does not, then fail.
- // If it is present but set to false, then log a warning and skip it.
- int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
- BooleanConfigAttribute enabledStub =
- new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
- getMessage(msgID), true);
- try
- {
- BooleanConfigAttribute enabledAttr =
- (BooleanConfigAttribute)
- providerEntry.getConfigAttribute(enabledStub);
- if (enabledAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
- String message = getMessage(msgID, String.valueOf(providerDN));
- throw new ConfigException(msgID, message);
- }
- else if (! enabledAttr.activeValue())
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_DISABLED;
- String message = getMessage(msgID, String.valueOf(providerDN));
- logError(ErrorLogCategory.CONFIGURATION,
- ErrorLogSeverity.SEVERE_WARNING, message, msgID);
- continue;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
- String message = getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new InitializationException(msgID, message, e);
- }
-
-
- // See if the entry contains an attribute that specifies the class name
- // for the synchronization provider implementation. If there is no such
- // attribute, then fail.
- String providerClassName;
- msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
- StringConfigAttribute classStub =
- new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
- getMessage(msgID), true, false, true);
- try
- {
- StringConfigAttribute classAttr =
- (StringConfigAttribute)
- providerEntry.getConfigAttribute(classStub);
- if (classAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
- String message = getMessage(msgID, String.valueOf(providerDN));
- throw new ConfigException(msgID, message);
- }
- else
- {
- providerClassName = classAttr.activeValue();
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
- String message = getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new InitializationException(msgID, message, e);
- }
-
-
- // Load the specified provider class. If an error occurs, then fail.
- Class providerClass;
- try
- {
- providerClass = DirectoryServer.loadClass(providerClassName);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
- String message = getMessage(msgID, String.valueOf(providerClassName),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new InitializationException(msgID, message, e);
- }
-
-
- // Make sure that the specified class is a valid synchronization provider.
- // If not, then fail.
- SynchronizationProvider provider;
- try
- {
- provider = (SynchronizationProvider) providerClass.newInstance();
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
- String message = getMessage(msgID, String.valueOf(providerClassName),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new InitializationException(msgID, message, e);
- }
-
-
- // Perform the necessary initialization for the synchronization provider.
- // If a problem occurs, then fail.
- try
- {
- provider.initializeSynchronizationProvider(providerEntry);
- }
- catch (ConfigException ce)
- {
- msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
- String message = getMessage(msgID, String.valueOf(providerDN),
- ce.getMessage());
- throw new ConfigException(msgID, message, ce);
- }
- catch (InitializationException ie)
- {
- msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
- String message = getMessage(msgID, String.valueOf(providerDN),
- ie.getMessage());
- throw new InitializationException(msgID, message, ie);
- }
- catch (Exception e)
- {
- msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
- String message = getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e));
- throw new ConfigException(msgID, message, e);
- }
-
-
- // Register the synchronization provider with the Directory Server.
- DirectoryServer.registerSynchronizationProvider(provider);
-
-
- // Put this provider in the hash so that we will be able to find it if it
- // is altered.
- registeredProviders.put(providerDN, provider);
}
}
/**
- * Indicates whether the configuration entry that will result from a proposed
- * modification is acceptable to this change listener.
- *
- * @param configEntry The configuration entry that will result from
- * the requested update.
- * @param unacceptableReason A buffer to which this method can append a
- * human-readable message explaining why the
- * proposed change is not acceptable.
- *
- * @return <CODE>true</CODE> if the proposed entry contains an acceptable
- * configuration, or <CODE>false</CODE> if it does not.
+ * {@inheritDoc}
*/
- public boolean configChangeIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
+ public ConfigChangeResult applyConfigurationChange(
+ SynchronizationProviderCfg configuration)
{
- DN providerDN = configEntry.getDN();
- SynchronizationProvider provider = registeredProviders.get(providerDN);
-
-
- // Check to see if this entry appears to contain a backend configuration.
- // If not, then reject it.
- try
- {
- SearchFilter providerFilter =
- SearchFilter.createFilterFromString("(objectClass=" +
- OC_SYNCHRONIZATION_PROVIDER +
- ")");
- if (! providerFilter.matchesEntry(configEntry.getEntry()))
- {
- int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
- unacceptableReason.append(getMessage(msgID,
- String.valueOf(providerDN)));
- return false;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
- unacceptableReason.append(getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
- return false;
- }
-
-
- // See if the entry contains an attribute that indicates whether the
- // provider should be enabled. If it does not, then reject it.
- int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
- BooleanConfigAttribute enabledStub =
- new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
- getMessage(msgID), true);
- try
- {
- BooleanConfigAttribute enabledAttr =
- (BooleanConfigAttribute) configEntry.getConfigAttribute(enabledStub);
- if (enabledAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
- unacceptableReason.append(getMessage(msgID,
- String.valueOf(providerDN)));
- return false;
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
- unacceptableReason.append(getMessage(msgID,
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
- return false;
- }
-
-
- // See if the entry contains an attribute that specifies the provider class.
- // If it does not, then fail.
- String className;
- msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
- StringConfigAttribute classStub =
- new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
- getMessage(msgID), true, false, true);
- try
- {
- StringConfigAttribute classAttr =
- (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
- if (classAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
- unacceptableReason.append(getMessage(msgID,
- String.valueOf(providerDN)));
- return false;
- }
- else
- {
- className = classAttr.pendingValue();
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
- unacceptableReason.append(getMessage(msgID,
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
- return false;
- }
-
-
- // If the provider is currently disabled, or if the class is different from
- // the one used by the running provider, then make sure that it is
- // acceptable.
- if ((provider == null) ||
- (! className.equals(provider.getClass().getName())))
- {
- Class providerClass;
- try
- {
- providerClass = DirectoryServer.loadClass(className);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
- unacceptableReason.append(getMessage(msgID, String.valueOf(className),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
- return false;
- }
-
- try
- {
- SynchronizationProvider newProvider =
- (SynchronizationProvider) providerClass.newInstance();
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
- unacceptableReason.append(getMessage(msgID, String.valueOf(className),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
- return false;
- }
- }
-
-
- // If we've gotten to this point, then it is acceptable as far as we are
- // concerned. If it is unacceptable according to the configuration for that
- // synchronization provider, then the provider itself will need to make that
- // determination.
- return true;
- }
-
-
-
- /**
- * Attempts to apply a new configuration to this Directory Server component
- * based on the provided changed entry.
- *
- * @param configEntry The configuration entry that containing the updated
- * configuration for this component.
- *
- * @return Information about the result of processing the configuration
- * change.
- */
- public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
- {
- DN providerDN = configEntry.getDN();
- SynchronizationProvider provider = registeredProviders.get(providerDN);
+ // Default result code.
ResultCode resultCode = ResultCode.SUCCESS;
boolean adminActionRequired = false;
ArrayList<String> messages = new ArrayList<String>();
+ // Attempt to get the existing synchronization provider. This will only
+ // succeed if it is currently enabled.
+ DN dn = configuration.dn();
+ SynchronizationProvider<SynchronizationProviderCfg> provider =
+ registeredProviders.get(dn);
- // Check to see if this entry appears to contain a synchronization provider
- // configuration. If not, then fail.
- try
+ // See whether the synchronization provider should be enabled.
+ if (provider == null)
{
- SearchFilter providerFilter =
- SearchFilter.createFilterFromString("(objectClass=" +
- OC_SYNCHRONIZATION_PROVIDER +
- ")");
- if (! providerFilter.matchesEntry(configEntry.getEntry()))
+ if (configuration.isEnabled())
{
- int msgID = MSGID_CONFIG_SYNCH_ENTRY_DOES_NOT_HAVE_PROVIDER_CONFIG;
- messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
- if (resultCode == ResultCode.SUCCESS)
+ // The synchronization provider needs to be enabled. Load, initialize,
+ // and register the synchronization provider as per the add listener
+ // method.
+ try
{
- resultCode = ResultCode.CONSTRAINT_VIOLATION;
+ // Perform initialization, load the synchronization provider's
+ // implementation class and initialize it.
+ provider = getSynchronizationProvider(configuration);
+
+ // Register the synchronization provider with the Directory Server.
+ DirectoryServer.registerSynchronizationProvider(provider);
+
+ // Put this synchronization provider in the hash map so that we will
+ // be able to find it if it is deleted or disabled.
+ registeredProviders.put(configuration.dn(), provider);
+ }
+ catch (ConfigException e)
+ {
+ if (debugEnabled())
+ {
+ debugCaught(DebugLogLevel.ERROR, e);
+ messages.add(e.getMessage());
+ resultCode = DirectoryServer.getServerErrorResultCode();
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ debugCaught(DebugLogLevel.ERROR, e);
+ }
+ int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+ messages.add(getMessage(msgID, String.valueOf(
+ configuration.getJavaImplementationClass()),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e)));
+ resultCode = DirectoryServer.getServerErrorResultCode();
}
}
}
- catch (Exception e)
+ else
{
- if (debugEnabled())
+ if (configuration.isEnabled())
{
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- int msgID = MSGID_CONFIG_SYNCH_CANNOT_CHECK_FOR_PROVIDER_CONFIG_OC;
- messages.add(getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
- }
-
-
- // See if the entry contains an attribute that indicates whether the
- // provider should be enabled. If it does not, then reject it.
- boolean shouldEnable = false;
- int msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_ENABLED;
- BooleanConfigAttribute enabledStub =
- new BooleanConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_ENABLED,
- getMessage(msgID), true);
- try
- {
- BooleanConfigAttribute enabledAttr =
- (BooleanConfigAttribute) configEntry.getConfigAttribute(enabledStub);
- if (enabledAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_NO_ENABLED_ATTR;
- messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
- if (resultCode == ResultCode.SUCCESS)
+ // The synchronization provider is currently active, so we don't
+ // need to do anything. Changes to the class name cannot be
+ // applied dynamically, so if the class name did change then
+ // indicate that administrative action is required for that
+ // change to take effect.
+ String className = configuration.getJavaImplementationClass();
+ if (!className.equals(provider.getClass().getName()))
{
- resultCode = ResultCode.CONSTRAINT_VIOLATION;
+ adminActionRequired = true;
}
}
else
{
- shouldEnable = enabledAttr.pendingValue();
+ // The connection handler is being disabled so remove it from
+ // the DirectorySerevr list, shut it down and remove it from the
+ // hash map.
+ DirectoryServer.deregisterSynchronizationProvider(provider);
+ provider.finalizeSynchronizationProvider();
+ registeredProviders.remove(dn);
}
}
- catch (Exception e)
+ // Return the configuration result.
+ return new ConfigChangeResult(resultCode, adminActionRequired,
+ messages);
+ }
+
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(
+ SynchronizationProviderCfg configuration,
+ List<String> unacceptableReasons)
+ {
+ if (configuration.isEnabled())
{
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_ENABLED_STATE;
- messages.add(getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
+ // It's enabled so always validate the class.
+ return isJavaClassAcceptable(configuration, unacceptableReasons);
+ } else
+ {
+ // It's disabled so ignore it.
+ return true;
}
+ }
- // See if the entry contains an attribute that specifies the provider class.
- // If it does not, then reject it.
- String className = null;
- msgID = MSGID_CONFIG_SYNCH_DESCRIPTION_PROVIDER_CLASS;
- StringConfigAttribute classStub =
- new StringConfigAttribute(ATTR_SYNCHRONIZATION_PROVIDER_CLASS,
- getMessage(msgID), true, false, true);
- try
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationAdd(
+ SynchronizationProviderCfg configuration)
+ {
+ // Default result code.
+ ResultCode resultCode = ResultCode.SUCCESS;
+ boolean adminActionRequired = false;
+ ArrayList<String> messages = new ArrayList<String>();
+
+ // Register as a change listener for this synchronization provider entry
+ // so that we will be notified if when it is disabled or enabled.
+ configuration.addChangeListener(this);
+
+ // Ignore this synchronization provider if it is disabled.
+ if (configuration.isEnabled())
{
- StringConfigAttribute classAttr =
- (StringConfigAttribute) configEntry.getConfigAttribute(classStub);
- if (classAttr == null)
- {
- msgID = MSGID_CONFIG_SYNCH_NO_CLASS_ATTR;
- messages.add(getMessage(msgID, String.valueOf(providerDN)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = ResultCode.CONSTRAINT_VIOLATION;
- }
- }
- else
- {
- className = classAttr.pendingValue();
- }
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_DETERMINE_CLASS;
- messages.add(getMessage(msgID, String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
- }
-
-
- // If the provider is currently disabled, or if the class is different from
- // the one used by the running provider, then make sure that it is
- // acceptable.
- SynchronizationProvider newProvider = null;
- if ((resultCode == ResultCode.SUCCESS) &&
- ((provider == null) ||
- (! provider.getClass().getName().equals(className))))
- {
- Class providerClass = null;
try
{
- providerClass = DirectoryServer.loadClass(className);
+ // Perform initialization, load the synchronization provider's
+ // implementation class and initialize it.
+ SynchronizationProvider<SynchronizationProviderCfg> provider =
+ getSynchronizationProvider(configuration);
+
+ // Register the synchronization provider with the Directory Server.
+ DirectoryServer.registerSynchronizationProvider(provider);
+
+ // Put this synchronization provider in the hash map so that we will be
+ // able to find it if it is deleted or disabled.
+ registeredProviders.put(configuration.dn(), provider);
}
- catch (Exception e)
+ catch (ConfigException e)
{
if (debugEnabled())
{
debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
- messages.add(getMessage(msgID, String.valueOf(className),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
+ messages.add(e.getMessage());
resultCode = DirectoryServer.getServerErrorResultCode();
}
}
-
- try
- {
- if (providerClass != null)
- {
- newProvider = (SynchronizationProvider) providerClass.newInstance();
- }
- }
catch (Exception e)
{
if (debugEnabled())
{
debugCaught(DebugLogLevel.ERROR, e);
}
-
- msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
- messages.add(getMessage(msgID, String.valueOf(className),
- String.valueOf(providerDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
+ int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+ messages.add(getMessage(msgID, String.valueOf(
+ configuration.getJavaImplementationClass()),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e)));
+ resultCode = DirectoryServer.getServerErrorResultCode();
}
}
+ // Return the configuration result.
+ return new ConfigChangeResult(resultCode, adminActionRequired,
+ messages);
+ }
- // If everything looks OK, then process the configuration change.
- if (resultCode == ResultCode.SUCCESS)
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationAddAcceptable(
+ SynchronizationProviderCfg configuration,
+ List<String> unacceptableReasons)
+ {
+ if (configuration.isEnabled())
{
- // If the provider is currently disabled but should be enabled, then do
- // so now.
- if (provider == null)
- {
- if (shouldEnable && (newProvider != null))
- {
- try
- {
- newProvider.initializeSynchronizationProvider(configEntry);
- registeredProviders.put(configEntryDN, newProvider);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- debugCaught(DebugLogLevel.ERROR, e);
- }
-
- msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
- messages.add(getMessage(msgID, String.valueOf(configEntryDN),
- stackTraceToSingleLineString(e)));
-
- if (resultCode == ResultCode.SUCCESS)
- {
- resultCode = DirectoryServer.getServerErrorResultCode();
- }
- }
- }
- }
+ // It's enabled so always validate the class.
+ return isJavaClassAcceptable(configuration, unacceptableReasons);
+ } else
+ {
+ // It's disabled so ignore it.
+ return true;
+ }
+ }
- // Otherwise, see if the enabled flag or class name changed and indicate
- // that it will require a restart to take effect.
- else
- {
- if (! shouldEnable)
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_HAS_BEEN_DISABLED;
- messages.add(getMessage(msgID, String.valueOf(configEntryDN)));
- adminActionRequired = true;
- }
- if (! provider.getClass().getName().equals(className))
- {
- msgID = MSGID_CONFIG_SYNCH_PROVIDER_CLASS_CHANGED;
- messages.add(getMessage(msgID, String.valueOf(configEntryDN),
- String.valueOf(provider.getClass().getName()),
- String.valueOf(className)));
- adminActionRequired = true;
- }
- }
+ /**
+ * Check if the class provided in the configuration is an acceptable
+ * java class for a synchronization provider.
+ *
+ * @param configuration The configuration for which the class must be
+ * checked.
+ * @param unacceptableReasons A list containing the reasons why the class is
+ * not acceptable.
+ *
+ * @return true if the class is acceptable or false if not.
+ */
+ @SuppressWarnings("unchecked")
+ private SynchronizationProvider<SynchronizationProviderCfg>
+ getSynchronizationProvider(SynchronizationProviderCfg configuration)
+ throws ConfigException
+ {
+ String className = configuration.getJavaImplementationClass();
+ SynchronizationProviderCfgDefn d =
+ SynchronizationProviderCfgDefn.getInstance();
+ ClassPropertyDefinition pd =
+ d.getJavaImplementationClassPropertyDefinition();
+
+ // Load the class
+ Class<? extends SynchronizationProvider> theClass;
+ SynchronizationProvider<SynchronizationProviderCfg> provider;
+ try
+ {
+ theClass = pd.loadClass(className, SynchronizationProvider.class);
+ } catch (Exception e)
+ {
+ // Handle the exception: put a message in the unacceptable reasons.
+ int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
+ String message = getMessage(msgID, String.valueOf(className),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e));
+ throw new ConfigException(msgID, message, e);
+ }
+ try
+ {
+ // Instantiate the class.
+ provider = theClass.newInstance();
+ } catch (Exception e)
+ {
+ // Handle the exception: put a message in the unacceptable reasons.
+ int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
+ String message = getMessage(msgID, String.valueOf(className),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e));
+ throw new ConfigException(msgID, message, e);
+ }
+ try
+ {
+ // Initialize the Synchronization Provider.
+ provider.initializeSynchronizationProvider(configuration);
+ } catch (Exception e)
+ {
+ // Handle the exception: put a message in the unacceptable reasons.
+ int msgID = MSGID_CONFIG_SYNCH_ERROR_INITIALIZING_PROVIDER;
+ String message = getMessage(msgID, String.valueOf(className),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e));
+ throw new ConfigException(msgID, message, e);
+ }
+ return provider;
+ }
+
+ /**
+ * Check if the class provided in the configuration is an acceptable
+ * java class for a synchronization provider.
+ *
+ * @param configuration The configuration for which the class must be
+ * checked.
+ * @param unacceptableReasons A list containing the reasons why the class is
+ * not acceptable.
+ *
+ * @return true if the class is acceptable or false if not.
+ */
+ private boolean isJavaClassAcceptable(
+ SynchronizationProviderCfg configuration,
+ List<String> unacceptableReasons)
+ {
+ String className = configuration.getJavaImplementationClass();
+ SynchronizationProviderCfgDefn d =
+ SynchronizationProviderCfgDefn.getInstance();
+ ClassPropertyDefinition pd =
+ d.getJavaImplementationClassPropertyDefinition();
+
+ // Load the class and cast it to a synchronizationProvider.
+ Class<? extends SynchronizationProvider> theClass;
+ try
+ {
+ theClass = pd.loadClass(className, SynchronizationProvider.class);
+ theClass.newInstance();
+ } catch (Exception e)
+ {
+ // Handle the exception: put a message in the unacceptable reasons.
+ int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_LOAD_PROVIDER_CLASS;
+ String message = getMessage(msgID, String.valueOf(className),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e));
+ unacceptableReasons.add(message);
+ return false;
+ }
+ // Check that the implementation class implements the correct interface.
+ try
+ {
+ // Determine the initialization method to use: it must take a
+ // single parameter which is the exact type of the configuration
+ // object.
+ theClass.getMethod("initializeSynchronizationProvider",
+ configuration.definition().getServerConfigurationClass());
+ } catch (Exception e)
+ {
+ // Handle the exception: put a message in the unacceptable reasons.
+ int msgID = MSGID_CONFIG_SYNCH_UNABLE_TO_INSTANTIATE_PROVIDER;
+ String message = getMessage(msgID, String.valueOf(className),
+ String.valueOf(configuration.dn()),
+ stackTraceToSingleLineString(e));
+ unacceptableReasons.add(message);
+ return false;
}
- return new ConfigChangeResult(resultCode, adminActionRequired, messages);
- }
-
-
-
- /**
- * Indicates whether the configuration entry that will result from a proposed
- * add is acceptable to this add listener.
- *
- * @param configEntry The configuration entry that will result from
- * the requested add.
- * @param unacceptableReason A buffer to which this method can append a
- * human-readable message explaining why the
- * proposed entry is not acceptable.
- *
- * @return <CODE>true</CODE> if the proposed entry contains an acceptable
- * configuration, or <CODE>false</CODE> if it does not.
- */
- public boolean configAddIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
- {
- // NYI
+ // The class is valid as far as we can tell.
return true;
}
-
-
/**
- * Attempts to apply a new configuration based on the provided added entry.
- *
- * @param configEntry The new configuration entry that contains the
- * configuration to apply.
- *
- * @return Information about the result of processing the configuration
- * change.
+ * {@inheritDoc}
*/
- public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
+ public ConfigChangeResult applyConfigurationDelete(
+ SynchronizationProviderCfg configuration)
{
- // NYI
- return null;
+ // Default result code.
+ ResultCode resultCode = ResultCode.SUCCESS;
+ boolean adminActionRequired = false;
+
+ // See if the entry is registered as a synchronization provider. If so,
+ // deregister and stop it.
+ DN dn = configuration.dn();
+ SynchronizationProvider provider = registeredProviders.get(dn);
+ if (provider != null)
+ {
+ DirectoryServer.deregisterSynchronizationProvider(provider);
+ provider.finalizeSynchronizationProvider();
+ }
+ return new ConfigChangeResult(resultCode, adminActionRequired);
}
/**
- * Indicates whether it is acceptable to remove the provided configuration
- * entry.
- *
- * @param configEntry The configuration entry that will be removed
- * from the configuration.
- * @param unacceptableReason A buffer to which this method can append a
- * human-readable message explaining why the
- * proposed delete is not acceptable.
- *
- * @return <CODE>true</CODE> if the proposed entry may be removed from the
- * configuration, or <CODE>false</CODE> if not.
+ * {@inheritDoc}
*/
- public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
+ public boolean isConfigurationDeleteAcceptable(
+ SynchronizationProviderCfg configuration,
+ List<String> unacceptableReasons)
{
- // NYI
+ // A delete should always be acceptable, so just return true.
return true;
}
-
-
-
- /**
- * Attempts to apply a new configuration based on the provided deleted entry.
- *
- * @param configEntry The new configuration entry that has been deleted.
- *
- * @return Information about the result of processing the configuration
- * change.
- */
- public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
- {
- // NYI
- return null;
- }
}
+
+
+
diff --git a/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java b/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
index 531569c..e813bd6 100644
--- a/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
+++ b/opends/src/server/org/opends/server/synchronization/changelog/Changelog.java
@@ -40,26 +40,24 @@
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.DirectoryThread;
import org.opends.server.config.ConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
-import org.opends.server.config.IntegerConfigAttribute;
-import org.opends.server.config.IntegerWithUnitConfigAttribute;
-import org.opends.server.config.StringConfigAttribute;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.messages.MessageHandler;
import org.opends.server.synchronization.protocol.SocketSession;
import org.opends.server.types.ConfigChangeResult;
import org.opends.server.types.DN;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
+import org.opends.server.types.ResultCode;
import com.sleepycat.je.DatabaseException;
@@ -73,7 +71,9 @@
*
* It is responsible for creating the changelog cache and managing it
*/
-public class Changelog implements Runnable, ConfigurableComponent
+public class Changelog
+ implements Runnable, ConfigurableComponent,
+ ConfigurationChangeListener<ChangelogServerCfg>
{
private short serverId;
private String serverURL;
@@ -85,7 +85,7 @@
private boolean runListen = true;
/* The list of changelog servers configured by the administrator */
- private List<String> changelogServers;
+ private Collection<String> changelogServers;
/* This table is used to store the list of dn for which we are currently
* handling servers.
@@ -106,212 +106,30 @@
private long trimAge; // the time (in sec) after which the changes must
// de deleted from the persistent storage.
- static final String CHANGELOG_SERVER_ATTR = "ds-cfg-changelog-server";
- static final String SERVER_ID_ATTR = "ds-cfg-changelog-server-id";
- static final String CHANGELOG_PORT_ATTR = "ds-cfg-changelog-port";
- static final String WINDOW_SIZE_ATTR = "ds-cfg-window-size";
- static final String QUEUE_SIZE_ATTR = "ds-cfg-changelog-max-queue-size";
- static final String CHANGELOG_DIR_PATH_ATTR = "ds-cfg-changelog-db-directory";
- static final String PURGE_DELAY_ATTR = "ds-cfg-changelog-purge-delay";
-
-
- static final IntegerConfigAttribute changelogPortStub =
- new IntegerConfigAttribute(CHANGELOG_PORT_ATTR, "changelog port",
- true, false, false, true, 0, true, 65535);
-
- static final IntegerConfigAttribute serverIdStub =
- new IntegerConfigAttribute(SERVER_ID_ATTR, "server ID", true, false,
- false, true, 0, true, 65535);
-
- static final StringConfigAttribute changelogStub =
- new StringConfigAttribute(CHANGELOG_SERVER_ATTR,
- "changelog server information", true, true, false);
-
- static final IntegerConfigAttribute windowStub =
- new IntegerConfigAttribute(WINDOW_SIZE_ATTR, "window size",
- false, false, false, true, 0, false, 0);
-
- static final IntegerConfigAttribute queueSizeStub =
- new IntegerConfigAttribute(QUEUE_SIZE_ATTR, "changelog queue size",
- false, false, false, true, 0, false, 0);
-
- static final StringConfigAttribute dbDirnameStub =
- new StringConfigAttribute(CHANGELOG_DIR_PATH_ATTR,
- "changelog storage directory path", false, false, true);
-
- /**
- * The set of time units that will be used for expressing the
- * changelog purge delay.
- */
- private static final LinkedHashMap<String,Double> purgeTimeUnits =
- new LinkedHashMap<String,Double>();
-
- static
- {
- purgeTimeUnits.put(TIME_UNIT_SECONDS_ABBR, 1D);
- purgeTimeUnits.put(TIME_UNIT_SECONDS_FULL, 1D);
- purgeTimeUnits.put(TIME_UNIT_MINUTES_ABBR, 60D);
- purgeTimeUnits.put(TIME_UNIT_MINUTES_FULL, 1D);
- purgeTimeUnits.put(TIME_UNIT_HOURS_ABBR, 60*60D);
- purgeTimeUnits.put(TIME_UNIT_HOURS_FULL, 60*60D);
- purgeTimeUnits.put(TIME_UNIT_DAYS_ABBR, 24*60*60D);
- purgeTimeUnits.put(TIME_UNIT_DAYS_FULL, 24*60*60D);
- }
-
- static final IntegerWithUnitConfigAttribute purgeDelayStub =
- new IntegerWithUnitConfigAttribute(PURGE_DELAY_ATTR,
- "changelog purge delay", false, purgeTimeUnits, true, 0, false, 0);
-
- /**
- * Check if a ConfigEntry is valid.
- * @param config The config entry that needs to be checked.
- * @param unacceptableReason A description of the reason why the config entry
- * is not acceptable (if return is false).
- * @return a boolean indicating if the configEntry is valid.
- */
- public static boolean checkConfigEntry(ConfigEntry config,
- StringBuilder unacceptableReason)
- {
- try
- {
- IntegerConfigAttribute changelogPortAttr;
- changelogPortAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(changelogPortStub);
-
- /* The config must provide a changelog port number
- */
- if (changelogPortAttr == null)
- {
- unacceptableReason.append(
- MessageHandler.getMessage(MSGID_NEED_CHANGELOG_PORT,
- config.getDN().toString()) );
- }
-
- /*
- * read the server Id information
- * this is a single valued integer, its value must fit on a
- * short integer
- */
- IntegerConfigAttribute serverIdAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(serverIdStub);
-
- if (serverIdAttr == null)
- {
- unacceptableReason.append(
- MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
- config.getDN().toString()) );
- }
-
- return true;
- } catch (ConfigException e)
- {
- return false;
- }
- }
-
/**
* Creates a new Changelog using the provided configuration entry.
*
- * @param config The configuration entry where configuration can be found.
- * @throws ConfigException When Configuration entry is invalid.
+ * @param configuration The configuration of this changelog.
+ * @throws ConfigException When Configuration is invalid.
*/
- public Changelog(ConfigEntry config) throws ConfigException
+ public Changelog(ChangelogServerCfg configuration) throws ConfigException
{
shutdown = false;
runListen = true;
-
- IntegerConfigAttribute changelogPortAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(changelogPortStub);
- /* if there is no changelog port configured, this process must not be a
- * changelog server
- */
- if (changelogPortAttr == null)
- {
- throw new ConfigException(MSGID_NEED_CHANGELOG_PORT,
- MessageHandler.getMessage(MSGID_NEED_CHANGELOG_PORT,
- config.getDN().toString()) );
- }
- int changelogPort = changelogPortAttr.activeIntValue();
- configAttributes.add(changelogPortAttr);
-
- /*
- * read the server Id information
- * this is a single valued integer, its value must fit on a
- * short integer
- */
- IntegerConfigAttribute serverIdAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(serverIdStub);
-
- if (serverIdAttr == null)
- {
- throw new ConfigException(MSGID_NEED_SERVER_ID,
- MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
- config.getDN().toString()) );
- }
- changelogServerId = (short) serverIdAttr.activeIntValue();
- configAttributes.add(serverIdAttr);
-
- /*
- * read the centralized changelog server configuration
- * this is a multivalued attribute
- */
- StringConfigAttribute changelogServer =
- (StringConfigAttribute) config.getConfigAttribute(changelogStub);
- changelogServers = new ArrayList<String>();
- if (changelogServer != null)
- {
- for (String serverURL : changelogServer.activeValues())
- {
- String[] splitStrings = serverURL.split(":");
- try
- {
- changelogServers.add(
- InetAddress.getByName(splitStrings[0]).getHostAddress()
- + ":" + splitStrings[1]);
- } catch (UnknownHostException e)
- {
- throw new ConfigException(MSGID_UNKNOWN_HOSTNAME,
- e.getLocalizedMessage());
- }
- }
- }
- configAttributes.add(changelogServer);
-
- IntegerConfigAttribute windowAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(windowStub);
- if (windowAttr == null)
- rcvWindow = 100; // Attribute is not present : use the default value
- else
- {
- rcvWindow = windowAttr.activeIntValue();
- configAttributes.add(windowAttr);
- }
-
- IntegerConfigAttribute queueSizeAttr =
- (IntegerConfigAttribute) config.getConfigAttribute(queueSizeStub);
- if (queueSizeAttr == null)
- queueSize = 10000; // Attribute is not present : use the default value
- else
- {
- queueSize = queueSizeAttr.activeIntValue();
- configAttributes.add(queueSizeAttr);
- }
-
- /*
- * read the storage directory path attribute
- */
- StringConfigAttribute dbDirnameAttr =
- (StringConfigAttribute) config.getConfigAttribute(dbDirnameStub);
- if (dbDirnameAttr == null)
+ int changelogPort = configuration.getChangelogPort();
+ changelogServerId = (short) configuration.getChangelogServerId();
+ changelogServers = configuration.getChangelogServer();
+ if (changelogServers == null)
+ changelogServers = new ArrayList<String>();
+ queueSize = configuration.getQueueSize();
+ trimAge = configuration.getChangelogPurgeDelay();
+ dbDirname = configuration.getChangelogDbDirectory();
+ rcvWindow = configuration.getWindowSize();
+ if (dbDirname == null)
{
dbDirname = "changelogDb";
}
- else
- {
- dbDirname = dbDirnameAttr.activeValue();
- configAttributes.add(changelogServer);
- }
- // Exists or Create
+ // Chech that this path exists or create it.
File f = getFileForPath(dbDirname);
try
{
@@ -326,24 +144,8 @@
e.getMessage() + " " + getFileForPath(dbDirname));
}
- /*
- * Read the Purge Delay (trim age) attribute
- */
- IntegerWithUnitConfigAttribute purgeDelayAttr =
- (IntegerWithUnitConfigAttribute) config.getConfigAttribute(
- purgeDelayStub);
- if (purgeDelayAttr == null)
- trimAge = 24*60*60; // not present : use the default value : 1 day
- else
- {
- trimAge = purgeDelayAttr.activeCalculatedValue();
- configAttributes.add(purgeDelayAttr);
- }
-
initialize(changelogServerId, changelogPort);
-
- configDn = config.getDN();
- DirectoryServer.registerConfigurableComponent(this);
+ configuration.addChangeListener(this);
}
/**
@@ -452,7 +254,7 @@
*/
for (String serverURL : changelogServers)
{
- if ((serverURL.compareTo(localURL) != 0) &&
+ if ((serverURL.compareTo(this.serverURL) != 0) &&
(!connectedChangelogs.contains(serverURL)))
{
this.connect(serverURL, changelogCache.getBaseDn());
@@ -629,7 +431,6 @@
}
dbEnv.shutdown();
- DirectoryServer.deregisterConfigurableComponent(this);
}
@@ -659,4 +460,56 @@
{
return trimAge * 1000;
}
+
+ /**
+ * Check if the provided configuration is acceptable for add.
+ *
+ * @param configuration The configuration to check.
+ * @param unacceptableReasons When the configuration is not acceptable, this
+ * table is use to return the reasons why this
+ * configuration is not acceptbale.
+ *
+ * @return true if the configuration is acceptable, false other wise.
+ */
+ public static boolean isConfigurationAcceptable(
+ ChangelogServerCfg configuration, List<String> unacceptableReasons)
+ {
+ int port = configuration.getChangelogPort();
+
+ try
+ {
+ ServerSocket tmpSocket = new ServerSocket();
+ tmpSocket.bind(new InetSocketAddress(port));
+ tmpSocket.close();
+ }
+ catch (Exception e)
+ {
+ String message = getMessage(MSGID_COULD_NOT_BIND_CHANGELOG, port,
+ e.getMessage());
+ unacceptableReasons.add(message);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationChange(
+ ChangelogServerCfg configuration)
+ {
+ // TODO : implement this
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(
+ ChangelogServerCfg configuration, List<String> unacceptableReasons)
+ {
+ // TODO : implement this
+ return true;
+ }
}
diff --git a/opends/src/server/org/opends/server/synchronization/common/LogMessages.java b/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
index d2fc088..da1e49f 100644
--- a/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
+++ b/opends/src/server/org/opends/server/synchronization/common/LogMessages.java
@@ -48,18 +48,6 @@
CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 1;
/**
- * Need at least one Changelog Server.
- */
- public static final int MSGID_NEED_CHANGELOG_SERVER =
- CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 2;
-
- /**
- * Need to have a server ID.
- */
- public static final int MSGID_NEED_SERVER_ID =
- CATEGORY_MASK_SYNC | SEVERITY_MASK_MILD_ERROR | 3;
-
- /**
* Invalid Changelog Server.
*/
public static final int MSGID_INVALID_CHANGELOG_SERVER =
@@ -380,11 +368,7 @@
public static void registerMessages()
{
MessageHandler.registerMessage(MSGID_SYNC_INVALID_DN,
- "The Synchronization configuration DN is invalid");
- MessageHandler.registerMessage(MSGID_NEED_CHANGELOG_SERVER,
- "At least one changelog server must be declared");
- MessageHandler.registerMessage(MSGID_NEED_SERVER_ID,
- "The Server Id must be defined");
+ "The configured DN is already used by another domain.");
MessageHandler.registerMessage(MSGID_INVALID_CHANGELOG_SERVER,
"Invalid changelog server configuration");
MessageHandler.registerMessage(MSGID_UNKNOWN_HOSTNAME,
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
index a985e6b..674d94a 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogBroker.java
@@ -33,8 +33,8 @@
import static org.opends.server.synchronization.common.LogMessages.*;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
+import java.util.Collection;
import java.util.LinkedHashSet;
-import java.util.List;
import java.util.TreeSet;
import java.util.concurrent.Semaphore;
import java.io.IOException;
@@ -75,7 +75,7 @@
public class ChangelogBroker implements InternalSearchListener
{
private boolean shutdown = false;
- private List<String> servers;
+ private Collection<String> servers;
private boolean connected = false;
private final Object lock = new Object();
private String changelogServer = "Not connected";
@@ -158,7 +158,7 @@
* @param servers list of servers used
* @throws Exception : in case of errors
*/
- public void start(List<String> servers)
+ public void start(Collection<String> servers)
throws Exception
{
/*
@@ -504,7 +504,6 @@
try
{
SynchronizationMessage msg = session.receive();
-
if (msg instanceof WindowMessage)
{
WindowMessage windowMsg = (WindowMessage) msg;
@@ -556,7 +555,8 @@
debugInfo("ChangelogBroker Stop Closing session");
}
- session.close();
+ if (session != null)
+ session.close();
} catch (IOException e)
{}
}
@@ -695,11 +695,31 @@
return numLostConnections;
}
- private void log(String message)
+
+ /**
+ * Change some config parameters.
+ *
+ * @param changelogServers The new list of changelog servers.
+ * @param maxReceiveQueue The max size of receive queue.
+ * @param maxReceiveDelay The max receive delay.
+ * @param maxSendQueue The max send queue.
+ * @param maxSendDelay The max Send Delay.
+ * @param window The max window size.
+ * @param heartbeatInterval The heartbeat interval.
+ */
+ public void changeConfig(Collection<String> changelogServers,
+ int maxReceiveQueue, int maxReceiveDelay, int maxSendQueue,
+ int maxSendDelay, int window, long heartbeatInterval)
{
- int msgID = MSGID_UNKNOWN_TYPE;
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.SEVERE_ERROR,
- message, msgID);
+ this.servers = changelogServers;
+ this.maxRcvWindow = window;
+ this.heartbeatInterval = heartbeatInterval;
+ this.maxReceiveDelay = maxReceiveDelay;
+ this.maxReceiveQueue = maxReceiveQueue;
+ this.maxSendDelay = maxSendDelay;
+ this.maxSendQueue = maxSendQueue;
+ // TODO : Changing those parameters requires to either restart a new
+ // session with the changelog server or renegociate the parameters that
+ // were sent in the ServerStart message
}
}
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java
new file mode 100644
index 0000000..68e50c8
--- /dev/null
+++ b/opends/src/server/org/opends/server/synchronization/plugin/ChangelogListener.java
@@ -0,0 +1,136 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.synchronization.plugin;
+
+import java.util.List;
+
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
+import org.opends.server.admin.std.server.MultimasterSynchronizationProviderCfg;
+import org.opends.server.config.ConfigException;
+import org.opends.server.synchronization.changelog.Changelog;
+import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.ResultCode;
+
+/**
+ * This class is used to create and object that can
+ * register in the admin framework as a listener for changes, add and delete
+ * on the Changelog Server configuration objects.
+ *
+ */
+public class ChangelogListener
+ implements ConfigurationAddListener<ChangelogServerCfg>,
+ ConfigurationDeleteListener<ChangelogServerCfg>
+{
+ Changelog changelog = null;
+
+ /**
+ * Build a Changelog Listener from the given Multimaster configuration.
+ *
+ * @param configuration The configuration that will be used to listen
+ * for changelog configuration changes.
+ *
+ * @throws ConfigException if the ChangelogListener can't register for
+ * listening to changes on the provided configuration
+ * object.
+ */
+ public ChangelogListener(
+ MultimasterSynchronizationProviderCfg configuration)
+ throws ConfigException
+ {
+ configuration.addChangelogServerAddListener(this);
+ configuration.addChangelogServerDeleteListener(this);
+
+ if (configuration.hasChangelogServer())
+ {
+ ChangelogServerCfg server = configuration.getChangelogServer();
+ changelog = new Changelog(server);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationAdd(
+ ChangelogServerCfg configuration)
+ {
+ try
+ {
+ changelog = new Changelog(configuration);
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ } catch (ConfigException e)
+ {
+ // we should never get to this point because the configEntry has
+ // already been validated in configAddisAcceptable
+ return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationAddAcceptable(
+ ChangelogServerCfg configuration, List<String> unacceptableReasons)
+ {
+ return Changelog.isConfigurationAcceptable(
+ configuration, unacceptableReasons);
+ }
+
+ /**
+ * Shutdown the Changelog servers.
+ */
+ public void shutdown()
+ {
+ if (changelog != null)
+ changelog.shutdown();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationDelete(
+ ChangelogServerCfg configuration)
+ {
+ // There can be only one changelog, just shutdown the changelog
+ // currently configured.
+ if (changelog != null)
+ {
+ changelog.shutdown();
+ }
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationDeleteAcceptable(
+ ChangelogServerCfg configuration, List<String> unacceptableReasons)
+ {
+ return true;
+ }
+}
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java b/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
index edbb868..0637e48 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java
@@ -26,34 +26,35 @@
*/
package org.opends.server.synchronization.plugin;
+import static org.opends.server.synchronization.common.LogMessages.HISTORICAL;
+
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.MultimasterDomainCfg;
+import org.opends.server.admin.std.server.MultimasterSynchronizationProviderCfg;
import org.opends.server.api.Backend;
import org.opends.server.api.BackupTaskListener;
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
import org.opends.server.api.ExportTaskListener;
import org.opends.server.api.ImportTaskListener;
import org.opends.server.api.RestoreTaskListener;
import org.opends.server.api.SynchronizationProvider;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.core.AddOperation;
-import org.opends.server.synchronization.changelog.Changelog;
-import org.opends.server.synchronization.common.LogMessages;
-import org.opends.server.types.DN;
import org.opends.server.core.DeleteOperation;
-import org.opends.server.types.DirectoryException;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Entry;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.Operation;
+import org.opends.server.synchronization.common.LogMessages;
import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
import org.opends.server.types.LDIFExportConfig;
import org.opends.server.types.LDIFImportConfig;
import org.opends.server.types.Modification;
@@ -61,8 +62,6 @@
import org.opends.server.types.ResultCode;
import org.opends.server.types.SynchronizationProviderResult;
-import static org.opends.server.synchronization.common.LogMessages.*;
-
/**
* This class is used to load the Synchronization code inside the JVM
* and to trigger initialization of the synchronization.
@@ -71,19 +70,19 @@
* synchronization code running during the operation process
* as pre-op, conflictRsolution, and post-op.
*/
-public class MultimasterSynchronization extends SynchronizationProvider
- implements ConfigAddListener, ConfigDeleteListener, ConfigChangeListener,
- BackupTaskListener, RestoreTaskListener, ImportTaskListener,
- ExportTaskListener
-
+public class MultimasterSynchronization
+ extends SynchronizationProvider<MultimasterSynchronizationProviderCfg>
+ implements ConfigurationAddListener<MultimasterDomainCfg>,
+ ConfigurationDeleteListener<MultimasterDomainCfg>,
+ BackupTaskListener, RestoreTaskListener, ImportTaskListener,
+ ExportTaskListener
{
static String CHANGELOG_DN = "cn=Changelog Server," +
"cn=Multimaster Synchronization, cn=Synchronization Providers, cn=config";
static String SYNCHRONIZATION_CLASS =
"ds-cfg-synchronization-provider-config";
- private DN changelogConfigEntryDn = null;
- private Changelog changelog = null;
+ private ChangelogListener changelog = null;
private static Map<DN, SynchronizationDomain> domains =
new HashMap<DN, SynchronizationDomain>() ;
@@ -91,46 +90,25 @@
/**
* {@inheritDoc}
*/
- public void initializeSynchronizationProvider(ConfigEntry configEntry)
+ @Override
+ public void initializeSynchronizationProvider(
+ MultimasterSynchronizationProviderCfg configuration)
throws ConfigException
{
LogMessages.registerMessages();
- configEntry.registerAddListener(this);
- configEntry.registerDeleteListener(this);
+ changelog = new ChangelogListener(configuration);
- /*
- * Read changelog server the changelog configuration entry
- */
- try
- {
- changelogConfigEntryDn = DN.decode(CHANGELOG_DN);
- ConfigEntry config =
- DirectoryServer.getConfigEntry(changelogConfigEntryDn);
- /*
- * If there is no such entry, this process must not be a changelog server
- */
- if (config != null)
- {
- changelog = new Changelog(config);
- }
- } catch (DirectoryException e)
- {
- /* never happens */
- throw new ConfigException(MSGID_SYNC_INVALID_DN,
- "Invalid Changelog configuration DN");
- }
+ // Register as an add and delete listener with the root configuration so we
+ // can be notified if Multimaster domain entries are added or removed.
+ configuration.addMultimasterDomainAddListener(this);
+ configuration.addMultimasterDomainDeleteListener(this);
- /*
- * Parse the list of entries below configEntry,
- * create one synchronization domain for each child
- */
- for (ConfigEntry domainEntry : configEntry.getChildren().values())
+ // Create the list of domains that are already defined.
+ for (String name : configuration.listMultimasterDomains())
{
- if (domainEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
- {
- createNewSynchronizationDomain(domainEntry);
- }
+ MultimasterDomainCfg domain = configuration.getMultimasterDomain(name);
+ createNewSynchronizationDomain(domain);
}
/*
@@ -151,124 +129,46 @@
}
/**
- * Indicates whether the configuration entry that will result from a proposed
- * modification is acceptable to this change listener.
- *
- * @param configEntry The configuration entry that will result from
- * the requested update.
- * @param unacceptableReason A buffer to which this method can append a
- * human-readable message explaining why the
- * proposed change is not acceptable.
- *
- * @return <CODE>true</CODE> if the proposed entry contains an acceptable
- * configuration, or <CODE>false</CODE> if it does not.
+ * {@inheritDoc}
*/
- public boolean configChangeIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
+ public boolean isConfigurationAddAcceptable(
+ MultimasterDomainCfg configuration, List<String> unacceptableReasons)
{
- return false; // TODO :NYI
- }
-
- /**
- * Attempts to apply a new configuration to this Directory Server component
- * based on the provided changed entry.
- *
- * @param configEntry The configuration entry that containing the updated
- * configuration for this component.
- *
- * @return Information about the result of processing the configuration
- * change.
- */
- public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
- {
- // TODO implement this method
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ return SynchronizationDomain.isConfigurationAcceptable(
+ configuration, unacceptableReasons);
}
/**
* {@inheritDoc}
*/
- public boolean configAddIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
+ public ConfigChangeResult applyConfigurationAdd(
+ MultimasterDomainCfg configuration)
{
- // Check if the added entry is the changelog config entry
try
{
- if (configEntry.getDN().equals(DN.decode(CHANGELOG_DN)))
- {
- return Changelog.checkConfigEntry(configEntry, unacceptableReason);
- }
- } catch (DirectoryException e)
+ createNewSynchronizationDomain(configuration);
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ } catch (ConfigException e)
{
- /* never happens */
- unacceptableReason.append("Invalid Changelog configuration DN");
- return false;
+ // we should never get to this point because the configEntry has
+ // already been validated in configAddisAcceptable
+ return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false);
}
-
- // otherwise it must be a Synchronization domain, check for
- // presence of the Synchronization configuration object class
- if (configEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
- {
- return SynchronizationDomain.checkConfigEntry(configEntry,
- unacceptableReason);
- }
-
- return false;
- }
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
- {
- // check if the entry is the changelog configuration entry
- if (configEntry.getDN().equals(changelogConfigEntryDn))
- {
- try
- {
- changelog = new Changelog(configEntry);
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- } catch (ConfigException e)
- {
- // we should never get to this point because the configEntry has
- // already been validated in configAddisAcceptable
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
- }
-
- // otherwise it must be a synchronization domain, check for
- // presence of the Synchronization configuration object class
- if (configEntry.hasObjectClass(SYNCHRONIZATION_CLASS))
- {
- try
- {
- createNewSynchronizationDomain(configEntry);
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- } catch (ConfigException e)
- {
- // we should never get to this point because the configEntry has
- // already been validated in configAddisAcceptable
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
- }
-
- // we should never get to this point because the configEntry has
- // already been validated in configAddisAcceptable
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
}
/**
* Creates a New Synchronization domain from its configEntry, do the
* necessary initialization and starts it so that it is
* fully operational when this method returns.
- * @param configEntry The entry whith the configuration of this domain.
+ * @param configuration The entry whith the configuration of this domain.
* @throws ConfigException When the configuration is not valid.
*/
- private void createNewSynchronizationDomain(ConfigEntry configEntry)
- throws ConfigException
+ private void createNewSynchronizationDomain(
+ MultimasterDomainCfg configuration)
+ throws ConfigException
{
SynchronizationDomain domain;
- domain = new SynchronizationDomain(configEntry);
+ domain = new SynchronizationDomain(configuration);
domains.put(domain.getBaseDN(), domain);
domain.start();
}
@@ -276,25 +176,7 @@
/**
* {@inheritDoc}
*/
- public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
- {
- // TODO Auto-generated method stub
- return true;
- }
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
- {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * {@inheritDoc}
- */
+ @Override
public void doPostOperation(AddOperation addOperation)
{
DN dn = addOperation.getEntryDN();
@@ -305,6 +187,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void doPostOperation(DeleteOperation deleteOperation)
{
DN dn = deleteOperation.getEntryDN();
@@ -314,6 +197,7 @@
/**
* {@inheritDoc}
*/
+ @Override
public void doPostOperation(ModifyDNOperation modifyDNOperation)
{
DN dn = modifyDNOperation.getEntryDN();
@@ -536,6 +420,7 @@
* applied to the schema.
*
*/
+ @Override
public void processSchemaChange(List<Modification> modifications)
{
SynchronizationDomain domain =
@@ -651,6 +536,29 @@
domain.backupEnd();
}
}
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationDelete(
+ MultimasterDomainCfg configuration)
+ {
+ DN dn = configuration.getSynchronizationDN();
+ SynchronizationDomain domain = domains.remove(dn);
+ if (domain != null)
+ domain.shutdown();
+
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationDeleteAcceptable(
+ MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+ {
+ return true;
+ }
}
diff --git a/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java b/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
index 743d24d..c597f18 100644
--- a/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
+++ b/opends/src/server/org/opends/server/synchronization/plugin/SynchronizationDomain.java
@@ -39,14 +39,13 @@
import static org.opends.server.synchronization.common.LogMessages.*;
import static org.opends.server.synchronization.plugin.Historical.ENTRYUIDNAME;
import static org.opends.server.synchronization.protocol.OperationContext.*;
-import static org.opends.server.util.ServerConstants.*;
import static org.opends.server.util.StaticUtils.createEntry;
import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.ArrayList;
-import java.util.LinkedHashMap;
+import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -55,20 +54,18 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.DataFormatException;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.server.MultimasterDomainCfg;
import org.opends.server.api.Backend;
-import org.opends.server.api.ConfigurableComponent;
import org.opends.server.api.DirectoryThread;
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.backends.jeb.BackendImpl;
import org.opends.server.backends.task.Task;
import org.opends.server.backends.task.TaskState;
-import org.opends.server.config.BooleanConfigAttribute;
import org.opends.server.config.ConfigAttribute;
import org.opends.server.config.ConfigEntry;
import org.opends.server.config.ConfigException;
import org.opends.server.config.DNConfigAttribute;
-import org.opends.server.config.IntegerConfigAttribute;
-import org.opends.server.config.IntegerWithUnitConfigAttribute;
import org.opends.server.config.StringConfigAttribute;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
@@ -77,7 +74,6 @@
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.core.ModifyOperation;
import org.opends.server.core.Operation;
-import org.opends.server.messages.MessageHandler;
import org.opends.server.protocols.asn1.ASN1Exception;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
@@ -130,7 +126,7 @@
* handle protocol messages from the changelog server.
*/
public class SynchronizationDomain extends DirectoryThread
- implements ConfigurableComponent
+ implements ConfigurationChangeListener<MultimasterDomainCfg>
{
private SynchronizationMonitor monitor;
@@ -254,7 +250,7 @@
private int listenerThreadNumber = 10;
private boolean receiveStatus = true;
- private List<String> changelogServers;
+ private Collection<String> changelogServers;
private DN baseDN;
@@ -263,8 +259,6 @@
private boolean shutdown = false;
- private DN configDn;
-
private InternalClientConnection conn =
InternalClientConnection.getRootConnection();
@@ -273,102 +267,30 @@
private boolean disabled = false;
private boolean stateSavingDisabled = false;
- static final String CHANGELOG_SERVER_ATTR = "ds-cfg-changelog-server";
- static final String BASE_DN_ATTR = "ds-cfg-synchronization-dn";
- static final String SERVER_ID_ATTR = "ds-cfg-directory-server-id";
- static final String RECEIVE_STATUS = "ds-cfg-receive-status";
- static final String MAX_RECEIVE_QUEUE = "ds-cfg-max-receive-queue";
- static final String MAX_RECEIVE_DELAY = "ds-cfg-max-receive-delay";
- static final String MAX_SEND_QUEUE = "ds-cfg-max-send-queue";
- static final String MAX_SEND_DELAY = "ds-cfg-max-send-delay";
- static final String WINDOW_SIZE = "ds-cfg-window-size";
- static final String HEARTBEAT_INTERVAL = "ds-cfg-heartbeat-interval";
+ private int window = 100;
- private static final StringConfigAttribute changelogStub =
- new StringConfigAttribute(CHANGELOG_SERVER_ATTR,
- "changelog server information", true, true, false);
-
- private static final IntegerConfigAttribute serverIdStub =
- new IntegerConfigAttribute(SERVER_ID_ATTR, "server ID", true, false,
- false, true, 0, true, 65535);
-
- private static final DNConfigAttribute baseDnStub =
- new DNConfigAttribute(BASE_DN_ATTR, "synchronization base DN",
- true, false, false);
-
- private static final BooleanConfigAttribute receiveStatusStub =
- new BooleanConfigAttribute(RECEIVE_STATUS, "receive status", false);
-
-
- /**
- * The set of time units that will be used for expressing the heartbeat
- * interval.
- */
- private static final LinkedHashMap<String,Double> timeUnits =
- new LinkedHashMap<String,Double>();
-
-
-
- static
- {
- timeUnits.put(TIME_UNIT_MILLISECONDS_ABBR, 1D);
- timeUnits.put(TIME_UNIT_MILLISECONDS_FULL, 1D);
- timeUnits.put(TIME_UNIT_SECONDS_ABBR, 1000D);
- timeUnits.put(TIME_UNIT_SECONDS_FULL, 1000D);
- }
/**
* Creates a new SynchronizationDomain using configuration from configEntry.
*
- * @param configEntry The ConfigEntry to use to read the configuration of this
- * SynchronizationDomain.
+ * @param configuration The configuration of this SynchronizationDomain.
* @throws ConfigException In case of invalid configuration.
*/
- public SynchronizationDomain(ConfigEntry configEntry) throws ConfigException
+ public SynchronizationDomain(MultimasterDomainCfg configuration)
+ throws ConfigException
{
super("Synchronization flush");
- /*
- * read the centralized changelog server configuration
- * this is a multivalued attribute
- */
- StringConfigAttribute changelogServer =
- (StringConfigAttribute) configEntry.getConfigAttribute(changelogStub);
-
- if (changelogServer == null)
- {
- throw new ConfigException(MSGID_NEED_CHANGELOG_SERVER,
- MessageHandler.getMessage(MSGID_NEED_CHANGELOG_SERVER,
- configEntry.getDN().toString()) );
- }
- changelogServers = changelogServer.activeValues();
- configAttributes.add(changelogServer);
-
- /*
- * read the server Id information
- * this is a single valued integer, its value must fit on a short integer
- */
- IntegerConfigAttribute serverIdAttr =
- (IntegerConfigAttribute) configEntry.getConfigAttribute(serverIdStub);
- if (serverIdAttr == null)
- {
- throw new ConfigException(MSGID_NEED_SERVER_ID,
- MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
- configEntry.getDN().toString()) );
- }
- serverId = (short) serverIdAttr.activeIntValue();
- configAttributes.add(serverIdAttr);
-
- /*
- * read the base DN
- */
- DNConfigAttribute baseDn =
- (DNConfigAttribute) configEntry.getConfigAttribute(baseDnStub);
- if (baseDn == null)
- baseDN = null; // Attribute is not present : don't set a limit
- else
- baseDN = baseDn.activeValue();
- configAttributes.add(baseDn);
+ // Read the configuration parameters.
+ changelogServers = configuration.getChangelogServer();
+ serverId = (short) configuration.getServerId();
+ baseDN = configuration.getSynchronizationDN();
+ maxReceiveQueue = configuration.getMaxReceiveQueue();
+ maxReceiveDelay = (int) configuration.getMaxReceiveDelay();
+ maxSendQueue = configuration.getMaxSendQueue();
+ maxSendDelay = (int) configuration.getMaxSendDelay();
+ window = configuration.getWindowSize();
+ heartbeatInterval = configuration.getHeartbeatInterval();
/*
* Modify conflicts are solved for all suffixes but the schema suffix
@@ -386,114 +308,25 @@
solveConflictFlag = true;
}
+ /*
+ * Create a new Persistent Server State that will be used to store
+ * the last ChangeNmber seen from all LDAP servers in the topology.
+ */
state = new PersistentServerState(baseDN);
/*
- * Read the Receive Status.
+ * Create a Synchronization monitor object responsible for publishing
+ * monitoring information below cn=monitor.
*/
- BooleanConfigAttribute receiveStatusAttr = (BooleanConfigAttribute)
- configEntry.getConfigAttribute(receiveStatusStub);
- if (receiveStatusAttr != null)
- {
- receiveStatus = receiveStatusAttr.activeValue();
- configAttributes.add(receiveStatusAttr);
- }
-
- /*
- * read the synchronization flow control configuration.
- */
- IntegerConfigAttribute maxReceiveQueueStub =
- new IntegerConfigAttribute(MAX_RECEIVE_QUEUE, "max receive queue",
- false, false, false, true, 0,false, 0);
-
- IntegerConfigAttribute maxReceiveQueueAttr = (IntegerConfigAttribute)
- configEntry.getConfigAttribute(maxReceiveQueueStub);
- if (maxReceiveQueueAttr == null)
- maxReceiveQueue = 0; // Attribute is not present : don't set a limit
- else
- {
- maxReceiveQueue = maxReceiveQueueAttr.activeIntValue();
- configAttributes.add(maxReceiveQueueAttr);
- }
-
- IntegerConfigAttribute maxReceiveDelayStub =
- new IntegerConfigAttribute(MAX_RECEIVE_DELAY, "max receive delay",
- false, false, false, true, 0, false, 0);
- IntegerConfigAttribute maxReceiveDelayAttr = (IntegerConfigAttribute)
- configEntry.getConfigAttribute(maxReceiveDelayStub);
- if (maxReceiveDelayAttr == null)
- maxReceiveDelay = 0; // Attribute is not present : don't set a limit
- else
- {
- maxReceiveDelay = maxReceiveDelayAttr.activeIntValue();
- configAttributes.add(maxReceiveDelayAttr);
- }
-
- IntegerConfigAttribute maxSendQueueStub =
- new IntegerConfigAttribute(MAX_SEND_QUEUE, "max send queue",
- false, false, false, true, 0, false, 0);
- IntegerConfigAttribute maxSendQueueAttr =
- (IntegerConfigAttribute) configEntry.getConfigAttribute(maxSendQueueStub);
- if (maxSendQueueAttr == null)
- maxSendQueue = 0; // Attribute is not present : don't set a limit
- else
- {
- maxSendQueue = maxSendQueueAttr.activeIntValue();
- configAttributes.add(maxSendQueueAttr);
- }
-
- IntegerConfigAttribute maxSendDelayStub =
- new IntegerConfigAttribute(MAX_SEND_DELAY, "max send delay",
- false, false, false, true, 0, false, 0);
- IntegerConfigAttribute maxSendDelayAttr =
- (IntegerConfigAttribute) configEntry.getConfigAttribute(maxSendDelayStub);
- if (maxSendDelayAttr == null)
- maxSendDelay = 0; // Attribute is not present : don't set a limit
- else
- {
- maxSendDelay = maxSendDelayAttr.activeIntValue();
- configAttributes.add(maxSendDelayAttr);
- }
-
- Integer window;
- IntegerConfigAttribute windowStub =
- new IntegerConfigAttribute(WINDOW_SIZE, "window size",
- false, false, false, true, 0, false, 0);
- IntegerConfigAttribute windowAttr =
- (IntegerConfigAttribute) configEntry.getConfigAttribute(windowStub);
- if (windowAttr == null)
- window = 100; // Attribute is not present : use the default value
- else
- {
- window = windowAttr.activeIntValue();
- configAttributes.add(windowAttr);
- }
-
- IntegerWithUnitConfigAttribute heartbeatStub =
- new IntegerWithUnitConfigAttribute(HEARTBEAT_INTERVAL,
- "heartbeat interval",
- false, timeUnits, true, 0, false, 0);
- IntegerWithUnitConfigAttribute heartbeatAttr =
- (IntegerWithUnitConfigAttribute)
- configEntry.getConfigAttribute(heartbeatStub);
- if (heartbeatAttr == null)
- {
- // Attribute is not present : use the default value
- heartbeatInterval = 1000;
- }
- else
- {
- heartbeatInterval = heartbeatAttr.activeCalculatedValue();
- configAttributes.add(heartbeatAttr);
- }
-
- configDn = configEntry.getDN();
- DirectoryServer.registerConfigurableComponent(this);
-
monitor = new SynchronizationMonitor(this);
DirectoryServer.registerMonitorProvider(monitor);
+ /*
+ * ChangeNumberGenerator is used to create new unique ChangeNumbers
+ * for each operation done on the synchronization domain.
+ */
changeNumberGenerator = new ChangeNumberGenerator(serverId, state);
+
/*
* create the broker object used to publish and receive changes
*/
@@ -519,14 +352,9 @@
* should we stop the modifications ?
*/
}
- }
- /**
- * {@inheritDoc}
- */
- public DN getConfigurableComponentEntryDN()
- {
- return configDn;
+ // listen for changes on the configuration
+ configuration.addChangeListener(this);
}
/**
@@ -537,112 +365,6 @@
return configAttributes;
}
- /**
- * {@inheritDoc}
- */
- public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
- List<String> unacceptableReasons)
- {
- boolean acceptable = true;
- StringConfigAttribute changelog = null;
- try
- {
- changelog = (StringConfigAttribute)
- configEntry.getConfigAttribute(changelogStub);
- } catch (ConfigException e)
- {
- acceptable = false;
- unacceptableReasons.add("Need at least one changelog server.");
- }
- if (changelog == null)
- {
- acceptable = false;
- unacceptableReasons.add("Need at least one changelog server.");
- }
- return acceptable;
- }
-
- /**
- * {@inheritDoc}
- */
- public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
- boolean detailedResults)
- {
- StringConfigAttribute changelog = null;
- List<String> newChangelogServers;
- boolean newReceiveStatus;
-
- try
- {
- /*
- * check if changelog server list changed
- */
- changelog = (StringConfigAttribute)
- configEntry.getConfigAttribute(changelogStub);
-
- newChangelogServers = changelog.activeValues();
-
- boolean sameConf = true;
- for (String s :newChangelogServers)
- if (!changelogServers.contains(s))
- sameConf = false;
- for (String s : changelogServers)
- if (!newChangelogServers.contains(s))
- sameConf = false;
-
- if (!sameConf)
- {
- broker.stop();
- changelogServers = newChangelogServers;
- broker.start(changelogServers);
- }
-
- /*
- * check if reception should be disabled
- */
- newReceiveStatus = ((BooleanConfigAttribute)
- configEntry.getConfigAttribute(receiveStatusStub)).activeValue();
- if (newReceiveStatus != receiveStatus)
- {
- /*
- * was disabled and moved to enabled
- */
- if (newReceiveStatus)
- {
- broker.restartReceive();
- for (int i=0; i<listenerThreadNumber; i++)
- {
- ListenerThread myThread = new ListenerThread(this);
- myThread.start();
- synchroThreads.add(myThread);
- }
- }
- else
- {
- /* was enabled and moved to disabled */
- broker.suspendReceive();
- // FIXME Need a way to stop these threads.
- // Setting the shutdown flag does not stop them until they have
- // consumed and discarded one more message each.
-// for (ListenerThread thread : synchroThreads)
-// {
-// thread.shutdown();
-// }
- synchroThreads.clear();
- }
- receiveStatus = newReceiveStatus;
- }
-
- } catch (Exception e)
- {
- /* this should never happen because the parameters have been
- * validated by hasAcceptableConfiguration
- */
- return new ConfigChangeResult(ResultCode.OPERATIONS_ERROR, false);
- }
-
- return new ConfigChangeResult(ResultCode.SUCCESS, false);
- }
/**
* Returns the base DN of this SynchronizationDomain.
@@ -1041,9 +763,7 @@
public void receiveAck(AckMessage ack)
{
UpdateMessage update;
- ChangeNumber changeNumber;
-
- changeNumber = ack.getChangeNumber();
+ ChangeNumber changeNumber = ack.getChangeNumber();
synchronized (pendingChanges)
{
@@ -1933,51 +1653,6 @@
}
/**
- * Check if a ConfigEntry is valid.
- * @param configEntry The config entry that needs to be checked.
- * @param unacceptableReason A description of the reason why the config entry
- * is not acceptable (if return is false).
- * @return a boolean indicating if the configEntry is valid.
- */
- public static boolean checkConfigEntry(ConfigEntry configEntry,
- StringBuilder unacceptableReason)
- {
- try
- {
- StringConfigAttribute changelogServer =
- (StringConfigAttribute) configEntry.getConfigAttribute(changelogStub);
-
- if (changelogServer == null)
- {
- unacceptableReason.append(
- MessageHandler.getMessage(MSGID_NEED_CHANGELOG_SERVER,
- configEntry.getDN().toString()) );
- return false;
- }
-
- /*
- * read the server Id information
- * this is a single valued integer, its value must fit on a short integer
- */
- IntegerConfigAttribute serverIdAttr =
- (IntegerConfigAttribute) configEntry.getConfigAttribute(serverIdStub);
- if (serverIdAttr == null)
- {
- unacceptableReason.append(
- MessageHandler.getMessage(MSGID_NEED_SERVER_ID,
- configEntry.getDN().toString()) );
- return false;
- }
- }
- catch (ConfigException e)
- {
- unacceptableReason.append(e.getMessage());
- return false;
- }
- return true;
- }
-
- /**
* Get the maximum receive window size.
*
* @return The maximum receive window size.
@@ -2026,7 +1701,6 @@
return broker.getNumLostConnections();
}
-
/**
* Check if the domain solve conflicts.
*
@@ -3109,4 +2783,60 @@
op.setResultCode(ResultCode.SUCCESS);
synchronize(op);
}
+
+ /**
+ * Check if the provided configuration is acceptable for add.
+ *
+ * @param configuration The configuration to check.
+ * @param unacceptableReasons When the configuration is not acceptable, this
+ * table is use to return the reasons why this
+ * configuration is not acceptbale.
+ *
+ * @return true if the configuration is acceptable, false other wise.
+ */
+ public static boolean isConfigurationAcceptable(
+ MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+ {
+ // Check that there is not already a domain with the same DN
+ // TODO : Check that the server id is a short
+ DN dn = configuration.getSynchronizationDN();
+ if (MultimasterSynchronization.findDomain(dn,null) != null)
+ {
+ String message = getMessage(MSGID_SYNC_INVALID_DN, dn.toString());
+ unacceptableReasons.add(message);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ConfigChangeResult applyConfigurationChange(
+ MultimasterDomainCfg configuration)
+ {
+ // server id and base dn are readonly.
+ // The other parameters needs to be renegociated with the Changelog Server.
+ // so that requires restarting the session with the Changelog Server.
+ changelogServers = configuration.getChangelogServer();
+ maxReceiveQueue = configuration.getMaxReceiveQueue();
+ maxReceiveDelay = (int) configuration.getMaxReceiveDelay();
+ maxSendQueue = configuration.getMaxSendQueue();
+ maxSendDelay = (int) configuration.getMaxSendDelay();
+ window = configuration.getWindowSize();
+ heartbeatInterval = configuration.getHeartbeatInterval();
+ broker.changeConfig(changelogServers, maxReceiveQueue, maxReceiveDelay,
+ maxSendQueue, maxSendDelay, window, heartbeatInterval);
+
+ return new ConfigChangeResult(ResultCode.SUCCESS, false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean isConfigurationChangeAcceptable(
+ MultimasterDomainCfg configuration, List<String> unacceptableReasons)
+ {
+ return true;
+ }
}
diff --git a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
index 44c33ce..5d97b38 100644
--- a/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
+++ b/opends/src/server/org/opends/server/tasks/AddSchemaFileTask.java
@@ -35,6 +35,7 @@
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
import org.opends.server.api.ClientConnection;
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.backends.task.Task;
@@ -298,7 +299,7 @@
if (! mods.isEmpty())
{
- for (SynchronizationProvider provider :
+ for (SynchronizationProvider<SynchronizationProviderCfg> provider :
DirectoryServer.getSynchronizationProviders())
{
try
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
index a6d43a0..521afec 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/InitOnLineTest.java
@@ -26,11 +26,7 @@
*/
package org.opends.server.synchronization;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_COMPLETION_TIME;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_DONE;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_INITIALIZE_LEFT;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_LOG_MESSAGES;
-import static org.opends.server.config.ConfigConstants.ATTR_TASK_STATE;
+import static org.opends.server.config.ConfigConstants.*;
import static org.opends.server.loggers.Error.logError;
import static org.opends.server.loggers.debug.DebugLogger.debugEnabled;
import static org.opends.server.loggers.debug.DebugLogger.debugInfo;
@@ -40,49 +36,35 @@
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.ServerSocket;
-import java.net.Socket;
import java.util.ArrayList;
-import java.util.LinkedHashSet;
-import java.util.List;
import java.util.UUID;
import org.opends.server.TestCaseUtils;
import org.opends.server.backends.task.TaskState;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DirectoryServer;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.messages.TaskMessages;
import org.opends.server.protocols.internal.InternalClientConnection;
import org.opends.server.protocols.internal.InternalSearchOperation;
import org.opends.server.schema.DirectoryStringSyntax;
import org.opends.server.synchronization.changelog.Changelog;
+import org.opends.server.synchronization.changelog.ChangelogFakeConfiguration;
import org.opends.server.synchronization.common.LogMessages;
-import org.opends.server.synchronization.common.ServerState;
import org.opends.server.synchronization.plugin.ChangelogBroker;
import org.opends.server.synchronization.plugin.SynchronizationDomain;
-import org.opends.server.synchronization.protocol.ChangelogStartMessage;
import org.opends.server.synchronization.protocol.DoneMessage;
import org.opends.server.synchronization.protocol.EntryMessage;
import org.opends.server.synchronization.protocol.ErrorMessage;
import org.opends.server.synchronization.protocol.InitializeRequestMessage;
import org.opends.server.synchronization.protocol.InitializeTargetMessage;
import org.opends.server.synchronization.protocol.RoutableMessage;
-import org.opends.server.synchronization.protocol.ServerStartMessage;
import org.opends.server.synchronization.protocol.SocketSession;
import org.opends.server.synchronization.protocol.SynchronizationMessage;
-import org.opends.server.types.Attribute;
import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
import org.opends.server.types.ErrorLogCategory;
import org.opends.server.types.ErrorLogSeverity;
-import org.opends.server.types.Modification;
-import org.opends.server.types.ModificationType;
import org.opends.server.types.ResultCode;
import org.opends.server.types.SearchFilter;
import org.opends.server.types.SearchScope;
@@ -193,14 +175,6 @@
// Synchro multi-master
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Synchro suffix
synchroServerEntry = null;
@@ -762,26 +736,10 @@
{
int chPort = getChangelogPort(changelogId);
- // Create a changelog server
- String changelogLdif = "dn: cn=Changelog Server\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
- + "cn: Changelog Server\n"
- + "ds-cfg-changelog-port: " + chPort + "\n"
- + "ds-cfg-changelog-server-id: " + changelogId + "\n"
-// + "ds-cfg-heartbeat-interval: 0 ms\n"
- + "ds-cfg-window-size: 100" + "\n";
-
- if (changelogId==changelog2ID)
- {
- changelogLdif += new String(
- "ds-cfg-changelog-server: localhost:"
- + getChangelogPort(changelog1ID)+"\n");
- }
- Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
- ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
- Changelog changelog = new Changelog(changelogConfig);
-
+ ChangelogFakeConfiguration conf =
+ new ChangelogFakeConfiguration(chPort, null, 0, changelogId, 0, 100,
+ null);
+ Changelog changelog = new Changelog(conf);
Thread.sleep(1000);
return changelog;
@@ -806,7 +764,8 @@
{
// suffix synchronized
String synchroServerStringDN = synchroPluginStringDN;
- String synchroServerLdif = "dn: cn=example," + synchroServerStringDN + "\n"
+ String synchroServerLdif =
+ "dn: cn=example, cn=domains" + synchroServerStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
+ "cn: example\n"
@@ -1483,6 +1442,6 @@
// fromthe changelog server.
server2 = null;
}
- super.cleanEntries();
+ super.cleanRealEntries();
}
}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
index 1478b9c..7cd2c2b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ProtocolWindowTest.java
@@ -273,14 +273,6 @@
// Multimaster Synchro plugin
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Change log
String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -294,7 +286,8 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// suffix synchronized
- String synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+ String synchroServerStringDN =
+ "cn=example, cn=domains, " + synchroPluginStringDN;
String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
index 95917ec..b4bf994 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/ReSyncTest.java
@@ -89,14 +89,6 @@
// Multimaster Synchro plugin
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Change log
String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -109,7 +101,8 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// suffix synchronized
- String synchroServerLdif = "dn: cn=example, " + synchroPluginStringDN + "\n"
+ String synchroServerLdif =
+ "dn: cn=example, cn=domains, " + synchroPluginStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
+ "cn: example\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
index 561cf3e..142bcf1 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SchemaSynchronizationTest.java
@@ -38,6 +38,7 @@
import java.util.List;
import org.opends.server.TestCaseUtils;
+import org.opends.server.admin.std.server.SynchronizationProviderCfg;
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
@@ -98,14 +99,6 @@
// Multimaster Synchro plugin
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Change log
String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -118,7 +111,8 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// suffix synchronized
- String synchroServerLdif = "dn: cn=example, " + synchroPluginStringDN + "\n"
+ String synchroServerLdif =
+ "dn: cn=example, cn=domains, " + synchroPluginStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
+ "cn: example\n"
@@ -276,7 +270,7 @@
Modification mod = new Modification(ModificationType.ADD, attr);
mods.add(mod);
- for (SynchronizationProvider provider :
+ for (SynchronizationProvider<SynchronizationProviderCfg> provider :
DirectoryServer.getSynchronizationProviders())
{
provider.processSchemaChange(mods);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
index 44b8188..9f91a5a 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/StressTest.java
@@ -231,14 +231,6 @@
// Multimaster Synchro plugin
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Change log
changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -250,7 +242,7 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// suffix synchronized
- synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+ synchroServerStringDN = "cn=example, cn=domains, " + synchroPluginStringDN;
String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
index 7374e38..da0c40b 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/SynchronizationTestCase.java
@@ -28,7 +28,6 @@
import static org.opends.server.loggers.Error.logError;
import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.net.SocketException;
@@ -41,8 +40,6 @@
import org.opends.server.DirectoryServerTestCase;
import org.opends.server.TestCaseUtils;
import org.opends.server.schema.IntegerSyntax;
-import org.opends.server.config.ConfigEntry;
-import org.opends.server.config.ConfigException;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.protocols.internal.InternalClientConnection;
@@ -50,7 +47,6 @@
import org.opends.server.protocols.ldap.LDAPFilter;
import org.opends.server.synchronization.common.ServerState;
import org.opends.server.synchronization.plugin.ChangelogBroker;
-import org.opends.server.synchronization.plugin.MultimasterSynchronization;
import org.opends.server.synchronization.plugin.PersistentServerState;
import org.opends.server.types.DN;
import org.opends.server.types.Entry;
@@ -84,8 +80,7 @@
* Created entries that need to be deleted for cleanup
*/
protected LinkedList<DN> entryList = new LinkedList<DN>();
-
- protected Entry synchroPluginEntry;
+ protected LinkedList<DN> configEntryList = new LinkedList<DN>();
protected Entry synchroServerEntry;
@@ -97,14 +92,10 @@
protected boolean schemaCheck;
/**
- *
- */
- MultimasterSynchronization mms = null;
-
- /**
* The synchronization plugin entry
*/
- protected String synchroPluginStringDN;
+ protected String synchroPluginStringDN =
+ "cn=Multimaster Synchronization, cn=Synchronization Providers,cn=config";
/**
* Set up the environment for performing the tests in this suite.
@@ -228,20 +219,19 @@
}
}
catch (Exception e)
- {
- }
+ { }
}
return broker;
}
/**
- * suppress all the entries created by the tests in this class
+ * suppress all the config entries created by the tests in this class
*/
- protected void cleanEntries()
+ protected void cleanConfigEntries()
{
logError(ErrorLogCategory.SYNCHRONIZATION,
ErrorLogSeverity.NOTICE,
- "SynchronizationTestCase/Cleaning entries" , 1);
+ "SynchronizationTestCase/Cleaning config entries" , 1);
DeleteOperation op;
// Delete entries
@@ -249,6 +239,38 @@
{
while (true)
{
+ DN dn = configEntryList.removeLast();
+ logError(ErrorLogCategory.SYNCHRONIZATION,
+ ErrorLogSeverity.NOTICE,
+ "cleaning config entry " + dn, 1);
+
+ op = new DeleteOperation(connection, InternalClientConnection
+ .nextOperationID(), InternalClientConnection.nextMessageID(), null,
+ dn);
+
+ op.run();
+ }
+ }
+ catch (NoSuchElementException e) {
+ // done
+ }
+ }
+
+ /**
+ * suppress all the real entries created by the tests in this class
+ */
+ protected void cleanRealEntries()
+ {
+ logError(ErrorLogCategory.SYNCHRONIZATION,
+ ErrorLogSeverity.NOTICE,
+ "SynchronizationTestCase/Cleaning entries" , 1);
+
+ DeleteOperation op;
+ // Delete entries
+ try
+ {
+ while (true)
+ {
DN dn = entryList.removeLast();
logError(ErrorLogCategory.SYNCHRONIZATION,
ErrorLogSeverity.NOTICE,
@@ -277,20 +299,8 @@
{
DirectoryServer.setCheckSchema(schemaCheck);
- // WORKAROUND FOR BUG #639 - BEGIN -
- if (mms != null)
- {
- logError(ErrorLogCategory.SYNCHRONIZATION,
- ErrorLogSeverity.NOTICE,
- "SynchronizationTestCase/FinalizeSynchronization Provider" , 1);
-
- DirectoryServer.deregisterSynchronizationProvider(mms);
- mms.finalizeSynchronizationProvider();
- mms = null;
- }
- // WORKAROUND FOR BUG #639 - END -
-
- cleanEntries();
+ cleanConfigEntries();
+ cleanRealEntries();
}
/**
@@ -298,48 +308,45 @@
*/
protected void configureSynchronization() throws Exception
{
- //
// Add the Multimaster synchronization plugin
+ String synchroPluginLdif = "dn: " + synchroPluginStringDN + "\n"
+ + "objectClass: top\n"
+ + "objectClass: ds-cfg-synchronization-provider\n"
+ + "objectClass: ds-cfg-multimaster-synchronization-provider\n"
+ + "ds-cfg-synchronization-provider-enabled: true\n"
+ + "ds-cfg-synchronization-provider-class: " +
+ "org.opends.server.synchronization.plugin.MultimasterSynchronization\n";
+ Entry synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
DirectoryServer.getConfigHandler().addEntry(synchroPluginEntry, null);
- entryList.add(synchroPluginEntry.getDN());
+ configEntryList.add(synchroPluginEntry.getDN());
assertNotNull(DirectoryServer.getConfigEntry(DN
.decode(synchroPluginStringDN)),
"Unable to add the Multimaster synchronization plugin");
-
- // WORKAROUND FOR BUG #639 - BEGIN -
- DN dn = DN.decode(synchroPluginStringDN);
- ConfigEntry mmsConfigEntry = DirectoryServer.getConfigEntry(dn);
- mms = new MultimasterSynchronization();
- try
- {
- mms.initializeSynchronizationProvider(mmsConfigEntry);
- }
- catch (ConfigException e)
- {
- assertTrue(false,
- "Unable to initialize the Multimaster synchronization plugin");
- }
- DirectoryServer.registerSynchronizationProvider(mms);
- // WORKAROUND FOR BUG #639 - END -
-
- //
- // Add the changelog server
- if (changeLogEntry!=null)
- {
- DirectoryServer.getConfigHandler().addEntry(changeLogEntry, null);
- assertNotNull(DirectoryServer.getConfigEntry(changeLogEntry.getDN()),
- "Unable to add the changeLog server");
- entryList.add(changeLogEntry.getDN());
- }
- if (synchroServerEntry!=null)
- {
- // We also have a replicated suffix (synchronization domain)
- DirectoryServer.getConfigHandler().addEntry(synchroServerEntry, null);
- assertNotNull(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()),
- "Unable to add the synchronized suffix");
- entryList.add(synchroServerEntry.getDN());
- }
+ // domains container entry.
+ String domainsLdif = "dn: "
+ + "cn=domains," + synchroPluginStringDN + "\n"
+ + "objectClass: top\n"
+ + "objectClass: ds-cfg-branch\n";
+ Entry domainsEntry = TestCaseUtils.entryFromLdifString(domainsLdif);
+ DirectoryServer.getConfigHandler().addEntry(domainsEntry, null);
+ configEntryList.add(domainsEntry.getDN());
+ assertNotNull(DirectoryServer.getConfigEntry(
+ DN.decode(synchroPluginStringDN)),
+ "Unable to add the Multimaster synchronization plugin");
+
+
+ // Add the changelog server
+ DirectoryServer.getConfigHandler().addEntry(changeLogEntry, null);
+ assertNotNull(DirectoryServer.getConfigEntry(changeLogEntry.getDN()),
+ "Unable to add the changeLog server");
+ configEntryList.add(changeLogEntry.getDN());
+
+ // We also have a replicated suffix (synchronization domain)
+ DirectoryServer.getConfigHandler().addEntry(synchroServerEntry, null);
+ assertNotNull(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()),
+ "Unable to add the synchronized server");
+ configEntryList.add(synchroServerEntry.getDN());
}
/**
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
index 7e7411e..95cb27d 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/UpdateOperationTest.java
@@ -133,14 +133,6 @@
// Multimaster Synchro plugin
synchroPluginStringDN = "cn=Multimaster Synchronization, "
+ synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
// Change log
String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
@@ -152,7 +144,8 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// suffix synchronized
- String synchroServerStringDN = "cn=example, " + synchroPluginStringDN;
+ String synchroServerStringDN =
+ "cn=example, cn=domains, " + synchroPluginStringDN;
String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
@@ -318,7 +311,7 @@
ErrorLogSeverity.NOTICE,
"Starting synchronization test : lostHeartbeatFailover" , 1);
- cleanEntries();
+ cleanRealEntries();
final DN baseDn = DN.decode("ou=People,dc=example,dc=com");
@@ -831,7 +824,7 @@
final DN baseDn = DN.decode("ou=People,dc=example,dc=com");
- cleanEntries();
+ cleanRealEntries();
ChangelogBroker broker =
openChangelogSession(baseDn, (short) 27, 100, 8989, 1000, true);
@@ -886,7 +879,7 @@
"The received synchronization message is not a MODIFY msg");
ModifyMsg modMsg = (ModifyMsg) msg;
- Operation receivedOp = modMsg.createOperation(connection);
+ modMsg.createOperation(connection);
assertTrue(DN.decode(modMsg.getDn()).compareTo(personEntry.getDN()) == 0,
"The received MODIFY synchronization message is not for the excepted DN");
@@ -908,7 +901,7 @@
assertTrue(msg instanceof ModifyDNMsg,
"The received synchronization message is not a MODIFY DN msg");
ModifyDNMsg moddnMsg = (ModifyDNMsg) msg;
- receivedOp = moddnMsg.createOperation(connection);
+ moddnMsg.createOperation(connection);
assertTrue(DN.decode(moddnMsg.getDn()).compareTo(personEntry.getDN()) == 0,
"The received MODIFY_DN message is not for the excepted DN");
@@ -927,7 +920,7 @@
assertTrue(msg instanceof DeleteMsg,
"The received synchronization message is not a MODIFY DN msg");
DeleteMsg delMsg = (DeleteMsg) msg;
- receivedOp = delMsg.createOperation(connection);
+ delMsg.createOperation(connection);
assertTrue(DN.decode(delMsg.getDn()).compareTo(DN
.decode("uid= new person,ou=People,dc=example,dc=com")) == 0,
"The received DELETE message is not for the excepted DN");
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java
new file mode 100644
index 0000000..1ff7a5e
--- /dev/null
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogFakeConfiguration.java
@@ -0,0 +1,190 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ * Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ * Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+package org.opends.server.synchronization.changelog;
+
+import java.util.SortedSet;
+
+import org.opends.server.admin.ManagedObjectDefinition;
+import org.opends.server.admin.PropertyProvider;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.std.client.ChangelogServerCfgClient;
+import org.opends.server.admin.std.server.ChangelogServerCfg;
+import org.opends.server.types.DN;
+
+/**
+ * This Class implements an object that can be used to instantiate
+ * The Changelog class for tests purpose.
+ */
+public class ChangelogFakeConfiguration implements ChangelogServerCfg
+{
+ int port;
+ String dirName;
+ int purgeDelay;
+ int serverId;
+ int queueSize;
+ int windowSize;
+ private SortedSet<String> servers;
+
+ public ChangelogFakeConfiguration(
+ int port, String dirName, int purgeDelay, int serverId,
+ int queueSize, int windowSize, SortedSet<String> servers)
+ {
+ this.port = port;
+ this.dirName = dirName;
+
+ if (purgeDelay == 0)
+ {
+ this.purgeDelay = 24*60*60;
+ }
+ else
+ {
+ this.purgeDelay = purgeDelay;
+ }
+
+ this.serverId = serverId;
+
+ if (queueSize == 0)
+ {
+ this.queueSize = 10000;
+ }
+ else
+ {
+ this.queueSize = queueSize;
+ }
+
+ if (windowSize == 0)
+ {
+ this.windowSize = 100;
+ }
+ else
+ {
+ this.windowSize = windowSize;
+ }
+
+ this.servers = servers;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addChangeListener(
+ ConfigurationChangeListener<ChangelogServerCfg> listener)
+ {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ManagedObjectDefinition<? extends ChangelogServerCfgClient,
+ ? extends ChangelogServerCfg> definition()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String getChangelogDbDirectory()
+ {
+ return dirName;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getChangelogPort()
+ {
+ return port;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public long getChangelogPurgeDelay()
+ {
+ return purgeDelay;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public SortedSet<String> getChangelogServer()
+ {
+ return servers;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getChangelogServerId()
+ {
+ return serverId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getQueueSize()
+ {
+ return queueSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getWindowSize()
+ {
+ return windowSize;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeChangeListener(
+ ConfigurationChangeListener<ChangelogServerCfg> listener)
+ {
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public DN dn()
+ {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public PropertyProvider properties()
+ {
+ return null;
+ }
+
+}
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
index dcf23e0..27e5382 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/ChangelogTest.java
@@ -34,9 +34,10 @@
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
import org.opends.server.TestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.core.ModifyDNOperation;
import org.opends.server.synchronization.SynchronizationTestCase;
import org.opends.server.synchronization.common.ChangeNumber;
@@ -98,17 +99,9 @@
changelogPort = socket.getLocalPort();
socket.close();
- String changelogLdif =
- "dn: cn=Changelog Server\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
- + "cn: Changelog Server\n"
- + "ds-cfg-changelog-port: "+ changelogPort + "\n"
- + "ds-cfg-changelog-server-id: 1\n"
- + "ds-cfg-window-size: 100";
- Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
- ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
- changelog = new Changelog(changelogConfig);
+ ChangelogFakeConfiguration conf =
+ new ChangelogFakeConfiguration(changelogPort, null, 0, 1, 0, 0, null);
+ changelog = new Changelog(conf);
}
/**
@@ -602,19 +595,13 @@
// for itest=0, create the 2 connected changelog servers
// for itest=1, create the 1rst changelog server, the second
// one will be created later
-
- String changelogLdif = "dn: cn=Changelog Server\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
- + "cn: Changelog Server\n"
- + "ds-cfg-changelog-port: " + changelogPorts[i] + "\n"
- + "ds-cfg-changelog-server: localhost:" + ((i == 0) ? changelogPorts[1] : changelogPorts[0]) + "\n"
- + "ds-cfg-changelog-server-id: " + changelogIds[0] + "\n"
- + "ds-cfg-window-size: 100" + "\n"
- + "ds-cfg-changelog-db-directory: changelogDb"+i;
- Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
- ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
- changelogs[i] = new Changelog(changelogConfig);
+ SortedSet<String> servers = new TreeSet<String>();
+ servers.add(
+ "localhost:" + ((i == 0) ? changelogPorts[1] : changelogPorts[0]));
+ ChangelogFakeConfiguration conf =
+ new ChangelogFakeConfiguration(changelogPorts[i], "changelogDb"+i, 0,
+ changelogIds[i], 0, 100, servers);
+ changelog = new Changelog(conf);
}
ChangelogBroker broker1 = null;
@@ -681,16 +668,13 @@
if (itest > 0)
{
socket.close();
- String changelogLdif = "dn: cn=Changelog Server\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
- + "cn: Changelog Server\n"
- + "ds-cfg-changelog-port: " + changelogPorts[1] + "\n"
- + "ds-cfg-changelog-server: localhost:" + changelogPorts[0] + "\n"
- + "ds-cfg-changelog-server-id: " + changelogIds[1] + "\n";
- Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
- ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
- changelogs[1] = new Changelog(changelogConfig);
+
+ SortedSet<String> servers = new TreeSet<String>();
+ servers.add("localhost:"+changelogPorts[0]);
+ ChangelogFakeConfiguration conf =
+ new ChangelogFakeConfiguration(changelogPorts[1], null, 0,
+ changelogIds[1], 0, 0, null);
+ changelogs[1] = new Changelog(conf);
// Connect broker 2 to changelog2
broker2 = openChangelogSession(DN.decode("dc=example,dc=com"),
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
index 5c13f9a..00174da 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/changelog/dbHandlerTest.java
@@ -30,13 +30,11 @@
import java.net.ServerSocket;
import org.opends.server.TestCaseUtils;
-import org.opends.server.config.ConfigEntry;
import org.opends.server.synchronization.SynchronizationTestCase;
import org.opends.server.synchronization.common.ChangeNumber;
import org.opends.server.synchronization.common.ChangeNumberGenerator;
import org.opends.server.synchronization.protocol.DeleteMsg;
import org.opends.server.types.DN;
-import org.opends.server.types.Entry;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
@@ -56,17 +54,10 @@
socket.close();
// configure a Changelog server.
- String changelogLdif =
- "dn: cn=Changelog Server\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-changelog-server-config\n"
- + "cn: Changelog Server\n"
- + "ds-cfg-changelog-port: "+ changelogPort + "\n"
- + "ds-cfg-changelog-server-id: 2\n"
- + "ds-cfg-changelog-purge-delay: 0 d";
- Entry tmp = TestCaseUtils.entryFromLdifString(changelogLdif);
- ConfigEntry changelogConfig = new ConfigEntry(tmp, null);
- Changelog changelog = new Changelog(changelogConfig);
+ ChangelogFakeConfiguration conf =
+ new ChangelogFakeConfiguration(changelogPort, null, 0,
+ 2, 0, 100, null);
+ Changelog changelog = new Changelog(conf);
// create or clean a directory for the dbHandler
String buildRoot = System.getProperty(TestCaseUtils.PROPERTY_BUILD_ROOT);
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
index 08ad95f..95b54a8 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/HistoricalTest.java
@@ -67,22 +67,6 @@
// Create an internal connection.
connection = InternalClientConnection.getRootConnection();
- // Top level synchronization provider.
- String synchroStringDN = "cn=Synchronization Providers,cn=config";
-
- // Multimaster synchronization plugin.
- synchroPluginStringDN = "cn=Multimaster Synchronization, "
- + synchroStringDN;
- String synchroPluginLdif = "dn: "
- + synchroPluginStringDN
- + "\n"
- + "objectClass: top\n"
- + "objectClass: ds-cfg-synchronization-provider\n"
- + "ds-cfg-synchronization-provider-enabled: true\n"
- + "ds-cfg-synchronization-provider-class: " +
- "org.opends.server.synchronization.MultimasterSynchronization\n";
- synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
-
// The synchronization server.
String changeLogStringDN = "cn=Changelog Server, " + synchroPluginStringDN;
String changeLogLdif = "dn: " + changeLogStringDN + "\n"
@@ -93,7 +77,7 @@
changeLogEntry = TestCaseUtils.entryFromLdifString(changeLogLdif);
// The suffix to be synchronized.
- String synchroServerStringDN = "o=test, " + synchroPluginStringDN;
+ String synchroServerStringDN = "o=test, cn=domains, " + synchroPluginStringDN;
String synchroServerLdif = "dn: " + synchroServerStringDN + "\n"
+ "objectClass: top\n"
+ "objectClass: ds-cfg-synchronization-provider-config\n"
diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
index 9b8f009..b7762e7 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/synchronization/plugin/ModifyConflictTest.java
@@ -38,7 +38,6 @@
import static org.opends.server.synchronization.protocol.OperationContext.*;
-import org.opends.server.TestAccessLogger;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
--
Gitblit v1.10.0