mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-07-29 00:38:46 -04:00
5
changelog/unreleased/bump-reva.md
Normal file
5
changelog/unreleased/bump-reva.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Bugfix: Bump Reva
|
||||
|
||||
bumps reva version
|
||||
|
||||
https://github.com/owncloud/ocis/pull/10539
|
||||
2
go.mod
2
go.mod
@@ -16,7 +16,7 @@ require (
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.11.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1
|
||||
github.com/cs3org/reva/v2 v2.26.4
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb
|
||||
github.com/davidbyttow/govips/v2 v2.15.0
|
||||
github.com/dhowden/tag v0.0.0-20240417053706-3d75831295e8
|
||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||
|
||||
4
go.sum
4
go.sum
@@ -255,8 +255,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
|
||||
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1 h1:RU6LT6mkD16xZs011+8foU7T3LrPvTTSWeTQ9OgfhkA=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20241105092511-3ad35d174fc1/go.mod h1:DedpcqXl193qF/08Y04IO0PpxyyMu8+GrkD6kWK2MEQ=
|
||||
github.com/cs3org/reva/v2 v2.26.4 h1:wUmNSkXglIHrn+yxwJtHDvlSzxadFPANENGnwmG+5wI=
|
||||
github.com/cs3org/reva/v2 v2.26.4/go.mod h1:KP0Zomt3dNIr/kU2M1mXzTIVFOtxBVS4qmBDMRCfrOQ=
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb h1:owRv9x5GlKKdqCCM70kZKCsLAcDkFPkyOb129Jmklt0=
|
||||
github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb/go.mod h1:KP0Zomt3dNIr/kU2M1mXzTIVFOtxBVS4qmBDMRCfrOQ=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
|
||||
22
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/assimilation.go
generated
vendored
22
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/assimilation.go
generated
vendored
@@ -59,6 +59,7 @@ const (
|
||||
ActionUpdate
|
||||
ActionMove
|
||||
ActionDelete
|
||||
ActionMoveFrom
|
||||
)
|
||||
|
||||
type queueItem struct {
|
||||
@@ -160,14 +161,14 @@ func (t *Tree) workScanQueue() {
|
||||
}
|
||||
|
||||
// Scan scans the given path and updates the id chache
|
||||
func (t *Tree) Scan(path string, action EventAction, isDir bool, recurse bool) error {
|
||||
func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
|
||||
// cases:
|
||||
switch action {
|
||||
case ActionCreate:
|
||||
if !isDir {
|
||||
// 1. New file (could be emitted as part of a new directory)
|
||||
// -> assimilate file
|
||||
// -> scan parent directory recursively
|
||||
// -> scan parent directory recursively to update tree size and catch nodes that weren't covered by an event
|
||||
if !t.scanDebouncer.InProgress(filepath.Dir(path)) {
|
||||
t.scanDebouncer.Debounce(scanItem{
|
||||
Path: path,
|
||||
@@ -216,8 +217,24 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool, recurse bool) e
|
||||
Recurse: isDir,
|
||||
})
|
||||
|
||||
case ActionMoveFrom:
|
||||
// 6. file/directory moved out of the watched directory
|
||||
// -> update directory
|
||||
if err := t.setDirty(filepath.Dir(path), true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() { _ = t.WarmupIDCache(filepath.Dir(path), false, true) }()
|
||||
|
||||
case ActionDelete:
|
||||
_ = t.HandleFileDelete(path)
|
||||
// 7. Deleted file or directory
|
||||
// -> update parent and all children
|
||||
t.scanDebouncer.Debounce(scanItem{
|
||||
Path: filepath.Dir(path),
|
||||
ForceRescan: true,
|
||||
Recurse: true,
|
||||
})
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -593,6 +610,7 @@ func (t *Tree) WarmupIDCache(root string, assimilate, onlyDirty bool) error {
|
||||
if !dirty {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
sizes[path] += 0 // Make sure to set the size to 0 for empty directories
|
||||
}
|
||||
|
||||
attribs, err := t.lookup.MetadataBackend().All(context.Background(), path)
|
||||
|
||||
24
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/gpfsfilauditloggingwatcher.go
generated
vendored
24
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/gpfsfilauditloggingwatcher.go
generated
vendored
@@ -1,3 +1,21 @@
|
||||
// Copyright 2018-2024 CERN
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// In applying this license, CERN does not waive the privileges and immunities
|
||||
// granted to it by virtue of its status as an Intergovernmental Organization
|
||||
// or submit itself to any jurisdiction.
|
||||
|
||||
package tree
|
||||
|
||||
import (
|
||||
@@ -64,15 +82,15 @@ start:
|
||||
}
|
||||
switch ev.Event {
|
||||
case "CREATE":
|
||||
go func() { _ = w.tree.Scan(ev.Path, ActionCreate, false, false) }()
|
||||
go func() { _ = w.tree.Scan(ev.Path, ActionCreate, false) }()
|
||||
case "CLOSE":
|
||||
bytesWritten, err := strconv.Atoi(ev.BytesWritten)
|
||||
if err == nil && bytesWritten > 0 {
|
||||
go func() { _ = w.tree.Scan(ev.Path, ActionUpdate, false, true) }()
|
||||
go func() { _ = w.tree.Scan(ev.Path, ActionUpdate, false) }()
|
||||
}
|
||||
case "RENAME":
|
||||
go func() {
|
||||
_ = w.tree.Scan(ev.Path, ActionMove, false, true)
|
||||
_ = w.tree.Scan(ev.Path, ActionMove, false)
|
||||
_ = w.tree.WarmupIDCache(ev.Path, false, false)
|
||||
}()
|
||||
}
|
||||
|
||||
52
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/gpfswatchfolderwatcher.go
generated
vendored
52
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/gpfswatchfolderwatcher.go
generated
vendored
@@ -1,3 +1,21 @@
|
||||
// Copyright 2018-2024 CERN
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// In applying this license, CERN does not waive the privileges and immunities
|
||||
// granted to it by virtue of its status as an Intergovernmental Organization
|
||||
// or submit itself to any jurisdiction.
|
||||
|
||||
package tree
|
||||
|
||||
import (
|
||||
@@ -29,13 +47,13 @@ func (w *GpfsWatchFolderWatcher) Watch(topic string) {
|
||||
Topic: topic,
|
||||
})
|
||||
|
||||
lwev := &lwe{}
|
||||
for {
|
||||
m, err := r.ReadMessage(context.Background())
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
lwev := &lwe{}
|
||||
err = json.Unmarshal(m.Value, lwev)
|
||||
if err != nil {
|
||||
continue
|
||||
@@ -45,22 +63,28 @@ func (w *GpfsWatchFolderWatcher) Watch(topic string) {
|
||||
continue
|
||||
}
|
||||
|
||||
isDir := strings.Contains(lwev.Event, "IN_ISDIR")
|
||||
go func() {
|
||||
isDir := strings.Contains(lwev.Event, "IN_ISDIR")
|
||||
|
||||
switch {
|
||||
case strings.Contains(lwev.Event, "IN_CREATE"):
|
||||
go func() { _ = w.tree.Scan(lwev.Path, ActionCreate, isDir, false) }()
|
||||
switch {
|
||||
case strings.Contains(lwev.Event, "IN_DELETE"):
|
||||
_ = w.tree.Scan(lwev.Path, ActionDelete, isDir)
|
||||
|
||||
case strings.Contains(lwev.Event, "IN_CLOSE_WRITE"):
|
||||
bytesWritten, err := strconv.Atoi(lwev.BytesWritten)
|
||||
if err == nil && bytesWritten > 0 {
|
||||
go func() { _ = w.tree.Scan(lwev.Path, ActionUpdate, isDir, true) }()
|
||||
case strings.Contains(lwev.Event, "IN_MOVE_FROM"):
|
||||
_ = w.tree.Scan(lwev.Path, ActionMoveFrom, isDir)
|
||||
|
||||
case strings.Contains(lwev.Event, "IN_CREATE"):
|
||||
_ = w.tree.Scan(lwev.Path, ActionCreate, isDir)
|
||||
|
||||
case strings.Contains(lwev.Event, "IN_CLOSE_WRITE"):
|
||||
bytesWritten, err := strconv.Atoi(lwev.BytesWritten)
|
||||
if err == nil && bytesWritten > 0 {
|
||||
_ = w.tree.Scan(lwev.Path, ActionUpdate, isDir)
|
||||
}
|
||||
case strings.Contains(lwev.Event, "IN_MOVED_TO"):
|
||||
_ = w.tree.Scan(lwev.Path, ActionMove, isDir)
|
||||
}
|
||||
case strings.Contains(lwev.Event, "IN_MOVED_TO"):
|
||||
go func() {
|
||||
_ = w.tree.Scan(lwev.Path, ActionMove, isDir, true)
|
||||
}()
|
||||
}
|
||||
}()
|
||||
}
|
||||
if err := r.Close(); err != nil {
|
||||
log.Fatal("failed to close reader:", err)
|
||||
|
||||
43
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/inotifywatcher.go
generated
vendored
43
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/inotifywatcher.go
generated
vendored
@@ -1,3 +1,21 @@
|
||||
// Copyright 2018-2024 CERN
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// In applying this license, CERN does not waive the privileges and immunities
|
||||
// granted to it by virtue of its status as an Intergovernmental Organization
|
||||
// or submit itself to any jurisdiction.
|
||||
|
||||
package tree
|
||||
|
||||
import (
|
||||
@@ -30,6 +48,7 @@ func (iw *InotifyWatcher) Watch(path string) {
|
||||
Events: []inotifywaitgo.EVENT{
|
||||
inotifywaitgo.CREATE,
|
||||
inotifywaitgo.MOVED_TO,
|
||||
inotifywaitgo.MOVED_FROM,
|
||||
inotifywaitgo.CLOSE_WRITE,
|
||||
inotifywaitgo.DELETE,
|
||||
},
|
||||
@@ -45,18 +64,18 @@ func (iw *InotifyWatcher) Watch(path string) {
|
||||
if isLockFile(event.Filename) || isTrash(event.Filename) || iw.tree.isUpload(event.Filename) {
|
||||
continue
|
||||
}
|
||||
switch e {
|
||||
case inotifywaitgo.DELETE:
|
||||
go func() { _ = iw.tree.HandleFileDelete(event.Filename) }()
|
||||
case inotifywaitgo.CREATE:
|
||||
go func() { _ = iw.tree.Scan(event.Filename, ActionCreate, event.IsDir, false) }()
|
||||
case inotifywaitgo.MOVED_TO:
|
||||
go func() {
|
||||
_ = iw.tree.Scan(event.Filename, ActionMove, event.IsDir, true)
|
||||
}()
|
||||
case inotifywaitgo.CLOSE_WRITE:
|
||||
go func() { _ = iw.tree.Scan(event.Filename, ActionUpdate, event.IsDir, true) }()
|
||||
}
|
||||
go func() {
|
||||
switch e {
|
||||
case inotifywaitgo.DELETE:
|
||||
_ = iw.tree.Scan(event.Filename, ActionDelete, event.IsDir)
|
||||
case inotifywaitgo.MOVED_FROM:
|
||||
_ = iw.tree.Scan(event.Filename, ActionMoveFrom, event.IsDir)
|
||||
case inotifywaitgo.CREATE, inotifywaitgo.MOVED_TO:
|
||||
_ = iw.tree.Scan(event.Filename, ActionCreate, event.IsDir)
|
||||
case inotifywaitgo.CLOSE_WRITE:
|
||||
_ = iw.tree.Scan(event.Filename, ActionUpdate, event.IsDir)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
case err := <-errors:
|
||||
|
||||
27
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/tree.go
generated
vendored
27
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/tree.go
generated
vendored
@@ -310,6 +310,12 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
|
||||
return errors.Wrap(err, "Decomposedfs: could not move child")
|
||||
}
|
||||
|
||||
// update the id cache
|
||||
if newNode.ID == "" {
|
||||
newNode.ID = oldNode.ID
|
||||
}
|
||||
_ = t.lookup.(*lookup.Lookup).CacheID(ctx, newNode.SpaceID, newNode.ID, filepath.Join(newNode.ParentPath(), newNode.Name))
|
||||
|
||||
// rename the lock (if it exists)
|
||||
if _, err := os.Stat(oldNode.LockFilePath()); err == nil {
|
||||
err = os.Rename(
|
||||
@@ -321,11 +327,6 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
|
||||
}
|
||||
}
|
||||
|
||||
// update the id cache
|
||||
if newNode.ID == "" {
|
||||
newNode.ID = oldNode.ID
|
||||
}
|
||||
_ = t.lookup.(*lookup.Lookup).CacheID(ctx, newNode.SpaceID, newNode.ID, filepath.Join(newNode.ParentPath(), newNode.Name))
|
||||
// update id cache for the moved subtree.
|
||||
if oldNode.IsDir(ctx) {
|
||||
err = t.WarmupIDCache(filepath.Join(newNode.ParentPath(), newNode.Name), false, false)
|
||||
@@ -334,11 +335,23 @@ func (t *Tree) Move(ctx context.Context, oldNode *node.Node, newNode *node.Node)
|
||||
}
|
||||
}
|
||||
|
||||
err = t.Propagate(ctx, oldNode, 0)
|
||||
// the size diff is the current treesize or blobsize of the old/source node
|
||||
var sizeDiff int64
|
||||
if oldNode.IsDir(ctx) {
|
||||
treeSize, err := oldNode.GetTreeSize(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sizeDiff = int64(treeSize)
|
||||
} else {
|
||||
sizeDiff = oldNode.Blobsize
|
||||
}
|
||||
|
||||
err = t.Propagate(ctx, oldNode, -sizeDiff)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Decomposedfs: Move: could not propagate old node")
|
||||
}
|
||||
err = t.Propagate(ctx, newNode, 0)
|
||||
err = t.Propagate(ctx, newNode, sizeDiff)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Decomposedfs: Move: could not propagate new node")
|
||||
}
|
||||
|
||||
253
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/propagator/sync.go
generated
vendored
253
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/propagator/sync.go
generated
vendored
@@ -30,6 +30,7 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/metadata/prefixes"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
|
||||
"github.com/rogpeppe/go-internal/lockedfile"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
||||
// SyncPropagator implements synchronous treetime & treesize propagation
|
||||
@@ -72,137 +73,137 @@ func (p SyncPropagator) Propagate(ctx context.Context, n *node.Node, sizeDiff in
|
||||
sTime := time.Now().UTC()
|
||||
|
||||
// we loop until we reach the root
|
||||
var err error
|
||||
for err == nil && n.ID != root.ID {
|
||||
sublog.Debug().Msg("propagating")
|
||||
var (
|
||||
err error
|
||||
stop bool
|
||||
)
|
||||
|
||||
attrs := node.Attributes{}
|
||||
|
||||
var f *lockedfile.File
|
||||
// lock parent before reading treesize or tree time
|
||||
|
||||
_, subspan := tracer.Start(ctx, "lockedfile.OpenFile")
|
||||
parentFilename := p.lookup.MetadataBackend().LockfilePath(n.ParentPath())
|
||||
f, err = lockedfile.OpenFile(parentFilename, os.O_RDWR|os.O_CREATE, 0600)
|
||||
subspan.End()
|
||||
if err != nil {
|
||||
sublog.Error().Err(err).
|
||||
Str("parent filename", parentFilename).
|
||||
Msg("Propagation failed. Could not open metadata for parent with lock.")
|
||||
return err
|
||||
}
|
||||
// always log error if closing node fails
|
||||
defer func() {
|
||||
// ignore already closed error
|
||||
cerr := f.Close()
|
||||
if err == nil && cerr != nil && !errors.Is(cerr, os.ErrClosed) {
|
||||
err = cerr // only overwrite err with en error from close if the former was nil
|
||||
}
|
||||
_ = os.Remove(f.Name())
|
||||
}()
|
||||
|
||||
if n, err = n.Parent(ctx); err != nil {
|
||||
sublog.Error().Err(err).
|
||||
Msg("Propagation failed. Could not read parent node.")
|
||||
return err
|
||||
}
|
||||
|
||||
if !n.HasPropagation(ctx) {
|
||||
sublog.Debug().Str("attr", prefixes.PropagationAttr).Msg("propagation attribute not set or unreadable, not propagating")
|
||||
// if the attribute is not set treat it as false / none / no propagation
|
||||
return nil
|
||||
}
|
||||
|
||||
sublog = sublog.With().Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Logger()
|
||||
|
||||
if p.treeTimeAccounting {
|
||||
// update the parent tree time if it is older than the nodes mtime
|
||||
updateSyncTime := false
|
||||
|
||||
var tmTime time.Time
|
||||
tmTime, err = n.GetTMTime(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
// missing attribute, or invalid format, overwrite
|
||||
sublog.Debug().Err(err).
|
||||
Msg("could not read tmtime attribute, overwriting")
|
||||
updateSyncTime = true
|
||||
case tmTime.Before(sTime):
|
||||
sublog.Debug().
|
||||
Time("tmtime", tmTime).
|
||||
Time("stime", sTime).
|
||||
Msg("parent tmtime is older than node mtime, updating")
|
||||
updateSyncTime = true
|
||||
default:
|
||||
sublog.Debug().
|
||||
Time("tmtime", tmTime).
|
||||
Time("stime", sTime).
|
||||
Dur("delta", sTime.Sub(tmTime)).
|
||||
Msg("parent tmtime is younger than node mtime, not updating")
|
||||
}
|
||||
|
||||
if updateSyncTime {
|
||||
// update the tree time of the parent node
|
||||
attrs.SetString(prefixes.TreeMTimeAttr, sTime.UTC().Format(time.RFC3339Nano))
|
||||
}
|
||||
|
||||
attrs.SetString(prefixes.TmpEtagAttr, "")
|
||||
}
|
||||
|
||||
// size accounting
|
||||
if p.treeSizeAccounting && sizeDiff != 0 {
|
||||
var newSize uint64
|
||||
|
||||
// read treesize
|
||||
treeSize, err := n.GetTreeSize(ctx)
|
||||
switch {
|
||||
case metadata.IsAttrUnset(err):
|
||||
// fallback to calculating the treesize
|
||||
sublog.Warn().Msg("treesize attribute unset, falling back to calculating the treesize")
|
||||
newSize, err = calculateTreeSize(ctx, p.lookup, n.InternalPath())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
case err != nil:
|
||||
sublog.Error().Err(err).
|
||||
Msg("Faild to propagate treesize change. Error when reading the treesize attribute from parent")
|
||||
return err
|
||||
case sizeDiff > 0:
|
||||
newSize = treeSize + uint64(sizeDiff)
|
||||
case uint64(-sizeDiff) > treeSize:
|
||||
// The sizeDiff is larger than the current treesize. Which would result in
|
||||
// a negative new treesize. Something must have gone wrong with the accounting.
|
||||
// Reset the current treesize to 0.
|
||||
sublog.Error().Uint64("treeSize", treeSize).Int64("sizeDiff", sizeDiff).
|
||||
Msg("Error when updating treesize of parent node. Updated treesize < 0. Reestting to 0")
|
||||
newSize = 0
|
||||
default:
|
||||
newSize = treeSize - uint64(-sizeDiff)
|
||||
}
|
||||
|
||||
// update the tree size of the node
|
||||
attrs.SetString(prefixes.TreesizeAttr, strconv.FormatUint(newSize, 10))
|
||||
sublog.Debug().Uint64("newSize", newSize).Msg("updated treesize of parent node")
|
||||
}
|
||||
|
||||
if err = n.SetXattrsWithContext(ctx, attrs, false); err != nil {
|
||||
sublog.Error().Err(err).Msg("Failed to update extend attributes of parent node")
|
||||
return err
|
||||
}
|
||||
|
||||
// Release node lock early, ignore already closed error
|
||||
_, subspan = tracer.Start(ctx, "f.Close")
|
||||
cerr := f.Close()
|
||||
subspan.End()
|
||||
if cerr != nil && !errors.Is(cerr, os.ErrClosed) {
|
||||
sublog.Error().Err(cerr).Msg("Failed to close parent node and release lock")
|
||||
return cerr
|
||||
}
|
||||
for err == nil && !stop && n.ID != root.ID {
|
||||
n, stop, err = p.propagateItem(ctx, n, sTime, sizeDiff, sublog)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
sublog.Error().Err(err).Msg("error propagating")
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (p SyncPropagator) propagateItem(ctx context.Context, n *node.Node, sTime time.Time, sizeDiff int64, log zerolog.Logger) (*node.Node, bool, error) {
|
||||
log.Debug().Msg("propagating")
|
||||
|
||||
attrs := node.Attributes{}
|
||||
|
||||
var f *lockedfile.File
|
||||
// lock parent before reading treesize or tree time
|
||||
|
||||
_, subspan := tracer.Start(ctx, "lockedfile.OpenFile")
|
||||
parentFilename := p.lookup.MetadataBackend().LockfilePath(n.ParentPath())
|
||||
f, err := lockedfile.OpenFile(parentFilename, os.O_RDWR|os.O_CREATE, 0600)
|
||||
subspan.End()
|
||||
if err != nil {
|
||||
log.Error().Err(err).
|
||||
Str("parent filename", parentFilename).
|
||||
Msg("Propagation failed. Could not open metadata for parent with lock.")
|
||||
return nil, true, err
|
||||
}
|
||||
// always log error if closing node fails
|
||||
defer func() {
|
||||
// ignore already closed error
|
||||
cerr := f.Close()
|
||||
if err == nil && cerr != nil && !errors.Is(cerr, os.ErrClosed) {
|
||||
err = cerr // only overwrite err with en error from close if the former was nil
|
||||
}
|
||||
}()
|
||||
|
||||
if n, err = n.Parent(ctx); err != nil {
|
||||
log.Error().Err(err).
|
||||
Msg("Propagation failed. Could not read parent node.")
|
||||
return n, true, err
|
||||
}
|
||||
|
||||
if !n.HasPropagation(ctx) {
|
||||
log.Debug().Str("attr", prefixes.PropagationAttr).Msg("propagation attribute not set or unreadable, not propagating")
|
||||
// if the attribute is not set treat it as false / none / no propagation
|
||||
return n, true, nil
|
||||
}
|
||||
|
||||
log = log.With().Str("spaceid", n.SpaceID).Str("nodeid", n.ID).Logger()
|
||||
|
||||
if p.treeTimeAccounting {
|
||||
// update the parent tree time if it is older than the nodes mtime
|
||||
updateSyncTime := false
|
||||
|
||||
var tmTime time.Time
|
||||
tmTime, err = n.GetTMTime(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
// missing attribute, or invalid format, overwrite
|
||||
log.Debug().Err(err).
|
||||
Msg("could not read tmtime attribute, overwriting")
|
||||
updateSyncTime = true
|
||||
case tmTime.Before(sTime):
|
||||
log.Debug().
|
||||
Time("tmtime", tmTime).
|
||||
Time("stime", sTime).
|
||||
Msg("parent tmtime is older than node mtime, updating")
|
||||
updateSyncTime = true
|
||||
default:
|
||||
log.Debug().
|
||||
Time("tmtime", tmTime).
|
||||
Time("stime", sTime).
|
||||
Dur("delta", sTime.Sub(tmTime)).
|
||||
Msg("parent tmtime is younger than node mtime, not updating")
|
||||
}
|
||||
|
||||
if updateSyncTime {
|
||||
// update the tree time of the parent node
|
||||
attrs.SetString(prefixes.TreeMTimeAttr, sTime.UTC().Format(time.RFC3339Nano))
|
||||
}
|
||||
|
||||
attrs.SetString(prefixes.TmpEtagAttr, "")
|
||||
}
|
||||
|
||||
// size accounting
|
||||
if p.treeSizeAccounting && sizeDiff != 0 {
|
||||
var newSize uint64
|
||||
|
||||
// read treesize
|
||||
treeSize, err := n.GetTreeSize(ctx)
|
||||
switch {
|
||||
case metadata.IsAttrUnset(err):
|
||||
// fallback to calculating the treesize
|
||||
log.Warn().Msg("treesize attribute unset, falling back to calculating the treesize")
|
||||
newSize, err = calculateTreeSize(ctx, p.lookup, n.InternalPath())
|
||||
if err != nil {
|
||||
return n, true, err
|
||||
}
|
||||
case err != nil:
|
||||
log.Error().Err(err).
|
||||
Msg("Faild to propagate treesize change. Error when reading the treesize attribute from parent")
|
||||
return n, true, err
|
||||
case sizeDiff > 0:
|
||||
newSize = treeSize + uint64(sizeDiff)
|
||||
case uint64(-sizeDiff) > treeSize:
|
||||
// The sizeDiff is larger than the current treesize. Which would result in
|
||||
// a negative new treesize. Something must have gone wrong with the accounting.
|
||||
// Reset the current treesize to 0.
|
||||
log.Error().Uint64("treeSize", treeSize).Int64("sizeDiff", sizeDiff).
|
||||
Msg("Error when updating treesize of parent node. Updated treesize < 0. Reestting to 0")
|
||||
newSize = 0
|
||||
default:
|
||||
newSize = treeSize - uint64(-sizeDiff)
|
||||
}
|
||||
|
||||
// update the tree size of the node
|
||||
attrs.SetString(prefixes.TreesizeAttr, strconv.FormatUint(newSize, 10))
|
||||
log.Debug().Uint64("newSize", newSize).Msg("updated treesize of parent node")
|
||||
}
|
||||
|
||||
if err = n.SetXattrsWithContext(ctx, attrs, false); err != nil {
|
||||
log.Error().Err(err).Msg("Failed to update extend attributes of parent node")
|
||||
return n, true, err
|
||||
}
|
||||
|
||||
return n, false, nil
|
||||
}
|
||||
|
||||
8
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go
generated
vendored
8
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload.go
generated
vendored
@@ -26,10 +26,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
@@ -40,7 +41,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload"
|
||||
"github.com/cs3org/reva/v2/pkg/storagespace"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Upload uploads data to the given resource
|
||||
@@ -90,7 +90,7 @@ func (fs *Decomposedfs) Upload(ctx context.Context, req storage.UploadRequest, u
|
||||
}
|
||||
}
|
||||
|
||||
if err := session.FinishUpload(ctx); err != nil {
|
||||
if err := session.FinishUploadDecomposed(ctx); err != nil {
|
||||
return &provider.ResourceInfo{}, err
|
||||
}
|
||||
|
||||
@@ -321,7 +321,7 @@ func (fs *Decomposedfs) InitiateUpload(ctx context.Context, ref *provider.Refere
|
||||
|
||||
if uploadLength == 0 {
|
||||
// Directly finish this upload
|
||||
err = session.FinishUpload(ctx)
|
||||
err = session.FinishUploadDecomposed(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
40
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go
generated
vendored
40
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go
generated
vendored
@@ -33,6 +33,12 @@ import (
|
||||
|
||||
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/pkg/errors"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
|
||||
"github.com/cs3org/reva/v2/pkg/appctx"
|
||||
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
|
||||
"github.com/cs3org/reva/v2/pkg/errtypes"
|
||||
@@ -41,11 +47,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/metadata/prefixes"
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node"
|
||||
"github.com/cs3org/reva/v2/pkg/utils"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/pkg/errors"
|
||||
tusd "github.com/tus/tusd/v2/pkg/handler"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -106,7 +107,25 @@ func (session *OcisSession) GetReader(ctx context.Context) (io.ReadCloser, error
|
||||
}
|
||||
|
||||
// FinishUpload finishes an upload and moves the file to the internal destination
|
||||
// implements tusd.DataStore interface
|
||||
// returns tusd errors
|
||||
func (session *OcisSession) FinishUpload(ctx context.Context) error {
|
||||
err := session.FinishUploadDecomposed(ctx)
|
||||
|
||||
// we need to return a tusd error here to make the tusd handler return the correct status code
|
||||
switch err.(type) {
|
||||
case errtypes.AlreadyExists:
|
||||
return tusd.NewError("ERR_ALREADY_EXISTS", err.Error(), http.StatusConflict)
|
||||
case errtypes.Aborted:
|
||||
return tusd.NewError("ERR_PRECONDITION_FAILED", err.Error(), http.StatusPreconditionFailed)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// FinishUploadDecomposed finishes an upload and moves the file to the internal destination
|
||||
// retures errtypes errors
|
||||
func (session *OcisSession) FinishUploadDecomposed(ctx context.Context) error {
|
||||
ctx, span := tracer.Start(session.Context(ctx), "FinishUpload")
|
||||
defer span.End()
|
||||
log := appctx.GetLogger(ctx)
|
||||
@@ -167,16 +186,7 @@ func (session *OcisSession) FinishUpload(ctx context.Context) error {
|
||||
|
||||
n, err := session.store.CreateNodeForUpload(session, attrs)
|
||||
if err != nil {
|
||||
session.store.Cleanup(ctx, session, true, false, false)
|
||||
// we need to return a tusd error here to make the tusd handler return the correct status code
|
||||
switch err.(type) {
|
||||
case errtypes.AlreadyExists:
|
||||
return ErrAlreadyExists
|
||||
case errtypes.Aborted:
|
||||
return tusd.NewError("ERR_PRECONDITION_FAILED", err.Error(), http.StatusPreconditionFailed)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
// increase the processing counter for every started processing
|
||||
// will be decreased in Cleanup()
|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -367,7 +367,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
|
||||
# github.com/cs3org/reva/v2 v2.26.4
|
||||
# github.com/cs3org/reva/v2 v2.26.5-0.20241111162950-e77dd61e7edb
|
||||
## explicit; go 1.22.0
|
||||
github.com/cs3org/reva/v2/cmd/revad/internal/grace
|
||||
github.com/cs3org/reva/v2/cmd/revad/runtime
|
||||
|
||||
Reference in New Issue
Block a user