dir package - to enforce dir RW lock by types (#332)

* save

* save
This commit is contained in:
Alex Sharov 2022-02-18 09:24:30 +07:00 committed by GitHub
parent d309d52fe2
commit d94c4ada78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 7 deletions

View File

@ -44,10 +44,3 @@ func RootContext() (context.Context, context.CancelFunc) {
}()
return ctx, cancel
}
func MustExist(path string) {
const perm = 0764 // user rwx, group rw, other r
if err := os.MkdirAll(path, perm); err != nil {
panic(err)
}
}

65
common/dir/rw_dir.go Normal file
View File

@ -0,0 +1,65 @@
package dir
import (
"errors"
"fmt"
"os"
"path/filepath"
"syscall"
"github.com/gofrs/flock"
"github.com/ledgerwatch/log/v3"
)
// Rw - type to represent Read-Write access to directory
// if some code accept this typ - it can be sure: dir exists, no other process now write there
// We have no specific Ro type, just use `string` for Ro directory path
type Rw struct {
dirLock *flock.Flock // prevents concurrent use of instance directory
Path string
}
func convertFileLockError(err error, dir string) error {
if errno, ok := err.(syscall.Errno); ok && dirInUseErrnos[uint(errno)] {
return fmt.Errorf("%w: %s\n", ErrDirUsed, dir)
}
return err
}
var dirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
var (
ErrDirUsed = errors.New("datadir already used by another process")
)
func OpenRw(dir string) (*Rw, error) {
MustExist(dir)
// Lock the instance directory to prevent concurrent use by another instance as well as
// accidental use of the instance directory as a database.
l := flock.New(filepath.Join(dir, "LOCK"))
locked, err := l.TryLock()
if err != nil {
return nil, convertFileLockError(err, dir)
}
if !locked {
return nil, fmt.Errorf("%w: %s\n", ErrDirUsed, dir)
}
return &Rw{dirLock: l, Path: dir}, nil
}
func (t *Rw) Close() {
// Release instance directory lock.
if t.dirLock != nil {
if err := t.dirLock.Unlock(); err != nil {
log.Error("Can't release snapshot dir lock", "err", err)
}
t.dirLock = nil
}
}
func MustExist(path string) {
const perm = 0764 // user rwx, group rw, other r
if err := os.MkdirAll(path, perm); err != nil {
panic(err)
}
}

1
go.mod
View File

@ -8,6 +8,7 @@ require (
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2
github.com/flanglet/kanzi-go v1.9.0
github.com/go-stack/stack v1.8.1
github.com/gofrs/flock v0.8.1
github.com/google/btree v1.0.1
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d

2
go.sum
View File

@ -33,6 +33,8 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=