package org.jboss.ha.hasessionstate.server;
import java.util.ArrayList;
import java.util.Iterator;
import org.jboss.ha.framework.interfaces.SubPartitionInfo;
import org.jboss.ha.framework.interfaces.SubPartitionsInfo;
public class HASessionStateTopologyComputerImpl implements HASessionStateTopologyComputer
{
protected long nodesPerSubPartition = 0;
protected String sessionStateIdentifier = null;
public HASessionStateTopologyComputerImpl ()
{
}
public void init (String sessionStateName, long nodesPerSubPartition)
{
this.sessionStateIdentifier = sessionStateName;
this.nodesPerSubPartition = nodesPerSubPartition;
}
public void start () {}
public SubPartitionsInfo computeNewTopology (SubPartitionsInfo currentTopology, ArrayList newReplicants)
{
if (newReplicants.size () < 1)
currentTopology.partitions = null;
else if (newReplicants.size () == 1)
{
if (currentTopology.partitions != null)
currentTopology = computeCompatibleComposition (currentTopology, newReplicants);
else
{
SubPartitionInfo aPartition = new SubPartitionInfo ();
aPartition.subPartitionName = getSubPartitionName (currentTopology);
aPartition.memberNodeNames.add (newReplicants.get (0));
SubPartitionInfo[] thePartition =
{ aPartition };
currentTopology.partitions = thePartition;
}
}
else if (currentTopology == null || currentTopology.partitions == null)
currentTopology = computerFirstComposition (currentTopology, newReplicants);
else
currentTopology = computeCompatibleComposition (currentTopology, newReplicants);
return currentTopology;
}
protected SubPartitionsInfo computerFirstComposition (SubPartitionsInfo splitingInfo, ArrayList replicants)
{
int i=0;
String rep = null;
ArrayList newConfig = new ArrayList ();
SubPartitionInfo aPartition = null;
int grpNumber = 0;
for (Iterator reps = replicants.iterator (); reps.hasNext (); i++)
{
rep = (String)reps.next ();
if ( (i%nodesPerSubPartition) == 0 )
{
grpNumber++;
aPartition = new SubPartitionInfo ();
aPartition.subPartitionName = getSubPartitionName (splitingInfo);
newConfig.add (aPartition);
}
aPartition.memberNodeNames.add (rep);
}
if (aPartition.memberNodeNames.size () == 1)
{
rep = (String) aPartition.memberNodeNames.get (0); newConfig.remove (grpNumber-1); aPartition = (SubPartitionInfo)(newConfig.get (grpNumber-1)); aPartition.memberNodeNames.add (rep); }
SubPartitionInfo[] newSpliting = new SubPartitionInfo[1];
newSpliting = (SubPartitionInfo[]) newConfig.toArray (newSpliting);
splitingInfo.partitions = newSpliting;
return splitingInfo;
}
protected SubPartitionsInfo computeCompatibleComposition (SubPartitionsInfo splitingInfo, ArrayList replicants)
{
SubPartitionInfo[] newSpliting = null;
ArrayList newSubParts = new ArrayList ();
for (int i=0; i<splitingInfo.partitions.length; i++)
{
SubPartitionInfo currentSubPart = splitingInfo.partitions[i];
SubPartitionInfo newCurrent = null;
Iterator iter = currentSubPart.memberNodeNames.iterator ();
while (iter.hasNext ())
{
String node = (String)iter.next ();
if (replicants.contains (node))
{
if (newCurrent == null)
{
newCurrent = (SubPartitionInfo)currentSubPart.clone ();
newCurrent.memberNodeNames.clear ();
}
newCurrent.memberNodeNames.add (node);
}
}
if (newCurrent != null)
newSubParts.add (newCurrent);
}
Iterator iter = replicants.iterator ();
ArrayList newMembersNotInAGroup = new ArrayList ();
while (iter.hasNext ())
{
boolean found = false;
String aMember = (String)iter.next ();
Iterator iterNewSubPart = newSubParts.iterator ();
while (iterNewSubPart.hasNext () && !found)
if (((SubPartitionInfo)iterNewSubPart.next ()).memberNodeNames.contains (aMember))
found = true;
if (!found)
newMembersNotInAGroup.add (aMember);
}
iter = null;
ArrayList smallerGroups = new ArrayList ();
ArrayList correctlySizedGroups = new ArrayList ();
ArrayList biggerGroups = new ArrayList ();
for (int i=0; i<newSubParts.size (); i++)
{
int groupSize = ((SubPartitionInfo)newSubParts.get (i)).memberNodeNames.size ();
if (groupSize < this.nodesPerSubPartition)
smallerGroups.add (newSubParts.get (i));
else if (groupSize > this.nodesPerSubPartition)
biggerGroups.add (newSubParts.get (i));
else
correctlySizedGroups.add (newSubParts.get (i));
}
java.util.Collections.sort (smallerGroups);
iter = newMembersNotInAGroup.iterator ();
while (iter.hasNext ())
{
String member = (String)iter.next ();
SubPartitionInfo target = null;
if (smallerGroups.size () > 0)
{
target = (SubPartitionInfo)smallerGroups.get (0); target.memberNodeNames.add (member);
if (target.memberNodeNames.size () == this.nodesPerSubPartition)
{
smallerGroups.remove (0);
correctlySizedGroups.add (target);
}
}
else
{
target = new SubPartitionInfo ();
target.setIsNewGroup ();
target.subPartitionName = getSubPartitionName (splitingInfo);
target.memberNodeNames.add (member);
smallerGroups.add (target);
java.util.Collections.sort (smallerGroups);
}
}
iter = biggerGroups.iterator ();
while (iter.hasNext ())
{
SubPartitionInfo big = (SubPartitionInfo)iter.next ();
if (smallerGroups.size () > 0)
{
String member = (String)big.memberNodeNames.get (big.memberNodeNames.size ()-1); SubPartitionInfo target = null;
target = (SubPartitionInfo)smallerGroups.get (0); target.memberNodeNames.add (member);
big.memberNodeNames.remove (big.memberNodeNames.size () -1);
if (target.memberNodeNames.size () == this.nodesPerSubPartition)
{
smallerGroups.remove (0);
correctlySizedGroups.add (target);
}
}
}
correctlySizedGroups.addAll (biggerGroups);
boolean thirdStepFinished = (smallerGroups.size () == 0);
while (!thirdStepFinished)
{
SubPartitionInfo current = (SubPartitionInfo)smallerGroups.get (smallerGroups.size ()-1);
for (int i = smallerGroups.size ()-2; i >= 0; i--)
{
SubPartitionInfo merger = (SubPartitionInfo)smallerGroups.get (i);
if ((merger.memberNodeNames.size () + current.memberNodeNames.size ()) <= this.nodesPerSubPartition)
{
current.merge (merger);
smallerGroups.remove (i);
}
if (current.memberNodeNames.size () == this.nodesPerSubPartition)
break;
}
if (current.memberNodeNames.size () > 1)
{
smallerGroups.remove (smallerGroups.size ()-1);
correctlySizedGroups.add (current);
}
thirdStepFinished = ( (smallerGroups.size () == 0) ||
((smallerGroups.size () == 1) && ( ((SubPartitionInfo)smallerGroups.get (0)).memberNodeNames.size () == 1)) );
}
if (smallerGroups.size () > 0)
{
if (correctlySizedGroups.size ()>0)
{
java.util.Collections.sort (correctlySizedGroups);
SubPartitionInfo merger = (SubPartitionInfo)smallerGroups.get (0);
SubPartitionInfo master = (SubPartitionInfo)correctlySizedGroups.get (0);
master.merge (merger);
}
else
{
correctlySizedGroups.add (smallerGroups.get (0));
}
}
newSpliting = new SubPartitionInfo[1];
newSpliting = (SubPartitionInfo[])correctlySizedGroups.toArray (newSpliting);
splitingInfo.partitions = newSpliting;
return splitingInfo;
}
protected String getSubPartitionName (SubPartitionsInfo manager)
{
return this.sessionStateIdentifier + "-Group-" + manager.getNextGroupId ();
}
}