use of com.ms.silverking.cloud.ring.IntersectionResult in project SilverKing by Morgan-Stanley.
the class RingTree method merge.
private void merge(List<RingEntry> destList, List<RingEntry> _sourceList) {
List<RingEntry> sourceList;
Collections.sort(destList, RingEntryPositionComparator.instance);
if (_sourceList.size() == 0) {
throw new RuntimeException("Unexpected empty source list");
}
if (debug) {
System.out.println("merge: ************************");
System.out.println("\t\t" + RingEntry.toString(destList, "\n"));
System.out.println("...................................");
System.out.println("\t\t" + RingEntry.toString(_sourceList, "\n"));
System.out.println("===================================");
}
RingEntry.ensureEntryRegionsDisjoint(destList);
// RingEntry.ensureEntryRegionsDisjoint(_sourceList); // c/o since we support non-disjoint now
sourceList = new ArrayList<>(_sourceList);
while (sourceList.size() > 0) {
RingEntry oldSourceEntry;
RingRegion oldSourceRegion;
boolean destScanActive;
int searchResult;
int startIndex;
int endIndex;
int insertionIndex;
oldSourceEntry = sourceList.remove(0);
oldSourceRegion = oldSourceEntry.getRegion();
searchResult = Collections.binarySearch(destList, oldSourceEntry, RingEntryPositionComparator.instance);
if (searchResult < 0) {
// no exact match for this position was found
// we can look at the two entries next to us to figure out what's up
insertionIndex = -(searchResult + 1);
startIndex = insertionIndex - 1;
if (startIndex < 0) {
startIndex = 0;
endIndex = destList.size();
} else {
endIndex = startIndex + 1;
}
} else {
// we found an exact match for this position, there will be some sort of match below
// should have perfect match, no insertion
insertionIndex = Integer.MIN_VALUE;
startIndex = searchResult;
endIndex = searchResult;
}
// For simplicity, we perform a naive loop through all dests even though
// it would be possible to avoid this loop.
destScanActive = true;
for (int destIndex = startIndex; destScanActive && destIndex <= endIndex && destIndex < destList.size(); ) {
RingEntry oldDestEntry;
RingRegion oldDestRegion;
IntersectionResult iResult;
oldDestEntry = destList.get(destIndex);
oldDestRegion = oldDestEntry.getRegion();
iResult = RingRegion.intersect(oldDestRegion, oldSourceRegion);
// and avoid computing how many are added by each step
switch(iResult.getIntersectionType()) {
case disjoint:
destIndex++;
break;
case isomorphic:
destList.remove(destIndex);
destList.add(destIndex, oldDestEntry.addOwners(oldSourceEntry));
// go on to next source entry
destScanActive = false;
break;
case abPartial:
destList.remove(destIndex);
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping()));
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping()));
// go on to next source entry
destScanActive = false;
break;
case baPartial:
destList.remove(destIndex);
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping()));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping()));
// go on to next source entry
destScanActive = false;
break;
case // fall through
aSubsumesB:
destList.remove(destIndex);
if (iResult.getANonOverlapping().size() == 1) {
if (oldDestEntry.getRegion().getStart() == oldSourceEntry.getRegion().getStart()) {
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping()));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
} else if (oldDestEntry.getRegion().getEnd() == oldSourceEntry.getRegion().getEnd()) {
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping()));
} else {
throw new RuntimeException("panic");
}
} else if (iResult.getANonOverlapping().size() == 2) {
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping().get(1)));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping().get(0)));
} else {
throw new RuntimeException("panic");
}
// go on to next source entry
destScanActive = false;
break;
case // fall through
bSubsumesA:
destList.remove(destIndex);
if (iResult.getBNonOverlapping().size() == 1) {
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping()));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
} else if (iResult.getBNonOverlapping().size() == 2) {
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping().get(1)));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping()).addOwners(oldSourceEntry));
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping().get(0)));
} else {
throw new RuntimeException("panic");
}
// go on to next source entry
destScanActive = false;
break;
case wrappedPartial:
// below is from abPartial
destList.remove(destIndex);
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping().get(1)).addOwners(oldSourceEntry));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getANonOverlapping()));
destList.add(destIndex, oldDestEntry.replaceRegion(iResult.getOverlapping().get(0)).addOwners(oldSourceEntry));
sourceList.add(0, oldSourceEntry.replaceRegion(iResult.getBNonOverlapping()));
// go on to next source entry
destScanActive = false;
break;
case nonIdenticalAllRingspace:
// This case is prevented by the fact RingRegion normalizes all all-ringspace regions
throw new RuntimeException("panic");
default:
throw new RuntimeException("panic");
}
}
if (destScanActive) {
// if we didn't add it, then add here
destList.add(insertionIndex, oldSourceEntry);
// destList.add(oldSourceEntry);
// Collections.sort(destList, RingEntryPositionComparator.instance);
}
}
RingEntry.ensureEntryRegionsDisjoint(destList);
if (debug) {
System.out.println("merge complete: **************");
System.out.println("\t\t" + RingEntry.toString(destList));
System.out.println("======================================");
System.out.println();
}
}
use of com.ms.silverking.cloud.ring.IntersectionResult in project SilverKing by Morgan-Stanley.
the class TopologyRingCreator method reduceDataMovement.
// ///////////////////////////////////////////////////////////
public TopologyRing reduceDataMovement(TopologyRing oldRing, TopologyRing newRing, RingTreeRecipe recipe) {
SingleRing _old;
SingleRing _new;
SingleRing _ring;
_old = (SingleRing) oldRing.clone(Mutability.Mutable);
_new = (SingleRing) newRing.clone(Mutability.Mutable);
_ring = new SingleRing(_new.getNodeClass(), _new.getVersion(), _new.getStoragePolicyName());
while (_new.getMembers().iterator().hasNext()) {
RingEntry nEntry;
RingEntry oEntry;
IntersectionResult ir;
RingEntry shifted_nEntry;
nEntry = _new.getMembers().iterator().next();
oEntry = findBestRegionFor(_old, nEntry);
shifted_nEntry = nEntry.shiftTo(oEntry.getRegion().getStart());
ir = RingRegion.intersect(oEntry.getRegion(), shifted_nEntry.getRegion());
switch(ir.getIntersectionType()) {
case isomorphic:
_ring.addEntry(shifted_nEntry);
_old.removeEntry(oEntry);
_new.removeEntry(nEntry);
break;
case aSubsumesB:
// only one sub-case possible here
// r1 r2 (r1 ignored in this case)
// aaaaaa (oEntry)
// bbbb (shifted_nEntry)
{
RingEntry oEntry_2;
RingRegion r2;
r2 = new RingRegion(LongRingspace.nextPoint(shifted_nEntry.getRegion().getEnd()), oEntry.getRegion().getEnd());
oEntry_2 = oEntry.replaceRegion(r2);
_ring.addEntry(shifted_nEntry);
_old.removeEntry(oEntry);
_new.removeEntry(nEntry);
_old.addEntry(oEntry_2);
}
break;
case bSubsumesA:
// only one sub-case possible here
// aaaa (oEntry)
// bbbbbb (shifted_nEntry)
// r1 r2
{
RingEntry shifted_nEntry_1;
RingEntry shifted_nEntry_2;
RingRegion r1;
RingRegion r2;
r1 = oEntry.getRegion();
r2 = new RingRegion(LongRingspace.nextPoint(oEntry.getRegion().getEnd()), shifted_nEntry.getRegion().getEnd());
shifted_nEntry_1 = shifted_nEntry.replaceRegion(r1);
shifted_nEntry_2 = shifted_nEntry.replaceRegion(r2);
_ring.addEntry(shifted_nEntry_1);
_old.removeEntry(oEntry);
_new.removeEntry(nEntry);
_new.addEntry(shifted_nEntry_2);
}
break;
case disjoint:
case abPartial:
case baPartial:
throw new RuntimeException("shift makes these cases impossible");
default:
throw new RuntimeException("panic");
}
}
_ring.freeze(recipe.weightSpecs);
_ring = (SingleRing) _ring.simplify();
_ring.freeze(recipe.weightSpecs);
return _ring;
}
use of com.ms.silverking.cloud.ring.IntersectionResult in project SilverKing by Morgan-Stanley.
the class RegionTreePruner method pruneNonLeafNode.
private static ChecksumNode pruneNonLeafNode(NonLeafChecksumNode node, RingRegion pruneRegion) {
List<ChecksumNode> newChildren;
IntersectionResult iResult;
if (!node.getRegion().overlaps(pruneRegion)) {
throw new RuntimeException("panic");
}
iResult = RingRegion.intersect(node.getRegion(), pruneRegion);
if (iResult.getIntersectionType() == IntersectionType.wrappedPartial) {
// FUTURE - handle this
throw new RuntimeException("wrappedPartial pruning not yet handled");
}
newChildren = new ArrayList<>();
for (ChecksumNode child : node.getChildren()) {
if (child.getRegion().overlaps(pruneRegion)) {
newChildren.add(_prune(child, pruneRegion));
}
}
return new NonLeafChecksumNode(iResult.getOverlapping().get(0), newChildren);
}
use of com.ms.silverking.cloud.ring.IntersectionResult in project SilverKing by Morgan-Stanley.
the class RegionTreePruner method pruneLeafNode.
private static ChecksumNode pruneLeafNode(LeafChecksumNode node, RingRegion pruneRegion) {
IntersectionResult iResult;
RingRegion oRegion;
// long[] _kvc;
List<KeyAndVersionChecksum> kvcList;
List<KeyAndVersionChecksum> prunedKVCList;
if (!node.getRegion().overlaps(pruneRegion)) {
throw new RuntimeException("panic");
}
iResult = RingRegion.intersect(node.getRegion(), pruneRegion);
if (iResult.getIntersectionType() == IntersectionType.wrappedPartial) {
// FUTURE - handle this
throw new RuntimeException("wrappedPartial pruning not yet handled");
}
oRegion = iResult.getOverlapping().get(0);
// _kvc = node.getKeyAndVersionChecksumsAsArray();
// FUTURE - improve the efficiency of this approach
// This is n log n, and each step is heavy
// Should be able to do at least log n with very light steps
kvcList = node.getKeyAndVersionChecksums();
prunedKVCList = new ArrayList<>(kvcList.size());
for (KeyAndVersionChecksum kvc : kvcList) {
if (pruneRegion.contains(KeyUtil.keyToCoordinate(kvc.getKey()))) {
prunedKVCList.add(kvc);
}
}
return new LeafChecksumNode(oRegion, prunedKVCList);
}
use of com.ms.silverking.cloud.ring.IntersectionResult in project SilverKing by Morgan-Stanley.
the class CentralConvergenceController method syncRegion.
// ////////////////////////////////////////////////////////////////
private void syncRegion(long ns, RingEntry targetEntry, SyncTargets syncTargets, Action upstreamDependency, List<ReplicaSyncRequest> srList) throws ConvergenceException {
List<RingEntry> sourceEntries;
// Log.warningAsyncf("syncRegion %x %s", ns, targetEntry);
sourceEntries = curMap.getEntries(targetEntry.getRegion());
if (!sourceEntries.isEmpty()) {
// Log.warningAsyncf("%x target %s\towners %s\n", ns, targetEntry.getRegion(), CollectionUtil.toString(sourceEntries));
for (RingEntry sourceEntry : sourceEntries) {
List<IPAndPort> sourceOwners;
List<IPAndPort> nonExcludedSourceOwners;
sourceOwners = new ArrayList<>(sourceEntry.getOwnersIPList(OwnerQueryMode.Primary));
Log.info("Filtering exclusion set: ", exclusionSet);
nonExcludedSourceOwners = exclusionSet.filterByIP(sourceOwners);
if (nonExcludedSourceOwners.size() != sourceOwners.size()) {
Log.warningAsync("Raw sourceOwners: ", sourceOwners);
Log.warningAsync("Filtered nonExcludedSourceOwners: ", nonExcludedSourceOwners);
}
if (nonExcludedSourceOwners.size() == 0) {
Log.warningAsyncf("%x All nonLocalOwners excluded. Ignoring exclusions for this entry.", ns);
} else {
sourceOwners = nonExcludedSourceOwners;
}
IntersectionResult iResult;
// We don't want to request the entire source region.
// We're only interested in the portion(s) of the source region that cover(s) the target region.
// Log.warningAsyncf("Intersection %s %s", sourceEntry.getRegion(), targetEntry.getRegion());
iResult = RingRegion.intersect(sourceEntry.getRegion(), targetEntry.getRegion());
for (RingRegion commonSubRegion : iResult.getOverlapping()) {
List<IPAndPort> targetOwners;
List<IPAndPort> nonExcludedTargetOwners;
targetOwners = new ArrayList<>(targetEntry.getOwnersIPList(syncTargets.getOwnerQueryMode()));
nonExcludedTargetOwners = exclusionSet.filterByIP(targetOwners);
for (IPAndPort newOwner : nonExcludedTargetOwners) {
if (sourceOwners.contains(newOwner) && !syncUnchangedOwners) {
Log.warningAsyncf("Skipping unchanged owner: %s", newOwner);
} else {
Action prev;
prev = upstreamDependency;
for (IPAndPort sourceOwner : nonExcludedSourceOwners) {
prev = syncReplica(ns, commonSubRegion, newOwner.port(dhtConfig.getPort()), sourceOwner.port(dhtConfig.getPort()), prev, srList);
}
}
}
}
}
} else {
// This should actually never occur as the getEntries() call above
// has no notion of local/non-local. It just returns the owners, and there
// should always be owners.
Log.warningAsyncf("Primary convergence %x. No previous non-local owners for entry: ", ns, targetEntry);
throw new ConvergenceException("Unexpected no previous non-local owners for entry");
}
// Log.warningAsyncf("Done syncRegion %x %s", ns, targetEntry);
}
Aggregations