private HostAndPartitionRendezVous(Domain domain, int partitionId, HostAndIndexInRing hostAndIndexInRing) { this.host = hostAndIndexInRing.getHost(); this.rendezVousHashValue = computeRendezVousHashValue(domain, partitionId, hostAndIndexInRing.getIndexInRing()); }
protected Host getHostResponsibleForPartition(List<HostAndIndexInRing> validHostsSorted, int partitionNumber) { int hostIndex = partitionNumber % validHostsSorted.size(); return validHostsSorted.get(hostIndex).getHost(); } }
@Override protected Map<Integer, Host> getPartitionsAssignment(Domain domain, List<HostAndIndexInRing> hosts) { Map<Host, List<Integer>> hostToPartitions = getHostToPartitions(domain, hosts); // Compute result Map<Integer, Host> result = new HashMap<Integer, Host>(); for (Map.Entry<Host, List<Integer>> entry : hostToPartitions.entrySet()) { for (Integer partitionNumber : entry.getValue()) { result.put(partitionNumber, entry.getKey()); } } return result; }
private Map<Integer, Host> getPartitionAssignment(int numPartitions, Host... hosts) { List<AbstractMappingPartitionAssigner.HostAndIndexInRing> hostAndIndexInRings = new ArrayList<AbstractMappingPartitionAssigner.HostAndIndexInRing>(); for (int i = 0; i < hosts.length; ++i) { Host host = hosts[i]; if (host != null) { hostAndIndexInRings.add(new AbstractMappingPartitionAssigner.HostAndIndexInRing(host, i)); } } RendezVousPartitionAssigner partitionAssigner = new RendezVousPartitionAssigner(); Domain domain = new MockDomain("domain", 0, numPartitions, null, null, null, null); return partitionAssigner.getPartitionsAssignment(domain, hostAndIndexInRings); } }
private Map<Host, List<Integer>> getHostToPartitions(Domain domain, List<HostAndIndexInRing> hosts) { int maxPartitionsPerHost = getMaxPartitionsPerHost(domain, hosts.size()); Map<Host, List<Integer>> result = new HashMap<Host, List<Integer>>(); result.put(hostAndIndex.getHost(), new ArrayList<Integer>()); List<Host> orderedHosts = getOrderedWeightedHosts(domain, partitionNumber, hosts); boolean assigned = false; for (Host host : orderedHosts) {
validHosts.add(new HostAndIndexInRing(host, hostIndex)); Map<Integer, Host> partitionAssignments = getPartitionsAssignment(domain, validHosts); for (Map.Entry<Integer, Host> entry : partitionAssignments.entrySet()) { int partitionNumber = entry.getKey();
@Test public void testDependsOnlyOnOrder() { final int numPartitions = 1000; Map<Integer, Host> mappingsA = getPartitionAssignment(numPartitions, host1, host2, host3); assertEquals(numPartitions, mappingsA.size()); Map<Integer, Host> mappingsB = getPartitionAssignment(numPartitions, host2, host3, host1); assertEquals(numPartitions, mappingsB.size()); assertEquals(partitionsAssignedTo(host1, mappingsA), partitionsAssignedTo(host2, mappingsB)); assertEquals(partitionsAssignedTo(host2, mappingsA), partitionsAssignedTo(host3, mappingsB)); assertEquals(partitionsAssignedTo(host3, mappingsA), partitionsAssignedTo(host1, mappingsB)); }
public RingGroupConductor(RingGroupConductorConfigurator configurator) throws IOException { this(configurator, new RingGroupUpdateTransitionFunctionImpl(new RendezVousPartitionAssigner(), statusFor(configurator) ), new RingGroupAutoconfigureTransitionFunction( configurator.getTargetHostsPerRing(), configurator.getConfiguredDomains(), statusFor(configurator) ) ); }
mappings = getPartitionAssignment(1, host1); assertEquals(1, mappings.size()); assertEquals(host1, mappings.get(0)); mappings = getPartitionAssignment(1, host1, host2, host3); assertEquals(1, numPartitionsAssigned(host1, mappings)); mappings = getPartitionAssignment(2, host1, host2, host3); assertEquals(2, mappings.size()); assertEquals(1, numPartitionsAssigned(host1, mappings)); assertEquals(0, numPartitionsAssigned(host2, mappings)); assertEquals(1, numPartitionsAssigned(host3, mappings)); mappings = getPartitionAssignment(3, host1, host2, host3); assertEquals(3, mappings.size()); assertEquals(1, numPartitionsAssigned(host1, mappings)); assertEquals(1, numPartitionsAssigned(host2, mappings)); assertEquals(1, numPartitionsAssigned(host3, mappings)); mappings = getPartitionAssignment(4, host1, host2, host3); assertEquals(4, mappings.size()); assertEquals(2, numPartitionsAssigned(host1, mappings)); assertEquals(0, numPartitionsAssigned(host2, mappings)); assertEquals(2, numPartitionsAssigned(host3, mappings)); mappings = getPartitionAssignment(5, host1, host2, host3); assertEquals(5, mappings.size()); assertEquals(2, numPartitionsAssigned(host1, mappings)); assertEquals(2, numPartitionsAssigned(host2, mappings));
Map<Domain, Map<Integer, Set<Host>>> domainToPartitionToHostsFullyServing, ThreeNestedMap<Domain, Integer, String, Long> domainPartitionBucketCounts) throws IOException { boolean isAssigned = partitionAssigner.isAssigned(host); boolean isUpToDate = Hosts.isUpToDate(host, domainGroup); boolean isFullyServing = PartitionUtils.isFullyServing(host, true, status); partitionAssigner.assign(host); return;
private List<Host> getOrderedWeightedHosts(Domain domain, int partitionNumber, List<HostAndIndexInRing> hosts) { List<HostAndPartitionRendezVous> hostAndPartitionRendezVousList = new ArrayList<HostAndPartitionRendezVous>(); for (HostAndIndexInRing hostAndIndexInRing : hosts) { hostAndPartitionRendezVousList.add(new HostAndPartitionRendezVous(domain, partitionNumber, hostAndIndexInRing)); } // Sort by rendez vous hash values Collections.sort(hostAndPartitionRendezVousList); // Build result List<Host> result = new ArrayList<Host>(); for (HostAndPartitionRendezVous hostAndPartitionRendezVous : hostAndPartitionRendezVousList) { result.add(hostAndPartitionRendezVous.host); } return result; }
@Override public void prepare(Ring ring, Set<DomainAndVersion> domainVersions, RingGroupConductorMode ringGroupConductorMode) throws IOException { this.domainVersions = domainVersions; this.ringGroupConductorMode = ringGroupConductorMode; this.hostToDomainToPartitionsMappings = getHostToDomainToPartitionsMapping(ring, domainVersions); domains = new HashSet<Domain>(); for (DomainAndVersion domainVersion : domainVersions) { domains.add(domainVersion.getDomain()); } }
@Override protected Map<Integer, Host> getPartitionsAssignment(Domain domain, List<HostAndIndexInRing> hosts) { Map<Integer, Host> result = new HashMap<Integer, Host>(); for (int partitionNumber = 0; partitionNumber < domain.getNumParts(); ++partitionNumber) { // Find a host for this partition result.put(partitionNumber, getHostResponsibleForPartition(hosts, partitionNumber)); } return result; }
@Test public void testConsistency() { final int numPartitions = 1000; Map<Integer, Host> mappingsA = getPartitionAssignment(numPartitions, host1, host2, host3); assertEquals(numPartitions, mappingsA.size()); Map<Integer, Host> mappingsB = getPartitionAssignment(numPartitions, host1, null, host3); assertEquals(numPartitions, mappingsB.size()); int consistent = 0; for (int partitionId = 0; partitionId < numPartitions; ++partitionId) { if (mappingsA.get(partitionId).equals(mappingsB.get(partitionId))) { ++consistent; } } assertEquals(665, consistent); }
@Override public void manageTransitions(Coordinator coordinator, RingGroup ringGroup) throws IOException { DomainGroup domainGroup = ringGroup.getDomainGroup(); if (domainGroup == null) { // Nothing to do LOG.info("Domain group not found. Nothing to do."); return; } Map<Domain, Map<Integer, Set<Host>>> domainToPartitionToHostsFullyServing = PartitionUtils.domainToPartitionToHostsServing(ringGroup, status); ThreeNestedMap<Domain, Integer, String, Long> domainPartitionBucketHostCounts = PartitionUtils.domainToPartitionToHostsServingInBucket(domainToPartitionToHostsFullyServing, status); SortedSet<Ring> rings = ringGroup.getRingsSorted(); int ringCount = rings.size(); for (Ring ring : rings) { partitionAssigner.prepare(ring, domainGroup.getDomainVersions(), ringGroup.getRingGroupConductorMode()); for (Host host : ring.getHostsSorted()) { manageTransitions(ringCount, host, domainGroup, domainToPartitionToHostsFullyServing, domainPartitionBucketHostCounts); } } }