vitess.io/vitess@v0.16.2/go/test/endtoend/filelock/filelock.go (about) 1 // Copyright 2018 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package filelock provides a platform-independent API for advisory file 6 // locking. Calls to functions in this package on platforms that do not support 7 // advisory locks will return errors for which IsNotSupported returns true. 8 package filelock 9 10 import ( 11 "errors" 12 "io/fs" 13 "os" 14 ) 15 16 // A File provides the minimal set of methods required to lock an open file. 17 // File implementations must be usable as map keys. 18 // The usual implementation is *os.File. 19 type File interface { 20 // Name returns the name of the file. 21 Name() string 22 23 // Fd returns a valid file descriptor. 24 // (If the File is an *os.File, it must not be closed.) 25 Fd() uintptr 26 27 // Stat returns the FileInfo structure describing file. 28 Stat() (fs.FileInfo, error) 29 } 30 31 // Lock places an advisory write lock on the file, blocking until it can be 32 // locked. 33 // 34 // If Lock returns nil, no other process will be able to place a read or write 35 // lock on the file until this process exits, closes f, or calls Unlock on it. 36 // 37 // If f's descriptor is already read- or write-locked, the behavior of Lock is 38 // unspecified. 39 // 40 // Closing the file may or may not release the lock promptly. Callers should 41 // ensure that Unlock is always called when Lock succeeds. 42 func Lock(f File) error { 43 return lock(f, writeLock) 44 } 45 46 // RLock places an advisory read lock on the file, blocking until it can be locked. 47 // 48 // If RLock returns nil, no other process will be able to place a write lock on 49 // the file until this process exits, closes f, or calls Unlock on it. 50 // 51 // If f is already read- or write-locked, the behavior of RLock is unspecified. 52 // 53 // Closing the file may or may not release the lock promptly. Callers should 54 // ensure that Unlock is always called if RLock succeeds. 55 func RLock(f File) error { 56 return lock(f, readLock) 57 } 58 59 // Unlock removes an advisory lock placed on f by this process. 60 // 61 // The caller must not attempt to unlock a file that is not locked. 62 func Unlock(f File) error { 63 return unlock(f) 64 } 65 66 // String returns the name of the function corresponding to lt 67 // (Lock, RLock, or Unlock). 68 func (lt lockType) String() string { 69 switch lt { 70 case readLock: 71 return "RLock" 72 case writeLock: 73 return "Lock" 74 default: 75 return "Unlock" 76 } 77 } 78 79 // IsNotSupported returns a boolean indicating whether the error is known to 80 // report that a function is not supported (possibly for a specific input). 81 // It is satisfied by ErrNotSupported as well as some syscall errors. 82 func IsNotSupported(err error) bool { 83 return isNotSupported(underlyingError(err)) 84 } 85 86 var ErrNotSupported = errors.New("operation not supported") 87 88 // underlyingError returns the underlying error for known os error types. 89 func underlyingError(err error) error { 90 switch err := err.(type) { 91 case *fs.PathError: 92 return err.Err 93 case *os.LinkError: 94 return err.Err 95 case *os.SyscallError: 96 return err.Err 97 } 98 return err 99 }