Add: singleThreadLock for sqlite performance, and change Db.Tag method

This commit is contained in:
2021-12-15 02:53:41 +08:00
parent 1c14997b85
commit 97083114fb
8 changed files with 146 additions and 16 deletions

View File

@@ -54,7 +54,13 @@ func (api *API) HandleInsertTag(w http.ResponseWriter, r *http.Request) {
return
}
tag, err := api.Db.InsertTag(req)
tagID, err := api.Db.InsertTag(req)
if err != nil {
api.HandleError(w, r, err)
return
}
tag, err := api.Db.GetTag(tagID)
if err != nil {
api.HandleError(w, r, err)
return
@@ -114,16 +120,14 @@ func (api *API) HandleUpdateTag(w http.ResponseWriter, r *http.Request) {
api.HandleError(w, r, err)
return
}
tag, err := api.Db.UpdateTag(req)
if err != nil {
api.HandleError(w, r, err)
return
}
err = json.NewEncoder(w).Encode(tag)
err = api.Db.UpdateTag(req)
if err != nil {
api.HandleError(w, r, err)
return
}
api.HandleOK(w, r)
}
type DeleteTagRequest struct {

View File

@@ -2,6 +2,7 @@ package database
import (
"database/sql"
"sync"
_ "github.com/mattn/go-sqlite3"
)
@@ -9,6 +10,7 @@ import (
type Database struct {
sqlConn *sql.DB
stmt *Stmt
singleThreadLock *sync.Mutex
}
func NewDatabase(dbName string) (*Database, error) {
@@ -30,6 +32,7 @@ func NewDatabase(dbName string) (*Database, error) {
database := &Database{
sqlConn: sqlConn,
stmt: stmt,
singleThreadLock: &sync.Mutex{},
}
return database, nil

View File

@@ -8,6 +8,9 @@ import (
)
func (database *Database) GetRandomFiles(limit int64) ([]File, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getRandomFiles.Query(limit)
if err != nil {
return nil, err
@@ -28,6 +31,9 @@ func (database *Database) GetRandomFiles(limit int64) ([]File, error) {
}
func (database *Database) GetRandomFilesWithTag(tagID, limit int64) ([]File, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getRandomFilesWithTag.Query(tagID, limit)
if err != nil {
return nil, err
@@ -48,6 +54,9 @@ func (database *Database) GetRandomFilesWithTag(tagID, limit int64) ([]File, err
}
func (database *Database) GetFilesInFolder(folder_id int64, limit int64, offset int64) ([]File, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getFilesInFolder.Query(folder_id, limit, offset)
if err != nil {
return nil, err
@@ -69,6 +78,9 @@ func (database *Database) GetFilesInFolder(folder_id int64, limit int64, offset
}
func (database *Database) SearchFolders(foldername string, limit int64, offset int64) ([]Folder, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.searchFolders.Query("%"+foldername+"%", limit, offset)
if err != nil {
return nil, errors.New("Error searching folders at query " + err.Error())
@@ -92,6 +104,10 @@ func (database *Database) GetFile(id int64) (*File, error) {
file := &File{
Db: database,
}
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
err := database.stmt.getFile.QueryRow(id).Scan(&file.ID, &file.Folder_id, &file.Filename, &file.Foldername, &file.Filesize)
if err != nil {
return nil, err
@@ -178,6 +194,10 @@ func (database *Database) GetFolder(folderId int64) (*Folder, error) {
folder := &Folder{
Db: database,
}
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
err := database.stmt.getFolder.QueryRow(folderId).Scan(&folder.Folder)
if err != nil {
return nil, err
@@ -186,6 +206,9 @@ func (database *Database) GetFolder(folderId int64) (*Folder, error) {
}
func (database *Database) SearchFiles(filename string, limit int64, offset int64) ([]File, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.searchFiles.Query("%"+filename+"%", limit, offset)
if err != nil {
return nil, errors.New("Error searching files at query " + err.Error())
@@ -210,6 +233,10 @@ func (database *Database) SearchFiles(filename string, limit int64, offset int64
func (database *Database) FindFolder(folder string) (int64, error) {
var id int64
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
err := database.stmt.findFolder.QueryRow(folder).Scan(&id)
if err != nil {
return 0, err
@@ -219,6 +246,10 @@ func (database *Database) FindFolder(folder string) (int64, error) {
func (database *Database) FindFile(folderId int64, filename string) (int64, error) {
var id int64
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
err := database.stmt.findFile.QueryRow(folderId, filename).Scan(&id)
if err != nil {
return 0, err
@@ -227,6 +258,10 @@ func (database *Database) FindFile(folderId int64, filename string) (int64, erro
}
func (database *Database) InsertFolder(folder string) (int64, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.insertFolder.Exec(folder, filepath.Base(folder))
if err != nil {
return 0, err
@@ -239,6 +274,9 @@ func (database *Database) InsertFolder(folder string) (int64, error) {
}
func (database *Database) InsertFile(folderId int64, filename string, filesize int64) (int64, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.insertFile.Exec(folderId, filename, filesize)
if err != nil {
return 0, err
@@ -274,6 +312,9 @@ func (database *Database) Insert(path string, filesize int64) (int64, error) {
}
func (database *Database) UpdateFoldername(folderId int64, foldername string) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.updateFoldername.Exec(foldername, folderId)
if err != nil {
return err

View File

@@ -1,6 +1,9 @@
package database
func (database *Database) InsertFeedback(time int64, content string, userID int64, header string) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.insertFeedback.Exec(time, content, userID, header)
if err != nil {
return err
@@ -9,6 +12,9 @@ func (database *Database) InsertFeedback(time int64, content string, userID int6
}
func (database *Database) GetFeedbacks() ([]*Feedback, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getFeedbacks.Query()
if err != nil {
return nil, err
@@ -32,6 +38,9 @@ func (database *Database) GetFeedbacks() ([]*Feedback, error) {
}
func (database *Database) DeleteFeedback(id int64) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.deleteFeedback.Exec(id)
if err != nil {
return err

View File

@@ -1,6 +1,9 @@
package database
func (database *Database) InsertReview(review *Review) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.insertReview.Exec(
review.UserId,
review.FileId,
@@ -10,6 +13,9 @@ func (database *Database) InsertReview(review *Review) error {
}
func (database *Database) GetReviewsOnFile(fileId int64) ([]*Review, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getReviewsOnFile.Query(fileId)
if err != nil {
return nil, err
@@ -42,6 +48,9 @@ func (database *Database) GetReviewsOnFile(fileId int64) ([]*Review, error) {
}
func (database *Database) GetReview(reviewId int64) (*Review, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
row := database.stmt.getReview.QueryRow(reviewId)
review := &Review{}
@@ -60,6 +69,9 @@ func (database *Database) GetReview(reviewId int64) (*Review, error) {
}
func (database *Database) UpdateReview(review *Review) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.updateReview.Exec(
review.Content,
review.UpdatedAt,
@@ -68,11 +80,17 @@ func (database *Database) UpdateReview(review *Review) error {
}
func (database *Database) DeleteReview(reviewId int64) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.deleteReview.Exec(reviewId)
return err
}
func (database *Database) GetReviewsByUser(userId int64) ([]*Review, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getReviewsByUser.Query(userId)
if err != nil {
return nil, err

View File

@@ -2,19 +2,26 @@ package database
import "errors"
func (database *Database) InsertTag(tag *Tag) (*Tag, error) {
func (database *Database) InsertTag(tag *Tag) (int64, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.insertTag.Exec(tag.Name, tag.Description, tag.CreatedByUserId)
if err != nil {
return nil, err
return 0, err
}
id, err := result.LastInsertId()
if err != nil {
return nil, err
return 0, err
}
return database.GetTag(id)
return id, nil
}
func (database *Database) GetTag(id int64) (*Tag, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
tag := &Tag{CreatedByUser: &User{}}
err := database.stmt.getTag.QueryRow(id).Scan(
&tag.ID, &tag.Name, &tag.Description,
@@ -27,6 +34,10 @@ func (database *Database) GetTag(id int64) (*Tag, error) {
func (database *Database) GetTags() ([]*Tag, error) {
tags := []*Tag{}
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getTags.Query()
if err != nil {
return nil, err
@@ -46,23 +57,30 @@ func (database *Database) GetTags() ([]*Tag, error) {
return tags, nil
}
func (database *Database) UpdateTag(tag *Tag) (*Tag, error) {
func (database *Database) UpdateTag(tag *Tag) (error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.updateTag.Exec(tag.Name, tag.Description, tag.ID)
if err != nil {
return nil, err
return err
}
rowsAffected, err := result.RowsAffected()
if err != nil {
return nil, err
return err
}
if rowsAffected == 0 {
return nil, errors.New("No rows affected")
return errors.New("No rows affected")
}
return database.GetTag(tag.ID)
return nil
}
// delete tag and all its references in file_has_tag
func (database *Database) DeleteTag(id int64) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
// begin transaction
tx, err := database.sqlConn.Begin()
if err != nil {

View File

@@ -1,6 +1,9 @@
package database
func (database *Database) PutTagOnFile(tagID, fileID, userID int64) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.putTagOnFile.Exec(tagID, fileID, userID)
if err != nil {
return err
@@ -12,6 +15,9 @@ func (database *Database) PutTagOnFile(tagID, fileID, userID int64) error {
}
func (database *Database) GetTagsOnFile(fileID int64) ([]*Tag, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getTagsOnFile.Query(fileID)
if err != nil {
return nil, err
@@ -31,6 +37,9 @@ func (database *Database) GetTagsOnFile(fileID int64) ([]*Tag, error) {
}
func (database *Database) DeleteTagOnFile(tagID, fileID int64) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
result, err := database.stmt.deleteTagOnFile.Exec(tagID, fileID)
if err != nil {
return err

View File

@@ -1,6 +1,9 @@
package database
func (database *Database) Login(username string, password string) (*User, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
user := &User{}
// get user from database
@@ -12,6 +15,9 @@ func (database *Database) Login(username string, password string) (*User, error)
}
func (database *Database) LoginAsAnonymous() (*User, error) {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
user := &User{}
// get user from database
@@ -38,6 +44,9 @@ func (database *Database) Register(username string, password string, usertype in
active = true
}
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err = database.stmt.insertUser.Exec(username, password, usertype, active, 0)
if err != nil {
return err
@@ -48,6 +57,9 @@ func (database *Database) Register(username string, password string, usertype in
func (database *Database) GetUserById(id int64) (*User, error) {
user := &User{}
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
// get user from database
err := database.stmt.getUserById.QueryRow(id).Scan(&user.ID, &user.Username, &user.Role, &user.Active, &user.AvatarId)
if err != nil {
@@ -58,6 +70,10 @@ func (database *Database) GetUserById(id int64) (*User, error) {
func (database *Database) CountAdmin() (int64, error) {
var count int64
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
err := database.stmt.countAdmin.QueryRow().Scan(&count)
if err != nil {
return 0, err
@@ -68,6 +84,9 @@ func (database *Database) CountAdmin() (int64, error) {
func (database *Database) GetUsers() ([]*User, error) {
users := make([]*User, 0)
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
rows, err := database.stmt.getUsers.Query()
if err != nil {
return nil, err
@@ -86,6 +105,9 @@ func (database *Database) GetUsers() ([]*User, error) {
}
func (database *Database) UpdateUserActive(id int64, active bool) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.updateUserActive.Exec(active, id)
if err != nil {
return err
@@ -94,6 +116,9 @@ func (database *Database) UpdateUserActive(id int64, active bool) error {
}
func (database *Database) UpdateUsername(id int64, username string) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.updateUsername.Exec(username, id)
if err != nil {
return err
@@ -102,6 +127,9 @@ func (database *Database) UpdateUsername(id int64, username string) error {
}
func (database *Database) UpdateUserPassword(id int64, password string) error {
database.singleThreadLock.Lock()
defer database.singleThreadLock.Unlock()
_, err := database.stmt.updateUserPassword.Exec(password, id)
if err != nil {
return err