Skip to content

Commit

Permalink
Combine stat responses for virtual refs
Browse files Browse the repository at this point in the history
  • Loading branch information
ishank011 committed Mar 23, 2021
1 parent 7d26007 commit d770434
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 25 deletions.
61 changes: 56 additions & 5 deletions internal/grpc/services/gateway/storageprovider.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/cs3org/reva/pkg/storage/utils/etag"
"github.com/cs3org/reva/pkg/utils"
"github.com/dgrijalva/jwt-go"
"github.com/google/uuid"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -1146,15 +1147,65 @@ func (s *svc) statSharesFolder(ctx context.Context) (*provider.StatResponse, err
}

func (s *svc) stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) {
// TODO(ishank011): enable for references spread across storage providers, eg. /eos
c, err := s.find(ctx, req.Ref)
providers, err := s.findProviders(ctx, req.Ref)
if err != nil {
return &provider.StatResponse{
Status: status.NewStatusFromErrType(ctx, "stat ref="+req.Ref.String(), err),
Status: status.NewStatusFromErrType(ctx, "stat ref: "+req.Ref.String(), err),
}, nil
}

return c.Stat(ctx, req)
resPath := req.Ref.GetPath()
if len(providers) == 1 && (resPath == "" || strings.HasPrefix(resPath, p.ProviderPath)) {
c, err := s.getStorageProviderClient(ctx, providers[0])
if err != nil {
return &provider.StatResponse{
Status: status.NewInternal(ctx, err, "error connecting to storage provider="+providers[0].Address),
}, nil
}
return c.Stat(ctx, req)
}

var totalSize uint64
var infos []*provider.ResourceInfo
for _, p := range providers {
c, err := s.getStorageProviderClient(ctx, p)
if err != nil {
return &provider.StatResponse{
Status: status.NewInternal(ctx, err, "error connecting to storage provider="+p.Address),
}, nil
}

if resPath != "" && !strings.HasPrefix(resPath, p.ProviderPath) {
req = &provider.StatRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Path{
Path: p.ProviderPath,
},
},
}
}
res, err := c.Stat(ctx, req)
if err != nil {
return nil, errors.Wrap(err, "gateway: error calling ListContainer")
}
totalSize += res.Info.Size
infos = append(infos, res.Info)
}

// TODO(ishank011): aggregrate other properties for references spread across storage providers, eg. /eos
return &provider.StatResponse{
Status: status.NewOK(ctx),
Info: &provider.ResourceInfo{
Id: &provider.ResourceId{
StorageId: "/",
OpaqueId: uuid.New().String(),
},
Type: provider.ResourceType_RESOURCE_TYPE_CONTAINER,
Etag: etag.GenerateEtagFromResources(nil, infos),
Path: resPath,
Size: totalSize,
},
}, nil
}

func (s *svc) Stat(ctx context.Context, req *provider.StatRequest) (*provider.StatResponse, error) {
Expand Down Expand Up @@ -1472,7 +1523,7 @@ func (s *svc) listContainer(ctx context.Context, req *provider.ListContainerRequ
c, err := s.getStorageProviderClient(ctx, p)
if err != nil {
return &provider.ListContainerResponse{
Status: status.NewInternal(ctx, err, "error connecting to storage provider="+providers[0].Address),
Status: status.NewInternal(ctx, err, "error connecting to storage provider="+p.Address),
}, nil
}

Expand Down
17 changes: 4 additions & 13 deletions internal/http/services/owncloud/ocs/handlers/cloud/users/users.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ import (

// Handler renders user data for the user id given in the url path
type Handler struct {
gatewayAddr string
gatewayAddr string
homeNamespace string
}

// Init initializes this and any contained handlers
func (h *Handler) Init(c *config.Config) error {
h.gatewayAddr = c.GatewaySvc
h.homeNamespace = c.HomeNamespace
return nil
}

Expand Down Expand Up @@ -115,21 +117,10 @@ func (h *Handler) handleUsers(w http.ResponseWriter, r *http.Request, u *userpb.
return
}

getHomeRes, err := gc.GetHome(ctx, &provider.GetHomeRequest{})
if err != nil {
sublog.Error().Err(err).Msg("error calling GetHome")
w.WriteHeader(http.StatusInternalServerError)
return
}
if getHomeRes.Status.Code != rpc.Code_CODE_OK {
ocdav.HandleErrorStatus(sublog, w, getHomeRes.Status)
return
}

getQuotaRes, err := gc.GetQuota(ctx, &gateway.GetQuotaRequest{
Ref: &provider.Reference{
Spec: &provider.Reference_Path{
Path: getHomeRes.Path,
Path: h.homeNamespace,
},
},
})
Expand Down
16 changes: 9 additions & 7 deletions pkg/storage/utils/etag/etag.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,17 @@ var (
// GenerateEtagFromResources creates a unique etag for the root folder deriving
// information from its multiple children
func GenerateEtagFromResources(root *provider.ResourceInfo, children []*provider.ResourceInfo) string {
if params := getEtagParams(eosMtimeEtag, root.Etag); len(params) > 0 {
mtime := time.Unix(int64(root.Mtime.Seconds), int64(root.Mtime.Nanos))
for _, r := range children {
m := time.Unix(int64(r.Mtime.Seconds), int64(r.Mtime.Nanos))
if m.After(mtime) {
mtime = m
if root != nil {
if params := getEtagParams(eosMtimeEtag, root.Etag); len(params) > 0 {
mtime := time.Unix(int64(root.Mtime.Seconds), int64(root.Mtime.Nanos))
for _, r := range children {
m := time.Unix(int64(r.Mtime.Seconds), int64(r.Mtime.Nanos))
if m.After(mtime) {
mtime = m
}
}
return fmt.Sprintf("\"%s:%d.%s\"", params["inode"], mtime.Unix(), strconv.FormatInt(mtime.UnixNano(), 10)[:3])
}
return fmt.Sprintf("\"%s:%d.%s\"", params["inode"], mtime.Unix(), strconv.FormatInt(mtime.UnixNano(), 10)[:3])
}

return combineEtags(children)
Expand Down

0 comments on commit d770434

Please sign in to comment.