From 3cf01ae30b690b3c6170b6a44b40e7fb6536e23f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=91=D0=BE=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 25 Feb 2026 16:12:25 +0200 Subject: [PATCH] added beta file locker; updates tests --- app/operator/file.go | 42 ++++++++++++++++++++++++++-------------- app/operator/operator.go | 2 ++ test/account_test.go | 24 +++++++++++------------ test/file_test.go | 14 +++++++------- test/image_test.go | 16 +++++++-------- 5 files changed, 57 insertions(+), 41 deletions(-) diff --git a/app/operator/file.go b/app/operator/file.go index d3d9d30..11691bc 100644 --- a/app/operator/file.go +++ b/app/operator/file.go @@ -51,12 +51,12 @@ func cleanFilepath(filename string) (string, error) { return filepath.Clean(filename), nil } -func (oper *Operator) FileInfo(ctx context.Context, operatorID string, param *FileInfoParams) (int, *FileInfoResult, error) { +func (oper *Operator) FileInfo(ctx context.Context, operatorID string, params *FileInfoParams) (int, *FileInfoResult, error) { var err error code := http.StatusOK res := &FileInfoResult{} - xfilepath, err := cleanFilepath(param.Filepath) + xfilepath, err := cleanFilepath(params.Filepath) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -65,6 +65,10 @@ func (oper *Operator) FileInfo(ctx context.Context, operatorID string, param *Fi filename := path.Base(xfilepath) collection := path.Dir(xfilepath) + resName := params.Filepath + oper.iLock.WaitAndLock(resName) + defer oper.iLock.Done(resName) + exist, fileDescr, err := oper.mdb.GetFileByCollectionName(ctx, collection, filename) if err != nil { code := http.StatusInternalServerError @@ -101,27 +105,31 @@ type PutFileResult struct{} const defaultContentType = "application/octet-stream" // TODO: checking catalog and file names conflict -func (oper *Operator) PutFile(ctx context.Context, operatorID string, param *PutFileParams) (int, *PutFileResult, error) { +func (oper *Operator) PutFile(ctx context.Context, operatorID string, params *PutFileParams) (int, *PutFileResult, error) { var err error res := &PutFileResult{} - if param.ContentSize == "" { + if params.ContentSize == "" { code := http.StatusLengthRequired err = fmt.Errorf("Required Content-Size header is empty") return code, res, err } - size, err := strconv.ParseInt(param.ContentSize, 10, 64) + size, err := strconv.ParseInt(params.ContentSize, 10, 64) if err != nil { code := http.StatusLengthRequired return code, res, err } - contentType := param.ContentType + contentType := params.ContentType if contentType == "" { contentType = defaultContentType } + resName := params.Filepath + oper.iLock.WaitAndLock(resName) + defer oper.iLock.Done(resName) + // TODO: convert file path to a unified and secure state - xfilepath, err := cleanFilepath(param.Filepath) + xfilepath, err := cleanFilepath(params.Filepath) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -129,7 +137,7 @@ func (oper *Operator) PutFile(ctx context.Context, operatorID string, param *Put filename := path.Base(xfilepath) collection := path.Dir(xfilepath) - tmpname, size, checksum, err := oper.store.WriteTempFile(param.Source) + tmpname, size, checksum, err := oper.store.WriteTempFile(params.Source) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -198,13 +206,11 @@ type GetFileResult struct { ContentUpdatedBy string } -func (oper *Operator) GetFile(ctx context.Context, operatorID string, param *GetFileParams) (int, *GetFileResult, error) { +func (oper *Operator) GetFile(ctx context.Context, operatorID string, params *GetFileParams) (int, *GetFileResult, error) { var err error res := &GetFileResult{} - // TODO: convert file path to a unified and secure state - - xfilepath, err := cleanFilepath(param.Filepath) + xfilepath, err := cleanFilepath(params.Filepath) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -212,6 +218,10 @@ func (oper *Operator) GetFile(ctx context.Context, operatorID string, param *Get filename := path.Base(xfilepath) collection := path.Dir(xfilepath) + resName := params.Filepath + oper.iLock.WaitAndLock(resName) + defer oper.iLock.Done(resName) + descrExists, fileDescr, err := oper.mdb.GetFileByCollectionName(ctx, collection, filename) if err != nil { code := http.StatusInternalServerError @@ -247,12 +257,12 @@ type DeleteFileParams struct { } type DeleteFileResult struct{} -func (oper *Operator) DeleteFile(ctx context.Context, operatorID string, param *DeleteFileParams) (int, *DeleteFileResult, error) { +func (oper *Operator) DeleteFile(ctx context.Context, operatorID string, params *DeleteFileParams) (int, *DeleteFileResult, error) { var err error res := &DeleteFileResult{} code := http.StatusOK - xfilepath, err := cleanFilepath(param.Filepath) + xfilepath, err := cleanFilepath(params.Filepath) if err != nil { code := http.StatusInternalServerError return code, res, err @@ -260,6 +270,10 @@ func (oper *Operator) DeleteFile(ctx context.Context, operatorID string, param * filename := path.Base(xfilepath) collection := path.Dir(xfilepath) + resName := params.Filepath + oper.iLock.WaitAndLock(resName) + defer oper.iLock.Done(resName) + descrExists, _, err := oper.mdb.GetFileByCollectionName(ctx, collection, filename) if err != nil { code = http.StatusInternalServerError diff --git a/app/operator/operator.go b/app/operator/operator.go index 70be449..34537ec 100644 --- a/app/operator/operator.go +++ b/app/operator/operator.go @@ -26,6 +26,7 @@ type Operator struct { store *storage.Storage logg *logger.Logger iLock *locker.Locker + fLock *locker.Locker } func NewOperator(params *OperatorParams) (*Operator, error) { @@ -35,6 +36,7 @@ func NewOperator(params *OperatorParams) (*Operator, error) { store: params.Store, } oper.iLock = locker.NewLocker() + oper.fLock = locker.NewLocker() oper.logg = logger.NewLoggerWithSubject("operator") return oper, err } diff --git a/test/account_test.go b/test/account_test.go index 9f486f1..6cda33a 100644 --- a/test/account_test.go +++ b/test/account_test.go @@ -70,7 +70,7 @@ func TestAccountLife(t *testing.T) { { // ServiceHello fmt.Printf("=== ServiceHello ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() helloRes, err := cli.ServiceHello(ctx, srvaddr+"/hello", 1*time.Second) require.NoError(t, err) @@ -84,7 +84,7 @@ func TestAccountLife(t *testing.T) { { // CreateAccount fmt.Printf("=== CreateAccount ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -95,7 +95,7 @@ func TestAccountLife(t *testing.T) { { // CreateGrant fmt.Printf("=== CreateGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -106,7 +106,7 @@ func TestAccountLife(t *testing.T) { { // UpdateGrant fmt.Printf("=== UpdateGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -116,7 +116,7 @@ func TestAccountLife(t *testing.T) { { // CreateGrant fmt.Printf("=== CreateGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -128,7 +128,7 @@ func TestAccountLife(t *testing.T) { { // GetGrant fmt.Printf("=== GetGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -143,7 +143,7 @@ func TestAccountLife(t *testing.T) { { // UpdateGrant fmt.Printf("=== UpdateGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -153,7 +153,7 @@ func TestAccountLife(t *testing.T) { { // GetGrant fmt.Printf("=== GetGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -168,7 +168,7 @@ func TestAccountLife(t *testing.T) { { // DeleteGrant fmt.Printf("=== DeleteGrant ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -178,7 +178,7 @@ func TestAccountLife(t *testing.T) { { // GetAccount fmt.Printf("=== GetAccount ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -191,7 +191,7 @@ func TestAccountLife(t *testing.T) { { // ListAccounts fmt.Printf("=== ListAccounts ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -209,7 +209,7 @@ func TestAccountLife(t *testing.T) { { // DeleteAccount fmt.Printf("=== DeleteAccount ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) diff --git a/test/file_test.go b/test/file_test.go index 81f9294..0da2bc8 100644 --- a/test/file_test.go +++ b/test/file_test.go @@ -72,7 +72,7 @@ func TestFileLife(t *testing.T) { { // ServiceHello fmt.Printf("=== ServiceHello ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() helloRes, err := cli.ServiceHello(ctx, srvaddr+"/hello", 1*time.Second) require.NoError(t, err) @@ -93,7 +93,7 @@ func TestFileLife(t *testing.T) { require.NoError(t, err) fmt.Printf("=== PutFile ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -103,7 +103,7 @@ func TestFileLife(t *testing.T) { { // FileInfo fmt.Printf("=== FileInfo ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -115,7 +115,7 @@ func TestFileLife(t *testing.T) { { // GetFile fmt.Printf("=== GetFile ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -129,7 +129,7 @@ func TestFileLife(t *testing.T) { { // ListFiles fmt.Printf("=== ListFiles ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -140,7 +140,7 @@ func TestFileLife(t *testing.T) { { // DeleteFile fmt.Printf("=== DeleteFile ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) @@ -150,7 +150,7 @@ func TestFileLife(t *testing.T) { { // !FileInfo fmt.Printf("=== FileInfo ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() ctx, _ = context.WithTimeout(ctx, 1*time.Second) diff --git a/test/image_test.go b/test/image_test.go index a628b15..78e9ca8 100644 --- a/test/image_test.go +++ b/test/image_test.go @@ -70,7 +70,7 @@ func TestImageLife(t *testing.T) { { // ServiceHello fmt.Printf("=== ServiceHello ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx := context.Background() helloRes, err := cli.ServiceHello(ctx, srvaddr+"/hello", 1*time.Second) require.NoError(t, err) @@ -79,26 +79,26 @@ func TestImageLife(t *testing.T) { { // PishImage fmt.Printf("=== PushImage ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) err := cli.PushImage(ctx, "test-oci.tar", srvaddr+"/foo/test:123") require.NoError(t, err) } { - // ImageInfo - fmt.Printf("=== ImageInfo ===\n") - cli := client.NewClient() + // ImageAmnifest + fmt.Printf("=== ImageManifest ===\n") + cli := client.NewClient(true) ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) - info, err := cli.ImageInfo(ctx, srvaddr+"/foo/test:123") + info, err := cli.ImageManifest(ctx, srvaddr+"/foo/test:123") require.NoError(t, err) infoYaml, err := yaml.Marshal(info) require.NoError(t, err) - fmt.Printf("imageInfo:\n%s\n", string(infoYaml)) + fmt.Printf("imagemanifest:\n%s\n", string(infoYaml)) } { // DeleteImage fmt.Printf("=== DeleteImage ===\n") - cli := client.NewClient() + cli := client.NewClient(true) ctx, _ := context.WithTimeout(context.Background(), 1*time.Second) err := cli.DeleteImage(ctx, srvaddr+"/foo/test:123") require.NoError(t, err)