Skip to content

Commit

Permalink
Support the App Locks with basic file locks. (#2591)
Browse files Browse the repository at this point in the history
* Make sure to support the App Locks with basic file locks.

* Add changelog entry.

* Handle error for ireadLocksIntoOpaque
  • Loading branch information
dragotin authored Feb 28, 2022
1 parent 7c47551 commit 3e80be7
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 9 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/applockslocked.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Set up App Locks with basic locks

To set up App Locks basic locks are used now

https://github.com/cs3org/reva/pull/2591
99 changes: 91 additions & 8 deletions pkg/storage/utils/decomposedfs/node/locks.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,42 @@ import (
"github.com/cs3org/reva/pkg/appctx"
ctxpkg "github.com/cs3org/reva/pkg/ctx"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/storage/utils/filelocks"
"github.com/cs3org/reva/pkg/utils"
"github.com/pkg/errors"
)

// SetLock sets a lock on the node
func (n *Node) SetLock(ctx context.Context, lock *provider.Lock) error {
// check existing lock

if l, _ := n.ReadLock(ctx); l != nil {
lockID, _ := ctxpkg.ContextGetLockID(ctx)
if l.LockId != lockID {
return errtypes.Locked(l.LockId)
}

err := os.Remove(n.LockFilePath())
if err != nil {
return err
}
}

fileLock, err := filelocks.AcquireWriteLock(n.LockFilePath())

if err != nil {
return err
}

defer func() {
rerr := filelocks.ReleaseLock(fileLock)

// if err is non nil we do not overwrite that
if err == nil {
err = rerr
}
}()

// O_EXCL to make open fail when the file already exists
f, err := os.OpenFile(n.LockFilePath(), os.O_EXCL|os.O_CREATE|os.O_WRONLY, 0600)
if err != nil {
Expand All @@ -57,11 +75,27 @@ func (n *Node) SetLock(ctx context.Context, lock *provider.Lock) error {
return errors.Wrap(err, "Decomposedfs: could not write lock file")
}

return nil
return err
}

// ReadLock reads the lock id for a node
func (n Node) ReadLock(ctx context.Context) (*provider.Lock, error) {

fileLock, err := filelocks.AcquireReadLock(n.LockFilePath())

if err != nil {
return nil, err
}

defer func() {
rerr := filelocks.ReleaseLock(fileLock)

// if err is non nil we do not overwrite that
if err == nil {
err = rerr
}
}()

f, err := os.Open(n.LockFilePath())
if err != nil {
if os.IsNotExist(err) {
Expand All @@ -76,11 +110,27 @@ func (n Node) ReadLock(ctx context.Context) (*provider.Lock, error) {
appctx.GetLogger(ctx).Error().Err(err).Msg("Decomposedfs: could not decode lock file, ignoring")
return nil, errors.Wrap(err, "Decomposedfs: could not read lock file")
}
return lock, nil
return lock, err
}

// RefreshLock refreshes the node's lock
func (n *Node) RefreshLock(ctx context.Context, lock *provider.Lock) error {

fileLock, err := filelocks.AcquireWriteLock(n.LockFilePath())

if err != nil {
return err
}

defer func() {
rerr := filelocks.ReleaseLock(fileLock)

// if err is non nil we do not overwrite that
if err == nil {
err = rerr
}
}()

f, err := os.OpenFile(n.LockFilePath(), os.O_RDWR, os.ModeExclusive)
switch {
case os.IsNotExist(err):
Expand Down Expand Up @@ -113,11 +163,27 @@ func (n *Node) RefreshLock(ctx context.Context, lock *provider.Lock) error {
return errors.Wrap(err, "Decomposedfs: could not write lock file")
}

return nil
return err
}

// Unlock unlocks the node
func (n *Node) Unlock(ctx context.Context, lock *provider.Lock) error {

fileLock, err := filelocks.AcquireWriteLock(n.LockFilePath())

if err != nil {
return err
}

defer func() {
rerr := filelocks.ReleaseLock(fileLock)

// if err is non nil we do not overwrite that
if err == nil {
err = rerr
}
}()

f, err := os.OpenFile(n.LockFilePath(), os.O_RDONLY, os.ModeExclusive)
switch {
case os.IsNotExist(err):
Expand All @@ -142,7 +208,10 @@ func (n *Node) Unlock(ctx context.Context, lock *provider.Lock) error {
return errtypes.PermissionDenied("mismatching holder")
}

return os.Remove(f.Name())
if err = os.Remove(f.Name()); err != nil {
return errors.Wrap(err, "Decomposedfs: could not remove lock file")
}
return err
}

// CheckLock compares the context lock with the node lock
Expand All @@ -165,11 +234,26 @@ func (n *Node) CheckLock(ctx context.Context) error {
return nil // ok
}

func readLocksIntoOpaque(ctx context.Context, lockPath string, ri *provider.ResourceInfo) {
func readLocksIntoOpaque(ctx context.Context, lockPath string, ri *provider.ResourceInfo) error {
fileLock, err := filelocks.AcquireReadLock(lockPath)

if err != nil {
return err
}

defer func() {
rerr := filelocks.ReleaseLock(fileLock)

// if err is non nil we do not overwrite that
if err == nil {
err = rerr
}
}()

f, err := os.Open(lockPath)
if err != nil {
appctx.GetLogger(ctx).Error().Err(err).Msg("Decomposedfs: could not open lock file")
return
return err
}
defer f.Close()

Expand All @@ -192,10 +276,9 @@ func readLocksIntoOpaque(ctx context.Context, lockPath string, ri *provider.Reso
Decoder: "json",
Value: b,
}
// TODO support advisory locks?
return err
}

// TODO only exclusive locks for WOPI? or advisory locks?
func (n *Node) hasLocks(ctx context.Context) bool {
_, err := os.Stat(n.LockFilePath()) // FIXME better error checking
return err == nil
Expand Down
5 changes: 4 additions & 1 deletion pkg/storage/utils/decomposedfs/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,10 @@ func (n *Node) AsResourceInfo(ctx context.Context, rp *provider.ResourcePermissi
// read locks
if _, ok := mdKeysMap[LockdiscoveryKey]; returnAllKeys || ok {
if n.hasLocks(ctx) {
readLocksIntoOpaque(ctx, n.LockFilePath(), ri)
err = readLocksIntoOpaque(ctx, n.LockFilePath(), ri)
if err != nil {
sublog.Debug().Err(errtypes.InternalError("lockfail"))
}
}
}

Expand Down

0 comments on commit 3e80be7

Please sign in to comment.