github.com/pingcap/tiflow@v0.0.0-20240520035814-5bf52d54e205/dm/pkg/v1workermeta/meta.go (about) 1 // Copyright 2020 PingCAP, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // See the License for the specific language governing permissions and 12 // limitations under the License. 13 14 package v1workermeta 15 16 import ( 17 "github.com/golang/protobuf/proto" 18 "github.com/pingcap/tiflow/dm/pb" 19 "github.com/pingcap/tiflow/dm/pkg/terror" 20 "github.com/syndtr/goleveldb/leveldb" 21 "github.com/syndtr/goleveldb/leveldb/util" 22 ) 23 24 // meta stores metadata of tasks. 25 type meta struct { 26 tasks map[string]*pb.V1SubTaskMeta 27 } 28 29 // newMeta returns a meta object. 30 func newMeta(db *leveldb.DB) (*meta, error) { 31 tasks, err := loadTaskMetas(db) 32 if err != nil { 33 return nil, err 34 } 35 36 return &meta{ 37 tasks: tasks, 38 }, nil 39 } 40 41 // TasksMeta returns meta of all tasks. 42 func (meta *meta) TasksMeta() map[string]*pb.V1SubTaskMeta { 43 tasks := make(map[string]*pb.V1SubTaskMeta, len(meta.tasks)) 44 for name, task := range meta.tasks { 45 tasks[name] = proto.Clone(task).(*pb.V1SubTaskMeta) 46 } 47 return tasks 48 } 49 50 // taskMetaPrefix is prefix of task meta key. 51 var taskMetaPrefix = []byte("!DM!TaskMeta") 52 53 // encodeTaskMetaKey encodes take name into a task meta key. 54 func encodeTaskMetaKey(name string) []byte { 55 key := append([]byte{}, taskMetaPrefix...) 56 return append(key, name...) 57 } 58 59 // loadTaskMetas loads all task metas from kv db. 60 func loadTaskMetas(db *leveldb.DB) (map[string]*pb.V1SubTaskMeta, error) { 61 if db == nil { 62 return nil, terror.ErrWorkerLogInvalidHandler.Generate() 63 } 64 65 var ( 66 tasks = make(map[string]*pb.V1SubTaskMeta) 67 err error 68 ) 69 70 iter := db.NewIterator(util.BytesPrefix(taskMetaPrefix), nil) 71 for iter.Next() { 72 taskBytes := iter.Value() 73 task := &pb.V1SubTaskMeta{} 74 err = task.Unmarshal(taskBytes) 75 if err != nil { 76 iter.Release() 77 return nil, terror.ErrWorkerLogUnmarshalTaskMeta.Delegate(err, taskBytes) 78 } 79 80 tasks[task.Name] = task 81 } 82 iter.Release() 83 84 err = iter.Error() 85 if err != nil { 86 return nil, terror.ErrWorkerLogFetchTaskFromMeta.Delegate(err, taskMetaPrefix) 87 } 88 89 return tasks, nil 90 } 91 92 // setTaskMeta saves task meta into kv db. 93 // it's used for testing. 94 func setTaskMeta(db *leveldb.DB, task *pb.V1SubTaskMeta) error { 95 if db == nil { 96 return terror.ErrWorkerLogInvalidHandler.Generate() 97 } 98 99 err := verifyTaskMeta(task) 100 if err != nil { 101 return terror.Annotatef(err, "verify task meta %+v", task) 102 } 103 104 taskBytes, err := task.Marshal() 105 if err != nil { 106 return terror.ErrWorkerLogMarshalTask.Delegate(err, task) 107 } 108 109 err = db.Put(encodeTaskMetaKey(task.Name), taskBytes, nil) 110 if err != nil { 111 return terror.ErrWorkerLogSaveTaskMeta.Delegate(err, task.Name) 112 } 113 114 return nil 115 } 116 117 // deleteTaskMeta deletes task meta from kv DB. 118 // it's used for testing. 119 func deleteTaskMeta(db *leveldb.DB, name string) error { 120 if db == nil { 121 return terror.ErrWorkerLogInvalidHandler.Generate() 122 } 123 124 err := db.Delete(encodeTaskMetaKey(name), nil) 125 if err != nil { 126 return terror.ErrWorkerLogDeleteTaskMeta.Delegate(err, name) 127 } 128 129 return nil 130 } 131 132 // verifyTaskMeta verifies legality of take meta. 133 // it's used for testing. 134 func verifyTaskMeta(task *pb.V1SubTaskMeta) error { 135 if task == nil { 136 return terror.ErrWorkerLogVerifyTaskMeta.New("empty task not valid") 137 } 138 139 if len(task.Name) == 0 { 140 return terror.ErrWorkerLogVerifyTaskMeta.New("empty task name not valid") 141 } 142 143 if len(task.Task) == 0 { 144 return terror.ErrWorkerLogVerifyTaskMeta.New("empty task config not valid") 145 } 146 147 if task.Stage == pb.Stage_InvalidStage { 148 return terror.ErrWorkerLogVerifyTaskMeta.Generatef("stage %s not valid", task.Stage) 149 } 150 151 if task.Op == pb.TaskOp_InvalidOp { 152 return terror.ErrWorkerLogVerifyTaskMeta.Generatef("task operation %s not valid", task.Op) 153 } 154 155 return nil 156 }