diff --git a/wavesrv/pkg/scbase/scbase.go b/wavesrv/pkg/scbase/scbase.go index bc9ab45ba..a4303f00d 100644 --- a/wavesrv/pkg/scbase/scbase.go +++ b/wavesrv/pkg/scbase/scbase.go @@ -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() diff --git a/wavesrv/pkg/sstore/fileops.go b/wavesrv/pkg/sstore/fileops.go index 7b1b9ab17..a58d425b0 100644 --- a/wavesrv/pkg/sstore/fileops.go +++ b/wavesrv/pkg/sstore/fileops.go @@ -12,6 +12,7 @@ import ( "log" "os" "path" + "sync" "time" "github.com/google/uuid" @@ -20,8 +21,11 @@ import ( "github.com/wavetermdev/waveterm/wavesrv/pkg/scbase" ) +var screenDirLock = &sync.Mutex{} +var screenDirCache = make(map[string]string) // locked with screenDirLock + 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 +37,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 +45,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 +72,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 +103,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 +117,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 +193,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 +222,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 +} diff --git a/wavesrv/pkg/sstore/sstore_migrate.go b/wavesrv/pkg/sstore/sstore_migrate.go index dd370e972..f00ec2b5e 100644 --- a/wavesrv/pkg/sstore/sstore_migrate.go +++ b/wavesrv/pkg/sstore/sstore_migrate.go @@ -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 @@ -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