tstor/src/vfs/utils.go

72 lines
1.3 KiB
Go
Raw Normal View History

2023-10-16 09:18:40 +00:00
package vfs
2024-01-28 20:22:49 +00:00
import (
2024-04-06 13:51:36 +00:00
"context"
2024-03-28 13:09:42 +00:00
"path"
2024-01-28 20:22:49 +00:00
"strings"
"sync"
2024-04-06 13:51:36 +00:00
"time"
2024-01-28 20:22:49 +00:00
)
2023-10-16 09:18:40 +00:00
2024-03-28 13:09:42 +00:00
const Separator = "/"
2024-05-19 21:24:09 +00:00
func IsRoot(filename string) bool {
2024-03-28 13:09:42 +00:00
return path.Clean(filename) == Separator
}
2023-10-16 09:18:40 +00:00
func trimRelPath(p, t string) string {
return strings.Trim(strings.TrimPrefix(p, t), "/")
}
2023-12-21 23:15:39 +00:00
// func clean(p string) string {
// return path.Clean(Separator + strings.ReplaceAll(p, "\\", "/"))
// }
func AbsPath(p string) string {
if p == "" || p[0] != '/' {
return Separator + p
}
return p
}
func AddTrailSlash(p string) string {
if p == "" || p[len(p)-1] != '/' {
return p + Separator
}
return p
2023-10-16 09:18:40 +00:00
}
2024-01-28 20:22:49 +00:00
// OnceValueWOErr returns a function that invokes f only once and returns the value
// returned by f . The returned function may be called concurrently.
//
// If f panics, the returned function will panic with the same value on every call.
func OnceValueWOErr[T any](f func() (T, error)) func() (T, error) {
var (
mu sync.Mutex
isExecuted bool
r1 T
err error
)
return func() (T, error) {
mu.Lock()
defer mu.Unlock()
if isExecuted && err == nil {
return r1, nil
}
r1, err = f()
return r1, err
}
}
2024-04-06 13:51:36 +00:00
func subTimeout(ctx context.Context) (context.Context, context.CancelFunc) {
if deadline, ok := ctx.Deadline(); ok {
timeout := time.Until(deadline) / 2
return context.WithTimeout(ctx, timeout)
}
return ctx, func() {}
}