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 := "" dataNodeSelector := ""
metaNodeSelector := "" metaNodeSelector := ""
markBrokenDiskThreshold := "" markBrokenDiskThreshold := ""
autoDecommissionDisk := ""
autoDecommissionDiskInterval := ""
autoDpMetaRepair := "" autoDpMetaRepair := ""
autoDpMetaRepairParallelCnt := ""
opMaxMpCntLimit := "" opMaxMpCntLimit := ""
dpRepairTimeout := "" dpRepairTimeout := ""
dpTimeout := "" dpTimeout := ""
@ -273,11 +276,36 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
} }
markBrokenDiskThreshold = fmt.Sprintf("%v", val) 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 autoDpMetaRepair != "" {
if _, err = strconv.ParseBool(autoDpMetaRepair); err != nil { if _, err = strconv.ParseBool(autoDpMetaRepair); err != nil {
return return
} }
} }
if autoDpMetaRepairParallelCnt != "" {
if _, err = strconv.ParseInt(autoDpMetaRepairParallelCnt, 10, 64); err != nil {
return
}
}
if dpRepairTimeout != "" { if dpRepairTimeout != "" {
var repairTimeout time.Duration var repairTimeout time.Duration
@ -308,7 +336,10 @@ func newClusterSetParasCmd(client *master.MasterClient) *cobra.Command {
if err = client.AdminAPI().SetClusterParas(optDelBatchCount, optMarkDeleteRate, optDelWorkerSleepMs, if err = client.AdminAPI().SetClusterParas(optDelBatchCount, optMarkDeleteRate, optDelWorkerSleepMs,
optAutoRepairRate, optLoadFactor, opMaxDpCntLimit, opMaxMpCntLimit, clientIDKey, optAutoRepairRate, optLoadFactor, opMaxDpCntLimit, opMaxMpCntLimit, clientIDKey,
dataNodesetSelector, metaNodesetSelector, dataNodesetSelector, metaNodesetSelector,
dataNodeSelector, metaNodeSelector, markBrokenDiskThreshold, autoDpMetaRepair, dpRepairTimeout, dpTimeout); err != nil { dataNodeSelector, metaNodeSelector, markBrokenDiskThreshold,
autoDecommissionDisk, autoDecommissionDiskInterval,
autoDpMetaRepair, autoDpMetaRepairParallelCnt,
dpRepairTimeout, dpTimeout); err != nil {
return return
} }
stdout("Cluster parameters has been set successfully. \n") 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(&metaNodeSelector, CliFlagMetaNodeSelector, "", "Set the node select policy(metanode) for cluster")
cmd.Flags().StringVar(&markBrokenDiskThreshold, CliFlagMarkDiskBrokenThreshold, "", "Threshold to mark disk as broken") 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(&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(&dpRepairTimeout, CliFlagDpRepairTimeout, "", "Data partition repair timeout(example: 1h)")
cmd.Flags().StringVar(&dpTimeout, CliFlagDpTimeout, "", "Data partition heartbeat timeout(example: 10s)") 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 return cmd
} }

View File

@ -68,75 +68,78 @@ const (
CliResourceConfig = "config" CliResourceConfig = "config"
// Flags // Flags
CliFlagName = "name" CliFlagName = "name"
CliFlagOnwer = "user" CliFlagOnwer = "user"
CliFlagDataPartitionSize = "dp-size" CliFlagDataPartitionSize = "dp-size"
CliFlagDataPartitionCount = "dp-count" CliFlagDataPartitionCount = "dp-count"
CliFlagMetaPartitionCount = "mp-count" CliFlagMetaPartitionCount = "mp-count"
CliFlagReplicas = "replicas" CliFlagReplicas = "replicas"
CliFlagEnable = "enable" CliFlagEnable = "enable"
CliFlagEnableFollowerRead = "follower-read" CliFlagEnableFollowerRead = "follower-read"
CliFlagAuthenticate = "authenticate" CliFlagAuthenticate = "authenticate"
CliFlagCapacity = "capacity" CliFlagCapacity = "capacity"
CliFlagBusiness = "description" CliFlagBusiness = "description"
CliFlagMPCount = "mp-count" CliFlagMPCount = "mp-count"
CliFlagDPCount = "dp-count" CliFlagDPCount = "dp-count"
CliFlagReplicaNum = "replica-num" CliFlagReplicaNum = "replica-num"
CliFlagSize = "size" CliFlagSize = "size"
CliFlagVolType = "vol-type" CliFlagVolType = "vol-type"
CliFlagFollowerRead = "follower-read" CliFlagFollowerRead = "follower-read"
CliFlagCacheRuleKey = "cache-rule-key" CliFlagCacheRuleKey = "cache-rule-key"
CliFlagEbsBlkSize = "ebs-blk-size" CliFlagEbsBlkSize = "ebs-blk-size"
CliFlagCacheCapacity = "cache-capacity" CliFlagCacheCapacity = "cache-capacity"
CliFlagCacheAction = "cache-action" CliFlagCacheAction = "cache-action"
CliFlagCacheThreshold = "cache-threshold" CliFlagCacheThreshold = "cache-threshold"
CliFlagCacheTTL = "cache-ttl" CliFlagCacheTTL = "cache-ttl"
CliFlagCacheHighWater = "cache-high-water" CliFlagCacheHighWater = "cache-high-water"
CliFlagCacheLowWater = "cache-low-water" CliFlagCacheLowWater = "cache-low-water"
CliFlagCacheLRUInterval = "cache-lru-interval" CliFlagCacheLRUInterval = "cache-lru-interval"
CliFlagCacheRule = "cache-rule" CliFlagCacheRule = "cache-rule"
CliFlagThreshold = "threshold" CliFlagThreshold = "threshold"
CliFlagAddress = "addr" CliFlagAddress = "addr"
CliFlagDiskPath = "path" CliFlagDiskPath = "path"
CliFlagAuthKey = "authkey" CliFlagAuthKey = "authkey"
CliFlagINodeStartID = "inode-start" CliFlagINodeStartID = "inode-start"
CliFlagId = "id" CliFlagId = "id"
CliFlagZoneName = "zone-name" CliFlagZoneName = "zone-name"
CliFlagDescription = "description" CliFlagDescription = "description"
CliFlagAutoRepairRate = "autoRepairRate" CliFlagAutoRepairRate = "autoRepairRate"
CliFlagDelBatchCount = "batchCount" CliFlagDelBatchCount = "batchCount"
CliFlagDelWorkerSleepMs = "deleteWorkerSleepMs" CliFlagDelWorkerSleepMs = "deleteWorkerSleepMs"
CliFlagLoadFactor = "loadFactor" CliFlagLoadFactor = "loadFactor"
CliFlagMarkDelRate = "markDeleteRate" CliFlagMarkDelRate = "markDeleteRate"
CliFlagMaxDpCntLimit = "maxDpCntLimit" CliFlagMaxDpCntLimit = "maxDpCntLimit"
CliFlagMaxMpCntLimit = "maxMpCntLimit" CliFlagMaxMpCntLimit = "maxMpCntLimit"
CliFlagDataNodeSelector = "dataNodeSelector" CliFlagDataNodeSelector = "dataNodeSelector"
CliFlagMetaNodeSelector = "metaNodeSelector" CliFlagMetaNodeSelector = "metaNodeSelector"
CliFlagDataNodesetSelector = "dataNodesetSelector" CliFlagDataNodesetSelector = "dataNodesetSelector"
CliFlagMetaNodesetSelector = "metaNodesetSelector" CliFlagMetaNodesetSelector = "metaNodesetSelector"
CliFlagCrossZone = "crossZone" CliFlagCrossZone = "crossZone"
CliNormalZonesFirst = "normalZonesFirst" CliNormalZonesFirst = "normalZonesFirst"
CliFlagCount = "count" CliFlagCount = "count"
CliDpReadOnlyWhenVolFull = "readonly-when-full" CliDpReadOnlyWhenVolFull = "readonly-when-full"
CliTxMask = "transaction-mask" CliTxMask = "transaction-mask"
CliTxTimeout = "transaction-timeout" CliTxTimeout = "transaction-timeout"
CliTxOpLimit = "transaction-limit" CliTxOpLimit = "transaction-limit"
CliTxConflictRetryNum = "tx-conflict-retry-num" CliTxConflictRetryNum = "tx-conflict-retry-num"
CliTxConflictRetryInterval = "tx-conflict-retry-Interval" CliTxConflictRetryInterval = "tx-conflict-retry-Interval"
CliTxForceReset = "transaction-force-reset" CliTxForceReset = "transaction-force-reset"
CliFlagMaxFiles = "maxFiles" CliFlagMaxFiles = "maxFiles"
CliFlagMaxBytes = "maxBytes" CliFlagMaxBytes = "maxBytes"
CliFlagMaxConcurrencyInode = "maxConcurrencyInode" CliFlagMaxConcurrencyInode = "maxConcurrencyInode"
CliFlagForceInode = "forceInode" CliFlagForceInode = "forceInode"
CliFlagEnableQuota = "enableQuota" CliFlagEnableQuota = "enableQuota"
CliFlagDeleteLockTime = "delete-lock-time" CliFlagDeleteLockTime = "delete-lock-time"
CliFlagClientIDKey = "clientIDKey" CliFlagClientIDKey = "clientIDKey"
CliFlagMarkDiskBrokenThreshold = "markBrokenDiskThreshold" CliFlagMarkDiskBrokenThreshold = "markBrokenDiskThreshold"
CliFlagForce = "force" CliFlagForce = "force"
CliFlagEnableCrossZone = "cross-zone" CliFlagEnableCrossZone = "cross-zone"
CliFlagAutoDpMetaRepair = "autoDpMetaRepair" CliFlagAutoDpMetaRepair = "autoDpMetaRepair"
CliFlagDpRepairTimeout = "dpRepairTimeout" CliFlagAutoDpMetaRepairParallelCnt = "autoDpMetaRepairParallelCnt"
CliFlagDpTimeout = "dpTimeout" CliFlagDpRepairTimeout = "dpRepairTimeout"
CliFlagDpTimeout = "dpTimeout"
CliFlagAutoDecommissionDisk = "autoDecommissionDisk"
CliFlagAutoDecommissionDiskInterval = "autoDecommissionDiskInterval"
// CliFlagSetDataPartitionCount = "count" use dp-count instead // CliFlagSetDataPartitionCount = "count" use dp-count instead

View File

@ -65,17 +65,19 @@ func formatClusterView(cv *proto.ClusterView, cn *proto.ClusterNodeInfo, cp *pro
sb.WriteString(fmt.Sprintf(" DataNode available : %v GB\n", cv.DataNodeStatInfo.AvailGB)) sb.WriteString(fmt.Sprintf(" DataNode available : %v GB\n", cv.DataNodeStatInfo.AvailGB))
sb.WriteString(fmt.Sprintf(" DataNode total : %v GB\n", cv.DataNodeStatInfo.TotalGB)) sb.WriteString(fmt.Sprintf(" DataNode total : %v GB\n", cv.DataNodeStatInfo.TotalGB))
sb.WriteString(fmt.Sprintf(" Volume count : %v\n", len(cv.VolStatInfo))) sb.WriteString(fmt.Sprintf(" Volume count : %v\n", len(cv.VolStatInfo)))
sb.WriteString(fmt.Sprintf(" Allow Mp Decomm : %v\n", formatEnabledDisabled(!cv.ForbidMpDecommission))) sb.WriteString(fmt.Sprintf(" Allow Mp Decomm : %v\n", formatEnabledDisabled(!cv.ForbidMpDecommission)))
sb.WriteString(fmt.Sprintf(" EbsAddr : %v\n", cp.EbsAddr)) sb.WriteString(fmt.Sprintf(" EbsAddr : %v\n", cp.EbsAddr))
sb.WriteString(fmt.Sprintf(" LoadFactor : %v\n", cn.LoadFactor)) sb.WriteString(fmt.Sprintf(" LoadFactor : %v\n", cn.LoadFactor))
sb.WriteString(fmt.Sprintf(" DpRepairTimeout : %v\n", cv.DpRepairTimeout)) sb.WriteString(fmt.Sprintf(" DpRepairTimeout : %v\n", cv.DpRepairTimeout))
sb.WriteString(fmt.Sprintf(" DataPartitionTimeout : %v\n", cv.DpTimeout)) sb.WriteString(fmt.Sprintf(" DataPartitionTimeout : %v\n", cv.DpTimeout))
sb.WriteString(fmt.Sprintf(" volDeletionDelayTime : %v h\n", cv.VolDeletionDelayTimeHour)) sb.WriteString(fmt.Sprintf(" volDeletionDelayTime : %v h\n", cv.VolDeletionDelayTimeHour))
sb.WriteString(fmt.Sprintf(" EnableAutoDecommission: %v\n", cv.EnableAutoDecommission)) sb.WriteString(fmt.Sprintf(" EnableAutoDecommission : %v\n", cv.EnableAutoDecommission))
sb.WriteString(fmt.Sprintf(" EnableAutoDpMetaRepair: %v\n", cv.EnableAutoDpMetaRepair)) sb.WriteString(fmt.Sprintf(" AutoDecommissionDiskIntervak : %v\n", cv.AutoDecommissionDiskInterval))
sb.WriteString(fmt.Sprintf(" MarkDiskBrokenThreshold : %v\n", strutil.FormatPercent(cv.MarkDiskBrokenThreshold))) sb.WriteString(fmt.Sprintf(" EnableAutoDpMetaRepair : %v\n", cv.EnableAutoDpMetaRepair))
sb.WriteString(fmt.Sprintf(" DecommissionDiskLimit: %v\n", cv.DecommissionDiskLimit)) 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))
return sb.String() return sb.String()
} }

View File

@ -1329,6 +1329,28 @@ func parseAndExtractSetNodeInfoParams(r *http.Request) (params map[string]interf
params[markDiskBrokenThresholdKey] = val 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 != "" { if value = r.FormValue(autoDpMetaRepairKey); value != "" {
noParams = false noParams = false
val := false val := false
@ -1340,6 +1362,17 @@ func parseAndExtractSetNodeInfoParams(r *http.Request) (params map[string]interf
params[autoDpMetaRepairKey] = val 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 != "" { if value = r.FormValue(dpTimeoutKey); value != "" {
noParams = false noParams = false
val := int64(0) val := int64(0)

View File

@ -783,29 +783,31 @@ func (m *Server) getCluster(w http.ResponseWriter, r *http.Request) {
}() }()
cv := &proto.ClusterView{ cv := &proto.ClusterView{
Name: m.cluster.Name, Name: m.cluster.Name,
CreateTime: time.Unix(m.cluster.CreateTime, 0).Format(proto.TimeFormat), CreateTime: time.Unix(m.cluster.CreateTime, 0).Format(proto.TimeFormat),
LeaderAddr: m.leaderInfo.addr, LeaderAddr: m.leaderInfo.addr,
DisableAutoAlloc: m.cluster.DisableAutoAllocate, DisableAutoAlloc: m.cluster.DisableAutoAllocate,
ForbidMpDecommission: m.cluster.ForbidMpDecommission, ForbidMpDecommission: m.cluster.ForbidMpDecommission,
MetaNodeThreshold: m.cluster.cfg.MetaNodeThreshold, MetaNodeThreshold: m.cluster.cfg.MetaNodeThreshold,
Applied: m.fsm.applied, Applied: m.fsm.applied,
MaxDataPartitionID: m.cluster.idAlloc.dataPartitionID, MaxDataPartitionID: m.cluster.idAlloc.dataPartitionID,
MaxMetaNodeID: m.cluster.idAlloc.commonID, MaxMetaNodeID: m.cluster.idAlloc.commonID,
MaxMetaPartitionID: m.cluster.idAlloc.metaPartitionID, MaxMetaPartitionID: m.cluster.idAlloc.metaPartitionID,
VolDeletionDelayTimeHour: m.cluster.cfg.volDelayDeleteTimeHour, VolDeletionDelayTimeHour: m.cluster.cfg.volDelayDeleteTimeHour,
DpRepairTimeout: m.cluster.GetDecommissionDataPartitionRecoverTimeOut(), DpRepairTimeout: m.cluster.GetDecommissionDataPartitionRecoverTimeOut(),
MarkDiskBrokenThreshold: m.cluster.getMarkDiskBrokenThreshold(), MarkDiskBrokenThreshold: m.cluster.getMarkDiskBrokenThreshold(),
EnableAutoDpMetaRepair: m.cluster.getEnableAutoDpMetaRepair(), EnableAutoDpMetaRepair: m.cluster.getEnableAutoDpMetaRepair(),
EnableAutoDecommission: m.cluster.AutoDecommissionDiskIsEnabled(), AutoDpMetaRepairParallelCnt: m.cluster.GetAutoDpMetaRepairParallelCnt(),
DecommissionDiskLimit: m.cluster.GetDecommissionDiskLimit(), EnableAutoDecommission: m.cluster.AutoDecommissionDiskIsEnabled(),
DpTimeout: time.Duration(m.cluster.getDataPartitionTimeoutSec()) * time.Second, AutoDecommissionDiskInterval: m.cluster.GetAutoDecommissionDiskInterval(),
MasterNodes: make([]proto.NodeView, 0), DecommissionDiskLimit: m.cluster.GetDecommissionDiskLimit(),
MetaNodes: make([]proto.NodeView, 0), DpTimeout: time.Duration(m.cluster.getDataPartitionTimeoutSec()) * time.Second,
DataNodes: make([]proto.NodeView, 0), MasterNodes: make([]proto.NodeView, 0),
VolStatInfo: make([]*proto.VolStatInfo, 0), MetaNodes: make([]proto.NodeView, 0),
BadPartitionIDs: make([]proto.BadPartitionView, 0), DataNodes: make([]proto.NodeView, 0),
BadMetaPartitionIDs: make([]proto.BadPartitionView, 0), VolStatInfo: make([]*proto.VolStatInfo, 0),
BadPartitionIDs: make([]proto.BadPartitionView, 0),
BadMetaPartitionIDs: make([]proto.BadPartitionView, 0),
} }
vols := m.cluster.allVolNames() vols := m.cluster.allVolNames()
@ -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 val, ok := params[autoDpMetaRepairKey]; ok {
if autoRepair, ok := val.(bool); ok { if autoRepair, ok := val.(bool); ok {
if err = m.cluster.setEnableAutoDpMetaRepair(autoRepair); err != nil { 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 val, ok := params[dpTimeoutKey]; ok {
if dpTimeout, ok := val.(int64); ok { if dpTimeout, ok := val.(int64); ok {
if err = m.cluster.setDataPartitionTimeout(dpTimeout); err != nil { 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()) 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) { func TestSetEnableAutoDpMetaRepair(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo) reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.getEnableAutoDpMetaRepair() oldVal := server.cluster.getEnableAutoDpMetaRepair()
@ -1657,6 +1681,18 @@ func TestSetEnableAutoDpMetaRepair(t *testing.T) {
require.EqualValues(t, oldVal, server.cluster.getEnableAutoDpMetaRepair()) 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) { func TestSetDpTimeout(t *testing.T) {
reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo) reqUrl := fmt.Sprintf("%v%v", hostAddr, proto.AdminSetNodeInfo)
oldVal := server.cluster.getDataPartitionTimeoutSec() oldVal := server.cluster.getDataPartitionTimeoutSec()

View File

@ -86,7 +86,8 @@ type Cluster struct {
apiLimiter *ApiLimiter apiLimiter *ApiLimiter
DecommissionDisks sync.Map DecommissionDisks sync.Map
DecommissionLimit uint64 DecommissionLimit uint64
EnableAutoDecommissionDisk bool EnableAutoDecommissionDisk atomicutil.Bool
AutoDecommissionInterval atomicutil.Int64
AutoDecommissionDiskMux sync.Mutex AutoDecommissionDiskMux sync.Mutex
checkAutoCreateDataPartition bool checkAutoCreateDataPartition bool
masterClient *masterSDK.MasterClient masterClient *masterSDK.MasterClient
@ -106,6 +107,7 @@ type Cluster struct {
S3ApiQosQuota *sync.Map // (api,uid,limtType) -> limitQuota S3ApiQosQuota *sync.Map // (api,uid,limtType) -> limitQuota
MarkDiskBrokenThreshold atomicutil.Float64 MarkDiskBrokenThreshold atomicutil.Float64
EnableAutoDpMetaRepair atomicutil.Bool EnableAutoDpMetaRepair atomicutil.Bool
AutoDpMetaRepairParallelCnt atomicutil.Uint32
} }
type delayDeleteVolInfo struct { type delayDeleteVolInfo struct {
@ -371,6 +373,7 @@ func newCluster(name string, leaderInfo *LeaderInfo, fsm *MetadataFsm, partition
c.S3ApiQosQuota = new(sync.Map) c.S3ApiQosQuota = new(sync.Map)
c.MarkDiskBrokenThreshold.Store(defaultMarkDiskBrokenThreshold) c.MarkDiskBrokenThreshold.Store(defaultMarkDiskBrokenThreshold)
c.EnableAutoDpMetaRepair.Store(defaultEnableDpMetaRepair) c.EnableAutoDpMetaRepair.Store(defaultEnableDpMetaRepair)
c.AutoDecommissionInterval.Store(int64(defaultAutoDecommissionDiskInterval))
return return
} }
@ -4257,7 +4260,7 @@ func (c *Cluster) scheduleToBadDisk() {
if c.partition.IsRaftLeader() && c.AutoDecommissionDiskIsEnabled() && c.metaReady { if c.partition.IsRaftLeader() && c.AutoDecommissionDiskIsEnabled() && c.metaReady {
c.checkBadDisk() 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 { func (c *Cluster) AutoDecommissionDiskIsEnabled() bool {
c.AutoDecommissionDiskMux.Lock() c.AutoDecommissionDiskMux.Lock()
defer c.AutoDecommissionDiskMux.Unlock() defer c.AutoDecommissionDiskMux.Unlock()
return c.EnableAutoDecommissionDisk return c.EnableAutoDecommissionDisk.Load()
} }
func (c *Cluster) SetAutoDecommissionDisk(flag bool) { func (c *Cluster) SetAutoDecommissionDisk(flag bool) {
c.AutoDecommissionDiskMux.Lock() c.AutoDecommissionDiskMux.Lock()
defer c.AutoDecommissionDiskMux.Unlock() 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 { func (c *Cluster) GetDecommissionDataPartitionRecoverTimeOut() time.Duration {

View File

@ -50,97 +50,100 @@ const (
forbiddenKey = "forbidden" forbiddenKey = "forbidden"
deleteVolKey = "delete" deleteVolKey = "delete"
forceDelVolKey = "forceDelVol" forceDelVolKey = "forceDelVol"
ebsBlkSizeKey = "ebsBlkSize" ebsBlkSizeKey = "ebsBlkSize"
cacheCapacity = "cacheCap" cacheCapacity = "cacheCap"
cacheActionKey = "cacheAction" cacheActionKey = "cacheAction"
cacheThresholdKey = "cacheThreshold" cacheThresholdKey = "cacheThreshold"
cacheTTLKey = "cacheTTL" cacheTTLKey = "cacheTTL"
cacheHighWaterKey = "cacheHighWater" cacheHighWaterKey = "cacheHighWater"
cacheLowWaterKey = "cacheLowWater" cacheLowWaterKey = "cacheLowWater"
cacheLRUIntervalKey = "cacheLRUInterval" cacheLRUIntervalKey = "cacheLRUInterval"
clientVersion = "version" clientVersion = "version"
domainIdKey = "domainId" domainIdKey = "domainId"
volOwnerKey = "owner" volOwnerKey = "owner"
volAuthKey = "authKey" volAuthKey = "authKey"
replicaNumKey = "replicaNum" replicaNumKey = "replicaNum"
followerReadKey = "followerRead" followerReadKey = "followerRead"
authenticateKey = "authenticate" authenticateKey = "authenticate"
akKey = "ak" akKey = "ak"
keywordsKey = "keywords" keywordsKey = "keywords"
zoneNameKey = "zoneName" zoneNameKey = "zoneName"
nodesetIdKey = "nodesetId" nodesetIdKey = "nodesetId"
crossZoneKey = "crossZone" crossZoneKey = "crossZone"
normalZonesFirstKey = "normalZonesFirst" normalZonesFirstKey = "normalZonesFirst"
userKey = "user" userKey = "user"
nodeHostsKey = "hosts" nodeHostsKey = "hosts"
nodeDeleteBatchCountKey = "batchCount" nodeDeleteBatchCountKey = "batchCount"
nodeMarkDeleteRateKey = "markDeleteRate" nodeMarkDeleteRateKey = "markDeleteRate"
nodeDeleteWorkerSleepMs = "deleteWorkerSleepMs" nodeDeleteWorkerSleepMs = "deleteWorkerSleepMs"
nodeAutoRepairRateKey = "autoRepairRate" nodeAutoRepairRateKey = "autoRepairRate"
nodeDpRepairTimeOutKey = "dpRepairTimeOut" nodeDpRepairTimeOutKey = "dpRepairTimeOut"
nodeDpMaxRepairErrCntKey = "dpMaxRepairErrCnt" nodeDpMaxRepairErrCntKey = "dpMaxRepairErrCnt"
clusterLoadFactorKey = "loadFactor" clusterLoadFactorKey = "loadFactor"
maxDpCntLimitKey = "maxDpCntLimit" maxDpCntLimitKey = "maxDpCntLimit"
maxMpCntLimitKey = "maxMpCntLimit" maxMpCntLimitKey = "maxMpCntLimit"
clusterCreateTimeKey = "clusterCreateTime" clusterCreateTimeKey = "clusterCreateTime"
descriptionKey = "description" descriptionKey = "description"
dpSelectorNameKey = "dpSelectorName" dpSelectorNameKey = "dpSelectorName"
dpSelectorParmKey = "dpSelectorParm" dpSelectorParmKey = "dpSelectorParm"
nodeTypeKey = "nodeType" nodeTypeKey = "nodeType"
ratio = "ratio" ratio = "ratio"
rdOnlyKey = "rdOnly" rdOnlyKey = "rdOnly"
srcAddrKey = "srcAddr" srcAddrKey = "srcAddr"
targetAddrKey = "targetAddr" targetAddrKey = "targetAddr"
forceKey = "force" forceKey = "force"
raftForceDelKey = "raftForceDel" raftForceDelKey = "raftForceDel"
enablePosixAclKey = "enablePosixAcl" enablePosixAclKey = "enablePosixAcl"
enableTxMaskKey = "enableTxMask" enableTxMaskKey = "enableTxMask"
txTimeoutKey = "txTimeout" txTimeoutKey = "txTimeout"
txConflictRetryNumKey = "txConflictRetryNum" txConflictRetryNumKey = "txConflictRetryNum"
txConflictRetryIntervalKey = "txConflictRetryInterval" txConflictRetryIntervalKey = "txConflictRetryInterval"
txOpLimitKey = "txOpLimit" txOpLimitKey = "txOpLimit"
txForceResetKey = "txForceReset" txForceResetKey = "txForceReset"
QosEnableKey = "qosEnable" QosEnableKey = "qosEnable"
DiskEnableKey = "diskenable" DiskEnableKey = "diskenable"
IopsWKey = "iopsWKey" IopsWKey = "iopsWKey"
IopsRKey = "iopsRKey" IopsRKey = "iopsRKey"
FlowWKey = "flowWKey" FlowWKey = "flowWKey"
FlowRKey = "flowRKey" FlowRKey = "flowRKey"
ClientReqPeriod = "reqPeriod" ClientReqPeriod = "reqPeriod"
ClientTriggerCnt = "triggerCnt" ClientTriggerCnt = "triggerCnt"
QosMasterLimit = "qosLimit" QosMasterLimit = "qosLimit"
decommissionLimit = "decommissionLimit" decommissionLimit = "decommissionLimit"
DiskDisableKey = "diskDisable" DiskDisableKey = "diskDisable"
Limit = "limit" Limit = "limit"
TimeOut = "timeout" TimeOut = "timeout"
CountByMeta = "countByMeta" CountByMeta = "countByMeta"
dpReadOnlyWhenVolFull = "dpReadOnlyWhenVolFull" dpReadOnlyWhenVolFull = "dpReadOnlyWhenVolFull"
PeriodicKey = "periodic" PeriodicKey = "periodic"
IPKey = "ip" IPKey = "ip"
OperateKey = "op" OperateKey = "op"
UIDKey = "uid" UIDKey = "uid"
CapacityKey = "capacity" CapacityKey = "capacity"
configKey = "config" configKey = "config"
MaxFilesKey = "maxFiles" MaxFilesKey = "maxFiles"
MaxBytesKey = "maxBytes" MaxBytesKey = "maxBytes"
fullPathKey = "fullPath" fullPathKey = "fullPath"
inodeKey = "inode" inodeKey = "inode"
quotaKey = "quotaId" quotaKey = "quotaId"
enableQuota = "enableQuota" enableQuota = "enableQuota"
dpDiscardKey = "dpDiscard" dpDiscardKey = "dpDiscard"
ignoreDiscardKey = "ignoreDiscard" ignoreDiscardKey = "ignoreDiscard"
TrashIntervalKey = "trashInterval" TrashIntervalKey = "trashInterval"
ClientIDKey = "clientIDKey" ClientIDKey = "clientIDKey"
verSeqKey = "verSeq" verSeqKey = "verSeq"
Periodic = "periodic" Periodic = "periodic"
DecommissionType = "decommissionType" DecommissionType = "decommissionType"
decommissionDiskLimit = "decommissionDiskLimit" decommissionDiskLimit = "decommissionDiskLimit"
dpRepairBlockSizeKey = "dpRepairBlockSize" dpRepairBlockSizeKey = "dpRepairBlockSize"
markDiskBrokenThresholdKey = "markDiskBrokenThreshold" markDiskBrokenThresholdKey = "markDiskBrokenThreshold"
decommissionTypeKey = "decommissionType" decommissionTypeKey = "decommissionType"
autoDpMetaRepairKey = "autoDpMetaRepair" autoDecommissionDiskKey = "autoDecommissionDisk"
dpTimeoutKey = "dpTimeout" autoDecommissionDiskIntervalKey = "autoDecommissionDiskInterval"
autoDpMetaRepairKey = "autoDpMetaRepair"
autoDpMetaRepairParallelCntKey = "autoDpMetaRepairParallelCnt"
dpTimeoutKey = "dpTimeout"
) )
const ( const (
@ -214,6 +217,8 @@ const (
defaultVolDelayDeleteTimeHour = 48 defaultVolDelayDeleteTimeHour = 48
defaultMarkDiskBrokenThreshold = 0 // decommission all dp from disk defaultMarkDiskBrokenThreshold = 0 // decommission all dp from disk
defaultEnableDpMetaRepair = false defaultEnableDpMetaRepair = false
defaultAutoDpMetaRepairPallarelCnt = 100
defaultAutoDecommissionDiskInterval = 10 * time.Second
maxMpCreationCount = 10 maxMpCreationCount = 10
) )

View File

@ -35,72 +35,76 @@ import (
transferred over the network. */ transferred over the network. */
type clusterValue struct { type clusterValue struct {
Name string Name string
CreateTime int64 CreateTime int64
Threshold float32 Threshold float32
LoadFactor float32 LoadFactor float32
DisableAutoAllocate bool DisableAutoAllocate bool
ForbidMpDecommission bool ForbidMpDecommission bool
DataNodeDeleteLimitRate uint64 DataNodeDeleteLimitRate uint64
MetaNodeDeleteBatchCount uint64 MetaNodeDeleteBatchCount uint64
MetaNodeDeleteWorkerSleepMs uint64 MetaNodeDeleteWorkerSleepMs uint64
DataNodeAutoRepairLimitRate uint64 DataNodeAutoRepairLimitRate uint64
MaxDpCntLimit uint64 MaxDpCntLimit uint64
MaxMpCntLimit uint64 MaxMpCntLimit uint64
FaultDomain bool FaultDomain bool
DiskQosEnable bool DiskQosEnable bool
QosLimitUpload uint64 QosLimitUpload uint64
DirChildrenNumLimit uint32 DirChildrenNumLimit uint32
DecommissionLimit uint64 DecommissionLimit uint64
CheckDataReplicasEnable bool CheckDataReplicasEnable bool
FileStatsEnable bool FileStatsEnable bool
ClusterUuid string ClusterUuid string
ClusterUuidEnable bool ClusterUuidEnable bool
MetaPartitionInodeIdStep uint64 MetaPartitionInodeIdStep uint64
MaxConcurrentLcNodes uint64 MaxConcurrentLcNodes uint64
DpMaxRepairErrCnt uint64 DpMaxRepairErrCnt uint64
DpRepairTimeOut uint64 DpRepairTimeOut uint64
EnableAutoDecommissionDisk bool EnableAutoDecommissionDisk bool
DecommissionDiskLimit uint32 AutoDecommissionDiskInterval int64
VolDeletionDelayTimeHour int64 DecommissionDiskLimit uint32
MarkDiskBrokenThreshold float64 VolDeletionDelayTimeHour int64
EnableAutoDpMetaRepair bool MarkDiskBrokenThreshold float64
DataPartitionTimeoutSec int64 EnableAutoDpMetaRepair bool
AutoDpMetaRepairParallelCnt uint32
DataPartitionTimeoutSec int64
} }
func newClusterValue(c *Cluster) (cv *clusterValue) { func newClusterValue(c *Cluster) (cv *clusterValue) {
cv = &clusterValue{ cv = &clusterValue{
Name: c.Name, Name: c.Name,
CreateTime: c.CreateTime, CreateTime: c.CreateTime,
LoadFactor: c.cfg.ClusterLoadFactor, LoadFactor: c.cfg.ClusterLoadFactor,
Threshold: c.cfg.MetaNodeThreshold, Threshold: c.cfg.MetaNodeThreshold,
DataNodeDeleteLimitRate: c.cfg.DataNodeDeleteLimitRate, DataNodeDeleteLimitRate: c.cfg.DataNodeDeleteLimitRate,
MetaNodeDeleteBatchCount: c.cfg.MetaNodeDeleteBatchCount, MetaNodeDeleteBatchCount: c.cfg.MetaNodeDeleteBatchCount,
MetaNodeDeleteWorkerSleepMs: c.cfg.MetaNodeDeleteWorkerSleepMs, MetaNodeDeleteWorkerSleepMs: c.cfg.MetaNodeDeleteWorkerSleepMs,
DataNodeAutoRepairLimitRate: c.cfg.DataNodeAutoRepairLimitRate, DataNodeAutoRepairLimitRate: c.cfg.DataNodeAutoRepairLimitRate,
DisableAutoAllocate: c.DisableAutoAllocate, DisableAutoAllocate: c.DisableAutoAllocate,
ForbidMpDecommission: c.ForbidMpDecommission, ForbidMpDecommission: c.ForbidMpDecommission,
MaxDpCntLimit: c.cfg.MaxDpCntLimit, MaxDpCntLimit: c.cfg.MaxDpCntLimit,
MaxMpCntLimit: c.cfg.MaxMpCntLimit, MaxMpCntLimit: c.cfg.MaxMpCntLimit,
FaultDomain: c.FaultDomain, FaultDomain: c.FaultDomain,
DiskQosEnable: c.diskQosEnable, DiskQosEnable: c.diskQosEnable,
QosLimitUpload: uint64(c.QosAcceptLimit.Limit()), QosLimitUpload: uint64(c.QosAcceptLimit.Limit()),
DirChildrenNumLimit: c.cfg.DirChildrenNumLimit, DirChildrenNumLimit: c.cfg.DirChildrenNumLimit,
DecommissionLimit: c.DecommissionLimit, DecommissionLimit: c.DecommissionLimit,
CheckDataReplicasEnable: c.checkDataReplicasEnable, CheckDataReplicasEnable: c.checkDataReplicasEnable,
FileStatsEnable: c.fileStatsEnable, FileStatsEnable: c.fileStatsEnable,
ClusterUuid: c.clusterUuid, ClusterUuid: c.clusterUuid,
ClusterUuidEnable: c.clusterUuidEnable, ClusterUuidEnable: c.clusterUuidEnable,
MetaPartitionInodeIdStep: c.cfg.MetaPartitionInodeIdStep, MetaPartitionInodeIdStep: c.cfg.MetaPartitionInodeIdStep,
MaxConcurrentLcNodes: c.cfg.MaxConcurrentLcNodes, MaxConcurrentLcNodes: c.cfg.MaxConcurrentLcNodes,
DpMaxRepairErrCnt: c.cfg.DpMaxRepairErrCnt, DpMaxRepairErrCnt: c.cfg.DpMaxRepairErrCnt,
DpRepairTimeOut: c.cfg.DpRepairTimeOut, DpRepairTimeOut: c.cfg.DpRepairTimeOut,
EnableAutoDecommissionDisk: c.EnableAutoDecommissionDisk, EnableAutoDecommissionDisk: c.EnableAutoDecommissionDisk.Load(),
DecommissionDiskLimit: c.GetDecommissionDiskLimit(), AutoDecommissionDiskInterval: c.AutoDecommissionInterval.Load(),
VolDeletionDelayTimeHour: c.cfg.volDelayDeleteTimeHour, DecommissionDiskLimit: c.GetDecommissionDiskLimit(),
MarkDiskBrokenThreshold: c.getMarkDiskBrokenThreshold(), VolDeletionDelayTimeHour: c.cfg.volDelayDeleteTimeHour,
EnableAutoDpMetaRepair: c.getEnableAutoDpMetaRepair(), MarkDiskBrokenThreshold: c.getMarkDiskBrokenThreshold(),
DataPartitionTimeoutSec: c.getDataPartitionTimeoutSec(), EnableAutoDpMetaRepair: c.getEnableAutoDpMetaRepair(),
AutoDpMetaRepairParallelCnt: c.AutoDpMetaRepairParallelCnt.Load(),
DataPartitionTimeoutSec: c.getDataPartitionTimeoutSec(),
} }
return cv return cv
} }
@ -1057,6 +1061,14 @@ func (c *Cluster) updateEnableAutoDpMetaRepair(val bool) {
c.EnableAutoDpMetaRepair.Store(val) 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) { func (c *Cluster) updateDecommissionDiskLimit(val uint32) {
if val < 1 { if val < 1 {
val = 1 val = 1
@ -1179,7 +1191,8 @@ func (c *Cluster) loadClusterValue() (err error) {
c.clusterUuid = cv.ClusterUuid c.clusterUuid = cv.ClusterUuid
c.clusterUuidEnable = cv.ClusterUuidEnable c.clusterUuidEnable = cv.ClusterUuidEnable
c.DecommissionLimit = cv.DecommissionLimit c.DecommissionLimit = cv.DecommissionLimit
c.EnableAutoDecommissionDisk = cv.EnableAutoDecommissionDisk c.EnableAutoDecommissionDisk.Store(cv.EnableAutoDecommissionDisk)
c.updateAutoDecommissionDiskInterval(cv.AutoDecommissionDiskInterval)
c.DecommissionLimit = cv.DecommissionLimit c.DecommissionLimit = cv.DecommissionLimit
c.cfg.volDelayDeleteTimeHour = cv.VolDeletionDelayTimeHour c.cfg.volDelayDeleteTimeHour = cv.VolDeletionDelayTimeHour
@ -1213,6 +1226,7 @@ func (c *Cluster) loadClusterValue() (err error) {
c.checkDataReplicasEnable = cv.CheckDataReplicasEnable c.checkDataReplicasEnable = cv.CheckDataReplicasEnable
c.updateMarkDiskBrokenThreshold(cv.MarkDiskBrokenThreshold) c.updateMarkDiskBrokenThreshold(cv.MarkDiskBrokenThreshold)
c.updateEnableAutoDpMetaRepair(cv.EnableAutoDpMetaRepair) c.updateEnableAutoDpMetaRepair(cv.EnableAutoDpMetaRepair)
c.updateAutoDpMetaRepairParallelCnt(cv.AutoDpMetaRepairParallelCnt)
c.updateDataPartitionTimeoutSec(cv.DataPartitionTimeoutSec) c.updateDataPartitionTimeoutSec(cv.DataPartitionTimeoutSec)
} }
return return

View File

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

View File

@ -117,31 +117,33 @@ type MetaReplicaInfo struct {
// ClusterView provides the view of a cluster. // ClusterView provides the view of a cluster.
type ClusterView struct { type ClusterView struct {
Name string Name string
CreateTime string CreateTime string
LeaderAddr string LeaderAddr string
DisableAutoAlloc bool DisableAutoAlloc bool
ForbidMpDecommission bool ForbidMpDecommission bool
MetaNodeThreshold float32 MetaNodeThreshold float32
Applied uint64 Applied uint64
MaxDataPartitionID uint64 MaxDataPartitionID uint64
MaxMetaNodeID uint64 MaxMetaNodeID uint64
MaxMetaPartitionID uint64 MaxMetaPartitionID uint64
VolDeletionDelayTimeHour int64 VolDeletionDelayTimeHour int64
MarkDiskBrokenThreshold float64 MarkDiskBrokenThreshold float64
EnableAutoDpMetaRepair bool EnableAutoDpMetaRepair bool
EnableAutoDecommission bool AutoDpMetaRepairParallelCnt int
DecommissionDiskLimit uint32 EnableAutoDecommission bool
DpRepairTimeout time.Duration AutoDecommissionDiskInterval time.Duration
DpTimeout time.Duration DecommissionDiskLimit uint32
DataNodeStatInfo *NodeStatInfo DpRepairTimeout time.Duration
MetaNodeStatInfo *NodeStatInfo DpTimeout time.Duration
VolStatInfo []*VolStatInfo DataNodeStatInfo *NodeStatInfo
BadPartitionIDs []BadPartitionView MetaNodeStatInfo *NodeStatInfo
BadMetaPartitionIDs []BadPartitionView VolStatInfo []*VolStatInfo
MasterNodes []NodeView BadPartitionIDs []BadPartitionView
MetaNodes []NodeView BadMetaPartitionIDs []BadPartitionView
DataNodes []NodeView MasterNodes []NodeView
MetaNodes []NodeView
DataNodes []NodeView
} }
// ClusterNode defines the structure of a cluster node // ClusterNode defines the structure of a cluster node

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, func (api *AdminAPI) SetClusterParas(batchCount, markDeleteRate, deleteWorkerSleepMs, autoRepairRate, loadFactor, maxDpCntLimit, maxMpCntLimit, clientIDKey string,
dataNodesetSelector, metaNodesetSelector, dataNodeSelector, metaNodeSelector string, markDiskBrokenThreshold 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) { ) (err error) {
request := newRequest(get, proto.AdminSetNodeInfo).Header(api.h) request := newRequest(get, proto.AdminSetNodeInfo).Header(api.h)
request.addParam("batchCount", batchCount) request.addParam("batchCount", batchCount)
@ -536,9 +538,18 @@ func (api *AdminAPI) SetClusterParas(batchCount, markDeleteRate, deleteWorkerSle
if markDiskBrokenThreshold != "" { if markDiskBrokenThreshold != "" {
request.addParam("markDiskBrokenThreshold", markDiskBrokenThreshold) request.addParam("markDiskBrokenThreshold", markDiskBrokenThreshold)
} }
if enableAutoDecommissionDisk != "" {
request.addParam("autoDecommissionDisk", enableAutoDecommissionDisk)
}
if autoDecommissionDiskInterval != "" {
request.addParam("autoDecommissionDiskInterval", autoDecommissionDiskInterval)
}
if enableAutoDpMetaRepair != "" { if enableAutoDpMetaRepair != "" {
request.addParam("autoDpMetaRepair", enableAutoDpMetaRepair) request.addParam("autoDpMetaRepair", enableAutoDpMetaRepair)
} }
if autoDpMetaRepairParallelCnt != "" {
request.addParam("autoDpMetaRepairParallelCnt", autoDpMetaRepairParallelCnt)
}
if dpRepairTimeout != "" { if dpRepairTimeout != "" {
request.addParam("dpRepairTimeOut", 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) swaped = atomic.CompareAndSwapUint32(&b.val, oldVal, val)
return 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.Load())
require.True(t, b.CompareAndSwap(true, false)) require.True(t, b.CompareAndSwap(true, false))
require.False(t, b.Load()) 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) { func (f *Float64) Store(val float64) {
atomic.StoreUint64(&f.val, math.Float64bits(val)) 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) testVal := float64(1.0)
f.Store(testVal) f.Store(testVal)
require.Equal(t, testVal, f.Load()) 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))
}