mirror of
				https://github.com/TeaOSLab/EdgeNode.git
				synced 2025-11-04 16:00:25 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			83 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2023 Liuxiangchao iwind.liu@gmail.com. All rights reserved. Official site: https://goedge.cn .
 | 
						|
 | 
						|
package fsutils
 | 
						|
 | 
						|
import (
 | 
						|
	"os"
 | 
						|
	"syscall"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
type Locker struct {
 | 
						|
	path string
 | 
						|
	fp   *os.File
 | 
						|
}
 | 
						|
 | 
						|
func NewLocker(path string) *Locker {
 | 
						|
	return &Locker{
 | 
						|
		path: path + ".lock",
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (this *Locker) TryLock() (ok bool, err error) {
 | 
						|
	if this.fp == nil {
 | 
						|
		fp, err := os.OpenFile(this.path, os.O_CREATE|os.O_WRONLY, 0666)
 | 
						|
		if err != nil {
 | 
						|
			return false, err
 | 
						|
		}
 | 
						|
		this.fp = fp
 | 
						|
	}
 | 
						|
	return this.tryLock()
 | 
						|
}
 | 
						|
 | 
						|
func (this *Locker) Lock() error {
 | 
						|
	if this.fp == nil {
 | 
						|
		fp, err := os.OpenFile(this.path, os.O_CREATE|os.O_WRONLY, 0666)
 | 
						|
		if err != nil {
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		this.fp = fp
 | 
						|
	}
 | 
						|
 | 
						|
	for {
 | 
						|
		b, err := this.tryLock()
 | 
						|
		if err != nil {
 | 
						|
			_ = this.fp.Close()
 | 
						|
			return err
 | 
						|
		}
 | 
						|
		if b {
 | 
						|
			return nil
 | 
						|
		}
 | 
						|
		time.Sleep(100 * time.Millisecond)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (this *Locker) Release() error {
 | 
						|
	err := this.fp.Close()
 | 
						|
	if err != nil {
 | 
						|
		return err
 | 
						|
	}
 | 
						|
	this.fp = nil
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (this *Locker) tryLock() (ok bool, err error) {
 | 
						|
	err = syscall.Flock(int(this.fp.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
 | 
						|
	if err == nil {
 | 
						|
		return true, nil
 | 
						|
	}
 | 
						|
 | 
						|
	errno, isErrNo := err.(syscall.Errno)
 | 
						|
	if !isErrNo {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	if !errno.Temporary() {
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	err = nil // 不提示错误
 | 
						|
 | 
						|
	return
 | 
						|
}
 |