chore:reva bump v.2.34 (#1139)

This commit is contained in:
Viktor Scharf
2025-06-30 10:00:47 +02:00
committed by GitHub
parent bb36239433
commit b30bb19ad7
97 changed files with 1479 additions and 829 deletions
@@ -38,6 +38,7 @@ import (
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
typesv1beta1 "github.com/cs3org/go-cs3apis/cs3/types/v1beta1"
"github.com/iancoleman/strcase"
"github.com/opencloud-eu/opencloud/services/thumbnails/pkg/thumbnail"
"github.com/opencloud-eu/reva/v2/internal/grpc/services/storageprovider"
"github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/config"
"github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/errors"
@@ -1287,6 +1288,13 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys)
}
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
// directories have no preview
appendToNotFound(prop.NotFound("oc:has-preview"))
} else if md.MimeType != "" {
hasPreview(md, appendToOK)
}
// ls do not report any properties as missing by default
if ls == nil {
// favorites from arbitrary metadata
@@ -1589,6 +1597,13 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
// see https://doc.owncloud.com/server/admin_manual/configuration/server/occ_command.html#maintenance-commands
// TODO(jfd): double check the client behavior with reva on backup restore
fallthrough
case "has-preview":
if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER {
// directories have no preview
appendToNotFound(prop.NotFound("oc:has-preview"))
} else if md.MimeType != "" {
hasPreview(md, appendToOK)
}
default:
appendToNotFound(prop.NotFound("oc:" + pf.Prop[i].Local))
}
@@ -1714,6 +1729,15 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p
return &response, nil
}
func hasPreview(md *provider.ResourceInfo, appendToOK func(p ...prop.PropertyXML)) {
_, match := thumbnail.SupportedMimeTypes[md.MimeType]
if match {
appendToOK(prop.Escaped("oc:has-preview", "1"))
} else {
appendToOK(prop.Escaped("oc:has-preview", "0"))
}
}
func activeLocks(log *zerolog.Logger, lock *provider.Lock) string {
if lock == nil || lock.Type == provider.LockType_LOCK_TYPE_INVALID {
return ""
@@ -125,7 +125,7 @@ func (h *appsHandler) webappTemplate(ctx context.Context, id *ocmpb.ShareId) (st
return "", errtypes.BadRequest("share does not contain webapp protocol")
}
return webapp.UriTemplate, nil
return webapp.Uri, nil
}
func getWebappProtocol(protocols []*ocmpb.Protocol) (*ocmpb.WebappProtocol, bool) {
+2 -2
View File
@@ -42,8 +42,8 @@ func NewWebappProtocol(uriTemplate string, viewMode appprovider.ViewMode) *ocm.P
return &ocm.Protocol{
Term: &ocm.Protocol_WebappOptions{
WebappOptions: &ocm.WebappProtocol{
UriTemplate: uriTemplate,
ViewMode: viewMode,
Uri: uriTemplate,
ViewMode: viewMode,
},
},
}
@@ -42,6 +42,12 @@ func New(m map[string]interface{}, stream events.Stream, log *zerolog.Logger) (s
return nil, err
}
if log == nil {
log = &zerolog.Logger{}
}
decomposedLog := log.With().Str("driver", "decomposed").Logger()
log = &decomposedLog
bs, err := blobstore.New(path.Join(o.Root))
if err != nil {
return nil, err
@@ -41,6 +41,12 @@ func New(m map[string]interface{}, stream events.Stream, log *zerolog.Logger) (s
return nil, err
}
if log == nil {
log = &zerolog.Logger{}
}
decomposeds3Log := log.With().Str("driver", "decomposeds3").Logger()
log = &decomposeds3Log
if !o.S3ConfigComplete() {
return nil, fmt.Errorf("S3 configuration incomplete")
}
+6
View File
@@ -69,6 +69,12 @@ func New(m map[string]interface{}, stream events.Stream, log *zerolog.Logger) (s
return nil, err
}
if log == nil {
log = &zerolog.Logger{}
}
posixLog := log.With().Str("driver", "posix").Logger()
log = &posixLog
fs := &posixFS{}
var um usermapper.Mapper
if o.UseSpaceGroups {
@@ -109,15 +109,15 @@ func (d *ScanDebouncer) Debounce(item scanItem) {
defer d.mutex.Unlock()
path := item.Path
force := item.ForceRescan
recurse := item.Recurse
if i, ok := d.pending.Load(item.Path); ok {
AssimilationPendingTasks.Dec()
queueItem := i.(*queueItem)
force = force || queueItem.item.ForceRescan
recurse = recurse || queueItem.item.Recurse
queueItem.timer.Stop()
}
AssimilationPendingTasks.Inc()
d.pending.Store(item.Path, &queueItem{
item: item,
timer: time.AfterFunc(d.after, func() {
@@ -132,13 +132,13 @@ func (d *ScanDebouncer) Debounce(item scanItem) {
return
}
AssimilationPendingTasks.Dec()
d.pending.Delete(path)
d.inProgress.Store(path, true)
defer d.inProgress.Delete(path)
d.f(scanItem{
Path: path,
ForceRescan: force,
Recurse: recurse,
Path: path,
Recurse: recurse,
})
}),
})
@@ -156,6 +156,15 @@ func (d *ScanDebouncer) InProgress(path string) bool {
return ok
}
// Pending returns true if the given path is currently pending to be processed
func (d *ScanDebouncer) Pending(path string) bool {
d.mutex.Lock()
defer d.mutex.Unlock()
_, ok := d.pending.Load(path)
return ok
}
func (t *Tree) workScanQueue() {
for i := 0; i < t.options.MaxConcurrency; i++ {
go func() {
@@ -189,19 +198,18 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
// 1. New file (could be emitted as part of a new directory)
// -> assimilate file
// -> 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)) {
AssimilationCounter.WithLabelValues(_labelFile, _labelAdded).Inc()
if !t.scanDebouncer.Pending(filepath.Dir(path)) {
t.scanDebouncer.Debounce(scanItem{
Path: path,
ForceRescan: false,
Path: path,
})
}
if err := t.setDirty(filepath.Dir(path), true); err != nil {
t.log.Error().Err(err).Str("path", path).Bool("isDir", isDir).Msg("failed to mark directory as dirty")
}
t.scanDebouncer.Debounce(scanItem{
Path: filepath.Dir(path),
ForceRescan: true,
Recurse: true,
Path: filepath.Dir(path),
Recurse: true,
})
} else {
// 2. New directory
@@ -209,10 +217,10 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
if err := t.setDirty(path, true); err != nil {
t.log.Error().Err(err).Str("path", path).Bool("isDir", isDir).Msg("failed to mark directory as dirty")
}
AssimilationCounter.WithLabelValues(_labelDir, _labelAdded).Inc()
t.scanDebouncer.Debounce(scanItem{
Path: path,
ForceRescan: true,
Recurse: true,
Path: path,
Recurse: true,
})
}
@@ -222,11 +230,16 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
// -> update file unless parent directory is being rescanned
if !t.scanDebouncer.InProgress(filepath.Dir(path)) {
t.scanDebouncer.Debounce(scanItem{
Path: path,
ForceRescan: true,
Path: path,
})
}
if !isDir {
AssimilationCounter.WithLabelValues(_labelFile, _labelUpdated).Inc()
} else {
AssimilationCounter.WithLabelValues(_labelDir, _labelUpdated).Inc()
}
case ActionMove:
t.log.Debug().Str("path", path).Bool("isDir", isDir).Msg("scanning path (ActionMove)")
// 4. Moved file
@@ -234,11 +247,16 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
// 5. Moved directory
// -> update directory and all children
t.scanDebouncer.Debounce(scanItem{
Path: path,
ForceRescan: isDir,
Recurse: isDir,
Path: path,
Recurse: isDir,
})
if !isDir {
AssimilationCounter.WithLabelValues(_labelFile, _labelMoved).Inc()
} else {
AssimilationCounter.WithLabelValues(_labelDir, _labelMoved).Inc()
}
case ActionMoveFrom:
t.log.Debug().Str("path", path).Bool("isDir", isDir).Msg("scanning path (ActionMoveFrom)")
// 6. file/directory moved out of the watched directory
@@ -258,6 +276,8 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
t.log.Error().Err(err).Str("path", path).Bool("isDir", isDir).Msg("failed to handle moved away item")
}
// We do not do metrics here because this has been handled in `ActionMove`
case ActionDelete:
t.log.Debug().Str("path", path).Bool("isDir", isDir).Msg("handling deleted item")
@@ -270,10 +290,15 @@ func (t *Tree) Scan(path string, action EventAction, isDir bool) error {
}
t.scanDebouncer.Debounce(scanItem{
Path: filepath.Dir(path),
ForceRescan: true,
Recurse: true,
Path: filepath.Dir(path),
Recurse: true,
})
if !isDir {
AssimilationCounter.WithLabelValues(_labelFile, _labelDeleted).Inc()
} else {
AssimilationCounter.WithLabelValues(_labelDir, _labelDeleted).Inc()
}
}
return nil
@@ -369,7 +394,7 @@ func (t *Tree) findSpaceId(path string) (string, error) {
}
func (t *Tree) assimilate(item scanItem) error {
t.log.Debug().Str("path", item.Path).Bool("rescan", item.ForceRescan).Bool("recurse", item.Recurse).Msg("assimilate")
t.log.Debug().Str("path", item.Path).Bool("recurse", item.Recurse).Msg("assimilate")
var err error
spaceID, id, parentID, mtime, err := t.lookup.MetadataBackend().IdentifyPath(context.Background(), item.Path)
@@ -379,7 +404,7 @@ func (t *Tree) assimilate(item scanItem) error {
if spaceID == "" {
// node didn't have a space ID attached. try to find it by walking up the path on disk
spaceID, err = t.findSpaceId(item.Path)
spaceID, err = t.findSpaceId(filepath.Dir(item.Path))
if err != nil {
return err
}
@@ -428,7 +453,7 @@ func (t *Tree) assimilate(item scanItem) error {
t.log.Error().Err(err).Str("path", item.Path).Msg("could not purge metadata")
}
go func() {
if err := t.assimilate(scanItem{Path: item.Path, ForceRescan: true}); err != nil {
if err := t.assimilate(scanItem{Path: item.Path}); err != nil {
t.log.Error().Err(err).Str("path", item.Path).Msg("could not re-assimilate")
}
}()
@@ -590,7 +615,7 @@ assimilate:
}
// assimilate parent first
err = t.assimilate(scanItem{Path: filepath.Dir(path), ForceRescan: false})
err = t.assimilate(scanItem{Path: filepath.Dir(path)})
if err != nil {
return nil, nil, err
}
@@ -822,7 +847,7 @@ func (t *Tree) WarmupIDCache(root string, assimilate, onlyDirty bool) error {
// this id clashes with an existing id -> re-assimilate
_, err := os.Stat(previousPath)
if err == nil {
_ = t.assimilate(scanItem{Path: path, ForceRescan: true})
_ = t.assimilate(scanItem{Path: path})
}
}
if err := t.lookup.CacheID(context.Background(), spaceID, id, path); err != nil {
@@ -830,7 +855,7 @@ func (t *Tree) WarmupIDCache(root string, assimilate, onlyDirty bool) error {
}
}
} else if assimilate {
if err := t.assimilate(scanItem{Path: path, ForceRescan: true}); err != nil {
if err := t.assimilate(scanItem{Path: path}); err != nil {
t.log.Error().Err(err).Str("path", path).Msg("could not assimilate item")
}
}
@@ -0,0 +1,32 @@
package tree
import (
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
)
var (
// constants for AssimilationCounter labels
_labelFile = "file"
_labelDir = "dir"
_labelAdded = "added"
_labelUpdated = "updated"
_labelDeleted = "deleted"
_labelMoved = "moved"
// AssimilationCounter is a Prometheus counter that tracks the number of files and directories assimilated by posixfs.
AssimilationCounter = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "reva_assimilation_count",
Help: "Number of files and directories assimilated by posixfs",
},
// type can be "file" or "dir"
// action can be "added", "updated", "deleted", "moved"
[]string{"type", "action"},
)
// AssimilationPendingTasks is a Prometheus gauge that tracks the number of active assimilation tasks.
AssimilationPendingTasks = promauto.NewGauge(prometheus.GaugeOpts{
Name: "reva_assimilation_active_tasks",
Help: "Number of active assimilation tasks in posixfs",
})
)
+2 -3
View File
@@ -65,9 +65,8 @@ type Watcher interface {
}
type scanItem struct {
Path string
ForceRescan bool
Recurse bool
Path string
Recurse bool
}
// Tree manages a hierarchical tree
@@ -8,6 +8,7 @@ import (
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
"github.com/google/renameio/v2"
@@ -108,6 +109,11 @@ func (b HybridBackend) GetInt64(ctx context.Context, n MetadataNode, key string)
func (b HybridBackend) list(ctx context.Context, n MetadataNode, acquireLock bool) (attribs []string, err error) {
filePath := n.InternalPath()
if len(filePath) == 0 {
return nil, &xattr.Error{Op: "HybridBackend.list", Path: n.InternalPath(), Err: syscall.ENOENT} // attribute not found
}
attrs, err := xattr.List(filePath)
if err == nil {
return attrs, nil