From a09e50d8d41c0f50c486742f4cc2343083c635e3 Mon Sep 17 00:00:00 2001
From: ludovicp <ludovicp@localhost>
Date: Fri, 25 Jun 2010 09:25:49 +0000
Subject: [PATCH] Fixes issues #4552 #4557, making sure plugins and internal services are properly handling subtree move or delete. The changes particularly resolve problems raised by the community with the referential integrity and the isMemberOf plug-ins. Unit-tests have been updated to cover those cases
---
opends/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java | 113 +++++++++++++++++++++++++++++++++++++++++++-------------
1 files changed, 86 insertions(+), 27 deletions(-)
diff --git a/opends/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java b/opends/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java
index e279194..5dab099 100644
--- a/opends/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java
+++ b/opends/src/server/org/opends/server/plugins/ReferentialIntegrityPlugin.java
@@ -35,6 +35,7 @@
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
@@ -53,6 +54,7 @@
import org.opends.server.api.ServerShutdownListener;
import org.opends.server.api.plugin.*;
import org.opends.server.config.ConfigException;
+import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
import org.opends.server.core.ModifyOperation;
import org.opends.server.loggers.debug.DebugTracer;
@@ -136,6 +138,12 @@
*/
public static final String MODIFYDN_DNS="modifyDNs";
+ /**
+ * Used to save a set in the delete operation attachment map that
+ * holds the subordinate entry DNs related to a delete operation.
+ */
+ public static final String DELETE_DNS="deleteDNs";
+
//The buffered reader that is used to read the log file by the background
//thread.
private BufferedReader reader;
@@ -163,6 +171,7 @@
case POST_OPERATION_DELETE:
case POST_OPERATION_MODIFY_DN:
case SUBORDINATE_MODIFY_DN:
+ case SUBORDINATE_DELETE:
// These are acceptable.
break;
@@ -305,6 +314,7 @@
case POSTOPERATIONDELETE:
case POSTOPERATIONMODIFYDN:
case SUBORDINATEMODIFYDN:
+ case SUBORDINATEDELETE:
// These are acceptable.
break;
default:
@@ -370,23 +380,18 @@
return PluginResult.PostOperation.continueOperationProcessing();
}
- if (modifyDNOperation.getNewSuperior() == null)
+ Map<DN,DN>modDNmap=
+ (Map<DN, DN>) modifyDNOperation.getAttachment(MODIFYDN_DNS);
+ if(modDNmap == null)
{
- // The entry was simply renamed below the same parent.
- DN oldEntryDN=modifyDNOperation.getOriginalEntry().getDN();
- DN newEntryDN=modifyDNOperation.getUpdatedEntry().getDN();
- Map<DN,DN> modDNmap=new LinkedHashMap<DN,DN>();
- modDNmap.put(oldEntryDN, newEntryDN);
- processModifyDN(modDNmap,(interval != 0));
+ modDNmap=new LinkedHashMap<DN,DN>();
+ modifyDNOperation.setAttachment(MODIFYDN_DNS, modDNmap);
}
- else
- {
- // The entry was moved below a new parent. Use the saved map of old DNs
- // and new DNs from the operation attachment.
- Map<DN,DN> modDNmap =
- (Map<DN, DN>) modifyDNOperation.getAttachment(MODIFYDN_DNS);
- processModifyDN(modDNmap, (interval != 0));
- }
+ DN oldEntryDN=modifyDNOperation.getOriginalEntry().getDN();
+ DN newEntryDN=modifyDNOperation.getUpdatedEntry().getDN();
+ modDNmap.put(oldEntryDN, newEntryDN);
+
+ processModifyDN(modDNmap, (interval != 0));
return PluginResult.PostOperation.continueOperationProcessing();
}
@@ -396,6 +401,7 @@
/**
* {@inheritDoc}
*/
+ @SuppressWarnings("unchecked")
public PluginResult.PostOperation doPostOperation(
PostOperationDeleteOperation deleteOperation)
{
@@ -406,7 +412,16 @@
return PluginResult.PostOperation.continueOperationProcessing();
}
- processDelete(deleteOperation.getEntryDN(), (interval != 0));
+ Set<DN> deleteDNset =
+ (Set<DN>) deleteOperation.getAttachment(DELETE_DNS);
+ if(deleteDNset == null)
+ {
+ deleteDNset = new HashSet<DN>();
+ deleteOperation.setAttachment(MODIFYDN_DNS, deleteDNset);
+ }
+ deleteDNset.add(deleteOperation.getEntryDN());
+
+ processDelete(deleteDNset, (interval != 0));
return PluginResult.PostOperation.continueOperationProcessing();
}
@@ -433,6 +448,27 @@
return PluginResult.SubordinateModifyDN.continueOperationProcessing();
}
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ public PluginResult.SubordinateDelete processSubordinateDelete(
+ DeleteOperation deleteOperation, Entry entry)
+ {
+ // This cast gives an unchecked cast warning, suppress it
+ // since the cast is ok.
+ Set<DN> deleteDNset =
+ (Set<DN>) deleteOperation.getAttachment(DELETE_DNS);
+ if(deleteDNset == null)
+ {
+ // First time through, create the set and set it in
+ // the operation attachment.
+ deleteDNset = new HashSet<DN>();
+ deleteOperation.setAttachment(DELETE_DNS, deleteDNset);
+ }
+ deleteDNset.add(entry.getDN());
+ return PluginResult.SubordinateDelete.continueOperationProcessing();
+ }
/**
* Verify that the specified attribute has either a distinguished name syntax
@@ -546,17 +582,17 @@
* a later time.
*
*/
- private void processDelete(DN entryDN, boolean log)
+ private void processDelete(Set<DN> deleteDNset, boolean log)
{
if(log)
{
- writeLog(entryDN);
+ writeLog(deleteDNset);
}
else
{
for(DN baseDN : getBaseDNsToSearch())
{
- searchBaseDN(baseDN, entryDN, null);
+ doBaseDN(baseDN, deleteDNset);
}
}
}
@@ -674,6 +710,24 @@
}
/**
+ * This method is used in foreground processing of a delete operation.
+ * It uses the specified set to perform base DN searching for each
+ * element.
+ *
+ * @param baseDN The DN to base the search at.
+ *
+ * @param deleteDNset The set containing the delete DNs.
+ *
+ */
+ private void doBaseDN(DN baseDN, Set<DN> deleteDNset)
+ {
+ for(DN deletedEntryDN : deleteDNset)
+ {
+ searchBaseDN(baseDN, deletedEntryDN, null);
+ }
+ }
+
+ /**
* For each attribute type, delete the specified old entry DN and
* optionally add the specified new entry DN if the DN is not null.
* The specified entry is used to see if it contains each attribute type so
@@ -812,18 +866,23 @@
}
/**
- * Write the specified entry DN to the log file. This entry DN is related to
- * a delete operation.
+ * Write the specified entry DNs to the log file.
+ * These entry DNs are related to a delete operation.
*
* @param deletedEntryDN The DN of the deleted entry.
*
*/
- private void writeLog(DN deletedEntryDN) {
- synchronized(logFile) {
- try {
+ private void writeLog(Set<DN> deleteDNset) {
+ synchronized(logFile)
+ {
+ try
+ {
setupWriter();
- writer.write(deletedEntryDN.toNormalizedString());
- writer.newLine();
+ for (DN deletedEntryDN : deleteDNset)
+ {
+ writer.write(deletedEntryDN.toNormalizedString());
+ writer.newLine();
+ }
writer.flush();
writer.close();
}
@@ -860,7 +919,7 @@
DN origDn = DN.decode(a[0]);
//If there is only a single DN string than it must be a delete.
if(a.length == 1) {
- processDelete(origDn, false);
+ processDelete(Collections.singleton(origDn), false);
} else {
DN movedDN=DN.decode(a[1]);
processModifyDN(origDn, movedDN);
--
Gitblit v1.10.0