github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/utils/lockfile/lockfile.go (about) 1 package lockfile 2 3 import ( 4 "errors" 5 "fmt" 6 "os" 7 "path" 8 "sync/atomic" 9 10 "github.com/Asutorufa/yuhaiin/pkg/log" 11 ) 12 13 type Lock struct { 14 lockfile string 15 payloadfile string 16 lockFile *os.File 17 18 locked atomic.Bool 19 } 20 21 func NewLock(lockfile, payload string) (*Lock, error) { 22 l := &Lock{lockfile: lockfile, payloadfile: lockfile + "_PAYLOAD"} 23 24 return l, l.Lock(payload) 25 } 26 27 func (l *Lock) Lock(payload string) error { 28 if l.locked.Load() { 29 return nil 30 } 31 32 _, err := os.Stat(path.Dir(l.lockfile)) 33 if errors.Is(err, os.ErrNotExist) { 34 err = os.MkdirAll(path.Dir(l.lockfile), os.ModePerm) 35 if err != nil { 36 return fmt.Errorf("make dir failed: %w", err) 37 } 38 } 39 40 l.lockFile, err = os.OpenFile(l.lockfile, os.O_CREATE|os.O_WRONLY, os.ModePerm) 41 if err != nil { 42 return fmt.Errorf("open lock file failed: %w", err) 43 } 44 45 err = LockFile(l.lockFile) 46 if err != nil { 47 return fmt.Errorf("lock file failed: %w", err) 48 } 49 50 l.locked.Store(true) 51 52 err = os.WriteFile(l.payloadfile, []byte(payload), os.ModePerm) 53 if err != nil { 54 log.Error("write host to file failed", "err", err) 55 } 56 return nil 57 } 58 59 func (l *Lock) Payload() (string, error) { 60 s, err := os.ReadFile(l.payloadfile) 61 if err != nil { 62 if os.IsNotExist(err) { 63 return "", nil 64 } 65 return "", fmt.Errorf("read lock file failed: %w", err) 66 } 67 return string(s), nil 68 } 69 70 func (l *Lock) UnLock() (erra error) { 71 err := os.Remove(l.payloadfile) 72 if err != nil { 73 erra = fmt.Errorf("%v\nremove host file failed: %w", erra, err) 74 } 75 err = l.lockFile.Close() 76 if err != nil { 77 erra = fmt.Errorf("%v\nunlock file failed: %w", erra, err) 78 } 79 80 l.locked.Store(false) 81 82 err = os.Remove(l.lockfile) 83 if err != nil { 84 erra = fmt.Errorf("%v\nremove lock file failed: %w", erra, err) 85 } 86 return 87 }