From 55a07ce2479e1b4c74dec15ce4e78e3fdf50a27c Mon Sep 17 00:00:00 2001
From: mrossign <mrossign@localhost>
Date: Wed, 16 Sep 2009 08:34:51 +0000
Subject: [PATCH] Fix for #4098 Initializing a fractional domain through import-ldif when server is down does not work
---
opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java | 947 ++++++++++++++++++++++++++++++++++-------------------------
1 files changed, 544 insertions(+), 403 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index 441af91..3890f49 100644
--- a/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -284,60 +284,8 @@
* Fractional replication variables.
*/
- // Return type of the parseFractionalConfig method
- private static final int NOT_FRACTIONAL = 0;
- private static final int EXCLUSIVE_FRACTIONAL = 1;
- private static final int INCLUSIVE_FRACTIONAL = 2;
-
- /**
- * Tells if fractional replication is enabled or not (some fractional
- * constraints have been put in place). If this is true then
- * fractionalExclusive explains the configuration mode and either
- * fractionalSpecificClassesAttributes or fractionalAllClassesAttributes or
- * both should be filled with something.
- */
- private boolean fractional = false;
-
- /**
- * - If true, tells that the configured fractional replication is exclusive:
- * Every attributes contained in fractionalSpecificClassesAttributes and
- * fractionalAllClassesAttributes should be ignored when replaying operation
- * in local backend.
- * - If false, tells that the configured fractional replication is inclusive:
- * Only attributes contained in fractionalSpecificClassesAttributes and
- * fractionalAllClassesAttributes should be taken into account in local
- * backend.
- */
- private boolean fractionalExclusive = true;
-
- /**
- * Used in fractional replication: holds attributes of a specific object
- * class.
- * - key = object class (name or OID of the class)
- * - value = the attributes of that class that should be taken into account
- * (inclusive or exclusive fractional replication) (name or OID of the
- * attribute)
- * When an operation coming from the network is to be locally replayed, if the
- * concerned entry has an objectClass attribute equals to 'key':
- * - inclusive mode: only the attributes in 'value' will be added/deleted/
- * modified
- * - exclusive mode: the attributes in 'value' will not be added/deleted/
- * modified
- */
- private Map<String, List<String>> fractionalSpecificClassesAttributes =
- new HashMap<String, List<String>>();
-
- /**
- * Used in fractional replication: holds attributes of any object class. When
- * an operation coming from the network is to be locally replayed:
- * - inclusive mode: only attributes of the matching entry not present in
- * fractionalAllClassesAttributes will be added/deleted/modified
- * - exclusive mode: attributes of the matching entry present in
- * fractionalAllClassesAttributes will not be added/deleted/modified
- * The attributes may be in human readable form of OID form.
- */
- private List<String> fractionalAllClassesAttributes =
- new ArrayList<String>();
+ // Holds the fractional configuration for this domain, if any.
+ private FractionalConfig fractionalConfig = null;
/**
* The list of attributes that cannot be used in fractional replication
@@ -371,7 +319,7 @@
private boolean followImport = true;
/**
- * This is the message id to be used when an import is stopped with error by
+ * The message id to be used when an import is stopped with error by
* the fractional replication ldif import plugin.
*/
private int importErrorMessageId = -1;
@@ -474,6 +422,7 @@
readAssuredConfig(configuration, false);
// Get fractional configuration
+ fractionalConfig = new FractionalConfig(baseDn);
readFractionalConfig(configuration, false);
setGroupId((byte)configuration.getGroupId());
@@ -628,44 +577,6 @@
}
/**
- * Returns true if fractional replication is configured in this domain.
- * @return True if fractional replication is configured in this domain.
- */
- public boolean isFractional()
- {
- return fractional;
- }
-
- /**
- * Returns true if the fractional replication configuration is exclusive mode
- * in this domain, false if inclusive mode.
- * @return True if the fractional replication configuration is exclusive mode
- * in this domain, false if inclusive mode.
- */
- public boolean isFractionalExclusive()
- {
- return fractionalExclusive;
- }
-
- /**
- * Returns the fractional configuration for specific classes.
- * @return The fractional configuration for specific classes.
- */
- public Map<String, List<String>> getFractionalSpecificClassesAttributes()
- {
- return fractionalSpecificClassesAttributes;
- }
-
- /**
- * Returns the fractional configuration for all classes.
- * @return The fractional configuration for all classes.
- */
- public List<String> getFractionalAllClassesAttributes()
- {
- return fractionalAllClassesAttributes;
- }
-
- /**
* Sets the error message id to be used when online import is stopped with
* error by the fractional replication ldif import plugin.
* @param importErrorMessageId The message to use.
@@ -695,34 +606,12 @@
private void readFractionalConfig(ReplicationDomainCfg configuration,
boolean allowReconnection)
{
- boolean needReconnection = false;
-
- // Prepare fractional configuration variables to parse
- Iterator<String> exclIt = null;
- SortedSet<String> fractionalExclude = configuration.getFractionalExclude();
- if (fractionalExclude != null)
- {
- exclIt = fractionalExclude.iterator();
- }
-
- Iterator<String> inclIt = null;
- SortedSet<String> fractionalInclude = configuration.getFractionalInclude();
- if (fractionalInclude != null)
- {
- inclIt = fractionalInclude.iterator();
- }
-
- // Get potentially new fractional configuration
- Map<String, List<String>> newFractionalSpecificClassesAttributes =
- new HashMap<String, List<String>>();
- List<String> newFractionalAllClassesAttributes = new ArrayList<String>();
-
- int newFractionalMode = NOT_FRACTIONAL;
+ // Read the configuration entry
+ FractionalConfig newFractionalConfig = null;
try
{
- newFractionalMode = parseFractionalConfig(exclIt, inclIt,
- newFractionalSpecificClassesAttributes,
- newFractionalAllClassesAttributes);
+ newFractionalConfig = FractionalConfig.toFractionalConfig(
+ configuration);
}
catch(ConfigException e)
{
@@ -738,14 +627,13 @@
/**
* Is there any change in fractional configuration ?
*/
+
// Compute current configuration
- int fractionalMode = fractionalConfigToInt();
+ boolean needReconnection = false;
try
{
- needReconnection = !isFractionalConfigEquivalent(fractionalMode,
- fractionalSpecificClassesAttributes, fractionalAllClassesAttributes,
- newFractionalMode, newFractionalSpecificClassesAttributes,
- newFractionalAllClassesAttributes);
+ needReconnection = !FractionalConfig.
+ isFractionalConfigEquivalent(fractionalConfig, newFractionalConfig);
}
catch (ConfigException e)
{
@@ -761,25 +649,28 @@
disableService();
// Set new configuration
- fractional = (newFractionalMode != NOT_FRACTIONAL);
- if (fractional)
+ int newFractionalMode = newFractionalConfig.fractionalConfigToInt();
+ fractionalConfig.setFractional(newFractionalMode !=
+ FractionalConfig.NOT_FRACTIONAL);
+ if (fractionalConfig.isFractional())
{
// Set new fractional configuration values
- if (newFractionalMode == EXCLUSIVE_FRACTIONAL)
- fractionalExclusive = true;
+ if (newFractionalMode == FractionalConfig.EXCLUSIVE_FRACTIONAL)
+ fractionalConfig.setFractionalExclusive(true);
else
- fractionalExclusive = false;
- fractionalSpecificClassesAttributes =
- newFractionalSpecificClassesAttributes;
- fractionalAllClassesAttributes = newFractionalAllClassesAttributes;
+ fractionalConfig.setFractionalExclusive(false);
+ fractionalConfig.setFractionalSpecificClassesAttributes(
+ newFractionalConfig.getFractionalSpecificClassesAttributes());
+ fractionalConfig.setFractionalAllClassesAttributes(
+ newFractionalConfig.fractionalAllClassesAttributes);
} else
{
// Reset default values
- fractionalExclusive = true;
- fractionalSpecificClassesAttributes =
- new HashMap<String, List<String>>();
- fractionalAllClassesAttributes =
- new ArrayList<String>();
+ fractionalConfig.setFractionalExclusive(true);
+ fractionalConfig.setFractionalSpecificClassesAttributes(
+ new HashMap<String, List<String>>());
+ fractionalConfig.setFractionalAllClassesAttributes(
+ new ArrayList<String>());
}
// Reconnect if required
@@ -873,7 +764,7 @@
// The backend is probably empty: if there is some fractional
// configuration in memory, we do not let the domain being connected,
// otherwise, it's ok
- if (fractional)
+ if (fractionalConfig.isFractional())
{
return false;
}
@@ -916,13 +807,14 @@
}
// Compare backend and local fractional configuration
- return isFractionalConfigConsistent(exclIt, inclIt);
+ return isFractionalConfigConsistent(fractionalConfig, exclIt, inclIt);
}
/**
* Return true if the fractional configuration passed as fractional
* configuration attribute values is equivalent to the fractional
* configuration stored in the local variables.
+ * @param fractionalConfig The local fractional configuration
* @param exclIt Fractional exclude mode configuration attribute values to
* analyze.
* @param inclIt Fractional include mode configuration attribute values to
@@ -931,7 +823,8 @@
* configuration attribute values is equivalent to the fractional
* configuration stored in the local variables.
*/
- public boolean isFractionalConfigConsistent(Iterator<String> exclIt,
+ static boolean isFractionalConfigConsistent(
+ FractionalConfig fractionalConfig, Iterator<String> exclIt,
Iterator<String> inclIt)
{
/*
@@ -943,68 +836,61 @@
new HashMap<String, List<String>>();
List<String> storedFractionalAllClassesAttributes = new ArrayList<String>();
- int storedFractionalMode = NOT_FRACTIONAL;
+ int storedFractionalMode = FractionalConfig.NOT_FRACTIONAL;
try
{
- storedFractionalMode = parseFractionalConfig(exclIt, inclIt,
- storedFractionalSpecificClassesAttributes,
+ storedFractionalMode = FractionalConfig.parseFractionalConfig(exclIt,
+ inclIt, storedFractionalSpecificClassesAttributes,
storedFractionalAllClassesAttributes);
} catch (ConfigException e)
{
// Should not happen as configuration in domain root entry is flushed
// from valid configuration in local variables
- Message message = NOTE_ERR_FRACTIONAL.get(baseDn.toString(),
- e.getLocalizedMessage());
+ Message message = NOTE_ERR_FRACTIONAL.get(
+ fractionalConfig.getBaseDn().toString(), e.getLocalizedMessage());
logError(message);
return false;
}
+ FractionalConfig storedFractionalConfig = new FractionalConfig(
+ fractionalConfig.getBaseDn());
+ storedFractionalConfig.setFractional(storedFractionalMode !=
+ FractionalConfig.NOT_FRACTIONAL);
+ // Set stored fractional configuration values
+ if (storedFractionalConfig.isFractional())
+ {
+ if (storedFractionalMode == FractionalConfig.EXCLUSIVE_FRACTIONAL)
+ storedFractionalConfig.setFractionalExclusive(true);
+ else
+ storedFractionalConfig.setFractionalExclusive(false);
+ }
+ storedFractionalConfig.setFractionalSpecificClassesAttributes(
+ storedFractionalSpecificClassesAttributes);
+ storedFractionalConfig.setFractionalAllClassesAttributes(
+ storedFractionalAllClassesAttributes);
+
/*
* Compare configuration stored in passed fractional configuration
* attributes with local variable one
*/
- // Compute current configuration from local variables
- int fractionalMode = fractionalConfigToInt();
try
{
- return isFractionalConfigEquivalent(fractionalMode,
- fractionalSpecificClassesAttributes, fractionalAllClassesAttributes,
- storedFractionalMode, storedFractionalSpecificClassesAttributes,
- storedFractionalAllClassesAttributes);
+ return FractionalConfig.
+ isFractionalConfigEquivalent(fractionalConfig, storedFractionalConfig);
} catch (ConfigException e)
{
// Should not happen as configuration in domain root entry is flushed
// from valid configuration in local variables so both should have already
// been checked
- Message message = NOTE_ERR_FRACTIONAL.get(baseDn.toString(),
- e.getLocalizedMessage());
+ Message message = NOTE_ERR_FRACTIONAL.get(
+ fractionalConfig.getBaseDn().toString(), e.getLocalizedMessage());
logError(message);
return false;
}
}
/**
- * Get an integer representation of the domain fractional configuration.
- * @return An integer representation of the domain fractional configuration.
- */
- public int fractionalConfigToInt()
- {
- int fractionalMode = -1;
- if (fractional)
- {
- if (fractionalExclusive)
- fractionalMode = EXCLUSIVE_FRACTIONAL;
- else
- fractionalMode = INCLUSIVE_FRACTIONAL;
- } else
- {
- fractionalMode = NOT_FRACTIONAL;
- }
- return fractionalMode;
- }
-
- /**
* Utility class to have get a sting iterator from an AtributeValue iterator.
* Assuming the attribute values are strings.
*/
@@ -1012,7 +898,6 @@
{
private Iterator<AttributeValue> attrValIt = null;
-
/**
* Creates a new AttributeValueStringIterator object.
* @param attrValIt The underlying attribute iterator to use, assuming
@@ -1050,83 +935,6 @@
}
/**
- * Compare 2 fractional replication configurations and returns true if they
- * are equivalent.
- * @param mode1 Fractional mode 1
- * @param specificClassesAttributes1 Specific classes attributes 1
- * @param allClassesAttributes1 All classes attributes 1
- * @param mode2 Fractional mode 1
- * @param specificClassesAttributes2 Specific classes attributes 2
- * @param allClassesAttributes2 Fractional mode 2
- * @return True if both configurations are equivalent.
- * @throws ConfigException If some classes or attributes could not be
- * retrieved from the schema.
- */
- private static boolean isFractionalConfigEquivalent(int mode1,
- Map<String, List<String>> specificClassesAttributes1,
- List<String> allClassesAttributes1, int mode2,
- Map<String, List<String>> specificClassesAttributes2,
- List<String> allClassesAttributes2) throws ConfigException
- {
- // Compare modes
- if (mode1 != mode2)
- return false;
-
- // Compare all classes attributes
- if (!isAttributeListEquivalent(allClassesAttributes1,
- allClassesAttributes2))
- return false;
-
- // Compare specific classes attributes
- if (specificClassesAttributes1.size() != specificClassesAttributes2.size())
- return false;
-
- // Check consistency of specific classes attributes
- /*
- * For each class in specificClassesAttributes1, check that the attribute
- * list is equivalent to specificClassesAttributes2 attribute list
- */
- Schema schema = DirectoryServer.getSchema();
- for (String className1 : specificClassesAttributes1.keySet())
- {
- // Get class from specificClassesAttributes1
- ObjectClass objectClass1 = schema.getObjectClass(className1);
- if (objectClass1 == null)
- {
- throw new ConfigException(
- NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS.get(className1));
- }
-
- // Look for matching one in specificClassesAttributes2
- boolean foundClass = false;
- for (String className2 : specificClassesAttributes2.keySet())
- {
- ObjectClass objectClass2 = schema.getObjectClass(className2);
- if (objectClass2 == null)
- {
- throw new ConfigException(
- NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS.get(className2));
- }
- if (objectClass1.equals(objectClass2))
- {
- foundClass = true;
- // Now compare the 2 attribute lists
- List<String> attributes1 = specificClassesAttributes1.get(className1);
- List<String> attributes2 = specificClassesAttributes2.get(className2);
- if (!isAttributeListEquivalent(attributes1, attributes2))
- return false;
- break;
- }
- }
- // Found matching class ?
- if (!foundClass)
- return false;
- }
-
- return true;
- }
-
- /**
* Compare 2 attribute lists and returns true if they are equivalent.
* @param attributes1 First attribute list to compare.
* @param attributes2 Second attribute list to compare.
@@ -1181,112 +989,6 @@
return true;
}
-
- /**
- * Parses a fractional replication configuration, filling the empty passed
- * variables and returning the used fractional mode. The 2 passed variables to
- * fill should be initialized (not null) and empty.
- * @param exclIt The list of fractional exclude configuration values (may be
- * null)
- * @param inclIt The list of fractional include configuration values (may be
- * null)
- * @param fractionalSpecificClassesAttributes An empty map to be filled with
- * what is read from the fractional configuration properties.
- * @param fractionalAllClassesAttributes An empty list to be filled with what
- * is read from the fractional configuration properties.
- * @return the fractional mode deduced from the passed configuration:
- * not fractional, exclusive fractional or inclusive fractional modes
- */
- private static int parseFractionalConfig (
- Iterator<String> exclIt, Iterator<String> inclIt,
- Map<String, List<String>> fractionalSpecificClassesAttributes,
- List<String> fractionalAllClassesAttributes) throws ConfigException
- {
- int fractional_mode = NOT_FRACTIONAL;
-
- // Determine if fractional-exclude or fractional-include property is used
- // : only one of them is allowed
- Iterator<String> fracConfIt = null;
-
- // Deduce the wished fractional mode
- if ((exclIt != null) && exclIt.hasNext())
- {
- if ((inclIt != null) && inclIt.hasNext())
- {
- throw new ConfigException(NOTE_ERR_FRACTIONAL_CONFIG_BOTH_MODES.get());
- }
- else
- {
- fractional_mode = EXCLUSIVE_FRACTIONAL;
- fracConfIt = exclIt;
- }
- }
- else
- {
- if ((inclIt != null) && inclIt.hasNext())
- {
- fractional_mode = INCLUSIVE_FRACTIONAL;
- fracConfIt = inclIt;
- }
- else
- {
- return NOT_FRACTIONAL;
- }
- }
-
- while (fracConfIt.hasNext())
- {
- // Parse a value with the form class:attr1,attr2...
- // or *:attr1,attr2...
- String fractCfgStr = fracConfIt.next();
- StringTokenizer st = new StringTokenizer(fractCfgStr, ":");
- int nTokens = st.countTokens();
- if (nTokens < 2)
- {
- throw new ConfigException(NOTE_ERR_FRACTIONAL_CONFIG_WRONG_FORMAT.
- get(fractCfgStr));
- }
- // Get the class name
- String classNameLower = st.nextToken().toLowerCase();
- boolean allClasses = classNameLower.equals("*");
- // Get the attributes
- String attributes = st.nextToken();
- st = new StringTokenizer(attributes, ",");
- while (st.hasMoreTokens())
- {
- String attrNameLower = st.nextToken().toLowerCase();
- // Store attribute in the appropriate variable
- if (allClasses)
- {
- // Avoid duplicate attributes
- if (!fractionalAllClassesAttributes.contains(attrNameLower))
- {
- fractionalAllClassesAttributes.add(attrNameLower);
- }
- }
- else
- {
- List<String> attrList =
- fractionalSpecificClassesAttributes.get(classNameLower);
- if (attrList != null)
- {
- // Avoid duplicate attributes
- if (!attrList.contains(attrNameLower))
- {
- attrList.add(attrNameLower);
- }
- } else
- {
- attrList = new ArrayList<String>();
- attrList.add(attrNameLower);
- fractionalSpecificClassesAttributes.put(classNameLower, attrList);
- }
- }
- }
- }
- return fractional_mode;
- }
-
/**
* Check that the passed fractional configuration is acceptable
* regarding configuration syntax, schema constraints...
@@ -1302,43 +1004,21 @@
* Parse fractional configuration
*/
- // Prepare fractional configuration variables to parse
- Iterator<String> exclIt = null;
- SortedSet<String> fractionalExclude = configuration.getFractionalExclude();
- if (fractionalExclude != null)
- {
- exclIt = fractionalExclude.iterator();
- }
+ // Read the configuration entry
+ FractionalConfig newFractionalConfig = FractionalConfig.toFractionalConfig(
+ configuration);
- Iterator<String> inclIt = null;
- SortedSet<String> fractionalInclude = configuration.getFractionalInclude();
- if (fractionalInclude != null)
+ if (!newFractionalConfig.isFractional())
{
- inclIt = fractionalInclude.iterator();
+ // Nothing to check
+ return;
}
// Prepare variables to be filled with config
Map<String, List<String>> newFractionalSpecificClassesAttributes =
- new HashMap<String, List<String>>();
- List<String> newFractionalAllClassesAttributes = new ArrayList<String>();
-
- int fractionalMode = parseFractionalConfig(exclIt, inclIt,
- newFractionalSpecificClassesAttributes,
- newFractionalAllClassesAttributes);
-
- switch (fractionalMode)
- {
- case NOT_FRACTIONAL:
- // Nothing to check
- return;
- case EXCLUSIVE_FRACTIONAL:
- case INCLUSIVE_FRACTIONAL:
- // Ok, checking done out of the switch statement
- break;
- default:
- // Should not happen
- return;
- }
+ newFractionalConfig.getFractionalSpecificClassesAttributes();
+ List<String> newFractionalAllClassesAttributes =
+ newFractionalConfig.getFractionalAllClassesAttributes();
/*
* Check attributes consistency : we only allow to filter MAY (optional)
@@ -1348,6 +1028,7 @@
// Check consistency of specific classes attributes
Schema schema = DirectoryServer.getSchema();
+ int fractionalMode = newFractionalConfig.fractionalConfigToInt();
for (String className : newFractionalSpecificClassesAttributes.keySet())
{
// Does the class exist ?
@@ -1381,7 +1062,7 @@
// No more checking for the extensibleObject class
if (!isExtensibleObjectClass)
{
- if (fractionalMode == EXCLUSIVE_FRACTIONAL)
+ if (fractionalMode == FractionalConfig.EXCLUSIVE_FRACTIONAL)
{
// Exclusive mode : the attribute must be optional
if (!fractionalClass.isOptional(attributeType))
@@ -1455,7 +1136,7 @@
public boolean fractionalFilterOperation(
PreOperationAddOperation addOperation, boolean performFiltering)
{
- return fractionalRemoveAttributesFromEntry(
+ return fractionalRemoveAttributesFromEntry(fractionalConfig,
addOperation.getEntryDN().getRDN(), addOperation.getObjectClasses(),
addOperation.getUserAttributes(), performFiltering);
}
@@ -1494,9 +1175,10 @@
Entry concernedEntry = modifyDNOperation.getOriginalEntry();
List<String> fractionalConcernedAttributes =
- createFractionalConcernedAttrList(
+ createFractionalConcernedAttrList(fractionalConfig,
concernedEntry.getObjectClasses().keySet());
+ boolean fractionalExclusive = fractionalConfig.isFractionalExclusive();
if ( fractionalExclusive && (fractionalConcernedAttributes.size() == 0) )
// No attributes to filter
return false;
@@ -1551,10 +1233,11 @@
}
/**
- * Remove attributes from an entry, according to the current fractional
+ * Remove attributes from an entry, according to the passed fractional
* configuration. The entry is represented by the 2 passed parameters.
* The attributes to be removed are removed using the remove method on the
* passed iterator for the attributes in the entry.
+ * @param fractionalConfig The fractional configuration to use
* @param entryRdn The rdn of the entry to add
* @param classes The object classes representing the entry to modify
* @param attributesMap The map of attributes/values to be potentially removed
@@ -1565,9 +1248,10 @@
* @return true if the operation contains some attributes subject to filtering
* by the fractional configuration
*/
- public boolean fractionalRemoveAttributesFromEntry(RDN entryRdn,
- Map<ObjectClass,String> classes, Map<AttributeType, List<Attribute>>
- attributesMap, boolean performFiltering)
+ static boolean fractionalRemoveAttributesFromEntry(
+ FractionalConfig fractionalConfig, RDN entryRdn,
+ Map<ObjectClass,String> classes, Map<AttributeType,
+ List<Attribute>> attributesMap, boolean performFiltering)
{
boolean hasSomeAttributesToFilter = false;
/*
@@ -1576,7 +1260,8 @@
*/
List<String> fractionalConcernedAttributes =
- createFractionalConcernedAttrList(classes.keySet());
+ createFractionalConcernedAttrList(fractionalConfig, classes.keySet());
+ boolean fractionalExclusive = fractionalConfig.isFractionalExclusive();
if ( fractionalExclusive && (fractionalConcernedAttributes.size() == 0) )
return false; // No attributes to filter
@@ -1724,13 +1409,14 @@
/**
* Prepares a list of attributes of interest for the fractional feature.
+ * @param fractionalConfig The fractional configuration to use
* @param entryObjectClasses The object classes of an entry on which an
* operation is going to be performed.
* @return The list of attributes of the entry to be excluded/included
* when the operation will be performed.
*/
- private List<String> createFractionalConcernedAttrList(
- Set<ObjectClass> entryObjectClasses)
+ private static List<String> createFractionalConcernedAttrList(
+ FractionalConfig fractionalConfig, Set<ObjectClass> entryObjectClasses)
{
/*
* Is the concerned entry of a type concerned by fractional replication
@@ -1742,6 +1428,11 @@
List<String> fractionalConcernedAttributes = new ArrayList<String>();
// Get object classes the entry matches
+ List<String> fractionalAllClassesAttributes =
+ fractionalConfig.getFractionalAllClassesAttributes();
+ Map<String, List<String>> fractionalSpecificClassesAttributes =
+ fractionalConfig.getFractionalSpecificClassesAttributes();
+
Set<String> fractionalClasses =
fractionalSpecificClassesAttributes.keySet();
for (ObjectClass entryObjectClass : entryObjectClasses)
@@ -1803,8 +1494,9 @@
Entry modifiedEntry = modifyOperation.getCurrentEntry();
List<String> fractionalConcernedAttributes =
- createFractionalConcernedAttrList(
+ createFractionalConcernedAttrList(fractionalConfig,
modifiedEntry.getObjectClasses().keySet());
+ boolean fractionalExclusive = fractionalConfig.isFractionalExclusive();
if ( fractionalExclusive && (fractionalConcernedAttributes.size() == 0) )
// No attributes to filter
return FRACTIONAL_HAS_NO_FRACTIONAL_FILTERED_ATTRIBUTES;
@@ -1959,7 +1651,7 @@
protected void initializeRemote(short target, short requestorID,
Task initTask) throws DirectoryException
{
- if ((target == RoutableMsg.ALL_SERVERS) && fractional)
+ if ((target == RoutableMsg.ALL_SERVERS) && fractionalConfig.isFractional())
{
Message msg = NOTE_ERR_FRACTIONAL_FORBIDDEN_FULL_UPDATE_FRACTIONAL.get(
baseDn.toString(), Short.toString(getServerId()));
@@ -2074,7 +1766,7 @@
ResultCode.UNWILLING_TO_PERFORM, msg);
}
- if (fractional)
+ if (fractionalConfig.isFractional())
{
if (addOperation.isSynchronizationOperation())
{
@@ -2212,7 +1904,7 @@
ResultCode.UNWILLING_TO_PERFORM, msg);
}
- if (fractional)
+ if (fractionalConfig.isFractional())
{
if (modifyDNOperation.isSynchronizationOperation())
{
@@ -2331,7 +2023,7 @@
ResultCode.UNWILLING_TO_PERFORM, msg);
}
- if (fractional)
+ if (fractionalConfig.isFractional())
{
if (modifyOperation.isSynchronizationOperation())
{
@@ -4798,4 +4490,453 @@
resultCode, message);
}
}
+
+ /**
+ * Gets the fractional configuration of this domain.
+ * @return The fractional configuration of this domain.
+ */
+ FractionalConfig getFractionalConfig()
+ {
+ return fractionalConfig;
+ }
+
+ /**
+ * This bean is a utility class used for holding the parsing
+ * result of a fractional configuration. It also contains some facility
+ * methods like fractional configuration comparison...
+ */
+ static class FractionalConfig
+ {
+ /**
+ * Tells if fractional replication is enabled or not (some fractional
+ * constraints have been put in place). If this is true then
+ * fractionalExclusive explains the configuration mode and either
+ * fractionalSpecificClassesAttributes or fractionalAllClassesAttributes or
+ * both should be filled with something.
+ */
+ private boolean fractional = false;
+
+ /**
+ * - If true, tells that the configured fractional replication is exclusive:
+ * Every attributes contained in fractionalSpecificClassesAttributes and
+ * fractionalAllClassesAttributes should be ignored when replaying operation
+ * in local backend.
+ * - If false, tells that the configured fractional replication is
+ * inclusive:
+ * Only attributes contained in fractionalSpecificClassesAttributes and
+ * fractionalAllClassesAttributes should be taken into account in local
+ * backend.
+ */
+ private boolean fractionalExclusive = true;
+
+ /**
+ * Used in fractional replication: holds attributes of a specific object
+ * class.
+ * - key = object class (name or OID of the class)
+ * - value = the attributes of that class that should be taken into account
+ * (inclusive or exclusive fractional replication) (name or OID of the
+ * attribute)
+ * When an operation coming from the network is to be locally replayed, if
+ * the concerned entry has an objectClass attribute equals to 'key':
+ * - inclusive mode: only the attributes in 'value' will be added/deleted/
+ * modified
+ * - exclusive mode: the attributes in 'value' will not be added/deleted/
+ * modified
+ */
+ private Map<String, List<String>> fractionalSpecificClassesAttributes =
+ new HashMap<String, List<String>>();
+
+ /**
+ * Used in fractional replication: holds attributes of any object class.
+ * When an operation coming from the network is to be locally replayed:
+ * - inclusive mode: only attributes of the matching entry not present in
+ * fractionalAllClassesAttributes will be added/deleted/modified
+ * - exclusive mode: attributes of the matching entry present in
+ * fractionalAllClassesAttributes will not be added/deleted/modified
+ * The attributes may be in human readable form of OID form.
+ */
+ private List<String> fractionalAllClassesAttributes =
+ new ArrayList<String>();
+
+ /**
+ * Base DN the fractional configuration is for.
+ */
+ private DN baseDn = null;
+
+ /**
+ * Constructs a new fractional configuration object.
+ * @param baseDn The base dn the object is for.
+ */
+ FractionalConfig(DN baseDn)
+ {
+ this.baseDn = baseDn;
+ }
+
+ /**
+ * Getter for fractional.
+ * @return True if the configuration has fractional enabled
+ */
+ boolean isFractional()
+ {
+ return fractional;
+ }
+
+ /**
+ * Set the fractional parameter.
+ * @param fractional The fractional parameter
+ */
+ void setFractional(boolean fractional)
+ {
+ this.fractional = fractional;
+ }
+
+ /**
+ * Getter for fractionalExclusive.
+ * @return True if the configuration has fractional exclusive enabled
+ */
+ boolean isFractionalExclusive()
+ {
+ return fractionalExclusive;
+ }
+
+ /**
+ * Set the fractionalExclusive parameter.
+ * @param fractionalExclusive The fractionalExclusive parameter
+ */
+ void setFractionalExclusive(boolean fractionalExclusive)
+ {
+ this.fractionalExclusive = fractionalExclusive;
+ }
+
+ /**
+ * Getter for fractionalSpecificClassesAttributes attribute.
+ * @return The fractionalSpecificClassesAttributes attribute.
+ */
+ Map<String, List<String>> getFractionalSpecificClassesAttributes()
+ {
+ return fractionalSpecificClassesAttributes;
+ }
+
+ /**
+ * Set the fractionalSpecificClassesAttributes parameter.
+ * @param fractionalSpecificClassesAttributes The
+ * fractionalSpecificClassesAttributes parameter to set.
+ */
+ void setFractionalSpecificClassesAttributes(Map<String,
+ List<String>> fractionalSpecificClassesAttributes)
+ {
+ this.fractionalSpecificClassesAttributes =
+ fractionalSpecificClassesAttributes;
+ }
+
+ /**
+ * Getter for fractionalSpecificClassesAttributes attribute.
+ * @return The fractionalSpecificClassesAttributes attribute.
+ */
+ List<String> getFractionalAllClassesAttributes()
+ {
+ return fractionalAllClassesAttributes;
+ }
+
+ /**
+ * Set the fractionalAllClassesAttributes parameter.
+ * @param fractionalAllClassesAttributes The
+ * fractionalSpecificClassesAttributes parameter to set.
+ */
+ void setFractionalAllClassesAttributes(
+ List<String> fractionalAllClassesAttributes)
+ {
+ this.fractionalAllClassesAttributes = fractionalAllClassesAttributes;
+ }
+
+ /**
+ * Getter for the base baseDn.
+ * @return The baseDn attribute.
+ */
+ DN getBaseDn()
+ {
+ return baseDn;
+ }
+
+ /**
+ * Extract the fractional configuration from the passed domain configuration
+ * entry.
+ * @param configuration The configuration object
+ * @return The fractional replication configuration.
+ * @throws ConfigException If an error occurred.
+ */
+ static FractionalConfig toFractionalConfig(
+ ReplicationDomainCfg configuration) throws ConfigException
+ {
+ // Prepare fractional configuration variables to parse
+ Iterator<String> exclIt = null;
+ SortedSet<String> fractionalExclude =
+ configuration.getFractionalExclude();
+ if (fractionalExclude != null)
+ {
+ exclIt = fractionalExclude.iterator();
+ }
+
+ Iterator<String> inclIt = null;
+ SortedSet<String> fractionalInclude =
+ configuration.getFractionalInclude();
+ if (fractionalInclude != null)
+ {
+ inclIt = fractionalInclude.iterator();
+ }
+
+ // Get potentially new fractional configuration
+ Map<String, List<String>> newFractionalSpecificClassesAttributes =
+ new HashMap<String, List<String>>();
+ List<String> newFractionalAllClassesAttributes = new ArrayList<String>();
+
+ int newFractionalMode = parseFractionalConfig(exclIt, inclIt,
+ newFractionalSpecificClassesAttributes,
+ newFractionalAllClassesAttributes);
+
+ // Create matching parsed config object
+ FractionalConfig result = new FractionalConfig(configuration.getBaseDN());
+ switch (newFractionalMode)
+ {
+ case NOT_FRACTIONAL:
+ result.setFractional(false);
+ result.setFractionalExclusive(true);
+ break;
+ case EXCLUSIVE_FRACTIONAL:
+ case INCLUSIVE_FRACTIONAL:
+ result.setFractional(true);
+ if (newFractionalMode == EXCLUSIVE_FRACTIONAL)
+ result.setFractionalExclusive(true);
+ else
+ result.setFractionalExclusive(false);
+ break;
+ }
+ result.setFractionalSpecificClassesAttributes(
+ newFractionalSpecificClassesAttributes);
+ result.setFractionalAllClassesAttributes(
+ newFractionalAllClassesAttributes);
+ return result;
+ }
+
+ /**
+ * Parses a fractional replication configuration, filling the empty passed
+ * variables and returning the used fractional mode. The 2 passed variables
+ * to fill should be initialized (not null) and empty.
+ * @param exclIt The list of fractional exclude configuration values (may be
+ * null)
+ * @param inclIt The list of fractional include configuration values (may be
+ * null)
+ * @param fractionalSpecificClassesAttributes An empty map to be filled with
+ * what is read from the fractional configuration properties.
+ * @param fractionalAllClassesAttributes An empty list to be filled with
+ * what is read from the fractional configuration properties.
+ * @return the fractional mode deduced from the passed configuration:
+ * not fractional, exclusive fractional or inclusive fractional
+ * modes
+ */
+ private static int parseFractionalConfig (
+ Iterator<String> exclIt, Iterator<String> inclIt,
+ Map<String, List<String>> fractionalSpecificClassesAttributes,
+ List<String> fractionalAllClassesAttributes) throws ConfigException
+ {
+ int fractional_mode = NOT_FRACTIONAL;
+
+ // Determine if fractional-exclude or fractional-include property is used
+ // : only one of them is allowed
+ Iterator<String> fracConfIt = null;
+
+ // Deduce the wished fractional mode
+ if ((exclIt != null) && exclIt.hasNext())
+ {
+ if ((inclIt != null) && inclIt.hasNext())
+ {
+ throw new ConfigException(
+ NOTE_ERR_FRACTIONAL_CONFIG_BOTH_MODES.get());
+ }
+ else
+ {
+ fractional_mode = EXCLUSIVE_FRACTIONAL;
+ fracConfIt = exclIt;
+ }
+ }
+ else
+ {
+ if ((inclIt != null) && inclIt.hasNext())
+ {
+ fractional_mode = INCLUSIVE_FRACTIONAL;
+ fracConfIt = inclIt;
+ }
+ else
+ {
+ return NOT_FRACTIONAL;
+ }
+ }
+
+ while (fracConfIt.hasNext())
+ {
+ // Parse a value with the form class:attr1,attr2...
+ // or *:attr1,attr2...
+ String fractCfgStr = fracConfIt.next();
+ StringTokenizer st = new StringTokenizer(fractCfgStr, ":");
+ int nTokens = st.countTokens();
+ if (nTokens < 2)
+ {
+ throw new ConfigException(NOTE_ERR_FRACTIONAL_CONFIG_WRONG_FORMAT.
+ get(fractCfgStr));
+ }
+ // Get the class name
+ String classNameLower = st.nextToken().toLowerCase();
+ boolean allClasses = classNameLower.equals("*");
+ // Get the attributes
+ String attributes = st.nextToken();
+ st = new StringTokenizer(attributes, ",");
+ while (st.hasMoreTokens())
+ {
+ String attrNameLower = st.nextToken().toLowerCase();
+ // Store attribute in the appropriate variable
+ if (allClasses)
+ {
+ // Avoid duplicate attributes
+ if (!fractionalAllClassesAttributes.contains(attrNameLower))
+ {
+ fractionalAllClassesAttributes.add(attrNameLower);
+ }
+ }
+ else
+ {
+ List<String> attrList =
+ fractionalSpecificClassesAttributes.get(classNameLower);
+ if (attrList != null)
+ {
+ // Avoid duplicate attributes
+ if (!attrList.contains(attrNameLower))
+ {
+ attrList.add(attrNameLower);
+ }
+ } else
+ {
+ attrList = new ArrayList<String>();
+ attrList.add(attrNameLower);
+ fractionalSpecificClassesAttributes.put(classNameLower, attrList);
+ }
+ }
+ }
+ }
+ return fractional_mode;
+ }
+
+ // Return type of the parseFractionalConfig method
+ static final int NOT_FRACTIONAL = 0;
+ static final int EXCLUSIVE_FRACTIONAL = 1;
+ static final int INCLUSIVE_FRACTIONAL = 2;
+
+ /**
+ * Get an integer representation of the domain fractional configuration.
+ * @return An integer representation of the domain fractional configuration.
+ */
+ int fractionalConfigToInt()
+ {
+ int fractionalMode = -1;
+ if (fractional)
+ {
+ if (fractionalExclusive)
+ fractionalMode = EXCLUSIVE_FRACTIONAL;
+ else
+ fractionalMode = INCLUSIVE_FRACTIONAL;
+ } else
+ {
+ fractionalMode = NOT_FRACTIONAL;
+ }
+ return fractionalMode;
+ }
+
+ /**
+ * Compare 2 fractional replication configurations and returns true if they
+ * are equivalent.
+ * @param fractionalConfig1 First fractional configuration
+ * @param fractionalConfig2 Second fractional configuration
+ * @return True if both configurations are equivalent.
+ * @throws ConfigException If some classes or attributes could not be
+ * retrieved from the schema.
+ */
+ static boolean isFractionalConfigEquivalent(
+ FractionalConfig fractionalConfig1, FractionalConfig fractionalConfig2)
+ throws ConfigException
+ {
+ // Comapre base DNs just to be consistent
+ if (!fractionalConfig1.getBaseDn().equals(fractionalConfig2.getBaseDn()))
+ return false;
+
+ // Compare modes
+ if ( (fractionalConfig1.isFractional() !=
+ fractionalConfig2.isFractional()) ||
+ (fractionalConfig1.isFractionalExclusive() !=
+ fractionalConfig2.isFractionalExclusive()) )
+ return false;
+
+ // Compare all classes attributes
+ List<String> allClassesAttributes1 =
+ fractionalConfig1.getFractionalAllClassesAttributes();
+ List<String> allClassesAttributes2 =
+ fractionalConfig2.getFractionalAllClassesAttributes();
+ if (!isAttributeListEquivalent(allClassesAttributes1,
+ allClassesAttributes2))
+ return false;
+
+ // Compare specific classes attributes
+ Map<String, List<String>> specificClassesAttributes1 =
+ fractionalConfig1.getFractionalSpecificClassesAttributes();
+ Map<String, List<String>> specificClassesAttributes2 =
+ fractionalConfig2.getFractionalSpecificClassesAttributes();
+ if (specificClassesAttributes1.size() !=
+ specificClassesAttributes2.size())
+ return false;
+
+ // Check consistency of specific classes attributes
+ /*
+ * For each class in specificClassesAttributes1, check that the attribute
+ * list is equivalent to specificClassesAttributes2 attribute list
+ */
+ Schema schema = DirectoryServer.getSchema();
+ for (String className1 : specificClassesAttributes1.keySet())
+ {
+ // Get class from specificClassesAttributes1
+ ObjectClass objectClass1 = schema.getObjectClass(className1);
+ if (objectClass1 == null)
+ {
+ throw new ConfigException(
+ NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS.get(className1));
+ }
+
+ // Look for matching one in specificClassesAttributes2
+ boolean foundClass = false;
+ for (String className2 : specificClassesAttributes2.keySet())
+ {
+ ObjectClass objectClass2 = schema.getObjectClass(className2);
+ if (objectClass2 == null)
+ {
+ throw new ConfigException(
+ NOTE_ERR_FRACTIONAL_CONFIG_UNKNOWN_OBJECT_CLASS.get(className2));
+ }
+ if (objectClass1.equals(objectClass2))
+ {
+ foundClass = true;
+ // Now compare the 2 attribute lists
+ List<String> attributes1 =
+ specificClassesAttributes1.get(className1);
+ List<String> attributes2 =
+ specificClassesAttributes2.get(className2);
+ if (!isAttributeListEquivalent(attributes1, attributes2))
+ return false;
+ break;
+ }
+ }
+ // Found matching class ?
+ if (!foundClass)
+ return false;
+ }
+
+ return true;
+ }
+ }
}
--
Gitblit v1.10.0