diff --git a/fileserver/fileop.go b/fileserver/fileop.go index 964d0a9..777a8e2 100644 --- a/fileserver/fileop.go +++ b/fileserver/fileop.go @@ -1852,12 +1852,14 @@ func updateBranch(repoID, newCommitID, oldCommitID, secondParentID string) error sqlStr = "SELECT commit_id FROM Branch WHERE name = ? AND repo_id = ?" } - trans, err := seafileDB.Begin() + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + trans, err := seafileDB.BeginTx(ctx, nil) if err != nil { err := fmt.Errorf("failed to start transaction: %v", err) return err } - row := trans.QueryRow(sqlStr, name, repoID) + row := trans.QueryRowContext(ctx, sqlStr, name, repoID) if err := row.Scan(&commitID); err != nil { if err != sql.ErrNoRows { trans.Rollback() @@ -1871,7 +1873,7 @@ func updateBranch(repoID, newCommitID, oldCommitID, secondParentID string) error } sqlStr = "UPDATE Branch SET commit_id = ? WHERE name = ? AND repo_id = ?" - _, err = trans.Exec(sqlStr, newCommitID, name, repoID) + _, err = trans.ExecContext(ctx, sqlStr, newCommitID, name, repoID) if err != nil { trans.Rollback() return err diff --git a/fileserver/option/option.go b/fileserver/option/option.go index b73f647..76be20f 100644 --- a/fileserver/option/option.go +++ b/fileserver/option/option.go @@ -6,6 +6,7 @@ import ( "path/filepath" "strconv" "strings" + "time" "gopkg.in/ini.v1" ) @@ -60,6 +61,9 @@ var ( // Go log level LogLevel string + + // DB default timeout + DBOpTimeout time.Duration ) func initDefaultOptions() { @@ -73,6 +77,7 @@ func initDefaultOptions() { DefaultQuota = InfiniteQuota FsCacheLimit = 2 << 30 FsIdListRequestTimeout = -1 + DBOpTimeout = 60 * time.Second } func LoadFileServerOptions(centralDir string) { diff --git a/fileserver/quota.go b/fileserver/quota.go index b82c1c6..2366eaa 100644 --- a/fileserver/quota.go +++ b/fileserver/quota.go @@ -1,6 +1,7 @@ package main import ( + "context" "database/sql" "fmt" @@ -63,7 +64,9 @@ func checkQuota(repoID string, delta int64) (int, error) { func getUserQuota(user string) (int64, error) { var quota int64 sqlStr := "SELECT quota FROM UserQuota WHERE user=?" - row := seafileDB.QueryRow(sqlStr, user) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, user) if err := row.Scan("a); err != nil { if err != sql.ErrNoRows { return -1, err @@ -85,7 +88,9 @@ func getUserUsage(user string) (int64, error) { "owner_id=? AND o.repo_id=RepoSize.repo_id " + "AND v.repo_id IS NULL" - row := seafileDB.QueryRow(sqlStr, user) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, user) if err := row.Scan(&usage); err != nil { if err != sql.ErrNoRows { return -1, err diff --git a/fileserver/repomgr/repomgr.go b/fileserver/repomgr/repomgr.go index 9f625bf..ad642fd 100644 --- a/fileserver/repomgr/repomgr.go +++ b/fileserver/repomgr/repomgr.go @@ -2,6 +2,7 @@ package repomgr import ( + "context" "database/sql" "fmt" "time" @@ -9,6 +10,7 @@ import ( // Change to non-blank imports when use _ "github.com/haiwen/seafile-server/fileserver/blockmgr" "github.com/haiwen/seafile-server/fileserver/commitmgr" + "github.com/haiwen/seafile-server/fileserver/option" log "github.com/sirupsen/logrus" ) @@ -70,14 +72,16 @@ func Get(id string) *Repo { `LEFT JOIN VirtualRepo v ON r.repo_id = v.repo_id ` + `WHERE r.repo_id = ? AND b.name = 'master'` - stmt, err := seafileDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + stmt, err := seafileDB.PrepareContext(ctx, query) if err != nil { log.Printf("failed to prepare sql : %s :%v", query, err) return nil } defer stmt.Close() - rows, err := stmt.Query(id) + rows, err := stmt.QueryContext(ctx, id) if err != nil { log.Printf("failed to query sql : %v", err) return nil @@ -198,14 +202,16 @@ func GetEx(id string) *Repo { `LEFT JOIN VirtualRepo v ON r.repo_id = v.repo_id ` + `WHERE r.repo_id = ? AND b.name = 'master'` - stmt, err := seafileDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + stmt, err := seafileDB.PrepareContext(ctx, query) if err != nil { log.Printf("failed to prepare sql : %s :%v", query, err) return nil } defer stmt.Close() - rows, err := stmt.Query(id) + rows, err := stmt.QueryContext(ctx, id) if err != nil { log.Printf("failed to query sql : %v", err) return nil @@ -291,7 +297,9 @@ func GetVirtualRepoInfo(repoID string) (*VRepoInfo, error) { sqlStr := "SELECT repo_id, origin_repo, path, base_commit FROM VirtualRepo WHERE repo_id = ?" vRepoInfo := new(VRepoInfo) - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&vRepoInfo.RepoID, &vRepoInfo.OriginRepoID, &vRepoInfo.Path, &vRepoInfo.BaseCommitID); err != nil { if err != sql.ErrNoRows { return nil, err @@ -306,7 +314,9 @@ func GetVirtualRepoInfoByOrigin(originRepo string) ([]*VRepoInfo, error) { sqlStr := "SELECT repo_id, origin_repo, path, base_commit " + "FROM VirtualRepo WHERE origin_repo=?" var vRepos []*VRepoInfo - row, err := seafileDB.Query(sqlStr, originRepo) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row, err := seafileDB.QueryContext(ctx, sqlStr, originRepo) if err != nil { return nil, err } @@ -329,7 +339,9 @@ func GetEmailByToken(repoID string, token string) (string, error) { var email string sqlStr := "SELECT email FROM RepoUserToken WHERE repo_id = ? AND token = ?" - row := seafileDB.QueryRow(sqlStr, repoID, token) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID, token) if err := row.Scan(&email); err != nil { if err != sql.ErrNoRows { return email, err @@ -343,7 +355,9 @@ func GetRepoStatus(repoID string) (int, error) { var status int sqlStr := "SELECT status FROM RepoInfo WHERE repo_id=?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&status); err != nil { if err != sql.ErrNoRows { return status, err @@ -357,7 +371,9 @@ func TokenPeerInfoExists(token string) (bool, error) { var exists string sqlStr := "SELECT token FROM RepoTokenPeerInfo WHERE token=?" - row := seafileDB.QueryRow(sqlStr, token) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, token) if err := row.Scan(&exists); err != nil { if err != sql.ErrNoRows { return false, err @@ -372,7 +388,9 @@ func AddTokenPeerInfo(token, peerID, peerIP, peerName, clientVer string, syncTim sqlStr := "INSERT INTO RepoTokenPeerInfo (token, peer_id, peer_ip, peer_name, sync_time, client_ver)" + "VALUES (?, ?, ?, ?, ?, ?)" - if _, err := seafileDB.Exec(sqlStr, token, peerID, peerIP, peerName, syncTime, clientVer); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + if _, err := seafileDB.ExecContext(ctx, sqlStr, token, peerID, peerIP, peerName, syncTime, clientVer); err != nil { return err } return nil @@ -382,7 +400,9 @@ func AddTokenPeerInfo(token, peerID, peerIP, peerName, clientVer string, syncTim func UpdateTokenPeerInfo(token, peerID, clientVer string, syncTime int64) error { sqlStr := "UPDATE RepoTokenPeerInfo SET " + "peer_ip=?, sync_time=?, client_ver=? WHERE token=?" - if _, err := seafileDB.Exec(sqlStr, peerID, syncTime, clientVer, token); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + if _, err := seafileDB.ExecContext(ctx, sqlStr, peerID, syncTime, clientVer, token); err != nil { return err } return nil @@ -401,14 +421,16 @@ func GetUploadTmpFile(repoID, filePath string) (string, error) { var tmpFile string sqlStr := "SELECT tmp_file_path FROM WebUploadTempFiles WHERE repo_id = ? AND file_path = ?" - row := seafileDB.QueryRow(sqlStr, repoID, filePath) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID, filePath) if err := row.Scan(&tmpFile); err != nil { if err != sql.ErrNoRows { return "", err } } if tmpFile == "" { - row := seafileDB.QueryRow(sqlStr, repoID, filePathNoSlash) + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID, filePathNoSlash) if err := row.Scan(&tmpFile); err != nil { if err != sql.ErrNoRows { return "", err @@ -427,7 +449,9 @@ func AddUploadTmpFile(repoID, filePath, tmpFile string) error { sqlStr := "INSERT INTO WebUploadTempFiles (repo_id, file_path, tmp_file_path) VALUES (?, ?, ?)" - _, err := seafileDB.Exec(sqlStr, repoID, filePath, tmpFile) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID, filePath, tmpFile) if err != nil { return err } @@ -447,7 +471,9 @@ func DelUploadTmpFile(repoID, filePath string) error { sqlStr := "DELETE FROM WebUploadTempFiles WHERE repo_id = ? AND file_path IN (?, ?)" - _, err := seafileDB.Exec(sqlStr, repoID, filePath, filePathNoSlash) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID, filePath, filePathNoSlash) if err != nil { return err } @@ -460,7 +486,9 @@ func setRepoCommitToDb(repoID, repoName string, updateTime int64, version int, i var encrypted int sqlStr := "SELECT 1 FROM RepoInfo WHERE repo_id=?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&exists); err != nil { if err != sql.ErrNoRows { return err @@ -477,13 +505,13 @@ func setRepoCommitToDb(repoID, repoName string, updateTime int64, version int, i if exists == 1 { sqlStr := "UPDATE RepoInfo SET name=?, update_time=?, version=?, is_encrypted=?, " + "last_modifier=? WHERE repo_id=?" - if _, err := seafileDB.Exec(sqlStr, repoName, updateTime, version, encrypted, lastModifier, repoID); err != nil { + if _, err := seafileDB.ExecContext(ctx, sqlStr, repoName, updateTime, version, encrypted, lastModifier, repoID); err != nil { return err } } else { sqlStr := "INSERT INTO RepoInfo (repo_id, name, update_time, version, is_encrypted, last_modifier) " + "VALUES (?, ?, ?, ?, ?, ?)" - if _, err := seafileDB.Exec(sqlStr, repoID, repoName, updateTime, version, encrypted, lastModifier); err != nil { + if _, err := seafileDB.ExecContext(ctx, sqlStr, repoID, repoName, updateTime, version, encrypted, lastModifier); err != nil { return err } } @@ -494,7 +522,9 @@ func setRepoCommitToDb(repoID, repoName string, updateTime int64, version int, i // SetVirtualRepoBaseCommitPath updates the table of VirtualRepo. func SetVirtualRepoBaseCommitPath(repoID, baseCommitID, newPath string) error { sqlStr := "UPDATE VirtualRepo SET base_commit=?, path=? WHERE repo_id=?" - if _, err := seafileDB.Exec(sqlStr, baseCommitID, newPath, repoID); err != nil { + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + if _, err := seafileDB.ExecContext(ctx, sqlStr, baseCommitID, newPath, repoID); err != nil { return err } return nil @@ -506,7 +536,9 @@ func GetVirtualRepoIDsByOrigin(repoID string) ([]string, error) { var id string var ids []string - row, err := seafileDB.Query(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row, err := seafileDB.QueryContext(ctx, sqlStr, repoID) if err != nil { return nil, err } @@ -531,7 +563,9 @@ func DelVirtualRepo(repoID string, cloudMode bool) error { return err } sqlStr := "DELETE FROM VirtualRepo WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } @@ -541,12 +575,14 @@ func DelVirtualRepo(repoID string, cloudMode bool) error { func removeVirtualRepoOndisk(repoID string, cloudMode bool) error { sqlStr := "DELETE FROM Repo WHERE repo_id = ?" - _, err := seafileDB.Exec(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } sqlStr = "SELECT name, repo_id, commit_id FROM Branch WHERE repo_id=?" - rows, err := seafileDB.Query(sqlStr, repoID) + rows, err := seafileDB.QueryContext(ctx, sqlStr, repoID) if err != nil { return err } @@ -559,63 +595,63 @@ func removeVirtualRepoOndisk(repoID string, cloudMode bool) error { } } sqlStr := "DELETE FROM RepoHead WHERE branch_name = ? AND repo_id = ?" - _, err := seafileDB.Exec(sqlStr, name, id) + _, err := seafileDB.ExecContext(ctx, sqlStr, name, id) if err != nil { return err } sqlStr = "DELETE FROM Branch WHERE name=? AND repo_id=?" - _, err = seafileDB.Exec(sqlStr, name, id) + _, err = seafileDB.ExecContext(ctx, sqlStr, name, id) if err != nil { return err } } sqlStr = "DELETE FROM RepoOwner WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } sqlStr = "DELETE FROM SharedRepo WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } sqlStr = "DELETE FROM RepoGroup WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } if !cloudMode { sqlStr = "DELETE FROM InnerPubRepo WHERE repo_id = ?" - _, err := seafileDB.Exec(sqlStr, repoID) + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } } sqlStr = "DELETE FROM RepoUserToken WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } sqlStr = "DELETE FROM RepoValidSince WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } sqlStr = "DELETE FROM RepoSize WHERE repo_id = ?" - _, err = seafileDB.Exec(sqlStr, repoID) + _, err = seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } var exists int sqlStr = "SELECT 1 FROM GarbageRepos WHERE repo_id=?" - row := seafileDB.QueryRow(sqlStr, repoID) + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&exists); err != nil { if err != sql.ErrNoRows { return err @@ -623,13 +659,13 @@ func removeVirtualRepoOndisk(repoID string, cloudMode bool) error { } if exists == 0 { sqlStr = "INSERT INTO GarbageRepos (repo_id) VALUES (?)" - _, err := seafileDB.Exec(sqlStr, repoID) + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } } else { sqlStr = "REPLACE INTO GarbageRepos (repo_id) VALUES (?)" - _, err := seafileDB.Exec(sqlStr, repoID) + _, err := seafileDB.ExecContext(ctx, sqlStr, repoID) if err != nil { return err } @@ -643,7 +679,9 @@ func IsVirtualRepo(repoID string) (bool, error) { var exists int sqlStr := "SELECT 1 FROM VirtualRepo WHERE repo_id = ?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&exists); err != nil { if err != sql.ErrNoRows { return false, err @@ -659,7 +697,9 @@ func GetRepoOwner(repoID string) (string, error) { var owner string sqlStr := "SELECT owner_id FROM RepoOwner WHERE repo_id=?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&owner); err != nil { if err != sql.ErrNoRows { return "", err diff --git a/fileserver/share/share.go b/fileserver/share/share.go index 56cefc7..4678a46 100644 --- a/fileserver/share/share.go +++ b/fileserver/share/share.go @@ -3,12 +3,14 @@ package share import ( + "context" "database/sql" "fmt" "path/filepath" "strconv" "strings" + "github.com/haiwen/seafile-server/fileserver/option" "github.com/haiwen/seafile-server/fileserver/repomgr" log "github.com/sirupsen/logrus" ) @@ -70,7 +72,9 @@ func checkVirtualRepoPerm(repoID, originRepoID, user, vPath string) string { } func getUserGroups(sqlStr string, args ...interface{}) ([]group, error) { - rows, err := ccnetDB.Query(sqlStr, args...) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := ccnetDB.QueryContext(ctx, sqlStr, args...) if err != nil { return nil, err } @@ -148,7 +152,9 @@ func getGroupsByUser(userName string, returnAncestors bool) ([]group, error) { func getGroupPaths(sqlStr string) (string, error) { var paths string - rows, err := ccnetDB.Query(sqlStr) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := ccnetDB.QueryContext(ctx, sqlStr) if err != nil { return paths, err } @@ -190,7 +196,9 @@ func checkGroupPermByUser(repoID string, userName string) (string, error) { } sqlBuilder.WriteString(")") - rows, err := seafileDB.Query(sqlBuilder.String(), repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := seafileDB.QueryContext(ctx, sqlBuilder.String(), repoID) if err != nil { err := fmt.Errorf("Failed to get group permission by user %s: %v", userName, err) return "", err @@ -220,7 +228,9 @@ func checkGroupPermByUser(repoID string, userName string) (string, error) { func checkSharedRepoPerm(repoID string, email string) (string, error) { sqlStr := "SELECT permission FROM SharedRepo WHERE repo_id=? AND to_email=?" - row := seafileDB.QueryRow(sqlStr, repoID, email) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID, email) var perm string if err := row.Scan(&perm); err != nil { @@ -234,7 +244,9 @@ func checkSharedRepoPerm(repoID string, email string) (string, error) { func checkInnerPubRepoPerm(repoID string) (string, error) { sqlStr := "SELECT permission FROM InnerPubRepo WHERE repo_id=?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) var perm string if err := row.Scan(&perm); err != nil { @@ -286,7 +298,9 @@ func getSharedDirsToUser(originRepoID string, toEmail string) (map[string]string sqlStr := "SELECT v.path, s.permission FROM SharedRepo s, VirtualRepo v WHERE " + "s.repo_id = v.repo_id AND s.to_email = ? AND v.origin_repo = ?" - rows, err := seafileDB.Query(sqlStr, toEmail, originRepoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := seafileDB.QueryContext(ctx, sqlStr, toEmail, originRepoID) if err != nil { err := fmt.Errorf("Failed to get shared directories by user %s: %v", toEmail, err) return nil, err @@ -342,7 +356,9 @@ func getSharedDirsToGroup(originRepoID string, groups []group) (map[string]strin "s.repo_id = v.repo_id AND v.origin_repo = ? "+ "AND s.group_id in (%s)", groupIDs) - rows, err := seafileDB.Query(sqlStr, originRepoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := seafileDB.QueryContext(ctx, sqlStr, originRepoID) if err != nil { err := fmt.Errorf("Failed to get shared directories: %v", err) return nil, err @@ -428,13 +444,15 @@ func GetReposByOwner(email string) ([]*SharedRepo, error) { "v.repo_id IS NULL " + "ORDER BY i.update_time DESC, o.repo_id" - stmt, err := seafileDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + stmt, err := seafileDB.PrepareContext(ctx, query) if err != nil { return nil, err } defer stmt.Close() - rows, err := stmt.Query(email) + rows, err := stmt.QueryContext(ctx, email) if err != nil { return nil, err @@ -483,13 +501,15 @@ func ListInnerPubRepos() ([]*SharedRepo, error) { "WHERE InnerPubRepo.repo_id=RepoOwner.repo_id AND " + "InnerPubRepo.repo_id = Branch.repo_id AND Branch.name = 'master'" - stmt, err := seafileDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + stmt, err := seafileDB.PrepareContext(ctx, query) if err != nil { return nil, err } defer stmt.Close() - rows, err := stmt.Query() + rows, err := stmt.QueryContext(ctx) if err != nil { return nil, err } @@ -552,14 +572,16 @@ func ListShareRepos(email, columnType string) ([]*SharedRepo, error) { return nil, err } - stmt, err := seafileDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + stmt, err := seafileDB.PrepareContext(ctx, query) if err != nil { return nil, err } defer stmt.Close() - rows, err := stmt.Query(email) + rows, err := stmt.QueryContext(ctx, email) if err != nil { return nil, err } @@ -632,7 +654,9 @@ func GetGroupReposByUser(user string, orgID int) ([]*SharedRepo, error) { } sqlBuilder.WriteString(" ) ORDER BY group_id") - rows, err := seafileDB.Query(sqlBuilder.String()) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := seafileDB.QueryContext(ctx, sqlBuilder.String()) if err != nil { return nil, err } diff --git a/fileserver/size_sched.go b/fileserver/size_sched.go index 430ea64..1b47ef4 100644 --- a/fileserver/size_sched.go +++ b/fileserver/size_sched.go @@ -1,6 +1,7 @@ package main import ( + "context" "fmt" "path/filepath" @@ -11,6 +12,7 @@ import ( "github.com/haiwen/seafile-server/fileserver/commitmgr" "github.com/haiwen/seafile-server/fileserver/diff" "github.com/haiwen/seafile-server/fileserver/fsmgr" + "github.com/haiwen/seafile-server/fileserver/option" "github.com/haiwen/seafile-server/fileserver/repomgr" "github.com/haiwen/seafile-server/fileserver/workerpool" log "github.com/sirupsen/logrus" @@ -121,7 +123,9 @@ func computeRepoSize(args ...interface{}) error { } func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount int64) error { - trans, err := seafileDB.Begin() + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + trans, err := seafileDB.BeginTx(ctx, nil) if err != nil { err := fmt.Errorf("failed to start transaction: %v", err) return err @@ -130,7 +134,7 @@ func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount int64) er var headID string sqlStr := "SELECT head_id FROM RepoSize WHERE repo_id=?" - row := trans.QueryRow(sqlStr, repoID) + row := trans.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&headID); err != nil { if err != sql.ErrNoRows { trans.Rollback() @@ -140,14 +144,14 @@ func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount int64) er if headID == "" { sqlStr := "INSERT INTO RepoSize (repo_id, size, head_id) VALUES (?, ?, ?)" - _, err = trans.Exec(sqlStr, repoID, size, newHeadID) + _, err = trans.ExecContext(ctx, sqlStr, repoID, size, newHeadID) if err != nil { trans.Rollback() return err } } else { sqlStr = "UPDATE RepoSize SET size = ?, head_id = ? WHERE repo_id = ?" - _, err = trans.Exec(sqlStr, size, newHeadID, repoID) + _, err = trans.ExecContext(ctx, sqlStr, size, newHeadID, repoID) if err != nil { trans.Rollback() return err @@ -156,7 +160,7 @@ func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount int64) er var exist int sqlStr = "SELECT 1 FROM RepoFileCount WHERE repo_id=?" - row = trans.QueryRow(sqlStr, repoID) + row = trans.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&exist); err != nil { if err != sql.ErrNoRows { trans.Rollback() @@ -166,14 +170,14 @@ func setRepoSizeAndFileCount(repoID, newHeadID string, size, fileCount int64) er if exist != 0 { sqlStr := "UPDATE RepoFileCount SET file_count=? WHERE repo_id=?" - _, err = trans.Exec(sqlStr, fileCount, repoID) + _, err = trans.ExecContext(ctx, sqlStr, fileCount, repoID) if err != nil { trans.Rollback() return err } } else { sqlStr := "INSERT INTO RepoFileCount (repo_id,file_count) VALUES (?,?)" - _, err = trans.Exec(sqlStr, repoID, fileCount) + _, err = trans.ExecContext(ctx, sqlStr, repoID, fileCount) if err != nil { trans.Rollback() return err @@ -197,7 +201,9 @@ func getOldRepoInfo(repoID string) (*RepoInfo, error) { "s.repo_id=f.repo_id WHERE s.repo_id=?" repoInfo := new(RepoInfo) - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&repoInfo.HeadID, &repoInfo.Size, &repoInfo.FileCount); err != nil { if err != sql.ErrNoRows { return nil, err diff --git a/fileserver/sync_api.go b/fileserver/sync_api.go index 57417da..bccb6d2 100644 --- a/fileserver/sync_api.go +++ b/fileserver/sync_api.go @@ -654,7 +654,9 @@ func headCommitsMultiCB(rsp http.ResponseWriter, r *http.Request) *appError { "repo_id IN (%s) LOCK IN SHARE MODE", repoIDs.String()) - rows, err := seafileDB.Query(sqlStr) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + rows, err := seafileDB.QueryContext(ctx, sqlStr) if err != nil { err := fmt.Errorf("Failed to get commit id: %v", err) return &appError{err, "", http.StatusInternalServerError} @@ -907,7 +909,9 @@ func getRepoStoreID(repoID string) (string, error) { var vInfo virtualRepoInfo var rID, originRepoID sql.NullString sqlStr := "SELECT repo_id, origin_repo FROM VirtualRepo where repo_id = ?" - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&rID, &originRepoID); err != nil { if err == sql.ErrNoRows { vInfo.storeID = repoID @@ -1077,7 +1081,9 @@ func getHeadCommit(rsp http.ResponseWriter, r *http.Request) *appError { repoID := vars["repoid"] sqlStr := "SELECT EXISTS(SELECT 1 FROM Repo WHERE repo_id=?)" var exists bool - row := seafileDB.QueryRow(sqlStr, repoID) + ctx, cancel := context.WithTimeout(context.Background(), option.DBOpTimeout) + defer cancel() + row := seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&exists); err != nil { if err != sql.ErrNoRows { log.Printf("DB error when check repo %s existence: %v", repoID, err) @@ -1097,7 +1103,7 @@ func getHeadCommit(rsp http.ResponseWriter, r *http.Request) *appError { var commitID string sqlStr = "SELECT commit_id FROM Branch WHERE name='master' AND repo_id=?" - row = seafileDB.QueryRow(sqlStr, repoID) + row = seafileDB.QueryRowContext(ctx, sqlStr, repoID) if err := row.Scan(&commitID); err != nil { if err != sql.ErrNoRows { diff --git a/notification-server/event.go b/notification-server/event.go index a77465c..83da12d 100644 --- a/notification-server/event.go +++ b/notification-server/event.go @@ -1,9 +1,11 @@ package main import ( + "context" "encoding/json" "reflect" "runtime/debug" + "time" log "github.com/sirupsen/logrus" ) @@ -114,14 +116,16 @@ func Notify(msg *Message) { func getGroupMembers(group int) map[string]struct{} { query := `SELECT user_name FROM GroupUser WHERE group_id = ?` - stmt, err := ccnetDB.Prepare(query) + ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) + defer cancel() + stmt, err := ccnetDB.PrepareContext(ctx, query) if err != nil { log.Printf("failed to prepare sql: %s:%v", query, err) return nil } defer stmt.Close() - rows, err := stmt.Query(group) + rows, err := stmt.QueryContext(ctx, group) if err != nil { log.Printf("failed to query sql: %v", err) return nil