Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

always find unique providers #4741

Merged
merged 1 commit into from
Jul 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog/unreleased/always-find-unique-providers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Bugfix: Always find unique providers

The gateway will now always try to find a single unique provider. It has stopped aggregating multiple ListContainer responses when we removed any business logic from it.

https://github.com/cs3org/reva/pull/4741
https://github.com/cs3org/reva/pull/4740
https://github.com/cs3org/reva/pull/2394
74 changes: 4 additions & 70 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -841,7 +841,7 @@ func (s *svc) Unlock(ctx context.Context, req *provider.UnlockRequest) (*provide

// Stat returns the Resoure info for a given resource by forwarding the request to the responsible provider.
func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) {
c, _, ref, err := s.findAndUnwrapUnique(ctx, req.Ref)
c, _, ref, err := s.findAndUnwrap(ctx, req.Ref)
if err != nil {
return &provider.StatResponse{
Status: status.NewNotFound(ctx, fmt.Sprintf("gateway could not find space for ref=%+v", req.Ref)),
Expand Down Expand Up @@ -1019,7 +1019,7 @@ func (s *svc) GetQuota(ctx context.Context, req *gateway.GetQuotaRequest) (*prov
// - contains the provider path, which is the mount point of the provider
// - may contain a list of storage spaces with their id and space path
func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, error) {
p, err := s.findSpaces(ctx, ref)
p, err := s.findSingleSpace(ctx, ref)
if err != nil {
return nil, nil, err
}
Expand All @@ -1028,32 +1028,20 @@ func (s *svc) find(ctx context.Context, ref *provider.Reference) (provider.Provi
return client, p[0], err
}

// findSpacesProvider looks up the provider that is responsible for the given request
// findSpacesProvider looks up the spaces provider that is responsible for the given request
// It will return a client that the caller can use to make the call, as well as the ProviderInfo. It:
// - contains the provider path, which is the mount point of the provider
// - may contain a list of storage spaces with their id and space path
func (s *svc) findSpacesProvider(ctx context.Context, ref *provider.Reference) (provider.SpacesAPIClient, *registry.ProviderInfo, error) {
p, err := s.findSpaces(ctx, ref)
if err != nil {
return nil, nil, err
}

client, err := s.getSpacesProviderClient(ctx, p[0])
return client, p[0], err
}

func (s *svc) findUnique(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, error) {
p, err := s.findSingleSpace(ctx, ref)
if err != nil {
return nil, nil, err
}

client, err := s.getStorageProviderClient(ctx, p[0])
client, err := s.getSpacesProviderClient(ctx, p[0])
return client, p[0], err
}

// FIXME findAndUnwrap currently just returns the first provider ... which may not be what is needed.
// for the ListRecycle call we need an exact match, for Stat and List we need to query all related providers
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the gateway is no longer smart. it does not aggregate any directories. clients have to do that now.

func (s *svc) findAndUnwrap(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, *provider.Reference, error) {
c, p, err := s.find(ctx, ref)
if err != nil {
Expand All @@ -1075,27 +1063,6 @@ func (s *svc) findAndUnwrap(ctx context.Context, ref *provider.Reference) (provi
return c, p, relativeReference, nil
}

func (s *svc) findAndUnwrapUnique(ctx context.Context, ref *provider.Reference) (provider.ProviderAPIClient, *registry.ProviderInfo, *provider.Reference, error) {
c, p, err := s.findUnique(ctx, ref)
if err != nil {
return nil, nil, nil, err
}

var (
root *provider.ResourceId
mountPath string
)
for _, space := range decodeSpaces(p) {
mountPath = decodePath(space)
root = space.Root
break // TODO can there be more than one space for a path?
}

relativeReference := unwrap(ref, mountPath, root)

return c, p, relativeReference, nil
}

func (s *svc) getSpacesProviderClient(_ context.Context, p *registry.ProviderInfo) (provider.SpacesAPIClient, error) {
c, err := pool.GetSpacesProviderServiceClient(p.Address)
if err != nil {
Expand Down Expand Up @@ -1131,39 +1098,6 @@ func (s *svc) getStorageRegistryClient(_ context.Context, address string) (regis
}, nil
}

func (s *svc) findSpaces(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) {
switch {
case ref == nil:
return nil, errtypes.BadRequest("missing reference")
case ref.ResourceId != nil:
if ref.ResourceId.OpaqueId == "" {
ref.ResourceId.OpaqueId = ref.ResourceId.SpaceId
}
case ref.Path != "": // TODO implement a mount path cache in the registry?
// nothing to do here either
default:
return nil, errtypes.BadRequest("invalid reference, at least path or id must be set")
}

filters := map[string]string{
"mask": "root", // we only need the root for routing
"path": ref.Path,
}
if ref.ResourceId != nil {
filters["storage_id"] = ref.ResourceId.StorageId
filters["space_id"] = ref.ResourceId.SpaceId
filters["opaque_id"] = ref.ResourceId.OpaqueId
}

listReq := &registry.ListStorageProvidersRequest{
Opaque: &typesv1beta1.Opaque{Map: make(map[string]*typesv1beta1.OpaqueEntry)},
}

sdk.EncodeOpaqueMap(listReq.Opaque, filters)

return s.findProvider(ctx, listReq)
}

func (s *svc) findSingleSpace(ctx context.Context, ref *provider.Reference) ([]*registry.ProviderInfo, error) {
switch {
case ref == nil:
Expand Down
4 changes: 2 additions & 2 deletions pkg/storage/registry/spaces/spaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ func (r *registry) GetProvider(ctx context.Context, space *providerpb.StorageSpa
// matches = /foo/bar <=> /foo/bar -> list(spaceid, .)
// below = /foo/bar/bif <=> /foo/bar -> list(spaceid, ./bif)
func (r *registry) ListProviders(ctx context.Context, filters map[string]string) ([]*registrypb.ProviderInfo, error) {
b, _ := strconv.ParseBool(filters["unique"])
unique, _ := strconv.ParseBool(filters["unique"])
unrestricted, _ := strconv.ParseBool(filters["unrestricted"])
mask := filters["mask"]
switch {
Expand All @@ -284,7 +284,7 @@ func (r *registry) ListProviders(ctx context.Context, filters map[string]string)

return r.findProvidersForResource(ctx, id, findMountpoint, findGrant, unrestricted, mask), nil
case filters["path"] != "":
return r.findProvidersForAbsolutePathReference(ctx, filters["path"], b, unrestricted, mask), nil
return r.findProvidersForAbsolutePathReference(ctx, filters["path"], unique, unrestricted, mask), nil
case len(filters) == 0:
// return all providers
return r.findAllProviders(ctx, mask), nil
Expand Down
Loading