From 972103091b00d019b98516adf64a2db12c20c749 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Mon, 20 Aug 2007 08:04:16 +0000
Subject: [PATCH] These changes rovides the ability to repair the consistency in the replication topology in the (hopefully) rare case when hardware failure or software bugs could break it (issue 788 and 791)
---
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java | 5
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java | 27 --
opendj-sdk/opends/resource/config/replication.ldif | 14 -
opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java | 8
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationRepairRequestControl.java | 130 +++++++++++++
opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java | 41 ++++
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java | 53 ++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationRepairControlTest.java | 133 +++++++++++++
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java | 5
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java | 19 -
opendj-sdk/opends/src/messages/messages/replication.properties | 30 +-
opendj-sdk/opends/resource/config/config.ldif | 29 ++
opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml | 9
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java | 4
opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java | 7
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java | 43 ++-
16 files changed, 461 insertions(+), 96 deletions(-)
diff --git a/opendj-sdk/opends/resource/config/config.ldif b/opendj-sdk/opends/resource/config/config.ldif
index 0bcfe74..6315958 100644
--- a/opendj-sdk/opends/resource/config/config.ldif
+++ b/opendj-sdk/opends/resource/config/config.ldif
@@ -601,6 +601,23 @@
ds-cfg-rotation-policy-dn: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
ds-cfg-retention-policy-dn: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
+dn: cn=Replication Repair Logger,cn=Loggers,cn=config
+objectClass: top
+objectClass: ds-cfg-logger
+objectClass: ds-cfg-error-logger
+objectClass: ds-cfg-file-based-error-logger
+cn: File-Based Error Logger
+ds-cfg-logger-class: org.opends.server.loggers.TextErrorLogPublisher
+ds-cfg-logger-enabled: true
+ds-cfg-log-file: logs/replication
+ds-cfg-log-file-mode: 640
+ds-cfg-default-severity: none
+ds-cfg-override-severity: SYNC=INFO,MILD_ERROR,MILD_WARNING,NOTICE
+ds-cfg-asynchronous-writes: false
+ds-cfg-rotation-policy-dn: cn=7 Days Time Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-rotation-policy-dn: cn=Size Limit Rotation Policy,cn=Log Rotation Policies,cn=config
+ds-cfg-retention-policy-dn: cn=File Count Retention Policy,cn=Log Retention Policies,cn=config
+
dn: cn=File-Based Debug Logger,cn=Loggers,cn=config
objectClass: top
objectClass: ds-cfg-logger
@@ -1921,3 +1938,15 @@
ds-cfg-num-worker-threads: 24
ds-cfg-max-work-queue-capacity: 0
+dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+objectClass: top
+objectClass: ds-cfg-synchronization-provider
+objectClass: ds-cfg-multimaster-synchronization-provider
+cn: Multimaster Synchronization
+ds-cfg-synchronization-provider-enabled: true
+ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication
+
+dn: cn=domains,cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
+objectClass: top
+objectClass: ds-cfg-branch
+cn: domains
diff --git a/opendj-sdk/opends/resource/config/replication.ldif b/opendj-sdk/opends/resource/config/replication.ldif
index 9b13133..fcb9935 100644
--- a/opendj-sdk/opends/resource/config/replication.ldif
+++ b/opendj-sdk/opends/resource/config/replication.ldif
@@ -9,20 +9,6 @@
# cn=Replication Server, cn=Multimaster Synchronization, cn=Synchronization Providers, cn=config
# entry.
-
-dn: cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config
-objectClass: top
-objectClass: ds-cfg-synchronization-provider
-objectClass: ds-cfg-multimaster-synchronization-provider
-cn: Multimaster Synchronization
-ds-cfg-synchronization-provider-enabled: true
-ds-cfg-synchronization-provider-class: org.opends.server.replication.plugin.MultimasterReplication
-
-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-replication-domain-config
diff --git a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
index e4548ec..067875c 100644
--- a/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
+++ b/opendj-sdk/opends/src/admin/defn/org/opends/server/admin/std/ErrorLogPublisherConfiguration.xml
@@ -57,6 +57,15 @@
Messages of all severity levels will be logged.
</adm:synopsis>
</adm:value>
+ <adm:value name="none">
+ <adm:synopsis>
+ No messages of any severity will be logged by default.
+ This value is intended to be used in conjunction with
+ the override-severity property to define an error
+ logger that will publish no error message beside the errors
+ of a given category.
+ </adm:synopsis>
+ </adm:value>
<adm:value name="fatal-error">
<adm:synopsis>
The error log severity that will be used for messages that
diff --git a/opendj-sdk/opends/src/messages/messages/replication.properties b/opendj-sdk/opends/src/messages/messages/replication.properties
index c71f537..0083d79 100644
--- a/opendj-sdk/opends/src/messages/messages/replication.properties
+++ b/opendj-sdk/opends/src/messages/messages/replication.properties
@@ -21,7 +21,12 @@
# CDDL HEADER END
#
# Portions Copyright 2006-2007 Sun Microsystems, Inc.
-
+#
+#
+# This file contains the primary Directory Server configuration. It must not
+# be directly edited while the server is online. The server configuration
+# should only be managed using the administration utilities provided with the
+# Directory Server.
#
@@ -55,8 +60,6 @@
MILD_ERR_COULD_NOT_BIND_CHANGELOG_6=Changelog failed to start : could not \
bind to the changelog listen port : %d. Error : %s
MILD_ERR_UNKNOWN_TYPE_7=Unknown operation type : %s
-MILD_ERR_ERROR_REPLAYING_OPERATION_8=Error %s when replaying operation with \
- changenumber %s %s : %s
MILD_ERR_OPERATION_NOT_FOUND_IN_PENDING_9=Internal Error : Operation %s \
change number %s was not found in pending list
MILD_ERR_COULD_NOT_INITIALIZE_DB_10=Changelog failed to start because the \
@@ -66,7 +69,7 @@
MILD_ERR_EXCEPTION_REPLAYING_OPERATION_12=An Exception was caught while \
replaying operation %s : %s
MILD_ERR_NEED_CHANGELOG_PORT_13=The replication server port must be defined
-MILD_ERR_ERROR_UPDATING_RUV_14=Error %s when updating server state %s : %s \
+DEBUG_ERROR_UPDATING_RUV_14=Error %s when updating server state %s : %s \
base dn : %s
MILD_ERR_ERROR_SEARCHING_RUV_15=Error %s when searching for server state %s : \
%s base dn : %s
@@ -79,8 +82,8 @@
server should be configured
NOTICE_EXCEPTION_STARTING_SESSION_20=Caught Exception during initial \
communication with replication server :
-NOTICE_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
- database
+MILD_ERR_CANNOT_RECOVER_CHANGES_21=Error when searching old changes from the \
+ database for base DN %s
NOTICE_COULD_NOT_FIND_CHANGELOG_WITH_MY_CHANGES_22=Could not find a \
replication server that has seen all the local changes. Going to replay \
changes
@@ -110,7 +113,7 @@
SEVERE_ERR_EXCEPTION_RECEIVING_REPLICATION_MESSAGE_34=An Exception was caught \
while receiving replication message : %s
MILD_ERR_LOOP_REPLAYING_OPERATION_35=A loop was detected while replaying \
- operation: %s
+ operation: %s error %s
MILD_ERR_FILE_CHECK_CREATE_FAILED_36=An Exception was caught while testing \
existence or trying to create the directory for the changelog database : %s
INFO_CHANGELOG_SERVER_ATTR_37=Specifies the list of replication servers to \
@@ -156,12 +159,12 @@
have the same ServerId : %d
SEVERE_ERR_BAD_HISTORICAL_56=Entry %s was containing some unknown historical \
information, This may cause some inconsistency for this entry
-SEVERE_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=A conflict was detected but the \
+MILD_ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE_57=A conflict was detected but the \
conflict information could not be added. Operation :
-SEVERE_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=An error happened trying the \
+MILD_ERR_CANNOT_RENAME_CONFLICT_ENTRY_58=An error happened trying to \
rename a conflicting entry :
-SEVERE_ERR_EXCEPTION_RENAME_CONFLICT_ENTRY_59=An Exception happened when \
- trying the rename a conflicting entry :
+MILD_ERR_EXCEPTION_RENAME_CONFLICT_ENTRY_59=An Exception happened when \
+ trying to rename a conflicting entry :
SEVERE_ERR_CHANGELOG_UNSUPPORTED_UTF8_ENCODING_60=The JVM does not support \
UTF-8. This is required to be able to encode the changes in the database. \
This replication server will now shutdown
@@ -179,3 +182,8 @@
and reopened
SEVERE_ERR_CHANGELOG_ERROR_SENDING_MSG_66=An unexpected error occurred while \
sending a Message to %s. This connection is going to be closed and reopened
+MILD_ERR_ERROR_REPLAYING_OPERATION_67=Could not replay operation %s with \
+ ChangeNumber %s error %s %s
+MILD_ERR_UNKNOWN_ATTRIBUTE_IN_HISTORICAL_68=The entry %s has historical \
+ information for attribute %s which is not defined in the schema. This \
+ information will be ignored
\ No newline at end of file
diff --git a/opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java b/opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java
index d8481ec..f36dfc3 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/loggers/TextErrorLogPublisher.java
@@ -194,6 +194,10 @@
defaultSeverities.add(Severity.SEVERE_ERROR);
defaultSeverities.add(Severity.SEVERE_WARNING);
}
+ else if (defSev.toString().equalsIgnoreCase(LOG_SEVERITY_NONE))
+ {
+ // don't add any severity
+ }
else
{
Severity errorSeverity =
@@ -424,6 +428,10 @@
defaultSeverities.add(Severity.SEVERE_ERROR);
defaultSeverities.add(Severity.SEVERE_WARNING);
}
+ else if (defSev.toString().equalsIgnoreCase(LOG_SEVERITY_NONE))
+ {
+ // don't add any severity
+ }
else
{
Severity errorSeverity =
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java
index 2e8b45e..c3fc150 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/FakeOperation.java
@@ -80,9 +80,7 @@
*
* @param mod A modification that must be adde to the list of modifications
* included in this fake operation.
- * @throws Exception when the addition of this type of modification
- * is not valid for this FakeOperation.
*/
- abstract public void addModification(Modification mod) throws Exception;
+ abstract public void addModification(Modification mod);
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
index f2c4f8a..2912126 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
@@ -374,8 +374,11 @@
* This attribute is unknown from the schema
* Just skip it, the modification will be processed but no
* historical information is going to be kept.
- * TODO : REPAIR tool should deal with this, add some logging.
+ * Log information for the repair tool.
*/
+ Message message = ERR_UNKNOWN_ATTRIBUTE_IN_HISTORICAL.get(
+ entry.getDN().toNormalizedString(), histVal.getAttrString());
+ logError(message);
continue;
}
@@ -453,19 +456,7 @@
if (fakeOperation != null)
{
- try
- {
- fakeOperation.addModification(mod);
- } catch (Exception e)
- {
- /*
- * TODO : REPAIR : This Exception shows that there are some
- * inconsistency in the historical information.
- * This method can't fix the problem.
- * This should be logged and somehow the repair
- * service should get called to fix the problem.
- */
- }
+ fakeOperation.addModification(mod);
}
else
{
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
index 016582b..82b8b6f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/MultimasterReplication.java
@@ -45,6 +45,7 @@
import org.opends.server.types.BackupConfig;
import org.opends.server.types.ConfigChangeResult;
+import org.opends.server.types.Control;
import org.opends.server.types.DN;
import org.opends.server.types.DirectoryException;
import org.opends.server.types.Entry;
@@ -67,6 +68,8 @@
import org.opends.server.types.operation.PreOperationModifyOperation;
import org.opends.messages.Message;
+import static org.opends.server.replication.plugin.
+ ReplicationRepairRequestControl.*;
/**
* This class is used to load the Replication code inside the JVM
@@ -91,20 +94,51 @@
/**
* Finds the domain for a given DN.
*
- * @param dn The DN for which the domain must be returned.
- * @param op An optional operation for which the check is done.
- * Can be null is the request has no associated operation.
- * @return The domain for this DN.
+ * @param dn The DN for which the domain must be returned.
+ * @param pluginOp An optional operation for which the check is done.
+ * Can be null is the request has no associated operation.
+ * @return The domain for this DN.
*/
- public static ReplicationDomain findDomain(DN dn, PluginOperation op)
+ public static ReplicationDomain findDomain(DN dn, PluginOperation pluginOp)
{
/*
* Don't run the special replication code on Operation that are
* specifically marked as don't synchronize.
*/
- if ((op != null) && (op instanceof Operation) &&
- (((Operation) op).dontSynchronize()))
- return null;
+ if ((pluginOp != null) && (pluginOp instanceof Operation))
+ {
+ Operation op = ((Operation) pluginOp);
+
+ if (op.dontSynchronize())
+ return null;
+
+ /*
+ * Check if the provided operation is a repair operation and set
+ * the synchronization flags if necessary.
+ * The repair operations are tagged as synchronization operations
+ * so that the core server let the operation modify the entryuuid
+ * and ds-sync-hist attributes.
+ * They are also tagged as dontSynchronize so that the replication
+ * code running later do not generate ChnageNumber, solve conflicts
+ * and forward the operation to the replication server.
+ */
+ for (Control c : op.getRequestControls())
+ {
+ if (c.getOID().equals(OID_REPLICATION_REPAIR_CONTROL))
+ {
+ op.setSynchronizationOperation(true);
+ op.setDontSynchronize(true);
+ // remove this control from the list of controls since
+ // it has now been processed and the local backend will
+ // fail if it finds a control that it does not know about and
+ // that is marked as critical.
+ List<Control> controls = op.getRequestControls();
+ controls.remove(c);
+ return null;
+ }
+ }
+ }
+
ReplicationDomain domain = null;
DN temp = dn;
@@ -188,6 +222,9 @@
DirectoryServer.registerRestoreTaskListener(this);
DirectoryServer.registerExportTaskListener(this);
DirectoryServer.registerImportTaskListener(this);
+
+ DirectoryServer.registerSupportedControl(
+ ReplicationRepairRequestControl.OID_REPLICATION_REPAIR_CONTROL);
}
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
index 1ca43bf..127d625 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/PersistentServerState.java
@@ -224,9 +224,10 @@
op.run();
ResultCode result = op.getResultCode();
- if (result != ResultCode.SUCCESS)
+ if ((result != ResultCode.SUCCESS) &&
+ ((result != ResultCode.NO_SUCH_OBJECT)))
{
- Message message = ERR_ERROR_UPDATING_RUV.get(
+ Message message = DEBUG_ERROR_UPDATING_RUV.get(
op.getResultCode().getResultCodeName().toString(),
op.toString(),
op.getErrorMessage().toString(),
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
index 69fede4..ab3ae34 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationBroker.java
@@ -330,10 +330,11 @@
* An error happened trying to search for the updates
* This server will start acepting again new updates but
* some inconsistencies will stay between servers.
- * TODO : REPAIR : log an error for the repair tool
+ * Log an error for the repair tool
* that will need to resynchronize the servers.
*/
- Message message = NOTE_CANNOT_RECOVER_CHANGES.get();
+ Message message = ERR_CANNOT_RECOVER_CHANGES.get(
+ baseDn.toNormalizedString());
logError(message);
}
else
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
index 31d803d..4713ac4 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationDomain.java
@@ -1272,8 +1272,9 @@
{
// Continue with the next change but the servers could now become
// inconsistent.
- // TODO : REPAIR : Should let the repair tool know about this
- Message message = ERR_LOOP_REPLAYING_OPERATION.get(op.toString());
+ // Let the repair tool know about this.
+ Message message = ERR_LOOP_REPLAYING_OPERATION.get(op.toString(),
+ op.getErrorMessage().toString());
logError(message);
numUnresolvedNamingConflicts.incrementAndGet();
@@ -1306,7 +1307,7 @@
* An Exception happened during the replay process.
* Continue with the next change but the servers will now start
* to be inconsistent.
- * TODO : REPAIR : Should let the repair tool know about this
+ * Let the repair tool know about this.
*/
Message message = ERR_EXCEPTION_REPLAYING_OPERATION.get(
stackTraceToSingleLineString(e), op.toString());
@@ -1473,7 +1474,11 @@
else
{
// The other type of errors can not be caused by naming conflicts.
- // TODO log a message for the repair tool.
+ // Log a message for the repair tool.
+ Message message = ERR_ERROR_REPLAYING_OPERATION.get(
+ op.toString(), ctx.getChangeNumber().toString(),
+ result.toString(), op.getErrorMessage().toString());
+ logError(message);
return true;
}
}
@@ -1538,7 +1543,11 @@
else
{
// The other type of errors can not be caused by naming conflicts.
- // TODO log a message for the repair tool.
+ // Log a message for the repair tool.
+ Message message = ERR_ERROR_REPLAYING_OPERATION.get(
+ op.toString(), ctx.getChangeNumber().toString(),
+ result.toString(), op.getErrorMessage().toString());
+ logError(message);
return true;
}
}
@@ -1651,7 +1660,11 @@
else
{
// The other type of errors can not be caused by naming conflicts.
- // TODO log a message for the repair tool.
+ // Log a message for the repair tool.
+ Message message = ERR_ERROR_REPLAYING_OPERATION.get(
+ op.toString(), ctx.getChangeNumber().toString(),
+ result.toString(), op.getErrorMessage().toString());
+ logError(message);
return true;
}
}
@@ -1745,7 +1758,11 @@
else
{
// The other type of errors can not be caused by naming conflicts.
- // TODO log a message for the repair tool.
+ // log a message for the repair tool.
+ Message message = ERR_ERROR_REPLAYING_OPERATION.get(
+ op.toString(), ctx.getChangeNumber().toString(),
+ result.toString(), op.getErrorMessage().toString());
+ logError(message);
return true;
}
}
@@ -1793,6 +1810,7 @@
}
else
{
+ // log error and information for the REPAIR tool.
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CANNOT_RENAME_CONFLICT_ENTRY.get());
mb.append(String.valueOf(entryDN));
@@ -1801,10 +1819,10 @@
mb.append(" ");
mb.append(String.valueOf(op.getResultCode()));
logError(mb.toMessage());
- // TODO : log error and information for the REPAIR tool.
}
} catch (DirectoryException e)
{
+ // log errror and information for the REPAIR tool.
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_EXCEPTION_RENAME_CONFLICT_ENTRY.get());
mb.append(String.valueOf(entryDN));
@@ -1813,7 +1831,6 @@
mb.append(" ");
mb.append(e.getLocalizedMessage());
logError(mb.toMessage());
- // TODO log errror and information for the REPAIR tool.
}
}
@@ -1836,6 +1853,7 @@
if (newOp.getResultCode() != ResultCode.SUCCESS)
{
+ // log information for the repair tool.
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CANNOT_RENAME_CONFLICT_ENTRY.get());
mb.append(String.valueOf(dn));
@@ -1844,9 +1862,6 @@
mb.append(" ");
mb.append(String.valueOf(newOp.getResultCode()));
logError(mb.toMessage());
- /*
- * TODO : REPAIR should log information for the repair tool.
- */
}
}
@@ -1876,15 +1891,13 @@
ModifyOperation newOp = conn.processModify(currentDN, mods);
if (newOp.getResultCode() != ResultCode.SUCCESS)
{
+ // Log information for the repair tool.
MessageBuilder mb = new MessageBuilder();
mb.append(ERR_CANNOT_ADD_CONFLICT_ATTRIBUTE.get());
mb.append(String.valueOf(op));
mb.append(" ");
mb.append(String.valueOf(newOp.getResultCode()));
logError(mb.toMessage());
- /*
- * TODO : REPAIR should log information for the repair tool.
- */
}
}
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationRepairRequestControl.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationRepairRequestControl.java
new file mode 100644
index 0000000..0ba0f78
--- /dev/null
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/ReplicationRepairRequestControl.java
@@ -0,0 +1,130 @@
+/*
+ * 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.replication.plugin;
+
+
+import org.opends.server.types.Control;
+import org.opends.server.types.LDAPException;
+
+
+
+/**
+ * This class implements the Sun-defined replication repair control.
+ * This control can be used to modify the content of a replicated database
+ * on a single server without impacting the other servers that are replicated
+ * with this server.
+ * It also allows to modify attributes like entryuuid and ds-sync-hist that
+ * are normally not modifiable from an external connection.
+ */
+public class ReplicationRepairRequestControl
+ extends Control
+{
+ /**
+ * The OID of the Replication repair Control.
+ */
+ public static final String
+ OID_REPLICATION_REPAIR_CONTROL = "1.3.6.1.4.1.26027.1.5.2";
+
+
+ /**
+ * Creates a new instance of the replication repair request control with the
+ * default settings.
+ */
+ public ReplicationRepairRequestControl()
+ {
+ super(OID_REPLICATION_REPAIR_CONTROL, false);
+
+ }
+
+
+
+ /**
+ * Creates a new instance of the replication repair control with the
+ * provided information.
+ *
+ * @param oid The OID to use for this control.
+ * @param isCritical Indicates whether support for this control should be
+ * considered a critical part of the client processing.
+ */
+ public ReplicationRepairRequestControl(String oid, boolean isCritical)
+ {
+ super(oid, isCritical);
+
+ }
+
+
+
+ /**
+ * Creates a new replication repair request control from the contents of the
+ * provided control.
+ *
+ * @param control The generic control containing the information to use to
+ * create this replication repair request control.
+ *
+ * @return The replication repair request control decoded from the provided
+ * control.
+ *
+ * @throws LDAPException If this control cannot be decoded as a valid
+ * replication repair request control.
+ */
+ public static ReplicationRepairRequestControl decodeControl(Control control)
+ throws LDAPException
+ {
+ return new ReplicationRepairRequestControl(control.getOID(),
+ control.isCritical());
+ }
+
+
+
+ /**
+ * Retrieves a string representation of this replication repair request
+ * control.
+ *
+ * @return A string representation of this replication repair request
+ * control.
+ */
+ public String toString()
+ {
+ StringBuilder buffer = new StringBuilder();
+ toString(buffer);
+ return buffer.toString();
+ }
+
+
+
+ /**
+ * Appends a string representation of this replication repair request control
+ * to the provided buffer.
+ *
+ * @param buffer The buffer to which the information should be appended.
+ */
+ public void toString(StringBuilder buffer)
+ {
+ buffer.append("ReplicationRepairRequestControl()");
+ }
+}
+
diff --git a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
index 6707392..9ce1489 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/util/ServerConstants.java
@@ -903,6 +903,13 @@
*/
public static final String LOG_SEVERITY_ALL = "all";
+ /**
+ * The English name for the basic none log severity used to log
+ * no error message beside some specific category.
+ */
+ public static final String LOG_SEVERITY_NONE = "none";
+
+
/**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
index a806599..0e7f481 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/workflowelement/localbackend/LocalBackendWorkflowElement.java
@@ -4702,6 +4702,47 @@
}
}
+ // If the attribute type is marked "NO-USER-MODIFICATION" then fail
+ // unless this is an internal operation or is related to
+ // synchronization in some way.
+ // This must be done before running the password policy code
+ // and any other code that may add attributes marked as
+ // "NO-USER-MODIFICATION"
+ //
+ // Note that doing this checks at this time
+ // of the processing does not make it possible for pre-parse plugins
+ // to add NO-USER-MODIFICATION attributes to the entry.
+ for (AttributeType at : userAttributes.keySet())
+ {
+ if (at.isNoUserModification())
+ {
+ if (! (localOp.isInternalOperation() ||
+ localOp.isSynchronizationOperation()))
+ {
+ localOp.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+ localOp.appendErrorMessage(ERR_ADD_ATTR_IS_NO_USER_MOD.get(
+ String.valueOf(entryDN), at.getNameOrOID()));
+
+ break addProcessing;
+ }
+ }
+ }
+
+ for (AttributeType at : operationalAttributes.keySet())
+ {
+ if (at.isNoUserModification())
+ {
+ if (! (localOp.isInternalOperation() ||
+ localOp.isSynchronizationOperation()))
+ {
+ localOp.setResultCode(ResultCode.UNWILLING_TO_PERFORM);
+ localOp.appendErrorMessage(ERR_ADD_ATTR_IS_NO_USER_MOD.get(
+ String.valueOf(entryDN), at.getNameOrOID()));
+
+ break addProcessing;
+ }
+ }
+ }
// Check to see if the entry already exists. We do this before
// checking whether the parent exists to ensure a referral entry
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
index 0a5dbef..4c6c666 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/ReplicationTestCase.java
@@ -322,33 +322,6 @@
*/
protected void configureReplication() throws Exception
{
- // Add the Multimaster replication 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.replication.plugin.MultimasterReplication\n";
- Entry synchroPluginEntry = TestCaseUtils.entryFromLdifString(synchroPluginLdif);
- DirectoryServer.getConfigHandler().addEntry(synchroPluginEntry, null);
- configEntryList.add(synchroPluginEntry.getDN());
- assertNotNull(DirectoryServer.getConfigEntry(DN
- .decode(synchroPluginStringDN)),
- "Unable to add the Multimaster replication plugin");
-
- // 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 replication plugin");
-
if (replServerEntry != null)
{
// Add the replication server
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationRepairControlTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationRepairControlTest.java
new file mode 100644
index 0000000..b78d06e
--- /dev/null
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/plugin/ReplicationRepairControlTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.replication.plugin;
+
+import org.opends.server.TestCaseUtils;
+import org.opends.server.replication.ReplicationTestCase;
+import org.opends.server.tools.LDAPModify;
+import org.testng.annotations.Test;
+import static org.testng.Assert.*;
+
+public class ReplicationRepairControlTest extends ReplicationTestCase
+{
+ @Test()
+ public void testRepairControl()
+ throws Exception
+ {
+ TestCaseUtils.startServer();
+
+ TestCaseUtils.initializeTestBackend(true);
+
+ // Test that we can't add an entry with the entryuuid attribute
+ // without specifying the replication repair control.
+ String path = TestCaseUtils.createTempFile(
+ "dn: uid=test.repair,o=test\n" +
+ "changetype: add\n" +
+ "objectClass: top\n" +
+ "objectClass: person" +
+ "objectClass: organizationalPerson" +
+ "objectClass: inetOrgPerson" +
+ "uid: test.repair" +
+ "givenName: Test" +
+ "sn: User" +
+ "cn: Test User" +
+ "userPassword: password" +
+ "entryuuid: d5b910d8-47cb-4ac0-9e5f-0f4a77de58d4");
+
+ String[] args =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-a",
+ "-f", path
+ };
+
+ assertEquals(LDAPModify.mainModify(args, false, null, null), 65);
+
+ // Test that we can't add an entry with the ds-sync-hist attribute
+ // without specifying the replication repair control.
+ String path1 = TestCaseUtils.createTempFile(
+ "dn: uid=test.repair,o=test\n" +
+ "changetype: add\n" +
+ "objectClass: top\n" +
+ "objectClass: person" +
+ "objectClass: organizationalPerson" +
+ "objectClass: inetOrgPerson" +
+ "uid: test.repair" +
+ "givenName: Test" +
+ "sn: User" +
+ "cn: Test User" +
+ "userPassword: password" +
+ "ds-sync-hist: description:00000108b3a6cbb800000001:del:deleted_value");
+
+ String[] args1 =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-a",
+ "-f", path1
+ };
+
+
+ assertEquals(LDAPModify.mainModify(args1, false, null, null), 65);
+
+ // Now Test specifying the replication repair control makes
+ // possible to add an entry with the entryuuid and ds-sync-hist attributes
+ // (notice the -J repairControlOid in the ldapmodify arguments)
+ String path2 = TestCaseUtils.createTempFile(
+ "dn: uid=test.repair,o=test\n" +
+ "changetype: add\n" +
+ "objectClass: top\n" +
+ "objectClass: person" +
+ "objectClass: organizationalPerson" +
+ "objectClass: inetOrgPerson" +
+ "uid: test.repair" +
+ "givenName: Test" +
+ "sn: User" +
+ "cn: Test User" +
+ "userPassword: password" +
+ "ds-sync-hist: description:00000108b3a6cbb800000001:del:deleted_value" +
+ "entryuuid: d5b910d8-47cb-4ac0-9e5f-0f4a77de58d4");
+
+ String[] args2 =
+ {
+ "-h", "127.0.0.1",
+ "-p", String.valueOf(TestCaseUtils.getServerLdapPort()),
+ "-D", "cn=Directory Manager",
+ "-w", "password",
+ "-J", "1.3.6.1.4.1.26027.1.5.2",
+ "-a",
+ "-f", path2
+ };
+
+ assertEquals(LDAPModify.mainModify(args2, false, null, null), 0);
+ }
+}
--
Gitblit v1.10.0