Search in sources :

Example 1 with IntersectionResult

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();
    }
}
Also used : RingRegion(com.ms.silverking.cloud.ring.RingRegion) IntersectionResult(com.ms.silverking.cloud.ring.IntersectionResult)

Example 2 with IntersectionResult

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;
}
Also used : RingRegion(com.ms.silverking.cloud.ring.RingRegion) IntersectionResult(com.ms.silverking.cloud.ring.IntersectionResult)

Example 3 with IntersectionResult

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);
}
Also used : IntersectionResult(com.ms.silverking.cloud.ring.IntersectionResult)

Example 4 with IntersectionResult

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);
}
Also used : KeyAndVersionChecksum(com.ms.silverking.cloud.dht.daemon.storage.KeyAndVersionChecksum) RingRegion(com.ms.silverking.cloud.ring.RingRegion) IntersectionResult(com.ms.silverking.cloud.ring.IntersectionResult)

Example 5 with IntersectionResult

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);
}
Also used : IPAndPort(com.ms.silverking.net.IPAndPort) RingRegion(com.ms.silverking.cloud.ring.RingRegion) IntersectionResult(com.ms.silverking.cloud.ring.IntersectionResult) RingEntry(com.ms.silverking.cloud.toporing.RingEntry)

Aggregations

IntersectionResult (com.ms.silverking.cloud.ring.IntersectionResult)6 RingRegion (com.ms.silverking.cloud.ring.RingRegion)5 RingEntry (com.ms.silverking.cloud.toporing.RingEntry)2 IPAndPort (com.ms.silverking.net.IPAndPort)2 KeyAndVersionChecksum (com.ms.silverking.cloud.dht.daemon.storage.KeyAndVersionChecksum)1