| @@ -39,14 +39,14 @@ func (s *ObjectService) ListByPath(ctx *gin.Context) { | |||
| return | |||
| } | |||
| objs, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, req.IsPrefix) | |||
| coms, objs, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, req.IsPrefix, req.NoRecursive) | |||
| if err != nil { | |||
| log.Warnf("listing objects: %s", err.Error()) | |||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, fmt.Sprintf("listing objects: %v", err))) | |||
| return | |||
| } | |||
| ctx.JSON(http.StatusOK, OK(cdsapi.ObjectListByPathResp{Objects: objs})) | |||
| ctx.JSON(http.StatusOK, OK(cdsapi.ObjectListByPathResp{CommonPrefixes: coms, Objects: objs})) | |||
| } | |||
| func (s *ObjectService) ListByIDs(ctx *gin.Context) { | |||
| @@ -191,7 +191,7 @@ func (s *ObjectService) DownloadByPath(ctx *gin.Context) { | |||
| return | |||
| } | |||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false) | |||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false, false) | |||
| if err != nil { | |||
| log.Warnf("getting object by path: %s", err.Error()) | |||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | |||
| @@ -266,7 +266,7 @@ func (s *ObjectService) UpdateInfoByPath(ctx *gin.Context) { | |||
| return | |||
| } | |||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, true) | |||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, true, false) | |||
| if err != nil { | |||
| log.Warnf("getting object by path: %s", err.Error()) | |||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | |||
| @@ -343,7 +343,7 @@ func (s *ObjectService) DeleteByPath(ctx *gin.Context) { | |||
| return | |||
| } | |||
| obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false) | |||
| _, obj, err := s.svc.ObjectSvc().GetByPath(req.UserID, req.PackageID, req.Path, false, false) | |||
| if err != nil { | |||
| log.Warnf("getting object by path: %s", err.Error()) | |||
| ctx.JSON(http.StatusOK, Failed(errorcode.OperationFailed, "get object by path failed")) | |||
| @@ -22,19 +22,19 @@ func (svc *Service) ObjectSvc() *ObjectService { | |||
| return &ObjectService{Service: svc} | |||
| } | |||
| func (svc *ObjectService) GetByPath(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string, isPrefix bool) ([]cdssdk.Object, error) { | |||
| func (svc *ObjectService) GetByPath(userID cdssdk.UserID, pkgID cdssdk.PackageID, path string, isPrefix bool, noRecursive bool) ([]string, []cdssdk.Object, error) { | |||
| coorCli, err := stgglb.CoordinatorMQPool.Acquire() | |||
| if err != nil { | |||
| return nil, fmt.Errorf("new coordinator client: %w", err) | |||
| return nil, nil, fmt.Errorf("new coordinator client: %w", err) | |||
| } | |||
| defer stgglb.CoordinatorMQPool.Release(coorCli) | |||
| listResp, err := coorCli.GetObjectsByPath(coormq.ReqGetObjectsByPath(userID, pkgID, path, isPrefix)) | |||
| listResp, err := coorCli.GetObjectsByPath(coormq.ReqGetObjectsByPath(userID, pkgID, path, isPrefix, noRecursive)) | |||
| if err != nil { | |||
| return nil, fmt.Errorf("requsting to coodinator: %w", err) | |||
| return nil, nil, fmt.Errorf("requsting to coodinator: %w", err) | |||
| } | |||
| return listResp.Objects, nil | |||
| return listResp.CommonPrefixes, listResp.Objects, nil | |||
| } | |||
| func (svc *ObjectService) GetByIDs(userID cdssdk.UserID, objectIDs []cdssdk.ObjectID) ([]*cdssdk.Object, error) { | |||
| @@ -2,6 +2,7 @@ package db2 | |||
| import ( | |||
| "fmt" | |||
| "strings" | |||
| "time" | |||
| "gorm.io/gorm/clause" | |||
| @@ -38,6 +39,44 @@ func (db *ObjectDB) GetWithPathPrefix(ctx SQLContext, packageID cdssdk.PackageID | |||
| return ret, err | |||
| } | |||
| func (db *ObjectDB) GetCommonPrefixes(ctx SQLContext, packageID cdssdk.PackageID, pathPrefix string) ([]string, error) { | |||
| var ret []string | |||
| sepCnt := strings.Count(pathPrefix, cdssdk.ObjectPathSeparator) + 1 | |||
| prefixStatm := fmt.Sprintf("Substring_Index(Path, '%s', %d)", cdssdk.ObjectPathSeparator, sepCnt) | |||
| err := ctx.Table("Object").Select(prefixStatm+" as Prefix"). | |||
| Where("PackageID = ?", packageID). | |||
| Where("Path like ?", pathPrefix+"%"). | |||
| Where(prefixStatm + " <> Path"). | |||
| Group("Prefix").Find(&ret).Error | |||
| if err != nil { | |||
| return nil, err | |||
| } | |||
| for i := range ret { | |||
| ret[i] = ret[i] + cdssdk.ObjectPathSeparator | |||
| } | |||
| return ret, nil | |||
| } | |||
| func (db *ObjectDB) GetDirectChildren(ctx SQLContext, packageID cdssdk.PackageID, pathPrefix string) ([]cdssdk.Object, error) { | |||
| var ret []cdssdk.Object | |||
| sepCnt := strings.Count(pathPrefix, cdssdk.ObjectPathSeparator) + 1 | |||
| prefixStatm := fmt.Sprintf("Substring_Index(Path, '%s', %d)", cdssdk.ObjectPathSeparator, sepCnt) | |||
| err := ctx.Table("Object"). | |||
| Where("PackageID = ?", packageID). | |||
| Where("Path like ?", pathPrefix+"%"). | |||
| Where(prefixStatm + " = Path"). | |||
| Find(&ret).Error | |||
| return ret, err | |||
| } | |||
| func (db *ObjectDB) BatchTestObjectID(ctx SQLContext, objectIDs []cdssdk.ObjectID) (map[cdssdk.ObjectID]bool, error) { | |||
| if len(objectIDs) == 0 { | |||
| return make(map[cdssdk.ObjectID]bool), nil | |||
| @@ -67,27 +67,31 @@ var _ = Register(Service.GetObjectsByPath) | |||
| type GetObjectsByPath struct { | |||
| mq.MessageBodyBase | |||
| UserID cdssdk.UserID `json:"userID"` | |||
| PackageID cdssdk.PackageID `json:"packageID"` | |||
| Path string `json:"path"` | |||
| IsPrefix bool `json:"isPrefix"` | |||
| UserID cdssdk.UserID `json:"userID"` | |||
| PackageID cdssdk.PackageID `json:"packageID"` | |||
| Path string `json:"path"` | |||
| IsPrefix bool `json:"isPrefix"` | |||
| NoRecursive bool `json:"noRecursive"` | |||
| } | |||
| type GetObjectsByPathResp struct { | |||
| mq.MessageBodyBase | |||
| Objects []model.Object `json:"objects"` | |||
| CommonPrefixes []string `json:"commonPrefixes"` | |||
| Objects []model.Object `json:"objects"` | |||
| } | |||
| func ReqGetObjectsByPath(userID cdssdk.UserID, packageID cdssdk.PackageID, path string, isPrefix bool) *GetObjectsByPath { | |||
| func ReqGetObjectsByPath(userID cdssdk.UserID, packageID cdssdk.PackageID, path string, isPrefix bool, noRecursive bool) *GetObjectsByPath { | |||
| return &GetObjectsByPath{ | |||
| UserID: userID, | |||
| PackageID: packageID, | |||
| Path: path, | |||
| IsPrefix: isPrefix, | |||
| UserID: userID, | |||
| PackageID: packageID, | |||
| Path: path, | |||
| IsPrefix: isPrefix, | |||
| NoRecursive: noRecursive, | |||
| } | |||
| } | |||
| func RespGetObjectsByPath(objects []model.Object) *GetObjectsByPathResp { | |||
| func RespGetObjectsByPath(commonPrefixes []string, objects []model.Object) *GetObjectsByPathResp { | |||
| return &GetObjectsByPathResp{ | |||
| Objects: objects, | |||
| CommonPrefixes: commonPrefixes, | |||
| Objects: objects, | |||
| } | |||
| } | |||
| func (client *Client) GetObjectsByPath(msg *GetObjectsByPath) (*GetObjectsByPathResp, error) { | |||
| @@ -56,6 +56,7 @@ func (svc *Service) GetObjects(msg *coormq.GetObjects) (*coormq.GetObjectsResp, | |||
| } | |||
| func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetObjectsByPathResp, *mq.CodeMessage) { | |||
| var coms []string | |||
| var objs []cdssdk.Object | |||
| err := svc.db2.DoTx(func(tx db2.SQLContext) error { | |||
| var err error | |||
| @@ -65,16 +66,31 @@ func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetO | |||
| return fmt.Errorf("getting package by id: %w", err) | |||
| } | |||
| if msg.IsPrefix { | |||
| objs, err = svc.db2.Object().GetWithPathPrefix(tx, msg.PackageID, msg.Path) | |||
| if err != nil { | |||
| return fmt.Errorf("getting objects with prefix: %w", err) | |||
| } | |||
| } else { | |||
| if !msg.IsPrefix { | |||
| objs, err = svc.db2.Object().GetByPath(tx, msg.PackageID, msg.Path) | |||
| if err != nil { | |||
| return fmt.Errorf("getting object by path: %w", err) | |||
| } | |||
| return nil | |||
| } | |||
| if !msg.NoRecursive { | |||
| objs, err = svc.db2.Object().GetWithPathPrefix(tx, msg.PackageID, msg.Path) | |||
| if err != nil { | |||
| return fmt.Errorf("getting objects with prefix: %w", err) | |||
| } | |||
| return nil | |||
| } | |||
| coms, err = svc.db2.Object().GetCommonPrefixes(tx, msg.PackageID, msg.Path) | |||
| if err != nil { | |||
| return fmt.Errorf("getting common prefixes: %w", err) | |||
| } | |||
| objs, err = svc.db2.Object().GetDirectChildren(tx, msg.PackageID, msg.Path) | |||
| if err != nil { | |||
| return fmt.Errorf("getting direct children: %w", err) | |||
| } | |||
| return nil | |||
| @@ -84,7 +100,7 @@ func (svc *Service) GetObjectsByPath(msg *coormq.GetObjectsByPath) (*coormq.GetO | |||
| return nil, mq.Failed(errorcode.OperationFailed, "get objects with prefix failed") | |||
| } | |||
| return mq.ReplyOK(coormq.RespGetObjectsByPath(objs)) | |||
| return mq.ReplyOK(coormq.RespGetObjectsByPath(coms, objs)) | |||
| } | |||
| func (svc *Service) GetPackageObjects(msg *coormq.GetPackageObjects) (*coormq.GetPackageObjectsResp, *mq.CodeMessage) { | |||