Skip to content

Commit

Permalink
decomposedfs: add locking support (#2460)
Browse files Browse the repository at this point in the history
* decomposedfs: add locking support

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* add lock implementation, refactor error handling

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* introduce lock ctx

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* add locked error and status code mapping

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* read lockid from opaque into ctx for delete

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* decomposedfs: make delete respect lock

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: simplify error code mapping

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* adjust to cs3 lock api update

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* utils: add and read plain opaque entries

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* fix delete lock

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* invalidate stat cache when setting lock

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* fix a few linter items

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* linter happyness

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: implment unlock

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* lock caching and unlocking

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* read locks on folders

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* check lock on writes

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* always assume locktype write

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocis only supports exclusive locks

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* add precodition failed errtype

* handle preconditionfailed in status conversion

* omit empty xml tags in lockdiscovery

* handle locked status on LOCK

* document oc10 lock behaviour as comment

* ocdav: handle errors for LOCK and UNLOCK

* storage: change fs.Unlock signature

* decomposedfs: refactor checkLock

* add LookupReferenceForPath comment

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* gateway: ignore unimplemented add/denyGrant response

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* use http.StatusMethodNotAllowed for mkcol error case

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* make hound happy

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: be more tolerant with the Lock-Token header

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: allow setting infinity timeout

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: use custem owner innerxml without href

* update expected failures

* ocdav: return conflict on missing intermediate target dir

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* decomposedfs: use checkLock() in the rest of cases

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* Do not choke when checking the lock of non-existent nodes

* Linter fixes

* Refactor: Move lock handling into the node domain

* Also delete the lock file when deleting a node

* Extract node lock-handling code into separate file, start writing tests

* Add missing license header

* Fix relocking already-locked nodes. Increase test coverage

* Hounds be happy

* Add unit tests for ReadLock and RefreshLock

* Also cover readLocksIntoOpaque in the tests

* Fix linter issue

* Do not log full nodes, it's very expensive and not very helpful

* Start adding grpc integration tests for locking

* Fix setting the lock for file uploads

* Allow for locking space-based resources

* Make sure to log the error before it's getting overwritten

* reuse xml.EscapeText directly

Co-authored-by: David Christofas <dchristofas@posteo.de>

* decomposedfs: use defer to close file when unlocking resource

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: explain why some http states are commented

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* ocdav: use http header status constants

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* clarify add/deny grant log

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

* update expected failures

Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>

Co-authored-by: André Duffeck <andre.duffeck@firondu.de>
Co-authored-by: David Christofas <dchristofas@posteo.de>
  • Loading branch information
3 people committed Feb 14, 2022
1 parent 4c185f9 commit b522aab
Show file tree
Hide file tree
Showing 52 changed files with 2,659 additions and 701 deletions.
5 changes: 5 additions & 0 deletions changelog/unreleased/decomposedfs-locking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: add locking support to decomposedfs

The decomposedfs now implements application level locking

https://github.com/cs3org/reva/pull/2460
3 changes: 3 additions & 0 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ func (s *svc) SetLock(ctx context.Context, req *provider.SetLockRequest) (*provi
return nil, errors.Wrap(err, "gateway: error calling SetLock")
}

s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId)
return res, nil
}

Expand Down Expand Up @@ -783,6 +784,7 @@ func (s *svc) RefreshLock(ctx context.Context, req *provider.RefreshLockRequest)
return nil, errors.Wrap(err, "gateway: error calling RefreshLock")
}

s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId)
return res, nil
}

Expand All @@ -803,6 +805,7 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide
return nil, errors.Wrap(err, "gateway: error calling Unlock")
}

s.cache.RemoveStat(ctxpkg.ContextMustGetUser(ctx), req.Ref.ResourceId)
return res, nil
}

Expand Down
39 changes: 15 additions & 24 deletions internal/grpc/services/gateway/usershareprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,27 @@ func (s *svc) CreateShare(ctx context.Context, req *collaboration.CreateShareReq
// TODO(labkode): if both commits are enabled they could be done concurrently.
if s.c.CommitShareToStorageGrant {
// If the share is a denial we call denyGrant instead.
var status *rpc.Status
if grants.PermissionsEqual(req.Grant.Permissions.Permissions, &provider.ResourcePermissions{}) {
denyGrantStatus, err := s.denyGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee)
status, err = s.denyGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee)
if err != nil {
return nil, errors.Wrap(err, "gateway: error denying grant in storage")
}
if denyGrantStatus.Code != rpc.Code_CODE_OK {
return &collaboration.CreateShareResponse{
Status: denyGrantStatus,
}, err
} else {
status, err = s.addGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, req.Grant.Permissions.Permissions)
if err != nil {
return nil, errors.Wrap(err, "gateway: error adding grant to storage")
}
return res, nil
}

addGrantStatus, err := s.addGrant(ctx, req.ResourceInfo.Id, req.Grant.Grantee, req.Grant.Permissions.Permissions)
if err != nil {
return nil, errors.Wrap(err, "gateway: error adding grant to storage")
}
if addGrantStatus.Code != rpc.Code_CODE_OK {
switch status.Code {
case rpc.Code_CODE_OK:
// ok
case rpc.Code_CODE_UNIMPLEMENTED:
appctx.GetLogger(ctx).Debug().Interface("status", status).Interface("req", req).Msg("storing grants not supported, ignoring")
default:
return &collaboration.CreateShareResponse{
Status: addGrantStatus,
Status: status,
}, err
}
}
Expand Down Expand Up @@ -493,12 +494,7 @@ func (s *svc) denyGrant(ctx context.Context, id *provider.ResourceId, g *provide
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling DenyGrant")
}
if grantRes.Status.Code != rpc.Code_CODE_OK {
return status.NewInternal(ctx,
"error committing share to storage grant"), nil
}

return status.NewOK(ctx), nil
return grantRes.Status, nil
}

func (s *svc) addGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee, p *provider.ResourcePermissions) (*rpc.Status, error) {
Expand Down Expand Up @@ -530,12 +526,7 @@ func (s *svc) addGrant(ctx context.Context, id *provider.ResourceId, g *provider
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling AddGrant")
}
if grantRes.Status.Code != rpc.Code_CODE_OK {
return status.NewInternal(ctx,
"error committing share to storage grant"), nil
}

return status.NewOK(ctx), nil
return grantRes.Status, nil
}

func (s *svc) updateGrant(ctx context.Context, id *provider.ResourceId, g *provider.Grantee, p *provider.ResourcePermissions) (*rpc.Status, error) {
Expand Down
Loading

0 comments on commit b522aab

Please sign in to comment.