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.
21
"github.com/cubefs/cubefs/util/log"
24
// This type defines the constructor used to create and initialize the selector.
25
type DataPartitionSelectorConstructor = func(param string) (DataPartitionSelector, error)
27
// DataPartitionSelector is the interface defines the methods necessary to implement
28
// a selector for data partition selecting.
29
type DataPartitionSelector interface {
30
// Name return name of current selector instance.
33
// Refresh refreshes current selector instance by specified data partitions.
34
Refresh(partitions []*DataPartition) error
36
// Select returns an data partition picked by selector.
37
Select(excludes map[string]struct{}) (*DataPartition, error)
39
// RemoveDP removes specified data partition.
40
RemoveDP(partitionID uint64)
42
// Count return number of data partitions held by selector.
47
dataPartitionSelectorConstructors = make(map[string]DataPartitionSelectorConstructor)
49
ErrDuplicatedDataPartitionSelectorConstructor = errors.New("duplicated data partition selector constructor")
50
ErrDataPartitionSelectorConstructorNotExist = errors.New("data partition selector constructor not exist")
53
// RegisterDataPartitionSelector registers a selector constructor.
54
// Users can register their own defined selector through this method.
55
func RegisterDataPartitionSelector(name string, constructor DataPartitionSelectorConstructor) error {
56
clearName := strings.TrimSpace(strings.ToLower(name))
57
if _, exist := dataPartitionSelectorConstructors[clearName]; exist {
58
return ErrDuplicatedDataPartitionSelectorConstructor
60
dataPartitionSelectorConstructors[clearName] = constructor
64
func newDataPartitionSelector(name string, param string) (newDpSelector DataPartitionSelector, err error) {
65
clearName := strings.TrimSpace(strings.ToLower(name))
66
constructor, exist := dataPartitionSelectorConstructors[clearName]
68
return nil, ErrDataPartitionSelectorConstructorNotExist
70
return constructor(param)
73
func (w *Wrapper) initDpSelector() (err error) {
74
w.dpSelectorChanged = false
75
selectorName := w.dpSelectorName
76
if strings.TrimSpace(selectorName) == "" {
77
log.LogInfof("initDpSelector: can not find dp selector[%v], use default selector", w.dpSelectorName)
78
selectorName = DefaultRandomSelectorName
80
var selector DataPartitionSelector
81
if selector, err = newDataPartitionSelector(selectorName, w.dpSelectorParm); err != nil {
82
log.LogErrorf("initDpSelector: dpSelector[%v] init failed caused by [%v], use default selector", w.dpSelectorName,
86
w.dpSelector = selector
90
func (w *Wrapper) refreshDpSelector(partitions []*DataPartition) {
92
dpSelector := w.dpSelector
93
dpSelectorChanged := w.dpSelectorChanged
96
if dpSelectorChanged {
97
selectorName := w.dpSelectorName
98
if strings.TrimSpace(selectorName) == "" {
99
log.LogWarnf("refreshDpSelector: can not find dp selector[%v], use default selector", w.dpSelectorName)
100
selectorName = DefaultRandomSelectorName
102
newDpSelector, err := newDataPartitionSelector(selectorName, w.dpSelectorParm)
104
log.LogErrorf("refreshDpSelector: change dpSelector to [%v %v] failed caused by [%v],"+
105
" use last valid selector. Please change dpSelector config through master.",
106
w.dpSelectorName, w.dpSelectorParm, err)
109
log.LogInfof("refreshDpSelector: change dpSelector to [%v %v]", w.dpSelectorName, w.dpSelectorParm)
110
w.dpSelector = newDpSelector
111
w.dpSelectorChanged = false
112
dpSelector = newDpSelector
117
_ = dpSelector.Refresh(partitions)
120
// getDataPartitionForWrite returns an available data partition for write.
121
func (w *Wrapper) GetDataPartitionForWrite(exclude map[string]struct{}) (*DataPartition, error) {
123
dpSelector := w.dpSelector
126
return dpSelector.Select(exclude)
129
func (w *Wrapper) RemoveDataPartitionForWrite(partitionID uint64) {
131
dpSelector := w.dpSelector
134
if dpSelector.Count() <= 1 {
138
dpSelector.RemoveDP(partitionID)