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  }