From d61981f74f734097274ed4c7180db6fa85544748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E8=B5=AB=E7=84=B6?= Date: Mon, 23 Dec 2024 18:01:54 +0800 Subject: [PATCH 1/2] Return 409 when gc conflict --- include/seafile-error.h | 1 + server/repo-op.c | 2 +- server/upload-file.c | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/include/seafile-error.h b/include/seafile-error.h index 1564760f..43eb1aec 100644 --- a/include/seafile-error.h +++ b/include/seafile-error.h @@ -24,5 +24,6 @@ #define POST_FILE_ERR_QUOTA_FULL 519 #define SEAF_ERR_CONCURRENT_UPLOAD 520 #define SEAF_ERR_FILES_WITH_SAME_NAME 521 +#define SEAF_ERR_GC_CONFLICT 522 #endif diff --git a/server/repo-op.c b/server/repo-op.c index 6c9993ad..528f3f6c 100644 --- a/server/repo-op.c +++ b/server/repo-op.c @@ -579,7 +579,7 @@ gen_new_commit (const char *repo_id, if (check_gc && gc_conflict) { seaf_warning ("Head branch update for repo %s conflicts with GC.\n", repo->id); - g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GENERAL, "GC Conflict"); + g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_GC_CONFLICT, "GC Conflict"); ret = -1; goto out; } diff --git a/server/upload-file.c b/server/upload-file.c index c85fe439..5316c6e9 100755 --- a/server/upload-file.c +++ b/server/upload-file.c @@ -612,6 +612,9 @@ upload_api_cb(evhtp_request_t *req, void *arg) } else if (error->code == SEAF_ERR_FILES_WITH_SAME_NAME) { error_code = -1; send_error_reply (req, EVHTP_RES_BADREQ, "Too many files with same name.\n"); + } else if (error->code == SEAF_ERR_GC_CONFLICT) { + error_code = -1; + send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n"); } g_clear_error (&error); } @@ -811,6 +814,9 @@ upload_blks_api_cb(evhtp_request_t *req, void *arg) error_code = ERROR_BLOCK_MISSING; } else if (error->code == POST_FILE_ERR_QUOTA_FULL) { error_code = ERROR_QUOTA; + } else if (error->code == SEAF_ERR_GC_CONFLICT) { + error_code = -1; + send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n"); } g_clear_error (&error); } @@ -1243,6 +1249,9 @@ upload_ajax_cb(evhtp_request_t *req, void *arg) } else if (error->code == SEAF_ERR_FILES_WITH_SAME_NAME) { error_code = -1; send_error_reply (req, EVHTP_RES_BADREQ, "Too many files with same name.\n"); + } else if (error->code == SEAF_ERR_GC_CONFLICT) { + error_code = -1; + send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n"); } g_clear_error (&error); } @@ -1527,6 +1536,9 @@ update_blks_api_cb(evhtp_request_t *req, void *arg) error_code = ERROR_NOT_EXIST; } else if (error->code == POST_FILE_ERR_QUOTA_FULL) { error_code = ERROR_QUOTA; + } else if (error->code == SEAF_ERR_GC_CONFLICT) { + error_code = -1; + send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n"); } g_clear_error (&error); } @@ -1788,6 +1800,9 @@ update_ajax_cb(evhtp_request_t *req, void *arg) if (error) { if (g_strcmp0 (error->message, "file does not exist") == 0) { error_code = ERROR_NOT_EXIST; + } else if (error->code == SEAF_ERR_GC_CONFLICT) { + error_code = -1; + send_error_reply (req, EVHTP_RES_CONFLICT, "GC Conflict.\n"); } g_clear_error (&error); } From 4dd9130ba4199f048a188c947276e3b630f56353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E8=B5=AB=E7=84=B6?= Date: Mon, 23 Dec 2024 18:11:32 +0800 Subject: [PATCH 2/2] Go return 409 when gc conflict --- fileserver/fileop.go | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/fileserver/fileop.go b/fileserver/fileop.go index 8827e165..42d330f7 100644 --- a/fileserver/fileop.go +++ b/fileserver/fileop.go @@ -1745,8 +1745,12 @@ func postMultiFiles(rsp http.ResponseWriter, r *http.Request, repoID, parentDir, retStr, err := postFilesAndGenCommit(fileNames, repo.ID, user, canonPath, replace, ids, sizes, lastModify, gcID) if err != nil { - err := fmt.Errorf("failed to post files and gen commit: %v", err) - return &appError{err, "", http.StatusInternalServerError} + if errors.Is(err, ErrGCConflict) { + return &appError{nil, "GC Conflict.\n", http.StatusConflict} + } else { + err := fmt.Errorf("failed to post files and gen commit: %v", err) + return &appError{err, "", http.StatusInternalServerError} + } } _, ok := r.Form["ret-json"] @@ -1848,7 +1852,7 @@ retry: _, err = genNewCommit(repo, headCommit, rootID, user, buf, handleConncurrentUpdate, lastGCID, true) if err != nil { if err != ErrConflict { - err := fmt.Errorf("failed to generate new commit: %v", err) + err := fmt.Errorf("failed to generate new commit: %w", err) return "", err } retryCnt++ @@ -1907,7 +1911,10 @@ func getCanonPath(p string) string { return filepath.Join(formatPath) } -var ErrConflict = fmt.Errorf("Concurent upload conflict") +var ( + ErrConflict = errors.New("Concurent upload conflict") + ErrGCConflict = errors.New("GC Conflict") +) func genNewCommit(repo *repomgr.Repo, base *commitmgr.Commit, newRoot, user, desc string, handleConncurrentUpdate bool, lastGCID string, checkGC bool) (string, error) { var retryCnt int @@ -2094,7 +2101,7 @@ func updateBranch(repoID, originRepoID, newCommitID, oldCommitID, secondParentID if lastGCID != gcID.String { err = fmt.Errorf("Head branch update for repo %s conflicts with GC.", repoID) trans.Rollback() - return true, err + return true, ErrGCConflict } } @@ -3247,8 +3254,12 @@ func putFile(rsp http.ResponseWriter, r *http.Request, repoID, parentDir, user, desc := fmt.Sprintf("Modified \"%s\"", fileName) _, err = genNewCommit(repo, headCommit, rootID, user, desc, true, gcID, true) if err != nil { - err := fmt.Errorf("failed to generate new commit: %v", err) - return &appError{err, "", http.StatusInternalServerError} + if errors.Is(err, ErrGCConflict) { + return &appError{nil, "GC Conflict.\n", http.StatusConflict} + } else { + err := fmt.Errorf("failed to generate new commit: %v", err) + return &appError{err, "", http.StatusInternalServerError} + } } if isAjax { @@ -3485,8 +3496,12 @@ func commitFileBlocks(repoID, parentDir, fileName, blockIDsJSON, user string, fi desc := fmt.Sprintf("Added \"%s\"", fileName) _, err = genNewCommit(repo, headCommit, rootID, user, desc, true, gcID, true) if err != nil { - err := fmt.Errorf("failed to generate new commit: %v", err) - return "", &appError{err, "", http.StatusInternalServerError} + if errors.Is(err, ErrGCConflict) { + return "", &appError{nil, "GC Conflict.\n", http.StatusConflict} + } else { + err := fmt.Errorf("failed to generate new commit: %v", err) + return "", &appError{err, "", http.StatusInternalServerError} + } } return fileID, nil