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/src/server/org/opends/server/synchronization/plugin/MultimasterSynchronization.java |  240 ++++++++++++++++++-----------------------------------------
 1 files changed, 74 insertions(+), 166 deletions(-)

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;
+  }
 }
 
 

--
Gitblit v1.10.0