opendj-sdk/opends/resource/admin/abbreviations.xsl
@@ -53,6 +53,7 @@ or $value = 'sha384' or $value = 'sha512' or $value = 'tls' or $value = 'des' or $value = 'aes' or $value = 'rc4' or $value = 'db' or $value = 'snmp' or $value = 'qos' or $value = 'ecl' "/> </xsl:template> </xsl:stylesheet> opendj-sdk/opends/resource/schema/02-config.ldif
@@ -3026,8 +3026,7 @@ ds-cfg-fractional-exclude $ ds-cfg-fractional-include $ ds-cfg-solve-conflicts $ ds-cfg-changetime-heartbeat-interval $ ds-cfg-ecl-include ) ds-cfg-changetime-heartbeat-interval ) X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.58 NAME 'ds-cfg-length-based-password-validator' @@ -4144,4 +4143,12 @@ STRUCTURAL MAY ( ds-cfg-num-worker-threads ) X-ORIGIN 'OpenDS Directory Server' ) objectClasses: ( 1.3.6.1.4.1.26027.1.2.234 NAME 'ds-cfg-external-changelog-domain' SUP top STRUCTURAL MUST ( cn $ ds-cfg-enabled ) MAY ( ds-cfg-ecl-include ) X-ORIGIN 'OpenDS Directory Server' ) opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ExternalChangelogDomainConfiguration.xml
New file @@ -0,0 +1,80 @@ <?xml version="1.0" encoding="utf-8"?> <!-- ! 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 ! ! ! Copyright 2009 Sun Microsystems, Inc. ! --> <adm:managed-object name="external-changelog-domain" plural-name="external-changelog-domains" package="org.opends.server.admin.std" xmlns:adm="http://www.opends.org/admin" xmlns:ldap="http://www.opends.org/admin-ldap" xmlns:cli="http://www.opends.org/admin-cli"> <adm:synopsis> The <adm:user-friendly-name /> provides configuration of the external changelog for the replication domain. </adm:synopsis> <adm:profile name="ldap"> <ldap:object-class> <ldap:name>ds-cfg-external-changelog-domain</ldap:name> <ldap:superior>top</ldap:superior> </ldap:object-class> </adm:profile> <adm:property name="enabled" mandatory="true"> <adm:synopsis> Indicates whether the <adm:user-friendly-name /> is enabled. </adm:synopsis> <adm:syntax> <adm:boolean /> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-enabled</ldap:name> </ldap:attribute> </adm:profile> </adm:property> <adm:property name="ecl-include" multi-valued="true" mandatory="false"> <adm:synopsis> Allows to include some target entry attributes in the external changelog. </adm:synopsis> <adm:description> Specifies an attribute that will be included in every External Change Log entry related to this replication domain. </adm:description> <adm:default-behavior> <adm:undefined/> </adm:default-behavior> <adm:syntax> <adm:attribute-type /> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-ecl-include</ldap:name> </ldap:attribute> </adm:profile> </adm:property> </adm:managed-object> opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ReplicationDomainConfiguration.xml
@@ -43,6 +43,14 @@ <ldap:superior>top</ldap:superior> </ldap:object-class> </adm:profile> <adm:relation name="external-changelog-domain"> <adm:one-to-one /> <adm:profile name="ldap"> <ldap:rdn-sequence> cn=External ChangeLog </ldap:rdn-sequence> </adm:profile> </adm:relation> <adm:property name="replication-server" multi-valued="true" mandatory="true"> <adm:synopsis> @@ -487,47 +495,4 @@ </ldap:attribute> </adm:profile> </adm:property> <adm:property name="ecl-include" multi-valued="true" mandatory="false"> <adm:synopsis> Allows to include some target entry attributes in the ECL. </adm:synopsis> <adm:description> Specifies an attribute that will be included in every External Change Log entry related to this replication domain. </adm:description> <adm:default-behavior> <adm:undefined/> </adm:default-behavior> <adm:syntax> <adm:string> <adm:pattern> <!-- This java regex is mostly derived from keystring BNF definition that can be found in RFC 2252, section "4.1. Common Encoding Aspects". This can be read as: (oid|\*):oid(,oid)*+ --> <adm:regex>^((([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+)|\\*):(([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+)(,(([a-zA-Z]([a-zA-Z]|[0-9]|-|;)*+)|(0|([1-9]([0-9])*+))(\\.(0|([1-9]([0-9])*+)))*+))*+$</adm:regex> <adm:usage>Syntax: className:attributeName[,attributeName] or *:attributeName[,attributeName]. Note that any class (className) or attribute (attributeName) definition can be replaced with its OID definition. Examples: inetOrgPerson:photo,jpegPhoto : 'photo' and 'jpegPhoto' attributes of any entry of type 'inetOrgPerson' class. This can also be 2.16.840.1.113730.3.2.2:0.9.2342.19200300.100.1.7,0.9.2342.19200300.100.1.60 or a mix. *:jpegPhoto : the 'jpegPhoto' attribute of any entry that has this attribute. This can also be *:0.9.2342.19200300.100.1.60 </adm:usage> <adm:synopsis> Defines attribute(s) of one particular class or of all possible classes, to exclude from the replication. </adm:synopsis> </adm:pattern> </adm:string> </adm:syntax> <adm:profile name="ldap"> <ldap:attribute> <ldap:name>ds-cfg-ecl-include</ldap:name> </ldap:attribute> </adm:profile> </adm:property> </adm:managed-object> opendj-sdk/opends/src/server/org/opends/server/replication/common/FirstChangeNumberVirtualAttributeProvider.java
@@ -134,7 +134,7 @@ { // Set a list of excluded domains (also exclude 'cn=changelog' itself) ArrayList<String> excludedDomains = MultimasterReplication.getPrivateDomains(); MultimasterReplication.getECLDisabledDomains(); if (!excludedDomains.contains( ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT)) excludedDomains.add(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT); opendj-sdk/opends/src/server/org/opends/server/replication/common/LastChangeNumberVirtualAttributeProvider.java
@@ -134,7 +134,7 @@ { // Set a list of excluded domains (also exclude 'cn=changelog' itself) ArrayList<String> excludedDomains = MultimasterReplication.getPrivateDomains(); MultimasterReplication.getECLDisabledDomains(); if (!excludedDomains.contains( ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT)) excludedDomains.add(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT); opendj-sdk/opends/src/server/org/opends/server/replication/common/LastCookieVirtualProvider.java
@@ -137,7 +137,7 @@ { // Set a list of excluded domains (also exclude 'cn=changelog' itself) ArrayList<String> excludedDomains = MultimasterReplication.getPrivateDomains(); MultimasterReplication.getECLDisabledDomains(); if (!excludedDomains.contains( ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT)) excludedDomains.add(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT); opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ExternalChangelogDomain.java
New file @@ -0,0 +1,178 @@ /* * 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 * * * Copyright 2006-2009 Sun Microsystems, Inc. */ package org.opends.server.replication.plugin; import java.util.List; import org.opends.messages.Message; 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.std.server.ExternalChangelogDomainCfg; import org.opends.server.types.AttributeType; import org.opends.server.types.ConfigChangeResult; import org.opends.server.types.DN; import org.opends.server.types.ResultCode; /** * This class specifies the external changelog feature for a replication * domain. */ public class ExternalChangelogDomain implements ConfigurationAddListener<ExternalChangelogDomainCfg>, ConfigurationDeleteListener<ExternalChangelogDomainCfg>, ConfigurationChangeListener<ExternalChangelogDomainCfg> { LDAPReplicationDomain domain; boolean isEnabled; /** * Constructor from a provided LDAPReplicationDomain. * @param domain The provided domain. * @param configuration The external changelog configuration. */ public ExternalChangelogDomain(LDAPReplicationDomain domain, ExternalChangelogDomainCfg configuration) { this.domain =domain; this.isEnabled = configuration.isEnabled(); configuration.addChangeListener(this); if (configuration.getECLInclude() != null) for (AttributeType eclInclude : configuration.getECLInclude()) domain.addEclInclude(eclInclude.getNormalizedPrimaryName()); } /** * {@inheritDoc} */ public ConfigChangeResult applyConfigurationAdd( ExternalChangelogDomainCfg configuration) { try { if (domain==null) { DN rdns = DN.decode( configuration.dn().getParent().getRDN().getAttributeValue(0). getNormalizedValue()); domain = MultimasterReplication.findDomain(rdns, null); } } catch (Exception e) { return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false); } this.isEnabled = configuration.isEnabled(); if (configuration.getECLInclude() != null) for (AttributeType eclInclude : configuration.getECLInclude()) domain.addEclInclude(eclInclude.getNormalizedPrimaryName()); return new ConfigChangeResult(ResultCode.SUCCESS, false); } /** * {@inheritDoc} */ public ConfigChangeResult applyConfigurationChange( ExternalChangelogDomainCfg configuration) { try { if (domain==null) { DN rdns = DN.decode( configuration.dn().getParent().getRDN().getAttributeValue(0). getNormalizedValue()); domain = MultimasterReplication.findDomain(rdns, null); } this.isEnabled = configuration.isEnabled(); if (configuration.getECLInclude() != null) for (AttributeType eclInclude : configuration.getECLInclude()) domain.addEclInclude(eclInclude.getNormalizedPrimaryName()); return new ConfigChangeResult(ResultCode.SUCCESS, false); } catch (Exception e) { return new ConfigChangeResult(ResultCode.CONSTRAINT_VIOLATION, false); } } /** * {@inheritDoc} */ public boolean isConfigurationAddAcceptable( ExternalChangelogDomainCfg configuration, List<Message> unacceptableReasons) { return true; } /** * {@inheritDoc} */ public boolean isConfigurationChangeAcceptable( ExternalChangelogDomainCfg configuration, List<Message> unacceptableReasons) { return true; } /** * {@inheritDoc} */ public boolean isConfigurationDeleteAcceptable( ExternalChangelogDomainCfg configuration, List<Message> unacceptableReasons) { return true; } /** * {@inheritDoc} */ public ConfigChangeResult applyConfigurationDelete( ExternalChangelogDomainCfg configuration) { // nothing to do return new ConfigChangeResult(ResultCode.SUCCESS, false); } /** * Specifies whether this domain is enabled/disabled regarding the ECL. * @return enabled/disabled for the ECL. */ boolean isEnabled() { return this.isEnabled; } } opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -41,6 +41,7 @@ import java.io.File; import java.io.InputStream; import java.io.OutputStream; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Collection; @@ -66,7 +67,9 @@ import org.opends.messages.Message; import org.opends.messages.MessageBuilder; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.AssuredType; import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.*; import org.opends.server.admin.std.server.ExternalChangelogDomainCfg; import org.opends.server.admin.std.server.ReplicationDomainCfg; import org.opends.server.api.AlertGenerator; import org.opends.server.api.Backend; @@ -157,6 +160,7 @@ import org.opends.server.types.operation.PreOperationModifyDNOperation; import org.opends.server.types.operation.PreOperationModifyOperation; import org.opends.server.types.operation.PreOperationOperation; import org.opends.server.util.LDIFReader; import org.opends.server.workflowelement.externalchangelog.ECLWorkflowElement; import org.opends.server.workflowelement.localbackend.*; @@ -256,6 +260,7 @@ * The DN of the configuration entry of this domain. */ private final DN configDn; private ExternalChangelogDomain eclDomain; /** * A boolean indicating if the thread used to save the persistentServerState @@ -432,7 +437,7 @@ setGroupId((byte)configuration.getGroupId()); setURLs(configuration.getReferralsUrl()); setCfgEclInclude(configuration.getEclInclude()); createECLDomainCfg(configuration); /* * Modify conflicts are solved for all suffixes but the schema suffix @@ -2305,6 +2310,15 @@ } /** * Delete this ReplicationDomain. */ public void delete() { shutdown(); removeECLDomainCfg(); } /** * Shutdown this ReplicationDomain. */ public void shutdown() @@ -4093,6 +4107,15 @@ solveConflictFlag = configuration.isSolveConflicts(); } try { createECLDomainCfg(configuration); } catch(Exception e) { return new ConfigChangeResult(ResultCode.OTHER, false); } return new ConfigChangeResult(ResultCode.SUCCESS, false); } @@ -4166,6 +4189,94 @@ /** * Remove from this domain configuration, the configuration of the * external change log. */ public void removeECLDomainCfg() { try { DN eclConfigEntryDN = DN.decode( "cn=external changeLog," + configDn); if (DirectoryServer.getConfigHandler().entryExists(eclConfigEntryDN)) { DirectoryServer.getConfigHandler().deleteEntry(eclConfigEntryDN, null); } } catch(Exception e) { TRACER.debugCaught(DebugLogLevel.ERROR, e); MessageBuilder mb = new MessageBuilder(); mb.append(e.getMessage()); Message msg = ERR_CHECK_CREATE_REPL_BACKEND_FAILED.get(mb.toString()); logError(msg); } } /** * Create the ECl configuration. * @param configuration The provided configuration. * @throws ConfigException a. */ public void createECLDomainCfg(ReplicationDomainCfg configuration) throws ConfigException { // create the ecl config if it does not exist // There may ot be any config entry related to this domain in some // unit test cases try { ExternalChangelogDomainCfg eclDomCfg = null; if (DirectoryServer.getConfigHandler().entryExists(configDn)) { try { eclDomCfg = configuration.getExternalChangelogDomain(); }catch(Exception e) {} if (eclDomCfg==null) { DN eclConfigEntryDN = DN.decode("cn=external changelog," + configDn); if (!DirectoryServer.getConfigHandler().entryExists(eclConfigEntryDN)) { String ldif = makeLdif( "dn: cn=external changelog," + configDn, "objectClass: top", "objectClass: ds-cfg-external-changelog-domain", "cn: external changelog", "ds-cfg-enabled: " + (!getBackend().isPrivateBackend())); LDIFImportConfig ldifImportConfig = new LDIFImportConfig( new StringReader(ldif)); LDIFReader reader = new LDIFReader(ldifImportConfig); Entry eclEntry = reader.readEntry(); DirectoryServer.getConfigHandler().addEntry(eclEntry, null); ldifImportConfig.close(); } } } eclDomCfg = configuration.getExternalChangelogDomain(); eclDomain = new ExternalChangelogDomain(this, eclDomCfg); } catch(Exception de) { throw new ConfigException( NOTE_ERR_UNABLE_TO_ENABLE_ECL.get( "Replication Domain on" + baseDn, de.getMessage() + " " + de.getCause().getMessage()), de); } } private static String makeLdif(String... lines) { StringBuilder buffer = new StringBuilder(); for (String line : lines) { buffer.append(line).append(EOL); } // Append an extra line so we can append LDIF Strings. buffer.append(EOL); return buffer.toString(); } /** * {@inheritDoc} */ @Override @@ -4197,7 +4308,6 @@ } catch(DirectoryException de) { //FIXME:DirectoryException is raised by initializeECL => fix err msg Message message = NOTE_ERR_UNABLE_TO_ENABLE_ECL.get( "Replication Domain on" + baseDn, @@ -5080,4 +5190,13 @@ return true; } } /** * Specifies whether this domain is enabled/disabled regarding the ECL. * @return enabled/disabled for the ECL. */ public boolean isECLEnabled() { return this.eclDomain.isEnabled(); } } opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -36,6 +36,7 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import static org.opends.server.util.StaticUtils.stackTraceToSingleLineString; import org.opends.messages.Message; import org.opends.server.admin.server.ConfigurationAddListener; import org.opends.server.admin.server.ConfigurationChangeListener; @@ -195,7 +196,7 @@ ReplicationDomainCfg configuration) throws ConfigException { LDAPReplicationDomain domain; LDAPReplicationDomain domain = null; try { domain = new LDAPReplicationDomain(configuration, updateToReplayQueue); @@ -208,14 +209,14 @@ } domains.put(domain.getBaseDN(), domain); return domain; } catch (ConfigException e) { logError(ERR_COULD_NOT_START_REPLICATION.get( configuration.dn().toString(), e.getLocalizedMessage())); return null; configuration.dn().toString(), e.getLocalizedMessage() + " " + stackTraceToSingleLineString(e))); } return domain; } /** @@ -251,7 +252,7 @@ LDAPReplicationDomain domain = domains.remove(dn); if (domain != null) domain.shutdown(); domain.delete(); // No replay threads running if no replication need if (domains.size() == 0) { @@ -822,18 +823,16 @@ * Gets the baseDn of the domains that have a private backend. * @return The private baseDN. */ public static ArrayList<String> getPrivateDomains() public static ArrayList<String> getECLDisabledDomains() { ArrayList<String> privateDNs = new ArrayList<String>(); ArrayList<String> disabledServiceIDs = new ArrayList<String>(); for (LDAPReplicationDomain domain : domains.values()) { Backend b = domain.getBackend(); if (b != null) if (b.isPrivateBackend()) privateDNs.add(domain.getBaseDN().toNormalizedString()); if (!domain.isECLEnabled()) disabledServiceIDs.add(domain.getBaseDN().toNormalizedString()); } return privateDNs; return disabledServiceIDs; } /** opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationBroker.java
@@ -2502,11 +2502,6 @@ domain.addEclInclude(attr); } } if (debugEnabled()) { TRACER.debugInfo("domain: " + domain.getServiceID() + " EclIncludes" + domain.getEclInclude()); } } } /** opendj-sdk/opends/src/server/org/opends/server/replication/service/ReplicationDomain.java
@@ -2909,14 +2909,4 @@ { return eClIncludes; } /** * Set the list of attributes to include in the ECL. * @param eclIncludes The list of attributes. */ protected void setCfgEclInclude(Set<String> eclIncludes) { this.cfgEclIncludes = eclIncludes; this.eClIncludes = eclIncludes; } } opendj-sdk/opends/src/server/org/opends/server/workflowelement/externalchangelog/ECLSearchOperation.java
@@ -248,7 +248,7 @@ // Set a list of excluded domains (also exclude 'cn=changelog' itself) ArrayList<String> excludedDomains = MultimasterReplication.getPrivateDomains(); MultimasterReplication.getECLDisabledDomains(); if (!excludedDomains.contains(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT)) excludedDomains.add(ServerConstants.DN_EXTERNAL_CHANGELOG_ROOT); startECLSessionMsg.setExcludedDNs(excludedDomains); opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ExternalChangeLogTest.java
@@ -89,6 +89,7 @@ import org.opends.server.replication.common.MultiDomainServerState; import org.opends.server.replication.common.ServerState; import org.opends.server.replication.plugin.DomainFakeCfg; import org.opends.server.replication.plugin.ExternalChangelogDomainFakeCfg; import org.opends.server.replication.plugin.LDAPReplicationDomain; import org.opends.server.replication.plugin.MultimasterReplication; import org.opends.server.replication.protocol.AddMsg; @@ -111,6 +112,7 @@ import org.opends.server.types.AbstractOperation; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeBuilder; import org.opends.server.types.AttributeType; import org.opends.server.types.AttributeValue; import org.opends.server.types.Attributes; import org.opends.server.types.ByteString; @@ -657,13 +659,20 @@ // Add the root entry in the backend Backend backend2 = initializeTestBackend(false, TEST_ROOT_DN_STRING2, TEST_BACKEND_ID2); backend2.setPrivateBackend(true); DN baseDn2 = DN.decode(TEST_ROOT_DN_STRING2); SortedSet<String> replServers = new TreeSet<String>(); replServers.add("localhost:"+replicationServerPort); DomainFakeCfg domainConf = new DomainFakeCfg(baseDn2, 1602, replServers); LDAPReplicationDomain domain2 = MultimasterReplication.createNewDomain(domainConf); ExternalChangelogDomainFakeCfg eclCfg = new ExternalChangelogDomainFakeCfg(true, null); domainConf.setExternalChangelogDomain(eclCfg); LDAPReplicationDomain domain2 = MultimasterReplication.createNewDomain(domainConf); domain2.start(); sleep(1000); Entry e = createEntry(baseDn2); addEntry(e); @@ -716,11 +725,11 @@ //} } } // // Set the backend private and do again a search on ECL that should // now not return the entry // domain2.getBackend().setPrivateBackend(true); eclCfg = new ExternalChangelogDomainFakeCfg(false, null); domainConf.setExternalChangelogDomain(eclCfg); domain2.applyConfigurationChange(domainConf); debugInfo(tn, "Search with cookie=" + cookie); searchOp = connection.processSearch( @@ -739,8 +748,8 @@ waitOpResult(searchOp, ResultCode.SUCCESS); entries = searchOp.getSearchEntries(); assertTrue(entries != null); assertTrue(entries.size()==1); assertTrue(entries != null, "Entries returned when test2 is ECL disabled."); assertTrue(entries.size()==1, "#Entry="+entries.size()+"when expected is 1"); if (entries != null) for (SearchResultEntry resultEntry : entries) { @@ -3514,9 +3523,13 @@ replServers.add("localhost:"+replicationServerPort); DomainFakeCfg domainConf = new DomainFakeCfg(baseDn2, 1702, replServers); SortedSet<String> includeAttributes = new TreeSet<String>(); includeAttributes.add("sn"); domainConf.setEclIncludes(includeAttributes); // SortedSet<String> includeAttributes = new TreeSet<String>(); // includeAttributes.add("sn"); SortedSet<AttributeType> eclInclude = new TreeSet<AttributeType>(); eclInclude.add(DirectoryServer.getAttributeType("sn")); ExternalChangelogDomainFakeCfg eclCfg = new ExternalChangelogDomainFakeCfg(true, eclInclude); domainConf.setExternalChangelogDomain(eclCfg); domain2 = MultimasterReplication.createNewDomain(domainConf); domain2.start(); @@ -3525,17 +3538,21 @@ baseDn3 = DN.decode(TEST_ROOT_DN_STRING3); domainConf = new DomainFakeCfg(baseDn3, 1703, replServers); includeAttributes = new TreeSet<String>(); includeAttributes.add("objectclass"); domainConf.setEclIncludes(includeAttributes); eclInclude = new TreeSet<AttributeType>(); eclInclude.add(DirectoryServer.getAttributeType("objectclass")); eclCfg = new ExternalChangelogDomainFakeCfg(true, eclInclude); domainConf.setExternalChangelogDomain(eclCfg); domain3 = MultimasterReplication.createNewDomain(domainConf); domain3.start(); domainConf = new DomainFakeCfg(baseDn2, 1704, replServers); includeAttributes = new TreeSet<String>(); includeAttributes.add("cn"); domainConf.setEclIncludes(includeAttributes); eclInclude = new TreeSet<AttributeType>(); eclInclude.add(DirectoryServer.getAttributeType("cn")); eclCfg = new ExternalChangelogDomainFakeCfg(true, eclInclude); domainConf.setExternalChangelogDomain(eclCfg); domain21 = MultimasterReplication.createNewDomain(domainConf); domain21.start(); opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/GenerationIdTest.java
@@ -26,6 +26,8 @@ */ package org.opends.server.replication; import static org.opends.server.TestCaseUtils.TEST_BACKEND_ID; import static org.opends.server.TestCaseUtils.TEST_ROOT_DN_STRING; import static org.opends.server.loggers.ErrorLogger.logError; import static org.opends.server.loggers.debug.DebugLogger.debugEnabled; import static org.opends.server.loggers.debug.DebugLogger.getTracer; @@ -54,7 +56,6 @@ import org.opends.server.core.DirectoryServer; import org.opends.server.loggers.debug.DebugTracer; import org.opends.server.protocols.internal.InternalSearchOperation; import org.opends.server.replication.service.ReplicationBroker; import org.opends.server.replication.common.ChangeNumberGenerator; import org.opends.server.replication.common.ServerStatus; import org.opends.server.replication.plugin.LDAPReplicationDomain; @@ -69,10 +70,12 @@ import org.opends.server.replication.server.ReplServerFakeConfiguration; import org.opends.server.replication.server.ReplicationBackend; import org.opends.server.replication.server.ReplicationServer; import org.opends.server.replication.service.ReplicationBroker; import org.opends.server.tasks.LdifFileWriter; import org.opends.server.types.Attribute; import org.opends.server.types.AttributeType; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; import org.opends.server.types.Entry; import org.opends.server.types.LDIFImportConfig; import org.opends.server.types.ResultCode; @@ -81,7 +84,6 @@ import org.opends.server.types.SearchScope; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; import static org.opends.server.TestCaseUtils.*; /** * Tests contained here: @@ -117,7 +119,6 @@ private ReplicationServer replServer2 = null; private ReplicationServer replServer3 = null; private boolean emptyOldChanges = true; LDAPReplicationDomain replDomain = null; private Entry taskInitRemoteS2; SocketSession ssSession = null; boolean ssShutdownRequested = false; @@ -440,12 +441,21 @@ "Unable to add the synchronized server"); configEntryList.add(synchroServerEntry.getDN()); replDomain = LDAPReplicationDomain.retrievesReplicationDomain(baseDn); if (replDomain != null) int waitCo=0; LDAPReplicationDomain doToco=null; while(waitCo<30) { debugInfo("ReplicationDomain: Import/Export is running ? " + replDomain.ieRunning()); doToco = LDAPReplicationDomain.retrievesReplicationDomain(baseDn); if ((doToco!=null) && (doToco.isConnected())) break; Thread.sleep(200); waitCo++; } assertTrue(doToco.isConnected(), "not connected after #attempt="+waitCo); if (doToco != null) { debugInfo("ReplicationDomain: Import/Export is running ? " + doToco.ieRunning()); } } catch(Exception e) @@ -469,6 +479,14 @@ assertTrue(synchroServerEntry != null); DN synchroServerDN = DN.decode(synchroServerStringDN); Entry ecle; ecle = DirectoryServer.getConfigHandler().getEntry( DN.decode("cn=external changelog," + synchroServerStringDN)); if (ecle!=null) { DirectoryServer.getConfigHandler().deleteEntry(ecle.getDN(), null); } DirectoryServer.getConfigHandler().deleteEntry(synchroServerDN, null); assertTrue(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()) == null, @@ -477,6 +495,23 @@ configEntryList.remove(configEntryList.indexOf(synchroServerDN)); LDAPReplicationDomain replDomainToDis = null; try { int waitCo=0; while(waitCo<30) { replDomainToDis = LDAPReplicationDomain.retrievesReplicationDomain(baseDn); Thread.sleep(200); waitCo++; } assert(replDomainToDis==null); } catch (DirectoryException e) { // success } } catch(Exception e) { @@ -703,7 +738,6 @@ // To search the replication server db later in these tests, we need // to attach the search backend to the replication server just created. Thread.sleep(500); ReplicationBackend b = (ReplicationBackend)DirectoryServer.getBackend("replicationChanges"); b.setServer(replServer1); @@ -829,7 +863,6 @@ // To search the replication server db later in these tests, we need // to attach the search backend to the replication server just created. Thread.sleep(500); b = (ReplicationBackend)DirectoryServer.getBackend("replicationChanges"); b.setServer(replServer1); @@ -1012,7 +1045,6 @@ addTask(taskReset, ResultCode.SUCCESS, null); waitTaskState(taskReset, TaskState.COMPLETED_SUCCESSFULLY, null); Thread.sleep(200); debugInfo("Verify that RS1 has still the right genID"); assertEquals(replServer1.getGenerationId(baseDn.toNormalizedString()), rgenId); @@ -1126,9 +1158,18 @@ debugInfo("Connecting DS to replServer1"); connectServer1ToChangelog(changelog1ID); Thread.sleep(1500); debugInfo("Expect genId are set in all replServers."); int waitRes=0; while(waitRes<100) { if ((replServer1.getGenerationId(baseDn.toNormalizedString())==EMPTY_DN_GENID) && (replServer2.getGenerationId(baseDn.toNormalizedString())==EMPTY_DN_GENID) && (replServer3.getGenerationId(baseDn.toNormalizedString())==EMPTY_DN_GENID)) break; waitRes++; Thread.sleep(100); } assertEquals(replServer1.getGenerationId(baseDn.toNormalizedString()), EMPTY_DN_GENID, " in replServer1"); assertEquals(replServer2.getGenerationId(baseDn.toNormalizedString()), EMPTY_DN_GENID, @@ -1138,8 +1179,17 @@ debugInfo("Disconnect DS from replServer1."); disconnectFromReplServer(changelog1ID); Thread.sleep(3000); waitRes=0; while(waitRes<100) { if ((replServer1.getGenerationId(baseDn.toNormalizedString())==-1) && (replServer2.getGenerationId(baseDn.toNormalizedString())==-1) && (replServer3.getGenerationId(baseDn.toNormalizedString())==-1)) break; waitRes++; Thread.sleep(100); } debugInfo( "Expect genIds to be resetted in all servers to -1 as no more DS in topo"); assertEquals(replServer1.getGenerationId(baseDn.toNormalizedString()), -1); @@ -1151,12 +1201,21 @@ debugInfo("Connecting DS to replServer2"); connectServer1ToChangelog(changelog2ID); Thread.sleep(3000); debugInfo( "Expect genIds to be set in all servers based on the added entries."); genId = readGenIdFromSuffixRootEntry(); assertTrue(genId != -1); waitRes=0; while(waitRes<100) { if ((replServer1.getGenerationId(baseDn.toNormalizedString())==genId) && (replServer2.getGenerationId(baseDn.toNormalizedString())==genId) && (replServer3.getGenerationId(baseDn.toNormalizedString())==genId)) break; waitRes++; Thread.sleep(100); } assertEquals(replServer1.getGenerationId(baseDn.toNormalizedString()), genId); assertEquals(replServer2.getGenerationId(baseDn.toNormalizedString()), genId); assertEquals(replServer3.getGenerationId(baseDn.toNormalizedString()), genId); @@ -1347,7 +1406,6 @@ // Read generationId - should be not retrievable since no entry debugInfo(testCase + " Connecting DS1 to replServer1(" + changelog1ID + ")"); connectServer1ToChangelog(changelog1ID); Thread.sleep(1000); debugInfo(testCase + " Expect genId attribute to be not retrievable"); genId = readGenIdFromSuffixRootEntry(); opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ProtocolWindowTest.java
@@ -119,6 +119,7 @@ DirectoryServer.getConfigHandler().addEntry(repDomainEntry, null); assertNotNull(DirectoryServer.getConfigEntry(repDomainEntry.getDN()), "Unable to add the synchronized server"); configEntryList.add(repDomainEntry.getDN()); ReplicationBroker broker = openReplicationSession(baseDn, 12, WINDOW_SIZE, replServerPort, 1000, true); opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -398,6 +398,29 @@ return broker; } protected void deleteEntry(DN dn) { try { if (dn.getParent().getRDN().toString().equalsIgnoreCase("cn=domains")) deleteEntry(DN.decode("cn=external changelog,"+dn.toString())); } catch(Exception e) {} DeleteOperationBasis op; op = new DeleteOperationBasis(connection, InternalClientConnection .nextOperationID(), InternalClientConnection.nextMessageID(), null, dn); op.run(); if ((op.getResultCode() != ResultCode.SUCCESS) && (op.getResultCode() != ResultCode.NO_SUCH_OBJECT)) { fail("Delete entry " + dn + " failed: " + op.getResultCode().getResultCodeName()); } } /** * suppress all the config entries created by the tests in this class */ @@ -406,27 +429,12 @@ logError(Message.raw(Category.SYNC, Severity.NOTICE, "ReplicationTestCase/Cleaning config entries")); DeleteOperationBasis op; // Delete entries try { while (true) { DN dn = configEntryList.removeLast(); logError(Message.raw(Category.SYNC, Severity.NOTICE, "cleaning config entry " + dn)); op = new DeleteOperationBasis(connection, InternalClientConnection .nextOperationID(), InternalClientConnection.nextMessageID(), null, dn); op.run(); if ((op.getResultCode() != ResultCode.SUCCESS) && (op.getResultCode() != ResultCode.NO_SUCH_OBJECT)) { fail("ReplicationTestCase/Cleaning config entries DEL " + dn + " failed: " + op.getResultCode().getResultCodeName()); } deleteEntry(dn); } } catch (NoSuchElementException e) { @@ -451,23 +459,7 @@ while (true) { DN dn = entryList.removeLast(); op = new DeleteOperationBasis(connection, InternalClientConnection.nextOperationID(), InternalClientConnection.nextMessageID(), null, dn); op.run(); if ((op.getResultCode() != ResultCode.SUCCESS) && (op.getResultCode() != ResultCode.NO_SUCH_OBJECT)) { logError(Message.raw(Category.SYNC, Severity.NOTICE, "ReplicationTestCase/Cleaning entries" + "DEL " + dn + " failed " + op.getResultCode().getResultCodeName())); } deleteEntry(dn); } } catch (NoSuchElementException e) { @@ -1171,29 +1163,8 @@ */ protected void removeDomain(Entry domainCfgEntry) { DeleteOperationBasis op; // Delete entries try { DN dn = domainCfgEntry.getDN(); logError(Message.raw(Category.SYNC, Severity.NOTICE, "cleaning config entry " + dn)); op = new DeleteOperationBasis(connection, InternalClientConnection. nextOperationID(), InternalClientConnection.nextMessageID(), null, dn); op.run(); if ((op.getResultCode() != ResultCode.SUCCESS) && (op.getResultCode() != ResultCode.NO_SUCH_OBJECT)) { fail("Deleting config entry" + dn + " failed: " + op.getResultCode().getResultCodeName()); } } catch (NoSuchElementException e) { // done } deleteEntry(dn); } /** opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/DomainFakeCfg.java
@@ -26,17 +26,21 @@ */ package org.opends.server.replication.plugin; import java.util.HashSet; import java.util.List; import java.util.SortedSet; import java.util.TreeSet; import org.opends.server.admin.Configuration; 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.ServerManagedObject; import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.AssuredType; import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.IsolationPolicy; import org.opends.server.admin.std.server.ExternalChangelogDomainCfg; import org.opends.server.admin.std.server.ReplicationDomainCfg; import org.opends.server.config.ConfigException; import org.opends.server.types.AttributeType; import org.opends.server.types.DN; import org.opends.server.types.DirectoryException; @@ -69,6 +73,8 @@ private SortedSet<String> fractionalIncludes = new TreeSet<String>(); private SortedSet<String> eclIncludes = new TreeSet<String>(); private ExternalChangelogDomainCfg eclCfg = new ExternalChangelogDomainFakeCfg(true, new TreeSet<AttributeType>()); /** * Creates a new Domain with the provided information @@ -365,8 +371,95 @@ this.eclIncludes = attrs; } public SortedSet<String> getEclInclude() public SortedSet<String> getECLInclude() { return this.eclIncludes; } public boolean hasExternalChangelogDomain() { return true; } /** * Gets the ECL Domain if it is present. * * @return Returns the ECL Domain if it is present. * @throws ConfigException * If the ECL Domain does not exist or it could not * be successfully decoded. */ public ExternalChangelogDomainCfg getExternalChangelogDomain() throws ConfigException { return eclCfg; } /** * Sets the ECL Domain if it is present. * * @return Returns the ECL Domain if it is present. * @throws ConfigException * If the ECL Domain does not exist or it could not * be successfully decoded. */ public void setExternalChangelogDomain(ExternalChangelogDomainCfg eclCfg) throws ConfigException { this.eclCfg=eclCfg;} /** * Registers to be notified when the ECL Domain is added. * * @param listener * The ECL Domain configuration add listener. * @throws ConfigException * If the add listener could not be registered. */ public void addECLDomainAddListener( ConfigurationAddListener<ExternalChangelogDomainCfg> listener) throws ConfigException {} /** * Deregisters an existing ECL Domain configuration add listener. * * @param listener * The ECL Domain configuration add listener. */ public void removeECLDomainAddListener( ConfigurationAddListener<ExternalChangelogDomainCfg> listener) {} /** * Registers to be notified the ECL Domain is deleted. * * @param listener * The ECL Domain configuration delete listener. * @throws ConfigException * If the delete listener could not be registered. */ public void addECLDomainDeleteListener( ConfigurationDeleteListener<ExternalChangelogDomainCfg> listener) throws ConfigException {} /** * Deregisters an existing ECL Domain configuration delete listener. * * @param listener * The ECL Domain configuration delete listener. */ public void removeECLDomainDeleteListener( ConfigurationDeleteListener<ExternalChangelogDomainCfg> listener) {} } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ExternalChangelogDomainFakeCfg.java
New file @@ -0,0 +1,154 @@ /* * 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 * * * Copyright 2007-2009 Sun Microsystems, Inc. */ package org.opends.server.replication.plugin; import java.util.SortedSet; import org.opends.server.admin.server.ConfigurationChangeListener; import org.opends.server.admin.std.server.ExternalChangelogDomainCfg; import org.opends.server.types.AttributeType; import org.opends.server.types.DN; /** * This class implement a configuration object for the ExternalChangelog domain * that can be used in unit tests to instantiate ExternalChangelogDomain. */ public class ExternalChangelogDomainFakeCfg implements ExternalChangelogDomainCfg { // The value of the "ecl-include" property. private SortedSet<AttributeType> pECLInclude; // The value of the "enabled" property. private boolean pEnabled; private DN pDN; /** * Creates a new Domain with the provided information * (assured mode disabled, default group id) */ public ExternalChangelogDomainFakeCfg(boolean isEnabled, SortedSet<AttributeType> eCLInclude) { this.pEnabled = isEnabled; this.pECLInclude = eCLInclude; } /** * {@inheritDoc} */ public Class<? extends ExternalChangelogDomainCfg> configurationClass() { return null; } /** * Register to be notified when this External Changelog Domain is changed. * * @param listener * The External Changelog Domain configuration change listener. */ public void addChangeListener( ConfigurationChangeListener<ExternalChangelogDomainCfg> listener) {} /** * Deregister an existing External Changelog Domain configuration change listener. * * @param listener * The External Changelog Domain configuration change listener. */ public void removeChangeListener( ConfigurationChangeListener<ExternalChangelogDomainCfg> listener) {} /** * Gets the "ecl-include" property. * <p> * Allows to include some target entry attributes in the external * changelog. * <p> * Specifies an attribute that will be included in every External * Change Log entry related to this replication domain. * * @return Returns an unmodifiable set containing the values of the "ecl-include" property. */ public SortedSet<AttributeType> getECLInclude() { return this.pECLInclude; } /** * Set eclInclude. * @param eclInclude the attribute to include. */ public void setECLInclude(SortedSet<AttributeType> eclInclude) { this.pECLInclude = eclInclude; } /** * Set enabled. * @param enabled a. */ public void setEnable(boolean enabled) { this.pEnabled = enabled; } /** * Gets the "enabled" property. * <p> * Indicates whether the External Changelog Domain is enabled for * use. * * @return Returns the value of the "enabled" property. */ public boolean isEnabled() { return this.pEnabled; } public DN dn() { return pDN; } public void setDN(DN dn) { this.pDN = dn; } } opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/server/MonitorTest.java
@@ -267,14 +267,9 @@ SYNCHRO_PLUGIN_DN; // Must have called connectServer1ToChangelog previously assertTrue(synchroServerEntry != null); DN synchroServerDN = DN.decode(synchroServerStringDN); DirectoryServer.getConfigHandler().deleteEntry(synchroServerDN, null); assertTrue(DirectoryServer.getConfigEntry(synchroServerEntry.getDN()) == null, "Unable to delete the synchronized domain"); deleteEntry(synchroServerDN); synchroServerEntry = null; configEntryList.remove(configEntryList.indexOf(synchroServerDN)); }