github.com/m3db/m3@v1.5.0/src/dbnode/topology/testutil/topology.go (about) 1 // Copyright (c) 2018 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package testutil 22 23 import ( 24 "fmt" 25 26 "github.com/m3db/m3/src/cluster/shard" 27 "github.com/m3db/m3/src/dbnode/sharding" 28 "github.com/m3db/m3/src/dbnode/topology" 29 ) 30 31 const ( 32 // SelfID is the string used to represent the ID of the origin node. 33 SelfID = "self" 34 ) 35 36 // MustNewTopologyMap returns a new topology.Map with provided parameters. 37 // It's a utility method to make tests easier to write. 38 func MustNewTopologyMap( 39 replicas int, 40 assignment map[string][]shard.Shard, 41 ) topology.Map { 42 v := NewTopologyView(replicas, assignment) 43 m, err := v.Map() 44 if err != nil { 45 panic(err.Error()) 46 } 47 return m 48 } 49 50 // NewTopologyView returns a new TopologyView with provided parameters. 51 // It's a utility method to make tests easier to write. 52 func NewTopologyView( 53 replicas int, 54 assignment map[string][]shard.Shard, 55 ) TopologyView { 56 total := 0 57 for _, shards := range assignment { 58 total += len(shards) 59 } 60 61 return TopologyView{ 62 HashFn: sharding.DefaultHashFn(total / replicas), 63 Replicas: replicas, 64 Assignment: assignment, 65 } 66 } 67 68 // TopologyView represents a snaphshot view of a topology.Map. 69 type TopologyView struct { 70 HashFn sharding.HashFn 71 Replicas int 72 Assignment map[string][]shard.Shard 73 } 74 75 // Map returns the topology.Map corresponding to a TopologyView. 76 func (v TopologyView) Map() (topology.Map, error) { 77 var ( 78 hostShardSets []topology.HostShardSet 79 allShards []shard.Shard 80 unique = make(map[uint32]struct{}) 81 ) 82 83 for hostID, assignedShards := range v.Assignment { 84 shardSet, _ := sharding.NewShardSet(assignedShards, v.HashFn) 85 host := topology.NewHost(hostID, fmt.Sprintf("%s:9000", hostID)) 86 hostShardSet := topology.NewHostShardSet(host, shardSet) 87 hostShardSets = append(hostShardSets, hostShardSet) 88 for _, s := range assignedShards { 89 if _, ok := unique[s.ID()]; !ok { 90 unique[s.ID()] = struct{}{} 91 uniqueShard := shard.NewShard(s.ID()).SetState(shard.Available) 92 allShards = append(allShards, uniqueShard) 93 } 94 } 95 } 96 97 shardSet, err := sharding.NewShardSet(allShards, v.HashFn) 98 if err != nil { 99 return nil, err 100 } 101 102 opts := topology.NewStaticOptions(). 103 SetHostShardSets(hostShardSets). 104 SetReplicas(v.Replicas). 105 SetShardSet(shardSet) 106 107 return topology.NewStaticMap(opts), nil 108 } 109 110 // HostShardStates is a human-readable way of describing an initial state topology 111 // on a host-by-host basis. 112 type HostShardStates map[string][]shard.Shard 113 114 // NewStateSnapshot creates a new initial topology state snapshot using HostShardStates 115 // as input. 116 func NewStateSnapshot(numMajorityReplicas int, hostShardStates HostShardStates) *topology.StateSnapshot { 117 topoState := &topology.StateSnapshot{ 118 Origin: topology.NewHost(SelfID, "127.0.0.1"), 119 MajorityReplicas: numMajorityReplicas, 120 ShardStates: make(map[topology.ShardID]map[topology.HostID]topology.HostShardState), 121 } 122 123 for host, shards := range hostShardStates { 124 for _, shard := range shards { 125 hostShardStates, ok := topoState.ShardStates[topology.ShardID(shard.ID())] 126 if !ok { 127 hostShardStates = make(map[topology.HostID]topology.HostShardState) 128 } 129 130 hostShardStates[topology.HostID(host)] = topology.HostShardState{ 131 Host: topology.NewHost(host, host+"address"), 132 ShardState: shard.State(), 133 } 134 topoState.ShardStates[topology.ShardID(shard.ID())] = hostShardStates 135 } 136 } 137 138 return topoState 139 }