1
// Copyright 2020 The CubeFS Authors.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
24
"github.com/cubefs/cubefs/util/log"
28
DefaultRandomSelectorName = "default"
32
_ = RegisterDataPartitionSelector(DefaultRandomSelectorName, newDefaultRandomSelector)
35
func newDefaultRandomSelector(_ string) (selector DataPartitionSelector, e error) {
36
selector = &DefaultRandomSelector{
37
localLeaderPartitions: make([]*DataPartition, 0),
38
partitions: make([]*DataPartition, 0),
43
type DefaultRandomSelector struct {
45
localLeaderPartitions []*DataPartition
46
partitions []*DataPartition
49
func (s *DefaultRandomSelector) Name() string {
50
return DefaultRandomSelectorName
53
func (s *DefaultRandomSelector) Refresh(partitions []*DataPartition) (err error) {
54
var localLeaderPartitions []*DataPartition
55
for i := 0; i < len(partitions); i++ {
56
if strings.Split(partitions[i].Hosts[0], ":")[0] == LocalIP {
57
localLeaderPartitions = append(localLeaderPartitions, partitions[i])
64
s.localLeaderPartitions = localLeaderPartitions
65
s.partitions = partitions
69
func (s *DefaultRandomSelector) Select(exclude map[string]struct{}) (dp *DataPartition, err error) {
70
dp = s.getLocalLeaderDataPartition(exclude)
76
partitions := s.partitions
79
dp = s.getRandomDataPartition(partitions, exclude)
84
log.LogErrorf("DefaultRandomSelector: no writable data partition with %v partitions and exclude(%v)",
85
len(partitions), exclude)
86
return nil, fmt.Errorf("no writable data partition")
89
func (s *DefaultRandomSelector) RemoveDP(partitionID uint64) {
91
rwPartitionGroups := s.partitions
92
localLeaderPartitions := s.localLeaderPartitions
96
for i = 0; i < len(rwPartitionGroups); i++ {
97
if rwPartitionGroups[i].PartitionID == partitionID {
101
if i >= len(rwPartitionGroups) {
104
newRwPartition := make([]*DataPartition, 0)
105
newRwPartition = append(newRwPartition, rwPartitionGroups[:i]...)
106
newRwPartition = append(newRwPartition, rwPartitionGroups[i+1:]...)
110
s.partitions = newRwPartition
114
for i = 0; i < len(localLeaderPartitions); i++ {
115
if localLeaderPartitions[i].PartitionID == partitionID {
119
if i >= len(localLeaderPartitions) {
122
newLocalLeaderPartitions := make([]*DataPartition, 0)
123
newLocalLeaderPartitions = append(newLocalLeaderPartitions, localLeaderPartitions[:i]...)
124
newLocalLeaderPartitions = append(newLocalLeaderPartitions, localLeaderPartitions[i+1:]...)
128
s.localLeaderPartitions = newLocalLeaderPartitions
133
func (s *DefaultRandomSelector) Count() int {
136
return len(s.partitions)
139
func (s *DefaultRandomSelector) getLocalLeaderDataPartition(exclude map[string]struct{}) *DataPartition {
141
localLeaderPartitions := s.localLeaderPartitions
143
return s.getRandomDataPartition(localLeaderPartitions, exclude)
146
func (s *DefaultRandomSelector) getRandomDataPartition(partitions []*DataPartition, exclude map[string]struct{}) (
148
length := len(partitions)
153
rand.Seed(time.Now().UnixNano())
154
index := rand.Intn(length)
155
dp = partitions[index]
156
if !isExcluded(dp, exclude) {
157
log.LogDebugf("DefaultRandomSelector: select dp[%v] address[%p], index %v", dp, dp, index)
161
log.LogWarnf("DefaultRandomSelector: first random partition was excluded, get partition from others")
164
for i := 0; i < length; i++ {
165
currIndex = (index + i) % length
166
if !isExcluded(partitions[currIndex], exclude) {
167
log.LogDebugf("DefaultRandomSelector: select dp[%v], index %v", partitions[currIndex], currIndex)
168
return partitions[currIndex]