feat(master): support config decommission settings

Signed-off-by: NaturalSelect <huangzhibin1@oppo.com>
This commit is contained in:
NaturalSelect 2024-06-20 19:01:02 +08:00 committed by AmazingChi
parent 8386685205
commit 5365949f7c
26 changed files with 931 additions and 289 deletions

View File

@ -253,7 +253,10 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
dataNodeSelector := ""
metaNodeSelector := ""
markBrokenDiskThreshold := ""
autoDecommissionDisk := ""
autoDecommissionDiskInterval := ""
autoDpMetaRepair := ""
autoDpMetaRepairParallelCnt := ""
opMaxMpCntLimit := ""
dpRepairTimeout := ""
dpTimeout := ""
@ -273,11 +276,36 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
}
markBrokenDiskThreshold = fmt.Sprintf("%v", val)
}
if autoDecommissionDisk != "" {
if _, err = strconv.ParseBool(autoDecommissionDisk); err != nil {
return
}
}
if autoDecommissionDiskInterval != "" {
var interval time.Duration
interval, err = time.ParseDuration(autoDecommissionDiskInterval)
if err != nil {
return
}
if interval < time.Second {
err = fmt.Errorf("auto decommission disk interval %v smaller than 1s", interval)
return
}
autoDecommissionDiskInterval = strconv.FormatInt(int64(interval), 10)
}
if autoDpMetaRepair != "" {
if _, err = strconv.ParseBool(autoDpMetaRepair); err != nil {
return
}
}
if autoDpMetaRepairParallelCnt != "" {
if _, err = strconv.ParseInt(autoDpMetaRepairParallelCnt, 10, 64); err != nil {
return
}
}
if dpRepairTimeout != "" {
var repairTimeout time.Duration
@ -308,7 +336,10 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
if err = client.AdminAPI().SetClusterParas(optDelBatchCount, optMarkDeleteRate, optDelWorkerSleepMs,
optAutoRepairRate, optLoadFactor, opMaxDpCntLimit, opMaxMpCntLimit, clientIDKey,
dataNodesetSelector, metaNodesetSelector,
dataNodeSelector, metaNodeSelector, markBrokenDiskThreshold, autoDpMetaRepair, dpRepairTimeout, dpTimeout); err != nil {
dataNodeSelector, metaNodeSelector, markBrokenDiskThreshold,
autoDecommissionDisk, autoDecommissionDiskInterval,
autoDpMetaRepair, autoDpMetaRepairParallelCnt,
dpRepairTimeout, dpTimeout); err != nil {
return
}
stdout("Cluster parameters has been set successfully. \n")
@ -328,8 +359,11 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
cmd.Flags().StringVar(&metaNodeSelector, CliFlagMetaNodeSelector, "", "Set the node select policy(metanode) for cluster")
cmd.Flags().StringVar(&markBrokenDiskThreshold, CliFlagMarkDiskBrokenThreshold, "", "Threshold to mark disk as broken")
cmd.Flags().StringVar(&autoDpMetaRepair, CliFlagAutoDpMetaRepair, "", "Enable or disable auto data partition meta repair")
cmd.Flags().StringVar(&autoDpMetaRepairParallelCnt, CliFlagAutoDpMetaRepairParallelCnt, "", "Parallel count of auto data partition meta repair")
cmd.Flags().StringVar(&dpRepairTimeout, CliFlagDpRepairTimeout, "", "Data partition repair timeout(example: 1h)")
cmd.Flags().StringVar(&dpTimeout, CliFlagDpTimeout, "", "Data partition heartbeat timeout(example: 10s)")
cmd.Flags().StringVar(&autoDecommissionDisk, CliFlagAutoDecommissionDisk, "", "Enable od disable auto decommission disk")
cmd.Flags().StringVar(&autoDecommissionDiskInterval, CliFlagAutoDecommissionDiskInterval, "", "Interval of auto decommission disk(example: 10s)")
return cmd
}

View File

@ -135,8 +135,11 @@ const (
CliFlagForce = "force"
CliFlagEnableCrossZone = "cross-zone"
CliFlagAutoDpMetaRepair = "autoDpMetaRepair"
CliFlagAutoDpMetaRepairParallelCnt = "autoDpMetaRepairParallelCnt"
CliFlagDpRepairTimeout = "dpRepairTimeout"
CliFlagDpTimeout = "dpTimeout"
CliFlagAutoDecommissionDisk = "autoDecommissionDisk"
CliFlagAutoDecommissionDiskInterval = "autoDecommissionDiskInterval"
// CliFlagSetDataPartitionCount = "count" use dp-count instead

View File

@ -72,10 +72,12 @@ func formatClusterView(cv *proto.ClusterView, cn *proto.ClusterNodeInfo, cp *pro
sb.WriteString(fmt.Sprintf(" DpRepairTimeout : %v\n", cv.DpRepairTimeout))
sb.WriteString(fmt.Sprintf(" DataPartitionTimeout : %v\n", cv.DpTimeout))
sb.WriteString(fmt.Sprintf(" volDeletionDelayTime : %v h\n", cv.VolDeletionDelayTimeHour))
sb.WriteString(fmt.Sprintf(" EnableAutoDecommission: %v\n", cv.EnableAutoDecommission))
sb.WriteString(fmt.Sprintf(" EnableAutoDpMetaRepair: %v\n", cv.EnableAutoDpMetaRepair))
sb.WriteString(fmt.Sprintf(" EnableAutoDecommission : %v\n", cv.EnableAutoDecommission))
sb.WriteString(fmt.Sprintf(" AutoDecommissionDiskIntervak : %v\n", cv.AutoDecommissionDiskInterval))
sb.WriteString(fmt.Sprintf(" EnableAutoDpMetaRepair : %v\n", cv.EnableAutoDpMetaRepair))
sb.WriteString(fmt.Sprintf(" AutoDpMetaRepairParallelCnt : %v\n", cv.AutoDpMetaRepairParallelCnt))
sb.WriteString(fmt.Sprintf(" MarkDiskBrokenThreshold : %v\n", strutil.FormatPercent(cv.MarkDiskBrokenThreshold)))
sb.WriteString(fmt.Sprintf(" DecommissionDiskLimit: %v\n", cv.DecommissionDiskLimit))
sb.WriteString(fmt.Sprintf(" DecommissionDiskLimit : %v\n", cv.DecommissionDiskLimit))
return sb.String()
}

View File

@ -1329,6 +1329,28 @@ func parseAndExtractSetNodeInfoParams(r *http.Request) (params map[string]interf
params[markDiskBrokenThresholdKey] = val
}
if value = r.FormValue(autoDecommissionDiskKey); value != "" {
noParams = false
val := false
val, err = strconv.ParseBool(value)
if err != nil {
err = unmatchedKey(autoDecommissionDiskKey)
return
}
params[autoDecommissionDiskKey] = val
}
if value = r.FormValue(autoDecommissionDiskIntervalKey); value != "" {
noParams = false
val := int64(0)
val, err = strconv.ParseInt(value, 10, 64)
if err != nil {
err = unmatchedKey(autoDecommissionDiskIntervalKey)
return
}
params[autoDecommissionDiskIntervalKey] = time.Duration(val)
}
if value = r.FormValue(autoDpMetaRepairKey); value != "" {
noParams = false
val := false
@ -1340,6 +1362,17 @@ func parseAndExtractSetNodeInfoParams(r *http.Request) (params map[string]interf
params[autoDpMetaRepairKey] = val
}
if value = r.FormValue(autoDpMetaRepairParallelCntKey); value != "" {
noParams = false
val := int64(0)
val, err = strconv.ParseInt(value, 10, 32)
if err != nil {
err = unmatchedKey(autoDpMetaRepairParallelCntKey)
return
}
params[autoDpMetaRepairParallelCntKey] = int(val)
}
if value = r.FormValue(dpTimeoutKey); value != "" {
noParams = false
val := int64(0)

View File

@ -797,7 +797,9 @@ func (m *Server) getCluster(w http.ResponseWriter, r *http.Request) {
DpRepairTimeout: m.cluster.GetDecommissionDataPartitionRecoverTimeOut(),
MarkDiskBrokenThreshold: m.cluster.getMarkDiskBrokenThreshold(),
EnableAutoDpMetaRepair: m.cluster.getEnableAutoDpMetaRepair(),
AutoDpMetaRepairParallelCnt: m.cluster.GetAutoDpMetaRepairParallelCnt(),
EnableAutoDecommission: m.cluster.AutoDecommissionDiskIsEnabled(),
AutoDecommissionDiskInterval: m.cluster.GetAutoDecommissionDiskInterval(),
DecommissionDiskLimit: m.cluster.GetDecommissionDiskLimit(),
DpTimeout: time.Duration(m.cluster.getDataPartitionTimeoutSec()) * time.Second,
MasterNodes: make([]proto.NodeView, 0),
@ -3160,6 +3162,27 @@ func (m *Server) setNodeInfoHandler(w http.ResponseWriter, r *http.Request) {
}
}
if val, ok := params[autoDecommissionDiskKey]; ok {
if autoDecomm, ok := val.(bool); ok {
old := m.cluster.EnableAutoDecommissionDisk.Load()
m.cluster.EnableAutoDecommissionDisk.Store(autoDecomm)
if err = m.cluster.syncPutCluster(); err != nil {
m.cluster.EnableAutoDecommissionDisk.Store(old)
sendErrReply(w, r, newErrHTTPReply(err))
return
}
}
}
if val, ok := params[autoDecommissionDiskIntervalKey]; ok {
if interval, ok := val.(time.Duration); ok {
if err = m.cluster.setAutoDecommissionDiskInterval(interval); err != nil {
sendErrReply(w, r, newErrHTTPReply(err))
return
}
}
}
if val, ok := params[autoDpMetaRepairKey]; ok {
if autoRepair, ok := val.(bool); ok {
if err = m.cluster.setEnableAutoDpMetaRepair(autoRepair); err != nil {
@ -3169,6 +3192,15 @@ func (m *Server) setNodeInfoHandler(w http.ResponseWriter, r *http.Request) {
}
}
if val, ok := params[autoDpMetaRepairParallelCntKey]; ok {
if cnt, ok := val.(int); ok {
if err = m.cluster.setAutoDpMetaRepairParallelCnt(cnt); err != nil {
sendErrReply(w, r, newErrHTTPReply(err))
return
}
}
}
if val, ok := params[dpTimeoutKey]; ok {
if dpTimeout, ok := val.(int64); ok {
if err = m.cluster.setDataPartitionTimeout(dpTimeout); err != nil {

View File

@ -1645,6 +1645,30 @@ func TestSetMarkDiskBrokenThreshold(t *testing.T) {
require.EqualValues(t, oldVal, server.cluster.getMarkDiskBrokenThreshold())
}
func TestSetEnableAutoDecommissionDisk(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.EnableAutoDecommissionDisk.Load()
setVal := !oldVal
setUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDecommissionDiskKey, setVal)
unsetUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDecommissionDiskKey, oldVal)
process(setUrl, t)
require.EqualValues(t, setVal, server.cluster.EnableAutoDecommissionDisk.Load())
process(unsetUrl, t)
require.EqualValues(t, oldVal, server.cluster.EnableAutoDecommissionDisk.Load())
}
func TestSetDecommissionDiskInterval(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.GetAutoDecommissionDiskInterval()
setVal := oldVal + 10*time.Second
setUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDecommissionDiskIntervalKey, int64(setVal))
unsetUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDecommissionDiskIntervalKey, int64(oldVal))
process(setUrl, t)
require.EqualValues(t, setVal, server.cluster.GetAutoDecommissionDiskInterval())
process(unsetUrl, t)
require.EqualValues(t, oldVal, server.cluster.GetAutoDecommissionDiskInterval())
}
func TestSetEnableAutoDpMetaRepair(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.getEnableAutoDpMetaRepair()
@ -1657,6 +1681,18 @@ func TestSetEnableAutoDpMetaRepair(t *testing.T) {
require.EqualValues(t, oldVal, server.cluster.getEnableAutoDpMetaRepair())
}
func TestSetAutoDpMetaRepairParallelCnt(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.GetAutoDpMetaRepairParallelCnt()
setVal := 200
setUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDpMetaRepairParallelCntKey, setVal)
unsetUrl := fmt.Sprintf("%v?%v=%v&dirSizeLimit=0", reqUrl, autoDpMetaRepairParallelCntKey, oldVal)
process(setUrl, t)
require.EqualValues(t, setVal, server.cluster.GetAutoDpMetaRepairParallelCnt())
process(unsetUrl, t)
require.EqualValues(t, oldVal, server.cluster.GetAutoDpMetaRepairParallelCnt())
}
func TestSetDpTimeout(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.getDataPartitionTimeoutSec()

View File

@ -86,7 +86,8 @@ type Cluster struct {
apiLimiter *ApiLimiter
DecommissionDisks sync.Map
DecommissionLimit uint64
EnableAutoDecommissionDisk bool
EnableAutoDecommissionDisk atomicutil.Bool
AutoDecommissionInterval atomicutil.Int64
AutoDecommissionDiskMux sync.Mutex
checkAutoCreateDataPartition bool
masterClient *masterSDK.MasterClient
@ -106,6 +107,7 @@ type Cluster struct {
S3ApiQosQuota *sync.Map // (api,uid,limtType) -> limitQuota
MarkDiskBrokenThreshold atomicutil.Float64
EnableAutoDpMetaRepair atomicutil.Bool
AutoDpMetaRepairParallelCnt atomicutil.Uint32
}
type delayDeleteVolInfo struct {
@ -371,6 +373,7 @@ func newCluster(name string, leaderInfo *LeaderInfo, fsm *MetadataFsm, partition
c.S3ApiQosQuota = new(sync.Map)
c.MarkDiskBrokenThreshold.Store(defaultMarkDiskBrokenThreshold)
c.EnableAutoDpMetaRepair.Store(defaultEnableDpMetaRepair)
c.AutoDecommissionInterval.Store(int64(defaultAutoDecommissionDiskInterval))
return
}
@ -4257,7 +4260,7 @@ func (c *Cluster) scheduleToBadDisk() {
if c.partition.IsRaftLeader() && c.AutoDecommissionDiskIsEnabled() && c.metaReady {
c.checkBadDisk()
}
time.Sleep(10 * time.Second)
time.Sleep(c.GetAutoDecommissionDiskInterval())
}
}()
}
@ -4916,13 +4919,50 @@ func (c *Cluster) addDecommissionDiskToNodeset(dd *DecommissionDisk) (err error)
func (c *Cluster) AutoDecommissionDiskIsEnabled() bool {
c.AutoDecommissionDiskMux.Lock()
defer c.AutoDecommissionDiskMux.Unlock()
return c.EnableAutoDecommissionDisk
return c.EnableAutoDecommissionDisk.Load()
}
func (c *Cluster) SetAutoDecommissionDisk(flag bool) {
c.AutoDecommissionDiskMux.Lock()
defer c.AutoDecommissionDiskMux.Unlock()
c.EnableAutoDecommissionDisk = flag
c.EnableAutoDecommissionDisk.Store(flag)
}
func (c *Cluster) GetAutoDecommissionDiskInterval() (interval time.Duration) {
tmp := c.AutoDecommissionInterval.Load()
if tmp == 0 {
tmp = int64(defaultAutoDecommissionDiskInterval)
}
interval = time.Duration(tmp)
return
}
func (c *Cluster) setAutoDecommissionDiskInterval(interval time.Duration) (err error) {
old := c.AutoDecommissionInterval.Load()
c.AutoDecommissionInterval.Store(int64(interval))
if err = c.syncPutCluster(); err != nil {
c.AutoDecommissionInterval.Store(old)
return
}
return
}
func (c *Cluster) GetAutoDpMetaRepairParallelCnt() (cnt int) {
cnt = int(c.AutoDpMetaRepairParallelCnt.Load())
if cnt == 0 {
cnt = defaultAutoDpMetaRepairPallarelCnt
}
return
}
func (c *Cluster) setAutoDpMetaRepairParallelCnt(cnt int) (err error) {
old := c.AutoDpMetaRepairParallelCnt.Load()
c.AutoDpMetaRepairParallelCnt.Store(uint32(cnt))
if err = c.syncPutCluster(); err != nil {
c.AutoDpMetaRepairParallelCnt.Store(old)
return
}
return
}
func (c *Cluster) GetDecommissionDataPartitionRecoverTimeOut() time.Duration {

View File

@ -139,7 +139,10 @@ const (
dpRepairBlockSizeKey = "dpRepairBlockSize"
markDiskBrokenThresholdKey = "markDiskBrokenThreshold"
decommissionTypeKey = "decommissionType"
autoDecommissionDiskKey = "autoDecommissionDisk"
autoDecommissionDiskIntervalKey = "autoDecommissionDiskInterval"
autoDpMetaRepairKey = "autoDpMetaRepair"
autoDpMetaRepairParallelCntKey = "autoDpMetaRepairParallelCnt"
dpTimeoutKey = "dpTimeout"
)
@ -214,6 +217,8 @@ const (
defaultVolDelayDeleteTimeHour = 48
defaultMarkDiskBrokenThreshold = 0 // decommission all dp from disk
defaultEnableDpMetaRepair = false
defaultAutoDpMetaRepairPallarelCnt = 100
defaultAutoDecommissionDiskInterval = 10 * time.Second
maxMpCreationCount = 10
)

View File

@ -61,10 +61,12 @@ type clusterValue struct {
DpMaxRepairErrCnt uint64
DpRepairTimeOut uint64
EnableAutoDecommissionDisk bool
AutoDecommissionDiskInterval int64
DecommissionDiskLimit uint32
VolDeletionDelayTimeHour int64
MarkDiskBrokenThreshold float64
EnableAutoDpMetaRepair bool
AutoDpMetaRepairParallelCnt uint32
DataPartitionTimeoutSec int64
}
@ -95,11 +97,13 @@ func newClusterValue(c *Cluster) (cv *clusterValue) {
MaxConcurrentLcNodes: c.cfg.MaxConcurrentLcNodes,
DpMaxRepairErrCnt: c.cfg.DpMaxRepairErrCnt,
DpRepairTimeOut: c.cfg.DpRepairTimeOut,
EnableAutoDecommissionDisk: c.EnableAutoDecommissionDisk,
EnableAutoDecommissionDisk: c.EnableAutoDecommissionDisk.Load(),
AutoDecommissionDiskInterval: c.AutoDecommissionInterval.Load(),
DecommissionDiskLimit: c.GetDecommissionDiskLimit(),
VolDeletionDelayTimeHour: c.cfg.volDelayDeleteTimeHour,
MarkDiskBrokenThreshold: c.getMarkDiskBrokenThreshold(),
EnableAutoDpMetaRepair: c.getEnableAutoDpMetaRepair(),
AutoDpMetaRepairParallelCnt: c.AutoDpMetaRepairParallelCnt.Load(),
DataPartitionTimeoutSec: c.getDataPartitionTimeoutSec(),
}
return cv
@ -1057,6 +1061,14 @@ func (c *Cluster) updateEnableAutoDpMetaRepair(val bool) {
c.EnableAutoDpMetaRepair.Store(val)
}
func (c *Cluster) updateAutoDecommissionDiskInterval(val int64) {
c.AutoDecommissionInterval.Store(val)
}
func (c *Cluster) updateAutoDpMetaRepairParallelCnt(cnt uint32) {
c.AutoDpMetaRepairParallelCnt.Store(cnt)
}
func (c *Cluster) updateDecommissionDiskLimit(val uint32) {
if val < 1 {
val = 1
@ -1179,7 +1191,8 @@ func (c *Cluster) loadClusterValue() (err error) {
c.clusterUuid = cv.ClusterUuid
c.clusterUuidEnable = cv.ClusterUuidEnable
c.DecommissionLimit = cv.DecommissionLimit
c.EnableAutoDecommissionDisk = cv.EnableAutoDecommissionDisk
c.EnableAutoDecommissionDisk.Store(cv.EnableAutoDecommissionDisk)
c.updateAutoDecommissionDiskInterval(cv.AutoDecommissionDiskInterval)
c.DecommissionLimit = cv.DecommissionLimit
c.cfg.volDelayDeleteTimeHour = cv.VolDeletionDelayTimeHour
@ -1213,6 +1226,7 @@ func (c *Cluster) loadClusterValue() (err error) {
c.checkDataReplicasEnable = cv.CheckDataReplicasEnable
c.updateMarkDiskBrokenThreshold(cv.MarkDiskBrokenThreshold)
c.updateEnableAutoDpMetaRepair(cv.EnableAutoDpMetaRepair)
c.updateAutoDpMetaRepairParallelCnt(cv.AutoDpMetaRepairParallelCnt)
c.updateDataPartitionTimeoutSec(cv.DataPartitionTimeoutSec)
}
return

View File

@ -607,7 +607,7 @@ func (vol *Vol) checkDataPartitions(c *Cluster) (cnt int) {
partitions := vol.dataPartitions.clonePartitions()
checkMetaDp := make(map[uint64]*DataPartition)
checkMetaPool := routinepool.NewRoutinePool(10)
checkMetaPool := routinepool.NewRoutinePool(c.GetAutoDpMetaRepairParallelCnt())
defer checkMetaPool.WaitAndClose()
var checkMetaDpWg sync.WaitGroup

View File

@ -130,7 +130,9 @@ type ClusterView struct {
VolDeletionDelayTimeHour int64
MarkDiskBrokenThreshold float64
EnableAutoDpMetaRepair bool
AutoDpMetaRepairParallelCnt int
EnableAutoDecommission bool
AutoDecommissionDiskInterval time.Duration
DecommissionDiskLimit uint32
DpRepairTimeout time.Duration
DpTimeout time.Duration

View File

@ -517,7 +517,9 @@ func (api *AdminAPI) SetMasterVolDeletionDelayTime(volDeletionDelayTimeHour int)
func (api *AdminAPI) SetClusterParas(batchCount, markDeleteRate, deleteWorkerSleepMs, autoRepairRate, loadFactor, maxDpCntLimit, maxMpCntLimit, clientIDKey string,
dataNodesetSelector, metaNodesetSelector, dataNodeSelector, metaNodeSelector string, markDiskBrokenThreshold string,
enableAutoDpMetaRepair string, dpRepairTimeout string, dpTimeout string,
enableAutoDecommissionDisk string, autoDecommissionDiskInterval string,
enableAutoDpMetaRepair string, autoDpMetaRepairParallelCnt string,
dpRepairTimeout string, dpTimeout string,
) (err error) {
request := newRequest(get, proto.AdminSetNodeInfo).Header(api.h)
request.addParam("batchCount", batchCount)
@ -536,9 +538,18 @@ func (api *AdminAPI) SetClusterParas(batchCount, markDeleteRate, deleteWorkerSle
if markDiskBrokenThreshold != "" {
request.addParam("markDiskBrokenThreshold", markDiskBrokenThreshold)
}
if enableAutoDecommissionDisk != "" {
request.addParam("autoDecommissionDisk", enableAutoDecommissionDisk)
}
if autoDecommissionDiskInterval != "" {
request.addParam("autoDecommissionDiskInterval", autoDecommissionDiskInterval)
}
if enableAutoDpMetaRepair != "" {
request.addParam("autoDpMetaRepair", enableAutoDpMetaRepair)
}
if autoDpMetaRepairParallelCnt != "" {
request.addParam("autoDpMetaRepairParallelCnt", autoDpMetaRepairParallelCnt)
}
if dpRepairTimeout != "" {
request.addParam("dpRepairTimeOut", dpRepairTimeout)
}

View File

@ -45,3 +45,12 @@ func (b *Bool) CompareAndSwap(old bool, newVal bool) (swaped bool) {
swaped = atomic.CompareAndSwapUint32(&b.val, oldVal, val)
return
}
func (b *Bool) Swap(new bool) (old bool) {
tmp := uint32(0)
if new {
tmp = 1
}
old = atomic.SwapUint32(&b.val, tmp) == 1
return
}

View File

@ -27,4 +27,6 @@ func TestAtomicBool(t *testing.T) {
require.True(t, b.Load())
require.True(t, b.CompareAndSwap(true, false))
require.False(t, b.Load())
require.False(t, b.Swap(true))
require.True(t, b.Load())
}

View File

@ -0,0 +1,42 @@
// Copyright 2023 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil
import (
"math"
"sync/atomic"
)
type Float32 struct {
val uint32
}
func (f *Float32) Load() float32 {
return math.Float32frombits(atomic.LoadUint32(&f.val))
}
func (f *Float32) Store(val float32) {
atomic.StoreUint32(&f.val, math.Float32bits(val))
}
func (f *Float32) CompareAndSwap(old float32, new float32) (swaped bool) {
swaped = atomic.CompareAndSwapUint32(&f.val, math.Float32bits(old), math.Float32bits(new))
return
}
func (f *Float32) Swap(new float32) (old float32) {
old = math.Float32frombits(atomic.SwapUint32(&f.val, math.Float32bits(new)))
return
}

View File

@ -0,0 +1,32 @@
// Copyright 2023 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil_test
import (
"testing"
"github.com/cubefs/cubefs/util/atomicutil"
"github.com/stretchr/testify/require"
)
func TestAtomicFloat32(t *testing.T) {
f := atomicutil.Float32{}
testVal := float32(1.0)
f.Store(testVal)
require.Equal(t, testVal, f.Load())
require.True(t, f.CompareAndSwap(testVal, 0))
require.EqualValues(t, 0, f.Swap(testVal))
require.EqualValues(t, testVal, f.Load())
}

View File

@ -30,3 +30,13 @@ func (f *Float64) Load() float64 {
func (f *Float64) Store(val float64) {
atomic.StoreUint64(&f.val, math.Float64bits(val))
}
func (f *Float64) CompareAndSwap(old float64, new float64) (swaped bool) {
swaped = atomic.CompareAndSwapUint64(&f.val, math.Float64bits(old), math.Float64bits(new))
return
}
func (f *Float64) Swap(new float64) (old float64) {
old = math.Float64frombits(atomic.SwapUint64(&f.val, math.Float64bits(new)))
return
}

View File

@ -26,4 +26,7 @@ func TestAtomicFloat64(t *testing.T) {
testVal := float64(1.0)
f.Store(testVal)
require.Equal(t, testVal, f.Load())
require.True(t, f.CompareAndSwap(testVal, 0))
require.EqualValues(t, 0, f.Swap(testVal))
require.EqualValues(t, testVal, f.Load())
}

50
util/atomicutil/int32.go Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil
import "sync/atomic"
type Int32 struct {
v int32
}
func (i *Int32) Load() (v int32) {
v = atomic.LoadInt32(&i.v)
return
}
func (i *Int32) Store(v int32) {
atomic.StoreInt32(&i.v, v)
}
func (i *Int32) CompareAndSwap(old int32, new int32) (swaped bool) {
swaped = atomic.CompareAndSwapInt32(&i.v, old, new)
return
}
func (i *Int32) Add(v int32) (new int32) {
new = atomic.AddInt32(&i.v, v)
return
}
func (i *Int32) Sub(v int32) (new int32) {
new = atomic.AddInt32(&i.v, -v)
return
}
func (i *Int32) Swap(v int32) (old int32) {
old = atomic.SwapInt32(&i.v, v)
return
}

View File

@ -0,0 +1,33 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil_test
import (
"testing"
"github.com/cubefs/cubefs/util/atomicutil"
"github.com/stretchr/testify/require"
)
func TestInt32(t *testing.T) {
i := atomicutil.Int32{}
i.Store(1)
require.EqualValues(t, 1, i.Load())
require.EqualValues(t, 2, i.Add(1))
require.EqualValues(t, 2, i.Swap(1))
require.True(t, i.CompareAndSwap(1, 2))
require.EqualValues(t, 2, i.Load())
require.EqualValues(t, 1, i.Sub(1))
}

50
util/atomicutil/int64.go Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil
import "sync/atomic"
type Int64 struct {
v int64
}
func (i *Int64) Load() (v int64) {
v = atomic.LoadInt64(&i.v)
return
}
func (i *Int64) Store(v int64) {
atomic.StoreInt64(&i.v, v)
}
func (i *Int64) CompareAndSwap(old int64, new int64) (swaped bool) {
swaped = atomic.CompareAndSwapInt64(&i.v, old, new)
return
}
func (i *Int64) Add(v int64) (new int64) {
new = atomic.AddInt64(&i.v, v)
return
}
func (i *Int64) Sub(v int64) (new int64) {
new = atomic.AddInt64(&i.v, -v)
return
}
func (i *Int64) Swap(v int64) (old int64) {
old = atomic.SwapInt64(&i.v, v)
return
}

View File

@ -0,0 +1,33 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil_test
import (
"testing"
"github.com/cubefs/cubefs/util/atomicutil"
"github.com/stretchr/testify/require"
)
func TestInt64(t *testing.T) {
i := atomicutil.Int64{}
i.Store(1)
require.EqualValues(t, 1, i.Load())
require.EqualValues(t, 2, i.Add(1))
require.EqualValues(t, 2, i.Swap(1))
require.True(t, i.CompareAndSwap(1, 2))
require.EqualValues(t, 2, i.Load())
require.EqualValues(t, 1, i.Sub(1))
}

50
util/atomicutil/uint32.go Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil
import "sync/atomic"
type Uint32 struct {
v uint32
}
func (i *Uint32) Load() (v uint32) {
v = atomic.LoadUint32(&i.v)
return
}
func (i *Uint32) Store(v uint32) {
atomic.StoreUint32(&i.v, v)
}
func (i *Uint32) CompareAndSwap(old uint32, new uint32) (swaped bool) {
swaped = atomic.CompareAndSwapUint32(&i.v, old, new)
return
}
func (i *Uint32) Add(v uint32) (new uint32) {
new = atomic.AddUint32(&i.v, v)
return
}
func (i *Uint32) Sub(v int32) (new uint32) {
new = atomic.AddUint32(&i.v, ^uint32(v-1))
return
}
func (i *Uint32) Swap(v uint32) (old uint32) {
old = atomic.SwapUint32(&i.v, v)
return
}

View File

@ -0,0 +1,33 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil_test
import (
"testing"
"github.com/cubefs/cubefs/util/atomicutil"
"github.com/stretchr/testify/require"
)
func TestUint64(t *testing.T) {
i := atomicutil.Uint32{}
i.Store(1)
require.EqualValues(t, 1, i.Load())
require.EqualValues(t, 2, i.Add(1))
require.EqualValues(t, 2, i.Swap(1))
require.True(t, i.CompareAndSwap(1, 2))
require.EqualValues(t, 2, i.Load())
require.EqualValues(t, 1, i.Sub(1))
}

50
util/atomicutil/uint64.go Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil
import "sync/atomic"
type Uint64 struct {
v uint64
}
func (i *Uint64) Load() (v uint64) {
v = atomic.LoadUint64(&i.v)
return
}
func (i *Uint64) Store(v uint64) {
atomic.StoreUint64(&i.v, v)
}
func (i *Uint64) CompareAndSwap(old uint64, new uint64) (swaped bool) {
swaped = atomic.CompareAndSwapUint64(&i.v, old, new)
return
}
func (i *Uint64) Add(v uint64) (new uint64) {
new = atomic.AddUint64(&i.v, v)
return
}
func (i *Uint64) Sub(v int64) (new uint64) {
new = atomic.AddUint64(&i.v, ^uint64(v-1))
return
}
func (i *Uint64) Swap(v uint64) (old uint64) {
old = atomic.SwapUint64(&i.v, v)
return
}

View File

@ -0,0 +1,33 @@
// Copyright 2024 The CubeFS Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied. See the License for the specific language governing
// permissions and limitations under the License.
package atomicutil_test
import (
"testing"
"github.com/cubefs/cubefs/util/atomicutil"
"github.com/stretchr/testify/require"
)
func TestUint32(t *testing.T) {
i := atomicutil.Uint32{}
i.Store(1)
require.EqualValues(t, 1, i.Load())
require.EqualValues(t, 2, i.Add(1))
require.EqualValues(t, 2, i.Swap(1))
require.True(t, i.CompareAndSwap(1, 2))
require.EqualValues(t, 2, i.Load())
require.EqualValues(t, 1, i.Sub(1))
}