enhance(lcnode): support multi task

1. add lcTaskCountLimit
2. delete Scanning and add WorkingCount
3. add lcnode addr in heartbeat resp and scan resp

Signed-off-by: zhaochenyang <zhaochenyang@oppo.com>
This commit is contained in:
zhaochenyang 2023-12-08 15:28:14 +08:00 committed by chenyangzhao
parent 1f855b084f
commit bd6608b8d0
12 changed files with 184 additions and 252 deletions

View File

@ -30,6 +30,7 @@ const (
configLcScanLimitPerSecondStr = "lcScanLimitPerSecond"
configSnapshotRoutineNumPerTaskStr = "snapshotRoutineNumPerTask"
configLcNodeTaskCountLimit = "lcNodeTaskCountLimit"
)
// Default of configuration value
@ -53,6 +54,7 @@ const (
defaultIntervalToCheckRegister = 2 * defaultLcNodeTimeOutSec
defaultUnboundedChanInitCapacity = 10000
defaultLcNodeTaskCountLimit = 1
)
var (
@ -65,4 +67,5 @@ var (
lcScanLimitPerSecond rate.Limit
snapshotRoutineNumPerTask int
lcNodeTaskCountLimit int
)

View File

@ -59,7 +59,8 @@ func (l *LcNode) opMasterHeartbeat(conn net.Conn, p *proto.Packet, remoteAddr st
l.scannerMutex.RLock()
for _, scanner := range l.lcScanners {
result := &proto.LcNodeRuleTaskResponse{
ID: scanner.ID,
ID: scanner.ID,
LcNode: l.localServerAddr,
LcNodeRuleTaskStatistics: proto.LcNodeRuleTaskStatistics{
Volume: scanner.Volume,
RuleId: scanner.rule.ID,
@ -74,7 +75,9 @@ func (l *LcNode) opMasterHeartbeat(conn net.Conn, p *proto.Packet, remoteAddr st
}
for _, scanner := range l.snapshotScanners {
info := &proto.SnapshotVerDelTaskResponse{
ID: scanner.ID,
ID: scanner.ID,
LcNode: l.localServerAddr,
SnapshotVerDelTask: scanner.verDelReq.Task,
SnapshotStatistics: proto.SnapshotStatistics{
VolName: scanner.Volume,
VerSeq: scanner.getTaskVerSeq(),
@ -88,6 +91,7 @@ func (l *LcNode) opMasterHeartbeat(conn net.Conn, p *proto.Packet, remoteAddr st
}
l.scannerMutex.RUnlock()
resp.LcTaskCountLimit = lcNodeTaskCountLimit
resp.Status = proto.TaskSucceeds
end:

View File

@ -128,11 +128,10 @@ func (s *LcScanner) Start() (err error) {
if err != nil {
log.LogErrorf("startScan err(%v): volume(%v), rule id(%v), scanning done!",
err, s.Volume, s.rule.ID)
t := time.Now()
response.ID = s.ID
response.EndTime = &t
response.Status = proto.TaskSucceeds
response.Done = true
response.LcNode = s.lcnode.localServerAddr
response.Status = proto.TaskFailed
response.Result = err.Error()
s.lcnode.scannerMutex.Lock()
delete(s.lcnode.lcScanners, s.ID)
@ -522,6 +521,7 @@ func (s *LcScanner) checkScanning() {
response.Status = proto.TaskSucceeds
response.Done = true
response.ID = s.ID
response.LcNode = s.lcnode.localServerAddr
response.Volume = s.Volume
response.RuleId = s.rule.ID
response.ExpiredNum = s.currentStat.ExpiredNum

View File

@ -195,6 +195,21 @@ func (l *LcNode) parseConfig(cfg *config.Config) (err error) {
}
log.LogInfof("loadConfig: setup config: %v(%v)", configLcScanLimitPerSecondStr, lcScanLimitPerSecond)
// parse lcNodeTaskCount
var count int64
countStr := cfg.GetString(configLcNodeTaskCountLimit)
if countStr != "" {
if count, err = strconv.ParseInt(countStr, 10, 64); err != nil {
return fmt.Errorf("%v,err:%v", proto.ErrInvalidCfg, err.Error())
}
}
if count <= 0 {
lcNodeTaskCountLimit = defaultLcNodeTaskCountLimit
} else {
lcNodeTaskCountLimit = int(count)
}
log.LogInfof("loadConfig: setup config: %v(%v)", configLcNodeTaskCountLimit, lcNodeTaskCountLimit)
return
}

View File

@ -418,6 +418,8 @@ func (s *SnapshotScanner) checkScanning(report bool) {
response.Status = proto.TaskSucceeds
response.Done = true
response.ID = s.ID
response.LcNode = s.lcnode.localServerAddr
response.SnapshotVerDelTask = s.verDelReq.Task
response.VolName = s.Volume
response.VerSeq = s.getTaskVerSeq()
response.FileNum = s.currentStat.FileNum

View File

@ -4297,13 +4297,13 @@ func (c *Cluster) addLcNode(nodeAddr string) (id uint64, err error) {
goto errHandler
}
c.lcNodes.Store(nodeAddr, ln)
c.lcMgr.lcNodeStatus.Lock()
delete(c.lcMgr.lcNodeStatus.WorkingNodes, nodeAddr)
c.lcMgr.lcNodeStatus.IdleNodes[nodeAddr] = nodeAddr
c.lcMgr.lcNodeStatus.WorkingCount[nodeAddr] = 0
c.lcMgr.lcNodeStatus.Unlock()
c.snapshotMgr.lcNodeStatus.Lock()
delete(c.snapshotMgr.lcNodeStatus.WorkingNodes, nodeAddr)
c.snapshotMgr.lcNodeStatus.IdleNodes[nodeAddr] = nodeAddr
c.snapshotMgr.lcNodeStatus.WorkingCount[nodeAddr] = 0
c.snapshotMgr.lcNodeStatus.Unlock()
log.LogInfof("action[addLcNode], clusterID[%v], lcNodeAddr: %v, id: %v, add idleNodes", c.Name, nodeAddr, ln.ID)
return ln.ID, nil
@ -4356,8 +4356,8 @@ func (c *Cluster) clearLcNodes() {
}
func (c *Cluster) delLcNode(nodeAddr string) (err error) {
c.lcMgr.lcRuleTaskStatus.RedoTask(c.lcMgr.lcNodeStatus.RemoveNode(nodeAddr))
c.snapshotMgr.lcSnapshotTaskStatus.RedoTask(c.snapshotMgr.lcNodeStatus.RemoveNode(nodeAddr))
c.lcMgr.lcNodeStatus.RemoveNode(nodeAddr)
c.snapshotMgr.lcNodeStatus.RemoveNode(nodeAddr)
lcNode, err := c.lcNode(nodeAddr)
if err != nil {

View File

@ -15,6 +15,7 @@
package master
import (
"math"
"sync"
"time"
@ -36,8 +37,8 @@ func newLifecycleManager() *lifecycleManager {
log.LogInfof("action[newLifecycleManager] construct")
lcMgr := &lifecycleManager{
lcConfigurations: make(map[string]*proto.LcConfiguration),
lcNodeStatus: NewLcNodeStatus(),
lcRuleTaskStatus: NewLcRuleTaskStatus(),
lcNodeStatus: newLcNodeStatus(),
lcRuleTaskStatus: newLcRuleTaskStatus(),
idleLcNodeCh: make(chan struct{}),
exitCh: make(chan struct{}),
}
@ -60,8 +61,7 @@ func (lcMgr *lifecycleManager) startLcScan() {
}
// start scan init
lcMgr.lcNodeStatus.WorkingNodes = make(map[string]string)
lcMgr.lcRuleTaskStatus = NewLcRuleTaskStatus()
lcMgr.lcRuleTaskStatus = newLcRuleTaskStatus()
for _, r := range tasks {
lcMgr.lcRuleTaskStatus.ToBeScanned[r.Id] = r
}
@ -84,45 +84,24 @@ func (lcMgr *lifecycleManager) genEnabledRuleTasks() []*proto.RuleTask {
}
func (lcMgr *lifecycleManager) scanning() bool {
log.LogInfof("scanning lcNodeStatus: %v", lcMgr.lcNodeStatus)
log.LogInfof("decide scanning, lcNodeStatus: %v, lcRuleTaskStatus: %v", lcMgr.lcNodeStatus, lcMgr.lcRuleTaskStatus)
if len(lcMgr.lcRuleTaskStatus.ToBeScanned) > 0 {
return true
}
//handling exceptions
if len(lcMgr.lcRuleTaskStatus.Scanning) > 0 {
scanning := lcMgr.lcRuleTaskStatus.Scanning
var nodes []string
lcMgr.cluster.lcNodes.Range(func(addr, value interface{}) bool {
nodes = append(nodes, addr.(string))
return true
})
for _, task := range scanning {
workingNodes := lcMgr.lcNodeStatus.WorkingNodes
var node string
for nodeAddr, t := range workingNodes {
if task.Id == t {
node = nodeAddr
}
}
if exist(node, nodes) {
log.LogInfof("scanning task: %v, exist node: %v, all nodes: %v", task, node, nodes)
return true
}
log.LogInfof("scanning task: %v, but not exist node: %v, all nodes: %v", task, node, nodes)
}
}
return false
}
func exist(node string, nodes []string) bool {
for _, n := range nodes {
if node == n {
for _, v := range lcMgr.lcRuleTaskStatus.Results {
if v.Done != true && time.Now().Before(v.UpdateTime.Add(time.Minute*10)) {
return true
}
}
for _, c := range lcMgr.lcNodeStatus.WorkingCount {
if c > 0 {
return true
}
}
log.LogInfof("decide scanning, scanning stop!")
return false
}
@ -131,7 +110,7 @@ func (lcMgr *lifecycleManager) process() {
now := time.Now()
lcMgr.lcRuleTaskStatus.StartTime = &now
for lcMgr.scanning() {
log.LogDebugf("wait idleLcNodeCh... ToBeScanned num(%v), Scanning num(%v)", len(lcMgr.lcRuleTaskStatus.ToBeScanned), len(lcMgr.lcRuleTaskStatus.Scanning))
log.LogDebugf("wait idleLcNodeCh... ToBeScanned num(%v)", len(lcMgr.lcRuleTaskStatus.ToBeScanned))
select {
case <-lcMgr.exitCh:
log.LogInfo("exitCh notified, lifecycleManager process exit")
@ -140,41 +119,35 @@ func (lcMgr *lifecycleManager) process() {
log.LogDebug("idleLcNodeCh notified")
// ToBeScanned -> Scanning
taskId := lcMgr.lcRuleTaskStatus.GetOneTask()
if taskId == "" {
log.LogWarn("lcRuleTaskStatus.GetOneTask, no task")
task := lcMgr.lcRuleTaskStatus.GetOneTask()
if task == nil {
log.LogDebugf("lcRuleTaskStatus.GetOneTask, no task")
continue
}
// idleNodes -> workingNodes
nodeAddr := lcMgr.lcNodeStatus.GetIdleNode(taskId)
nodeAddr := lcMgr.lcNodeStatus.GetIdleNode()
if nodeAddr == "" {
log.LogWarn("no idle lcnode, redo task")
lcMgr.lcRuleTaskStatus.RedoTask(taskId)
lcMgr.lcRuleTaskStatus.RedoTask(task)
continue
}
val, ok := lcMgr.cluster.lcNodes.Load(nodeAddr)
if !ok {
log.LogErrorf("lcNodes.Load, nodeAddr(%v) is not available, redo task", nodeAddr)
lcMgr.lcRuleTaskStatus.RedoTask(lcMgr.lcNodeStatus.RemoveNode(nodeAddr))
lcMgr.lcNodeStatus.RemoveNode(nodeAddr)
lcMgr.lcRuleTaskStatus.RedoTask(task)
continue
}
node := val.(*LcNode)
task := lcMgr.lcRuleTaskStatus.GetTaskFromScanning(taskId) // task can not be nil
if task == nil {
log.LogErrorf("task is nil, release node(%v)", nodeAddr)
lcMgr.lcNodeStatus.ReleaseNode(nodeAddr)
continue
}
adminTask := node.createLcScanTask(lcMgr.cluster.masterAddr(), task)
lcMgr.cluster.addLcNodeTasks([]*proto.AdminTask{adminTask})
log.LogDebugf("add lifecycle scan task(%v) to lcnode(%v)", *task, nodeAddr)
}
}
now = time.Now()
lcMgr.lcRuleTaskStatus.EndTime = &now
end := time.Now()
lcMgr.lcRuleTaskStatus.EndTime = &end
log.LogInfof("lifecycleManager process finish, lcRuleTaskStatus results(%v)", lcMgr.lcRuleTaskStatus.Results)
}
@ -219,120 +192,94 @@ func (lcMgr *lifecycleManager) DelS3BucketLifecycle(VolName string) {
//-----------------------------------------------
type OpLcNode interface {
GetIdleNode(taskId string) (nodeAddr string)
RemoveNode(nodeAddr string) (taskId string)
ReleaseNode(nodeAddr string) (taskId string)
GetIdleNode() (nodeAddr string)
RemoveNode(nodeAddr string)
UpdateNode(nodeAddr string, count int)
}
// update status by heartbeat
type lcNodeStatus struct {
sync.RWMutex
IdleNodes map[string]string //ip:ip
WorkingNodes map[string]string //ip:taskId
WorkingCount map[string]int //ip:count, number of tasks being processed on this node
}
func NewLcNodeStatus() *lcNodeStatus {
func newLcNodeStatus() *lcNodeStatus {
return &lcNodeStatus{
IdleNodes: make(map[string]string),
WorkingNodes: make(map[string]string),
WorkingCount: make(map[string]int),
}
}
func (ns *lcNodeStatus) GetIdleNode(taskId string) (nodeAddr string) {
func (ns *lcNodeStatus) GetIdleNode() (nodeAddr string) {
ns.Lock()
defer ns.Unlock()
if len(ns.IdleNodes) == 0 {
if len(ns.WorkingCount) == 0 {
return
}
for n := range ns.IdleNodes {
nodeAddr = n
delete(ns.IdleNodes, nodeAddr)
ns.WorkingNodes[nodeAddr] = taskId
return
var min = math.MaxInt
for n, c := range ns.WorkingCount {
if c <= min {
nodeAddr = n
min = c
}
}
return
}
func (ns *lcNodeStatus) RemoveNode(nodeAddr string) (taskId string) {
func (ns *lcNodeStatus) RemoveNode(nodeAddr string) {
ns.Lock()
defer ns.Unlock()
taskId = ns.WorkingNodes[nodeAddr]
delete(ns.IdleNodes, nodeAddr)
delete(ns.WorkingNodes, nodeAddr)
delete(ns.WorkingCount, nodeAddr)
return
}
func (ns *lcNodeStatus) ReleaseNode(nodeAddr string) (taskId string) {
func (ns *lcNodeStatus) UpdateNode(nodeAddr string, count int) {
ns.Lock()
defer ns.Unlock()
taskId = ns.WorkingNodes[nodeAddr]
delete(ns.WorkingNodes, nodeAddr)
ns.IdleNodes[nodeAddr] = nodeAddr
ns.WorkingCount[nodeAddr] = count
return
}
//-----------------------------------------------
type OpLcTask interface {
GetOneTask() (taskId string)
RedoTask(taskId string)
DeleteScanningTask(taskId string)
}
type lcRuleTaskStatus struct {
sync.RWMutex
ToBeScanned map[string]*proto.RuleTask
Scanning map[string]*proto.RuleTask
Results map[string]*proto.LcNodeRuleTaskResponse
StartTime *time.Time
EndTime *time.Time
}
func NewLcRuleTaskStatus() *lcRuleTaskStatus {
func newLcRuleTaskStatus() *lcRuleTaskStatus {
return &lcRuleTaskStatus{
ToBeScanned: make(map[string]*proto.RuleTask),
Scanning: make(map[string]*proto.RuleTask),
Results: make(map[string]*proto.LcNodeRuleTaskResponse),
}
}
func (rs *lcRuleTaskStatus) GetOneTask() (taskId string) {
func (rs *lcRuleTaskStatus) GetOneTask() (task *proto.RuleTask) {
rs.Lock()
defer rs.Unlock()
if len(rs.ToBeScanned) == 0 {
return
}
for k, v := range rs.ToBeScanned {
taskId = k
rs.Scanning[k] = v
delete(rs.ToBeScanned, k)
return
for _, t := range rs.ToBeScanned {
task = t
break
}
delete(rs.ToBeScanned, task.Id)
return
}
func (rs *lcRuleTaskStatus) RedoTask(taskId string) {
func (rs *lcRuleTaskStatus) RedoTask(task *proto.RuleTask) {
rs.Lock()
defer rs.Unlock()
if taskId == "" {
if task == nil {
return
}
if task, ok := rs.Scanning[taskId]; ok {
rs.ToBeScanned[taskId] = task
delete(rs.Scanning, taskId)
}
}
func (rs *lcRuleTaskStatus) DeleteScanningTask(taskId string) {
rs.Lock()
defer rs.Unlock()
if taskId == "" {
return
}
delete(rs.Scanning, taskId)
rs.ToBeScanned[task.Id] = task
}
func (rs *lcRuleTaskStatus) AddResult(resp *proto.LcNodeRuleTaskResponse) {
@ -340,9 +287,3 @@ func (rs *lcRuleTaskStatus) AddResult(resp *proto.LcNodeRuleTaskResponse) {
defer rs.Unlock()
rs.Results[resp.ID] = resp
}
func (rs *lcRuleTaskStatus) GetTaskFromScanning(taskId string) *proto.RuleTask {
rs.Lock()
defer rs.Unlock()
return rs.Scanning[taskId]
}

View File

@ -87,60 +87,50 @@ func (c *Cluster) handleLcNodeHeartbeatResp(nodeAddr string, resp *proto.LcNodeH
lcNode.ReportTime = time.Now()
lcNode.Unlock()
//update lcNodeStatus
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v], LcScanningTasks[%v], SnapshotScanningTasks[%v]", nodeAddr, len(resp.LcScanningTasks), len(resp.SnapshotScanningTasks))
c.lcMgr.lcNodeStatus.UpdateNode(nodeAddr, len(resp.LcScanningTasks))
c.snapshotMgr.lcNodeStatus.UpdateNode(nodeAddr, len(resp.SnapshotScanningTasks))
//handle LcScanningTasks
if len(resp.LcScanningTasks) != 0 {
for _, taskRsp := range resp.LcScanningTasks {
c.lcMgr.lcRuleTaskStatus.Lock()
for _, taskRsp := range resp.LcScanningTasks {
c.lcMgr.lcRuleTaskStatus.Lock()
if c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID] != nil && c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID].Done {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] task[%v] already done", nodeAddr, taskRsp.ID)
} else {
c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID] = taskRsp
}
c.lcMgr.lcRuleTaskStatus.Unlock()
log.LogDebugf("action[handleLcNodeHeartbeatResp], lcNode[%v] taskRsp: %v", nodeAddr, taskRsp)
//avoid updating TaskResults incorrectly when received handleLcNodeLcScanResp first and then handleLcNodeHeartbeatResp
if c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID] != nil && c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID].Done {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] task[%v] already done", nodeAddr, taskRsp.ID)
} else {
t := time.Now()
taskRsp.UpdateTime = &t
c.lcMgr.lcRuleTaskStatus.Results[taskRsp.ID] = taskRsp
}
} else {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] is idle for LcScanningTasks", nodeAddr)
c.lcMgr.lcRuleTaskStatus.DeleteScanningTask(c.lcMgr.lcNodeStatus.ReleaseNode(nodeAddr))
c.lcMgr.lcRuleTaskStatus.Unlock()
log.LogDebugf("action[handleLcNodeHeartbeatResp], lcNode[%v] taskRsp: %v", nodeAddr, taskRsp)
}
if len(resp.LcScanningTasks) < resp.LcTaskCountLimit {
log.LogInfof("action[handleLcNodeHeartbeatResp], notify idle lcNode[%v], now LcScanningTasks[%v]", nodeAddr, len(resp.LcScanningTasks))
c.lcMgr.notifyIdleLcNode()
}
//handle SnapshotScanningTasks
if len(resp.SnapshotScanningTasks) != 0 {
for _, taskRsp := range resp.SnapshotScanningTasks {
c.snapshotMgr.lcSnapshotTaskStatus.Lock()
for _, taskRsp := range resp.SnapshotScanningTasks {
c.snapshotMgr.lcSnapshotTaskStatus.Lock()
if c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID] != nil && c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID].Done {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot task[%v] already done", nodeAddr, taskRsp.ID)
} else {
c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID] = taskRsp
//update processing status
if pInfo, ok := c.snapshotMgr.lcSnapshotTaskStatus.ProcessingVerInfos[taskRsp.ID]; ok {
pInfo.UpdateTime = time.Now().Unix()
log.LogDebugf("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot task[%v] update time", nodeAddr, taskRsp.ID)
} else {
c.snapshotMgr.lcSnapshotTaskStatus.ProcessingVerInfos[taskRsp.ID] = &proto.SnapshotVerDelTask{
Id: fmt.Sprintf("%s:%d", taskRsp.VolName, taskRsp.VerSeq),
VolName: taskRsp.VolName,
UpdateTime: time.Now().Unix(),
VolVersionInfo: &proto.VolVersionInfo{
Ver: taskRsp.VerSeq,
Status: proto.VersionDeleting,
},
}
log.LogWarnf("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot task[%v] not in processing add it", nodeAddr, taskRsp.ID)
}
}
c.snapshotMgr.lcSnapshotTaskStatus.Unlock()
log.LogDebugf("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot taskRsp: %v", nodeAddr, taskRsp)
//avoid updating TaskResults incorrectly when received handleLcNodeLcScanResp first and then handleLcNodeHeartbeatResp
if c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID] != nil && c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID].Done {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot task[%v] already done", nodeAddr, taskRsp.ID)
} else {
t := time.Now()
taskRsp.UpdateTime = &t
c.snapshotMgr.lcSnapshotTaskStatus.TaskResults[taskRsp.ID] = taskRsp
}
} else {
log.LogInfof("action[handleLcNodeHeartbeatResp], lcNode[%v] is idle for SnapshotScanningTasks", nodeAddr)
c.snapshotMgr.lcSnapshotTaskStatus.DeleteScanningTask(c.snapshotMgr.lcNodeStatus.ReleaseNode(nodeAddr))
c.snapshotMgr.lcSnapshotTaskStatus.Unlock()
log.LogDebugf("action[handleLcNodeHeartbeatResp], lcNode[%v] snapshot taskRsp: %v", nodeAddr, taskRsp)
}
if len(resp.SnapshotScanningTasks) < resp.LcTaskCountLimit {
log.LogInfof("action[handleLcNodeHeartbeatResp], notify idle lcNode[%v], now SnapshotScanningTasks[%v]", nodeAddr, len(resp.SnapshotScanningTasks))
c.snapshotMgr.notifyIdleLcNode()
}
@ -156,17 +146,16 @@ func (c *Cluster) handleLcNodeLcScanResp(nodeAddr string, resp *proto.LcNodeRule
switch resp.Status {
case proto.TaskFailed:
c.lcMgr.lcRuleTaskStatus.RedoTask(resp.ID)
log.LogWarnf("action[handleLcNodeLcScanResp] scanning failed, resp(%v), no redo", resp)
return
case proto.TaskSucceeds:
c.lcMgr.lcRuleTaskStatus.AddResult(resp)
c.lcMgr.lcRuleTaskStatus.DeleteScanningTask(resp.ID)
log.LogInfof("action[handleLcNodeLcScanResp] scanning completed, resp(%v)", resp)
return
default:
log.LogInfof("action[handleLcNodeLcScanResp] scanning received, resp(%v)", resp)
return
}
c.lcMgr.lcNodeStatus.ReleaseNode(nodeAddr)
log.LogInfof("action[handleLcNodeLcScanResp] scanning completed, resp(%v)", resp)
return
}
@ -178,7 +167,9 @@ func (c *Cluster) handleLcNodeSnapshotScanResp(nodeAddr string, resp *proto.Snap
switch resp.Status {
case proto.TaskFailed:
c.snapshotMgr.lcSnapshotTaskStatus.RedoTask(resp.ID)
c.snapshotMgr.lcSnapshotTaskStatus.RedoTask(resp.SnapshotVerDelTask)
log.LogWarnf("action[handleLcNodeSnapshotScanResp] scanning failed, resp(%v), redo", resp)
return
case proto.TaskSucceeds:
//1.mark done for VersionMgr
var vol *Vol
@ -192,13 +183,11 @@ func (c *Cluster) handleLcNodeSnapshotScanResp(nodeAddr string, resp *proto.Snap
//2. mark done for snapshotMgr
c.snapshotMgr.lcSnapshotTaskStatus.AddResult(resp)
c.snapshotMgr.lcSnapshotTaskStatus.DeleteScanningTask(resp.ID)
log.LogInfof("action[handleLcNodeSnapshotScanResp] scanning completed, resp(%v)", resp)
return
default:
log.LogInfof("action[handleLcNodeSnapshotScanResp] scanning received, resp(%v)", resp)
return
}
c.snapshotMgr.lcNodeStatus.ReleaseNode(nodeAddr)
log.LogInfof("action[handleLcNodeSnapshotScanResp] scanning completed, resp(%v)", resp)
return
}

View File

@ -34,8 +34,8 @@ type snapshotDelManager struct {
func newSnapshotManager() *snapshotDelManager {
log.LogInfof("action[newSnapshotManager] construct")
snapshotMgr := &snapshotDelManager{
lcSnapshotTaskStatus: NewLcSnapshotVerStatus(),
lcNodeStatus: NewLcNodeStatus(),
lcSnapshotTaskStatus: newLcSnapshotVerStatus(),
lcNodeStatus: newLcNodeStatus(),
idleNodeCh: make(chan struct{}),
exitCh: make(chan struct{}),
}
@ -51,33 +51,28 @@ func (m *snapshotDelManager) process() {
case <-m.idleNodeCh:
log.LogDebug("idleLcNodeCh notified")
taskId := m.lcSnapshotTaskStatus.GetOneTask()
if taskId == "" {
log.LogDebugf("no snapshot ver del task available")
task := m.lcSnapshotTaskStatus.GetOneTask()
if task == nil {
log.LogDebugf("lcSnapshotTaskStatus.GetOneTask, no task")
continue
}
nodeAddr := m.lcNodeStatus.GetIdleNode(taskId)
nodeAddr := m.lcNodeStatus.GetIdleNode()
if nodeAddr == "" {
log.LogWarn("no idle lcnode, redo task")
m.lcSnapshotTaskStatus.RedoTask(taskId)
m.lcSnapshotTaskStatus.RedoTask(task)
continue
}
val, ok := m.cluster.lcNodes.Load(nodeAddr)
if !ok {
log.LogErrorf("lcNodes.Load, nodeAddr(%v) is not available, redo task", nodeAddr)
m.lcSnapshotTaskStatus.RedoTask(m.lcNodeStatus.RemoveNode(nodeAddr))
m.lcNodeStatus.RemoveNode(nodeAddr)
m.lcSnapshotTaskStatus.RedoTask(task)
continue
}
node := val.(*LcNode)
task := m.lcSnapshotTaskStatus.GetTaskFromScanning(taskId)
if task == nil {
log.LogErrorf("task is nil, release node(%v)", nodeAddr)
m.lcNodeStatus.ReleaseNode(nodeAddr)
continue
}
adminTask := node.createSnapshotVerDelTask(m.cluster.masterAddr(), task)
m.cluster.addLcNodeTasks([]*proto.AdminTask{adminTask})
log.LogDebugf("add snapshot version del task(%v) to lcnode(%v)", *task, nodeAddr)
@ -103,20 +98,18 @@ func (m *snapshotDelManager) notifyIdleLcNode() {
type lcSnapshotVerStatus struct {
sync.RWMutex
VerInfos map[string]*proto.SnapshotVerDelTask
ProcessingVerInfos map[string]*proto.SnapshotVerDelTask
TaskResults map[string]*proto.SnapshotVerDelTaskResponse
VerInfos map[string]*proto.SnapshotVerDelTask
TaskResults map[string]*proto.SnapshotVerDelTaskResponse
}
func NewLcSnapshotVerStatus() *lcSnapshotVerStatus {
func newLcSnapshotVerStatus() *lcSnapshotVerStatus {
return &lcSnapshotVerStatus{
VerInfos: make(map[string]*proto.SnapshotVerDelTask, 0),
ProcessingVerInfos: make(map[string]*proto.SnapshotVerDelTask, 0),
TaskResults: make(map[string]*proto.SnapshotVerDelTaskResponse, 0),
VerInfos: make(map[string]*proto.SnapshotVerDelTask, 0),
TaskResults: make(map[string]*proto.SnapshotVerDelTaskResponse, 0),
}
}
func (vs *lcSnapshotVerStatus) GetOneTask() (taskId string) {
func (vs *lcSnapshotVerStatus) GetOneTask() (task *proto.SnapshotVerDelTask) {
var min int64 = math.MaxInt64
vs.Lock()
@ -128,52 +121,32 @@ func (vs *lcSnapshotVerStatus) GetOneTask() (taskId string) {
for _, i := range vs.VerInfos {
if i.VolVersionInfo.DelTime < min {
min = i.VolVersionInfo.DelTime
taskId = i.Id
task = i
}
}
info := vs.VerInfos[taskId]
delete(vs.VerInfos, taskId)
info.UpdateTime = time.Now().Unix()
vs.ProcessingVerInfos[taskId] = info
delete(vs.VerInfos, task.Id)
return
}
func (vs *lcSnapshotVerStatus) RedoTask(taskId string) {
func (vs *lcSnapshotVerStatus) RedoTask(task *proto.SnapshotVerDelTask) {
vs.Lock()
defer vs.Unlock()
if taskId == "" {
if task == nil {
return
}
if pInfo, ok := vs.ProcessingVerInfos[taskId]; ok {
vs.VerInfos[taskId] = pInfo
delete(vs.ProcessingVerInfos, taskId)
}
}
func (vs *lcSnapshotVerStatus) DeleteScanningTask(taskId string) {
vs.Lock()
defer vs.Unlock()
if taskId == "" {
return
}
delete(vs.ProcessingVerInfos, taskId)
vs.VerInfos[task.Id] = task
}
func (vs *lcSnapshotVerStatus) AddVerInfo(task *proto.SnapshotVerDelTask) {
vs.Lock()
defer vs.Unlock()
if pInfo, ok := vs.ProcessingVerInfos[task.Id]; ok {
if time.Since(time.Unix(pInfo.UpdateTime, 0)) < time.Second*time.Duration(5*defaultIntervalToCheck) {
log.LogDebugf("VerInfo: %v is already in processing", task)
return
} else {
log.LogWarnf("VerInfo: %v is in processing, but expired", task)
}
}
if _, ok := vs.TaskResults[task.Id]; ok {
log.LogDebugf("VerInfo: %v is in TaskResults, already in processing", task)
return
}
vs.VerInfos[task.Id] = task
log.LogDebugf("Add VerInfo task: %v", task)
}
@ -188,15 +161,15 @@ func (vs *lcSnapshotVerStatus) DeleteOldResult() {
vs.Lock()
defer vs.Unlock()
for k, v := range vs.TaskResults {
if v.Done == true && time.Now().After(v.EndTime.Add(time.Hour*1)) {
// delete result that already done
if v.Done == true && time.Now().After(v.EndTime.Add(time.Minute*10)) {
delete(vs.TaskResults, k)
log.LogDebugf("delete old result: %v", v)
log.LogDebugf("delete result already done: %v", v)
}
// delete result that not done but no updating
if v.Done != true && time.Now().After(v.UpdateTime.Add(time.Minute*10)) {
delete(vs.TaskResults, k)
log.LogWarnf("delete result that not done but no updating: %v", v)
}
}
}
func (vs *lcSnapshotVerStatus) GetTaskFromScanning(taskId string) *proto.SnapshotVerDelTask {
vs.Lock()
defer vs.Unlock()
return vs.ProcessingVerInfos[taskId]
}

View File

@ -689,6 +689,7 @@ type MetaNodeHeartbeatResponse struct {
type LcNodeHeartbeatResponse struct {
Status uint8
Result string
LcTaskCountLimit int
LcScanningTasks map[string]*LcNodeRuleTaskResponse
SnapshotScanningTasks map[string]*SnapshotVerDelTaskResponse
}

View File

@ -83,12 +83,14 @@ type RuleTask struct {
}
type LcNodeRuleTaskResponse struct {
ID string
StartTime *time.Time
EndTime *time.Time
Done bool
Status uint8
Result string
ID string
LcNode string
StartTime *time.Time
EndTime *time.Time
UpdateTime *time.Time
Done bool
Status uint8
Result string
LcNodeRuleTaskStatistics
}

View File

@ -13,17 +13,19 @@ type SnapshotVerDelTaskRequest struct {
type SnapshotVerDelTask struct {
Id string
VolName string
UpdateTime int64
VolVersionInfo *VolVersionInfo
}
type SnapshotVerDelTaskResponse struct {
ID string
StartTime *time.Time
EndTime *time.Time
Done bool
Status uint8
Result string
ID string
LcNode string
StartTime *time.Time
EndTime *time.Time
UpdateTime *time.Time
Done bool
Status uint8
Result string
SnapshotVerDelTask *SnapshotVerDelTask
SnapshotStatistics
}