Historical.java revision a395dd575518d9e5280fc5d5d5ef47c61b174647
/*
* 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
* 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
*
*
* Copyright 2006-2008 Sun Microsystems, Inc.
*/
/**
* This class is used to store historical information that is
* used to resolve modify conflicts
*
* It is assumed that the common case is not to have conflict and
* therefore is optimized (in order of importance) for :
* 1- detecting potential conflict
* 2- fast update of historical information for non-conflicting change
* 3- fast and efficient purge
* 4- compact
* 5- solve conflict. This should also be as fast as possible but
* not at the cost of any of the other previous objectives
*
* One Historical object is created for each entry in the entry cache
* each Historical Object contains a list of attribute historical information
*/
public class Historical
{
/**
* The name of the attribute used to store historical information.
*/
/**
* Name used to store attachment of historical information in the
* operation.
*/
/**
* The name of the entryuuid attribute.
*/
/*
* contains Historical information for each attribute sorted by attribute type
*/
/**
* {@inheritDoc}
*/
{
}
/**
* Process an operation.
* This method is responsible for detecting and resolving conflict for
* modifyOperation. This is done by using the historical information.
*
* @param modifyOperation the operation to be processed
* @param modifiedEntry the entry that is being modified (before modification)
* @return true if the replayed operation was in conflict
*/
{
boolean bConflict = false;
modsIterator.hasNext(); )
{
modifiedEntry, m))
{
bConflict = true;
}
}
return bConflict;
}
/**
* Append replacement of state information to a given modification.
*
* @param modifyOperation the modification.
*/
{
/*
* If this is a local operation we need first to update the historical
* information, then update the entry with the historical information
* If this is a replicated operation the historical information has
* already been set in the resolveConflict phase and we only need
* to update the entry
*/
{
{
}
}
}
/**
* Get the AttrInfo for a given Modification.
* The AttrInfo is the object that is used to store the historical
* information of a given attribute type.
* If there is no historical information for this attribute yet, a new
* empty AttrInfo is created and returned.
*
* @param mod The Modification that must be used.
* @return The AttrInfo corresponding to the given Modification.
*/
{
if (isHistoricalAttribute(modAttr))
{
// Don't keep historical information for the attribute that is
// used to store the historical information.
return null;
}
if (attrInfoWithOptions != null)
{
}
else
{
attrInfoWithOptions = new AttrInfoWithOptions();
}
{
}
return attrInfo;
}
/**
* Encode the historical information in an operational attribute.
* @return The historical information encoded in an operational attribute.
*/
{
{
{
boolean delAttr = false;
{
{
optionsBuilder.append(s);
}
}
/* generate the historical information for deleted attributes */
if (deleteTime != null)
{
delAttr = true;
}
/* generate the historical information for modified attribute values */
{
{
strValue);
}
{
{
delAttr = false;
}
else
{
{
":add";
}
else
{
}
}
strValue);
}
}
if (delAttr)
{
+ ":attrDel";
}
}
}
{
}
else
{
}
return attr;
}
/**
* read the historical information from the entry attribute and
* load it into the Historical object attached to the entry.
* @param entry The entry which historical information must be loaded
* @return the generated Historical information
*/
{
{
return histObj;
}
try
{
{
{
{
/*
* This attribute is unknown from the schema
* Just skip it, the modification will be processed but no
* historical information is going to be kept.
* Log information for the repair tool.
*/
continue;
}
/* if attribute type does not match we create new
* AttrInfoWithOptions and AttrInfo
* we also add old AttrInfoWithOptions into histObj.attributesInfo
* if attribute type match but options does not match we create new
* AttrInfo that we add to AttrInfoWithOptions
* if both match we keep everything
*/
if (attrType != lastAttrType)
{
attrInfoWithOptions = new AttrInfoWithOptions();
}
else
{
{
}
}
}
}
} catch (Exception e)
{
// Any exception happening here means that the coding of the hsitorical
// information was wrong.
// Log an error and continue with an empty historical.
}
/* set the reference to the historical information in the entry */
return histObj;
}
/**
* Use this historical information to generate fake operations that would
* result in this historical information.
* TODO : This is only implemented for modify operation, should implement ADD
* DELETE and MODRDN.
* @param entry The Entry to use to generate the FakeOperation Iterable.
*
* @return an Iterable of FakeOperation that would result in this historical
* information.
*/
{
{
{
{
if (fakeOperation != null)
{
}
else
{
if (uuidString != null)
{
cn, uuidString);
}
}
}
}
}
return operations.values();
}
/**
* Get the Attribute used to store the historical information from
* the given Entry.
*
* @param entry The entry containing the historical information.
*
* @return The Attribute used to store the historical information.
*/
{
}
/**
* Get the entry unique Id in String form.
*
* @param entry The entry for which the unique id should be returned.
*
* @return The Unique Id of the entry if it has one. null, otherwise.
*/
{
{
{
}
}
return uuidString;
}
/**
* Get the Entry Unique Id from an add operation.
* This must be called after the entry uuid preop plugin (i.e no
* sooner than the replication provider pre-op)
*
* @param op The operation
* @return The Entry Unique Id String form.
*/
{
{
{
}
}
return uuidString;
}
/**
* Check if a given attribute is an attribute used to store historical
* information.
*
* @param attr The attribute that needs to be checked.
*
* @return a boolean indicating if the given attribute is
* used to store historical information.
*/
{
}
}