mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e2ff745f55 | |||
| eab8e3be02 | |||
| e589d9c4fa |
@@ -824,7 +824,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
if len(os.Args) >= 2 && strings.HasPrefix(os.Args[1], "--migrate") {
|
||||
err := sstore.MigrateCommandOpts(os.Args[1:])
|
||||
err := sstore.MainDBMigrateCommandOpts(os.Args[1:])
|
||||
if err != nil {
|
||||
log.Printf("[error] migrate cmd: %v\n", err)
|
||||
}
|
||||
@@ -836,7 +836,7 @@ func main() {
|
||||
return
|
||||
}
|
||||
GlobalAuthKey = authKey
|
||||
err = sstore.TryMigrateUp()
|
||||
err = sstore.MainDBTryMigrateUp()
|
||||
if err != nil {
|
||||
log.Printf("[error] migrate up: %v\n", err)
|
||||
return
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
DROP TABLE file;
|
||||
@@ -0,0 +1,9 @@
|
||||
CREATE TABLE file (
|
||||
screenid varchar(36) NOT NULL,
|
||||
lineid varchar(36) NOT NULL,
|
||||
filename varchar(200) NOT NULL,
|
||||
filetype varchar(20) NOT NULL,
|
||||
diskfilename varchar(250) NOT NULL,
|
||||
contents blob NOT NULL,
|
||||
PRIMARY KEY (screenid, lineid, filename)
|
||||
);
|
||||
@@ -122,7 +122,7 @@ func createWaveAuthKeyFile(fileName string) (string, error) {
|
||||
|
||||
func ReadWaveAuthKey() (string, error) {
|
||||
homeDir := GetWaveHomeDir()
|
||||
err := ensureDir(homeDir)
|
||||
err := EnsureDir(homeDir)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot find/create WAVETERM_HOME directory %q", homeDir)
|
||||
}
|
||||
@@ -149,7 +149,7 @@ func ReadWaveAuthKey() (string, error) {
|
||||
|
||||
func AcquireWaveLock() (*os.File, error) {
|
||||
homeDir := GetWaveHomeDir()
|
||||
err := ensureDir(homeDir)
|
||||
err := EnsureDir(homeDir)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find/create WAVETERM_HOME directory %q", homeDir)
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func EnsureSessionDir(sessionId string) (string, error) {
|
||||
}
|
||||
scHome := GetWaveHomeDir()
|
||||
sdir = path.Join(scHome, SessionsDirBaseName, sessionId)
|
||||
err := ensureDir(sdir)
|
||||
err := EnsureDir(sdir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -197,35 +197,13 @@ func GetSessionsDir() string {
|
||||
return sdir
|
||||
}
|
||||
|
||||
func EnsureScreenDir(screenId string) (string, error) {
|
||||
if screenId == "" {
|
||||
return "", fmt.Errorf("cannot get screen dir for blank sessionid")
|
||||
}
|
||||
BaseLock.Lock()
|
||||
sdir, ok := ScreenDirCache[screenId]
|
||||
BaseLock.Unlock()
|
||||
if ok {
|
||||
return sdir, nil
|
||||
}
|
||||
scHome := GetWaveHomeDir()
|
||||
sdir = path.Join(scHome, ScreensDirBaseName, screenId)
|
||||
err := ensureDir(sdir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
BaseLock.Lock()
|
||||
ScreenDirCache[screenId] = sdir
|
||||
BaseLock.Unlock()
|
||||
return sdir, nil
|
||||
}
|
||||
|
||||
func GetScreensDir() string {
|
||||
waveHome := GetWaveHomeDir()
|
||||
sdir := path.Join(waveHome, ScreensDirBaseName)
|
||||
return sdir
|
||||
}
|
||||
|
||||
func ensureDir(dirName string) error {
|
||||
func EnsureDir(dirName string) error {
|
||||
info, err := os.Stat(dirName)
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
err = os.MkdirAll(dirName, 0700)
|
||||
@@ -259,20 +237,6 @@ func PtyOutFile_Sessions(sessionId string, cmdId string) (string, error) {
|
||||
return fmt.Sprintf("%s/%s.ptyout.cf", sdir, cmdId), nil
|
||||
}
|
||||
|
||||
func PtyOutFile(screenId string, lineId string) (string, error) {
|
||||
sdir, err := EnsureScreenDir(screenId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if screenId == "" {
|
||||
return "", fmt.Errorf("cannot get ptyout file for blank screenid")
|
||||
}
|
||||
if lineId == "" {
|
||||
return "", fmt.Errorf("cannot get ptyout file for blank lineid")
|
||||
}
|
||||
return fmt.Sprintf("%s/%s.ptyout.cf", sdir, lineId), nil
|
||||
}
|
||||
|
||||
func GenWaveUUID() string {
|
||||
for {
|
||||
rtn := uuid.New().String()
|
||||
|
||||
@@ -477,9 +477,7 @@ func GetConnectUpdate(ctx context.Context) (*ConnectUpdate, error) {
|
||||
}
|
||||
query := `SELECT * FROM screen ORDER BY archived, screenidx, archivedts`
|
||||
screens := dbutil.SelectMapsGen[*ScreenType](tx, query)
|
||||
for _, screen := range screens {
|
||||
update.Screens = append(update.Screens, screen)
|
||||
}
|
||||
update.Screens = append(update.Screens, screens...)
|
||||
query = `SELECT * FROM remote_instance`
|
||||
riArr := dbutil.SelectMapsGen[*RemoteInstance](tx, query)
|
||||
for _, ri := range riArr {
|
||||
@@ -674,7 +672,7 @@ func fmtUniqueName(name string, defaultFmtStr string, startIdx int, strs []strin
|
||||
} else {
|
||||
fmtStr = defaultFmtStr
|
||||
}
|
||||
if strings.Index(fmtStr, "%d") == -1 {
|
||||
if !strings.Contains(fmtStr, "%d") {
|
||||
panic("invalid fmtStr: " + fmtStr)
|
||||
}
|
||||
for {
|
||||
@@ -1159,7 +1157,7 @@ func ArchiveScreen(ctx context.Context, sessionId string, screenId string) (Upda
|
||||
return fmt.Errorf("cannot close screen (not found)")
|
||||
}
|
||||
if isWebShare(tx, screenId) {
|
||||
return fmt.Errorf("cannot archive screen while web-sharing. stop web-sharing before trying to archive.")
|
||||
return fmt.Errorf("cannot archive screen while web-sharing. stop web-sharing before trying to archive")
|
||||
}
|
||||
query = `SELECT archived FROM screen WHERE sessionid = ? AND screenid = ?`
|
||||
closeVal := tx.GetBool(query, sessionId, screenId)
|
||||
|
||||
@@ -12,16 +12,184 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jmoiron/sqlx"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/cirfile"
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/shexec"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbase"
|
||||
)
|
||||
|
||||
const MaxFileDBInlineFileSize = 10 * 1024
|
||||
|
||||
var screenDirLock = &sync.Mutex{}
|
||||
var screenDirCache = make(map[string]string) // locked with screenDirLock
|
||||
|
||||
var globalFileDBCache = makeFileDBCache()
|
||||
|
||||
type fileDBCacheEntry struct {
|
||||
ScreenId string
|
||||
CVar *sync.Cond // condition variable to lock entry fields and wait on InUse flag
|
||||
DB *sqlx.DB // can be nil (when not in use), will need to be reopend on access
|
||||
InUse bool
|
||||
Migrated bool // only try to migrate the DB once per run
|
||||
Waiters int
|
||||
LastUse time.Time
|
||||
OpenErr error // we cache open errors (and return them on GetDB)
|
||||
}
|
||||
|
||||
// we store all screens in this cache (added on demand)
|
||||
// when not in use we can close the DB object
|
||||
type FileDBCache struct {
|
||||
Lock *sync.Mutex
|
||||
Cache map[string]*fileDBCacheEntry // key = screenid
|
||||
}
|
||||
|
||||
// will create an entry if it doesn't exist
|
||||
func (dbc *FileDBCache) GetEntry(screenId string) *fileDBCacheEntry {
|
||||
dbc.Lock.Lock()
|
||||
defer dbc.Lock.Unlock()
|
||||
entry := dbc.Cache[screenId]
|
||||
if entry != nil {
|
||||
return entry
|
||||
}
|
||||
entry = &fileDBCacheEntry{
|
||||
ScreenId: screenId,
|
||||
CVar: sync.NewCond(&sync.Mutex{}),
|
||||
DB: nil,
|
||||
Migrated: false,
|
||||
InUse: false,
|
||||
Waiters: 0,
|
||||
LastUse: time.Time{},
|
||||
}
|
||||
dbc.Cache[screenId] = entry
|
||||
return entry
|
||||
}
|
||||
|
||||
func makeFileDBCache() *FileDBCache {
|
||||
return &FileDBCache{
|
||||
Lock: &sync.Mutex{},
|
||||
Cache: make(map[string]*fileDBCacheEntry),
|
||||
}
|
||||
}
|
||||
|
||||
func MakeFileDBUrl(screenId string) (string, error) {
|
||||
screenDir, err := EnsureScreenDir(screenId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
fileDBName := path.Join(screenDir, "filedb.db")
|
||||
return fmt.Sprintf("file:%s?cache=shared&mode=rwc&_journal_mode=WAL&_busy_timeout=5000", fileDBName), nil
|
||||
}
|
||||
|
||||
func MakeFileDB(screenId string) (*sqlx.DB, error) {
|
||||
dbUrl, err := MakeFileDBUrl(screenId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return sqlx.Open("sqlite3", dbUrl)
|
||||
}
|
||||
|
||||
// will close the DB if not in use (and no waiters)
|
||||
// returns (closed, closeErr)
|
||||
// if we cannot close the DB (in use), then we return (false, nil)
|
||||
// if DB is already closed, we'll return (true, nil)
|
||||
// if there is an error closing the DB, we'll return (true, err)
|
||||
// on successful close returns (true, nil)
|
||||
func (entry *fileDBCacheEntry) CloseDB() (bool, error) {
|
||||
entry.CVar.L.Lock()
|
||||
defer entry.CVar.L.Unlock()
|
||||
if entry.DB == nil {
|
||||
return true, nil
|
||||
}
|
||||
if entry.InUse || entry.Waiters > 0 {
|
||||
return false, nil
|
||||
}
|
||||
err := entry.DB.Close()
|
||||
entry.DB = nil
|
||||
return true, err
|
||||
}
|
||||
|
||||
// will create DB if doesn't exist
|
||||
// will Wait() on CVar if InUse
|
||||
// updates Waiters appropriately
|
||||
func (entry *fileDBCacheEntry) GetDB() (*sqlx.DB, error) {
|
||||
entry.CVar.L.Lock()
|
||||
defer entry.CVar.L.Unlock()
|
||||
if entry.OpenErr != nil {
|
||||
return nil, entry.OpenErr
|
||||
}
|
||||
entry.Waiters++
|
||||
for {
|
||||
if entry.InUse {
|
||||
entry.CVar.Wait()
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
entry.Waiters--
|
||||
if !entry.Migrated {
|
||||
FileDBMigrateUp(entry.ScreenId)
|
||||
entry.Migrated = true
|
||||
}
|
||||
if entry.DB == nil {
|
||||
db, err := MakeFileDB(entry.ScreenId)
|
||||
if err != nil {
|
||||
entry.OpenErr = err
|
||||
return nil, err
|
||||
}
|
||||
entry.DB = db
|
||||
}
|
||||
entry.InUse = true
|
||||
entry.LastUse = time.Now()
|
||||
return entry.DB, nil
|
||||
}
|
||||
|
||||
func (entry *fileDBCacheEntry) ReleaseDB() {
|
||||
entry.CVar.L.Lock()
|
||||
defer entry.CVar.L.Unlock()
|
||||
entry.InUse = false
|
||||
entry.CVar.Signal()
|
||||
}
|
||||
|
||||
func (c *FileDBCache) GetDB(screenId string) (*sqlx.DB, error) {
|
||||
entry := c.GetEntry(screenId)
|
||||
return entry.GetDB()
|
||||
}
|
||||
|
||||
func (c *FileDBCache) ReleaseDB(screenId string, db *sqlx.DB) {
|
||||
entry := c.Cache[screenId]
|
||||
entry.ReleaseDB()
|
||||
}
|
||||
|
||||
// fulfills the txwrap DBGetter interface
|
||||
type FileDBGetter struct {
|
||||
ScreenId string
|
||||
}
|
||||
|
||||
func (g FileDBGetter) GetDB(ctx context.Context) (*sqlx.DB, error) {
|
||||
return globalFileDBCache.GetDB(g.ScreenId)
|
||||
}
|
||||
|
||||
func (g FileDBGetter) ReleaseDB(db *sqlx.DB) {
|
||||
globalFileDBCache.ReleaseDB(g.ScreenId, db)
|
||||
}
|
||||
|
||||
func TryConvertPtyFile(ctx context.Context, screenId string, lineId string) error {
|
||||
stat, err := StatCmdPtyFile(ctx, screenId, lineId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("convert ptyfile, cannot stat: %w", err)
|
||||
}
|
||||
if stat.DataSize > MaxFileDBInlineFileSize {
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func CreateCmdPtyFile(ctx context.Context, screenId string, lineId string, maxSize int64) error {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -33,7 +201,7 @@ func CreateCmdPtyFile(ctx context.Context, screenId string, lineId string, maxSi
|
||||
}
|
||||
|
||||
func StatCmdPtyFile(ctx context.Context, screenId string, lineId string) (*cirfile.Stat, error) {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -41,7 +209,7 @@ func StatCmdPtyFile(ctx context.Context, screenId string, lineId string) (*cirfi
|
||||
}
|
||||
|
||||
func ClearCmdPtyFile(ctx context.Context, screenId string, lineId string) error {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -68,7 +236,7 @@ func AppendToCmdPtyBlob(ctx context.Context, screenId string, lineId string, dat
|
||||
if pos < 0 {
|
||||
return nil, fmt.Errorf("invalid seek pos '%d' in AppendToCmdPtyBlob", pos)
|
||||
}
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -99,7 +267,7 @@ func AppendToCmdPtyBlob(ctx context.Context, screenId string, lineId string, dat
|
||||
|
||||
// returns (real-offset, data, err)
|
||||
func ReadFullPtyOutFile(ctx context.Context, screenId string, lineId string) (int64, []byte, error) {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@@ -113,7 +281,7 @@ func ReadFullPtyOutFile(ctx context.Context, screenId string, lineId string) (in
|
||||
|
||||
// returns (real-offset, data, err)
|
||||
func ReadPtyOutFile(ctx context.Context, screenId string, lineId string, offset int64, maxSize int64) (int64, []byte, error) {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return 0, nil, err
|
||||
}
|
||||
@@ -189,7 +357,7 @@ func FullSessionDiskSize() (map[string]SessionDiskSizeType, error) {
|
||||
}
|
||||
|
||||
func DeletePtyOutFile(ctx context.Context, screenId string, lineId string) error {
|
||||
ptyOutFileName, err := scbase.PtyOutFile(screenId, lineId)
|
||||
ptyOutFileName, err := PtyOutFile(screenId, lineId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -218,10 +386,46 @@ func deleteScreenDirMakeCtx(screenId string) {
|
||||
}
|
||||
|
||||
func DeleteScreenDir(ctx context.Context, screenId string) error {
|
||||
screenDir, err := scbase.EnsureScreenDir(screenId)
|
||||
screenDir, err := EnsureScreenDir(screenId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting screendir: %w", err)
|
||||
}
|
||||
log.Printf("delete screen dir, remove-all %s\n", screenDir)
|
||||
return os.RemoveAll(screenDir)
|
||||
}
|
||||
|
||||
func EnsureScreenDir(screenId string) (string, error) {
|
||||
if screenId == "" {
|
||||
return "", fmt.Errorf("cannot get screen dir for blank sessionid")
|
||||
}
|
||||
screenDirLock.Lock()
|
||||
sdir, ok := screenDirCache[screenId]
|
||||
screenDirLock.Unlock()
|
||||
if ok {
|
||||
return sdir, nil
|
||||
}
|
||||
scHome := scbase.GetWaveHomeDir()
|
||||
sdir = path.Join(scHome, scbase.ScreensDirBaseName, screenId)
|
||||
err := scbase.EnsureDir(sdir)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
screenDirLock.Lock()
|
||||
screenDirCache[screenId] = sdir
|
||||
screenDirLock.Unlock()
|
||||
return sdir, nil
|
||||
}
|
||||
|
||||
func PtyOutFile(screenId string, lineId string) (string, error) {
|
||||
sdir, err := EnsureScreenDir(screenId)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if screenId == "" {
|
||||
return "", fmt.Errorf("cannot get ptyout file for blank screenid")
|
||||
}
|
||||
if lineId == "" {
|
||||
return "", fmt.Errorf("cannot get ptyout file for blank lineid")
|
||||
}
|
||||
return fmt.Sprintf("%s/%s.ptyout.cf", sdir, lineId), nil
|
||||
}
|
||||
|
||||
@@ -22,27 +22,41 @@ import (
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
)
|
||||
|
||||
const MaxMigration = 31
|
||||
const MaxMainDBMigration = 31
|
||||
const MigratePrimaryScreenVersion = 9
|
||||
const CmdScreenSpecialMigration = 13
|
||||
const CmdLineSpecialMigration = 20
|
||||
const RISpecialMigration = 30
|
||||
|
||||
func MakeMigrate() (*migrate.Migrate, error) {
|
||||
func MakeMainDBMigrate() (*migrate.Migrate, error) {
|
||||
fsVar, err := iofs.New(sh2db.MigrationFS, "migrations")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening iofs: %w", err)
|
||||
}
|
||||
// migrationPathUrl := fmt.Sprintf("file://%s", path.Join(wd, "db", "migrations"))
|
||||
dbUrl := fmt.Sprintf("sqlite3://%s", GetDBName())
|
||||
m, err := migrate.NewWithSourceInstance("iofs", fsVar, dbUrl)
|
||||
// m, err := migrate.New(migrationPathUrl, dbUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("making migration db[%s]: %w", GetDBName(), err)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func MakeFileDBMigrate(screenId string) (*migrate.Migrate, error) {
|
||||
fsVar, err := iofs.New(sh2db.MigrationFS, "filedb-migrations")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("opening iofs: %w", err)
|
||||
}
|
||||
dbUrl, err := MakeFileDBUrl(screenId)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("making file db url for screenid %s: %w", screenId, err)
|
||||
}
|
||||
m, err := migrate.NewWithSourceInstance("iofs", fsVar, dbUrl)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("making migration db[%s]: %w", dbUrl, err)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func copyFile(srcFile string, dstFile string, notFoundOk bool) error {
|
||||
if srcFile == dstFile {
|
||||
return fmt.Errorf("cannot copy %s to itself", srcFile)
|
||||
@@ -95,11 +109,7 @@ func MigrateUpStep(m *migrate.Migrate, newVersion uint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func MigrateUp(targetVersion uint) error {
|
||||
m, err := MakeMigrate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
func MigrateUp(m *migrate.Migrate, targetVersion uint) error {
|
||||
curVersion, dirty, err := MigrateVersion(m)
|
||||
if dirty {
|
||||
return fmt.Errorf("cannot migrate up, database is dirty")
|
||||
@@ -135,11 +145,7 @@ func MigrateUp(targetVersion uint) error {
|
||||
// returns curVersion, dirty, error
|
||||
func MigrateVersion(m *migrate.Migrate) (uint, bool, error) {
|
||||
if m == nil {
|
||||
var err error
|
||||
m, err = MakeMigrate()
|
||||
if err != nil {
|
||||
return 0, false, err
|
||||
}
|
||||
return 0, false, fmt.Errorf("migrate object is nil")
|
||||
}
|
||||
curVersion, dirty, err := m.Version()
|
||||
if err == migrate.ErrNilVersion {
|
||||
@@ -148,52 +154,60 @@ func MigrateVersion(m *migrate.Migrate) (uint, bool, error) {
|
||||
return curVersion, dirty, err
|
||||
}
|
||||
|
||||
func MigrateDown() error {
|
||||
m, err := MakeMigrate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.Down()
|
||||
func MigrateDown(m *migrate.Migrate) error {
|
||||
err := m.Down()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MigrateGoto(n uint) error {
|
||||
curVersion, _, _ := MigrateVersion(nil)
|
||||
func MigrateGoto(m *migrate.Migrate, n uint) error {
|
||||
curVersion, _, _ := MigrateVersion(m)
|
||||
if curVersion == n {
|
||||
return nil
|
||||
}
|
||||
if curVersion < n {
|
||||
return MigrateUp(n)
|
||||
return MigrateUp(m, n)
|
||||
}
|
||||
m, err := MakeMigrate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = m.Migrate(n)
|
||||
err := m.Migrate(n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TryMigrateUp() error {
|
||||
curVersion, _, _ := MigrateVersion(nil)
|
||||
func MainDBTryMigrateUp() error {
|
||||
m, err := MakeMainDBMigrate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error trying to run main-db migrations: %w", err)
|
||||
}
|
||||
return TryMigrateUp(m)
|
||||
}
|
||||
|
||||
func FileDBMigrateUp(screenId string) error {
|
||||
m, err := MakeFileDBMigrate(screenId)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error trying to run file-db migrations for screenid %s: %w", screenId, err)
|
||||
}
|
||||
return m.Up()
|
||||
}
|
||||
|
||||
func TryMigrateUp(m *migrate.Migrate) error {
|
||||
curVersion, _, _ := MigrateVersion(m)
|
||||
log.Printf("[db] db version = %d\n", curVersion)
|
||||
if curVersion >= MaxMigration {
|
||||
if curVersion >= MaxMainDBMigration {
|
||||
return nil
|
||||
}
|
||||
err := MigrateUp(MaxMigration)
|
||||
err := MigrateUp(m, MaxMainDBMigration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return MigratePrintVersion()
|
||||
return MigratePrintVersion(m)
|
||||
}
|
||||
|
||||
func MigratePrintVersion() error {
|
||||
version, dirty, err := MigrateVersion(nil)
|
||||
func MigratePrintVersion(m *migrate.Migrate) error {
|
||||
version, dirty, err := MigrateVersion(m)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting db version: %v", err)
|
||||
}
|
||||
@@ -204,22 +218,25 @@ func MigratePrintVersion() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func MigrateCommandOpts(opts []string) error {
|
||||
var err error
|
||||
func MainDBMigrateCommandOpts(opts []string) error {
|
||||
m, err := MakeMainDBMigrate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("error trying to run main-db migrations: %w", err)
|
||||
}
|
||||
if opts[0] == "--migrate-up" {
|
||||
fmt.Printf("migrate-up %v\n", GetDBName())
|
||||
time.Sleep(3 * time.Second)
|
||||
err = MigrateUp(MaxMigration)
|
||||
err = MigrateUp(m, MaxMainDBMigration)
|
||||
} else if opts[0] == "--migrate-down" {
|
||||
fmt.Printf("migrate-down %v\n", GetDBName())
|
||||
time.Sleep(3 * time.Second)
|
||||
err = MigrateDown()
|
||||
err = MigrateDown(m)
|
||||
} else if opts[0] == "--migrate-goto" {
|
||||
n, err := strconv.Atoi(opts[1])
|
||||
if err == nil {
|
||||
fmt.Printf("migrate-goto %v => %d\n", GetDBName(), n)
|
||||
time.Sleep(3 * time.Second)
|
||||
err = MigrateGoto(uint(n))
|
||||
err = MigrateGoto(m, uint(n))
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("invalid migration command")
|
||||
@@ -230,5 +247,5 @@ func MigrateCommandOpts(opts []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return MigratePrintVersion()
|
||||
return MigratePrintVersion(m)
|
||||
}
|
||||
|
||||
@@ -91,12 +91,12 @@ func RunMigration20() error {
|
||||
|
||||
func processMigration20Chunk(ctx context.Context, mchunk []cmdMigration20Type) error {
|
||||
for _, mig := range mchunk {
|
||||
newFile, err := scbase.PtyOutFile(mig.ScreenId, mig.LineId)
|
||||
newFile, err := PtyOutFile(mig.ScreenId, mig.LineId)
|
||||
if err != nil {
|
||||
log.Printf("ptyoutfile(lineid) error: %v\n", err)
|
||||
continue
|
||||
}
|
||||
oldFile, err := scbase.PtyOutFile(mig.ScreenId, mig.CmdId)
|
||||
oldFile, err := PtyOutFile(mig.ScreenId, mig.CmdId)
|
||||
if err != nil {
|
||||
log.Printf("ptyoutfile(cmdid) error: %v\n", err)
|
||||
continue
|
||||
@@ -142,7 +142,7 @@ func RunMigration13() error {
|
||||
}
|
||||
err := os.RemoveAll(scbase.GetSessionsDir())
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot remove old sessions dir %s: %w\n", scbase.GetSessionsDir(), err)
|
||||
return fmt.Errorf("cannot remove old sessions dir %s: %w", scbase.GetSessionsDir(), err)
|
||||
}
|
||||
txErr = WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE client SET cmdstoretype = 'screen'`
|
||||
@@ -158,7 +158,7 @@ func RunMigration13() error {
|
||||
|
||||
func processMigration13Chunk(ctx context.Context, mchunk []cmdMigration13Type) error {
|
||||
for _, mig := range mchunk {
|
||||
newFile, err := scbase.PtyOutFile(mig.ScreenId, mig.CmdId)
|
||||
newFile, err := PtyOutFile(mig.ScreenId, mig.CmdId)
|
||||
if err != nil {
|
||||
log.Printf("ptyoutfile error: %v\n", err)
|
||||
continue
|
||||
|
||||
Reference in New Issue
Block a user