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/core/SubentryManager.java | 302 +++++++++++++++++++++++++++++++++-----------------
1 files changed, 199 insertions(+), 103 deletions(-)
diff --git a/opends/src/server/org/opends/server/core/SubentryManager.java b/opends/src/server/org/opends/server/core/SubentryManager.java
index 60a8c4e..b95f626 100644
--- a/opends/src/server/org/opends/server/core/SubentryManager.java
+++ b/opends/src/server/org/opends/server/core/SubentryManager.java
@@ -34,6 +34,7 @@
import org.opends.server.api.Backend;
import org.opends.server.api.BackendInitializationListener;
+import org.opends.server.api.DITCacheMap;
import org.opends.server.api.SubentryChangeListener;
import org.opends.server.api.plugin.InternalDirectoryServerPlugin;
import org.opends.server.api.plugin.PluginResult;
@@ -101,6 +102,9 @@
// A mapping between the DNs and applicable collective subentries.
private HashMap<DN,List<SubEntry>> dn2CollectiveSubEntry;
+ // A mapping between subentry DNs and subentry objects.
+ private DITCacheMap<SubEntry> dit2SubEntry;
+
// Internal search all operational attributes.
private LinkedHashSet<String> requestAttrs;
@@ -142,6 +146,7 @@
dn2SubEntry = new HashMap<DN,List<SubEntry>>();
dn2CollectiveSubEntry = new HashMap<DN,List<SubEntry>>();
+ dit2SubEntry = new DITCacheMap<SubEntry>();
changeListeners =
new CopyOnWriteArrayList<SubentryChangeListener>();
@@ -228,6 +233,7 @@
dn2SubEntry.put(subDN, subList);
}
}
+ dit2SubEntry.put(entry.getDN(), subEntry);
subList.add(subEntry);
}
finally
@@ -258,6 +264,7 @@
SubEntry subEntry = listIterator.next();
if (subEntry.getDN().equals(entry.getDN()))
{
+ dit2SubEntry.remove(entry.getDN());
listIterator.remove();
removed = true;
break;
@@ -283,6 +290,7 @@
SubEntry subEntry = listIterator.next();
if (subEntry.getDN().equals(entry.getDN()))
{
+ dit2SubEntry.remove(entry.getDN());
listIterator.remove();
removed = true;
break;
@@ -657,6 +665,7 @@
SubEntry subEntry = listIterator.next();
if (backend.handlesEntry(subEntry.getDN()))
{
+ dit2SubEntry.remove(subEntry.getDN());
listIterator.remove();
// Notify change listeners.
@@ -694,6 +703,7 @@
SubEntry subEntry = listIterator.next();
if (backend.handlesEntry(subEntry.getDN()))
{
+ dit2SubEntry.remove(subEntry.getDN());
listIterator.remove();
// Notify change listeners.
@@ -731,17 +741,63 @@
{
if (entry.isSubentry() || entry.isLDAPSubentry())
{
+ lock.writeLock().lock();
try
{
- addSubEntry(entry);
+ try
+ {
+ addSubEntry(entry);
+
+ // Notify change listeners.
+ for (SubentryChangeListener changeListener :
+ changeListeners)
+ {
+ try
+ {
+ changeListener.handleSubentryAdd(entry);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+
+ // FIXME -- Handle this.
+ }
+ }
+ finally
+ {
+ lock.writeLock().unlock();
+ }
+ }
+ }
+
+ private void doPostDelete(Entry entry)
+ {
+ lock.writeLock().lock();
+ try
+ {
+ for (SubEntry subEntry : dit2SubEntry.getSubtree(entry.getDN()))
+ {
+ removeSubEntry(subEntry.getEntry());
// Notify change listeners.
for (SubentryChangeListener changeListener :
- changeListeners)
+ changeListeners)
{
try
{
- changeListener.handleSubentryAdd(entry);
+ changeListener.handleSubentryDelete(subEntry.getEntry());
}
catch (Exception e)
{
@@ -752,40 +808,10 @@
}
}
}
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // FIXME -- Handle this.
- }
}
- }
-
- private void doPostDelete(Entry entry)
- {
- if (entry.isSubentry() || entry.isLDAPSubentry())
+ finally
{
- removeSubEntry(entry);
-
- // Notify change listeners.
- for (SubentryChangeListener changeListener :
- changeListeners)
- {
- try
- {
- changeListener.handleSubentryDelete(entry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
- }
- }
+ lock.writeLock().unlock();
}
}
@@ -793,39 +819,20 @@
{
boolean notify = false;
- if (oldEntry.isSubentry() || oldEntry.isLDAPSubentry())
+ lock.writeLock().lock();
+ try
{
- removeSubEntry(oldEntry);
- notify = true;
- }
- if (newEntry.isSubentry() || newEntry.isLDAPSubentry())
- {
- try
+ if (oldEntry.isSubentry() || oldEntry.isLDAPSubentry())
{
- addSubEntry(newEntry);
+ removeSubEntry(oldEntry);
notify = true;
}
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // FIXME -- Handle this.
- }
- }
-
- if (notify)
- {
- // Notify change listeners.
- for (SubentryChangeListener changeListener :
- changeListeners)
+ if (newEntry.isSubentry() || newEntry.isLDAPSubentry())
{
try
{
- changeListener.handleSubentryModify(
- oldEntry, newEntry);
+ addSubEntry(newEntry);
+ notify = true;
}
catch (Exception e)
{
@@ -833,48 +840,96 @@
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
+
+ // FIXME -- Handle this.
}
}
+
+ if (notify)
+ {
+ // Notify change listeners.
+ for (SubentryChangeListener changeListener :
+ changeListeners)
+ {
+ try
+ {
+ changeListener.handleSubentryModify(
+ oldEntry, newEntry);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
+ }
+ }
+ finally
+ {
+ lock.writeLock().unlock();
}
}
private void doPostModifyDN(Entry oldEntry, Entry newEntry)
{
- if (oldEntry.isSubentry() || oldEntry.isLDAPSubentry())
+ String oldDNString = oldEntry.getDN().toNormalizedString();
+ String newDNString = newEntry.getDN().toNormalizedString();
+
+ lock.writeLock().lock();
+ try
{
- removeSubEntry(oldEntry);
- try
+ Collection<SubEntry> setToDelete =
+ dit2SubEntry.getSubtree(oldEntry.getDN());
+ for (SubEntry subentry : setToDelete)
{
- addSubEntry(newEntry);
- }
- catch (Exception e)
- {
- if (debugEnabled())
- {
- TRACER.debugCaught(DebugLogLevel.ERROR, e);
- }
-
- // FIXME -- Handle this.
- }
-
- // Notify change listeners.
- for (SubentryChangeListener changeListener :
- changeListeners)
- {
+ removeSubEntry(subentry.getEntry());
+ oldEntry = subentry.getEntry();
try
{
- changeListener.handleSubentryModify(
- oldEntry, newEntry);
+ StringBuilder builder = new StringBuilder(
+ subentry.getEntry().getDN().toNormalizedString());
+ int oldDNIndex = builder.lastIndexOf(oldDNString);
+ builder.replace(oldDNIndex, builder.length(),
+ newDNString);
+ String subentryDNString = builder.toString();
+ newEntry = subentry.getEntry().duplicate(false);
+ newEntry.setDN(DN.decode(subentryDNString));
+ addSubEntry(newEntry);
}
catch (Exception e)
{
+ // Shouldnt happen.
if (debugEnabled())
{
TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
}
+
+ // Notify change listeners.
+ for (SubentryChangeListener changeListener :
+ changeListeners)
+ {
+ try
+ {
+ changeListener.handleSubentryModify(
+ oldEntry, newEntry);
+ }
+ catch (Exception e)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
+ }
+ }
+ }
}
}
+ finally
+ {
+ lock.writeLock().unlock();
+ }
}
/**
@@ -920,27 +975,36 @@
{
Entry entry = deleteOperation.getEntryToDelete();
- if (entry.isSubentry() || entry.isLDAPSubentry())
+ lock.readLock().lock();
+ try
{
- for (SubentryChangeListener changeListener :
- changeListeners)
+ for (SubEntry subEntry : dit2SubEntry.getSubtree(entry.getDN()))
{
- try
+ for (SubentryChangeListener changeListener :
+ changeListeners)
{
- changeListener.checkSubentryDeleteAcceptable(entry);
- }
- catch (DirectoryException de)
- {
- if (debugEnabled())
+ try
{
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ changeListener.checkSubentryDeleteAcceptable(
+ subEntry.getEntry());
}
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
- return PluginResult.PreOperation.stopProcessing(
- de.getResultCode(), de.getMessageObject());
+ return PluginResult.PreOperation.stopProcessing(
+ de.getResultCode(), de.getMessageObject());
+ }
}
}
}
+ finally
+ {
+ lock.readLock().unlock();
+ }
return PluginResult.PreOperation.continueOperationProcessing();
}
@@ -991,29 +1055,61 @@
{
Entry oldEntry = modifyDNOperation.getOriginalEntry();
Entry newEntry = modifyDNOperation.getUpdatedEntry();
+ String oldDNString = oldEntry.getDN().toNormalizedString();
+ String newDNString = newEntry.getDN().toNormalizedString();
- if (oldEntry.isSubentry() || oldEntry.isLDAPSubentry())
+ lock.readLock().lock();
+ try
{
- for (SubentryChangeListener changeListener :
- changeListeners)
+ Collection<SubEntry> setToDelete =
+ dit2SubEntry.getSubtree(oldEntry.getDN());
+ for (SubEntry subentry : setToDelete)
{
+ oldEntry = subentry.getEntry();
try
{
- changeListener.checkSubentryModifyAcceptable(
- oldEntry, newEntry);
+ StringBuilder builder = new StringBuilder(
+ subentry.getEntry().getDN().toNormalizedString());
+ int oldDNIndex = builder.lastIndexOf(oldDNString);
+ builder.replace(oldDNIndex, builder.length(),
+ newDNString);
+ String subentryDNString = builder.toString();
+ newEntry = subentry.getEntry().duplicate(false);
+ newEntry.setDN(DN.decode(subentryDNString));
}
- catch (DirectoryException de)
+ catch (Exception e)
{
+ // Shouldnt happen.
if (debugEnabled())
{
- TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ TRACER.debugCaught(DebugLogLevel.ERROR, e);
}
+ }
+ for (SubentryChangeListener changeListener :
+ changeListeners)
+ {
+ try
+ {
+ changeListener.checkSubentryModifyAcceptable(
+ oldEntry, newEntry);
+ }
+ catch (DirectoryException de)
+ {
+ if (debugEnabled())
+ {
+ TRACER.debugCaught(DebugLogLevel.ERROR, de);
+ }
- return PluginResult.PreOperation.stopProcessing(
- de.getResultCode(), de.getMessageObject());
+ return PluginResult.PreOperation.stopProcessing(
+ de.getResultCode(), de.getMessageObject());
+ }
}
}
}
+ finally
+ {
+ lock.readLock().unlock();
+ }
return PluginResult.PreOperation.continueOperationProcessing();
}
--
Gitblit v1.10.0