Changing password and use cache when uploading
This commit is contained in:
133
upload/upload.go
Normal file
133
upload/upload.go
Normal file
@@ -0,0 +1,133 @@
|
||||
package upload
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/google/uuid"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"opensavecloudserver/config"
|
||||
"opensavecloudserver/database"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
locks map[int]GameUploadToken
|
||||
mu sync.Mutex
|
||||
)
|
||||
|
||||
type GameUploadToken struct {
|
||||
GameId int `json:"-"`
|
||||
UploadToken string `json:"upload_token"`
|
||||
Expire time.Time `json:"expire"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
locks = make(map[int]GameUploadToken)
|
||||
go func() {
|
||||
for {
|
||||
time.Sleep(time.Minute)
|
||||
clearLocks()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// AskForUpload Create a lock for upload a new revision of a game
|
||||
func AskForUpload(userId, gameId int) (*GameUploadToken, error) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
_, err := database.GameInfoById(userId, gameId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := locks[gameId]; !ok {
|
||||
token := uuid.New()
|
||||
lock := GameUploadToken{
|
||||
GameId: gameId,
|
||||
UploadToken: token.String(),
|
||||
}
|
||||
locks[gameId] = lock
|
||||
return &lock, nil
|
||||
}
|
||||
return nil, errors.New("game already locked")
|
||||
}
|
||||
|
||||
func CheckUploadToken(uploadToken string) (int, bool) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for _, lock := range locks {
|
||||
if lock.UploadToken == uploadToken {
|
||||
return lock.GameId, true
|
||||
}
|
||||
}
|
||||
return -1, false
|
||||
}
|
||||
|
||||
func UploadSave(file multipart.File, game *database.Game) error {
|
||||
filePath := path.Join(config.Path().Cache, string(rune(game.UserId)))
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
err = os.Mkdir(filePath, 0766)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
filePath = path.Join(filePath, game.PathStorage)
|
||||
f, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = moveToStorage(filePath, game)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func moveToStorage(cachePath string, game *database.Game) error {
|
||||
filePath := path.Join(config.Path().Storage, string(rune(game.UserId)))
|
||||
if _, err := os.Stat(filePath); err != nil {
|
||||
err = os.Mkdir(filePath, 0766)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
filePath = path.Join(filePath, game.PathStorage)
|
||||
if _, err := os.Stat(filePath); err == nil {
|
||||
if err = os.Remove(filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := os.Rename(cachePath, filePath); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func UnlockGame(gameId int) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
delete(locks, gameId)
|
||||
}
|
||||
|
||||
// clearLocks clear lock of zombi upload
|
||||
func clearLocks() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
now := time.Now()
|
||||
toUnlock := make([]int, 0)
|
||||
for gameId, lock := range locks {
|
||||
if lock.Expire.After(now) {
|
||||
toUnlock = append(toUnlock, gameId)
|
||||
}
|
||||
}
|
||||
for _, gameId := range toUnlock {
|
||||
delete(locks, gameId)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user