utils

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 13, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Index

Constants

View Source
const (
	HTTPTimeout = 30 * time.Second
	MaxRetries  = 3
	BaseBackoff = 100 * time.Millisecond
)
View Source
const StaleTempAge = time.Hour

StaleTempAge is the age threshold for removing stale temp files during GC.

Variables

This section is empty.

Functions

func AtomicWriteFile

func AtomicWriteFile(path string, data []byte, perm os.FileMode) error

AtomicWriteFile writes data to a file atomically using temp + fsync + rename. This prevents partial writes from being visible to readers.

func AtomicWriteJSON

func AtomicWriteJSON(path string, v any) error

AtomicWriteJSON marshals v to JSON and writes it atomically.

func CheckSocket

func CheckSocket(socketPath string) error

CheckSocket verifies that a Unix socket is connectable.

func CleanStaleRecords

func CleanStaleRecords[T any](
	items map[string]*T,
	nameMap map[string]string,
	targetIDs []string,
	nameOf func(*T) string,
	isStale func(*T) bool,
)

CleanStaleRecords removes records matching targetIDs from items, with a staleness re-check via isStale to guard against TOCTOU. nameOf extracts the name for nameMap cleanup ("" means no name entry).

func DetectHugePages

func DetectHugePages() bool

DetectHugePages reads /proc/sys/vm/nr_hugepages and returns true if the host has hugepages configured (value > 0). Returns false on any error (non-Linux, file missing, etc.).

func DoAPI

func DoAPI(ctx context.Context, hc *http.Client, method, url string, body []byte, expectedStatus int) ([]byte, error)

DoAPI sends an HTTP request and validates the response status code. url must be a fully-formed URL (e.g., "http://localhost/api/v1/vm.shutdown"). Returns the response body on success. For 204 No Content the body is nil.

func DoAPIOnce added in v0.3.9

func DoAPIOnce(ctx context.Context, hc *http.Client, method, url string, body []byte, successCodes ...int) ([]byte, error)

DoAPIOnce sends a single request without DoWithRetry. Use for endpoints whose action is non-idempotent: a retry after the request landed but the response was lost would surface as a duplicate / conflict error rather than a real failure (e.g. CH vm.add-fs / vm.add-device, snapshot/create).

func DoAPIWithRetry added in v0.3.9

func DoAPIWithRetry(ctx context.Context, hc *http.Client, method, url string, body []byte, successCodes ...int) ([]byte, error)

DoAPIWithRetry wraps DoAPI in DoWithRetry and tolerates extra success codes (e.g. some endpoints return 200 OK while their idiomatic success is 204). successCodes[0] is the primary code passed to DoAPI; codes[1:] are accepted as success on retry (silent nil-body return).

func DoWithRetry

func DoWithRetry[T any](ctx context.Context, fn func() (T, error)) (T, error)

DoWithRetry retries fn with exponential backoff for transient errors.

func EnsureDirs

func EnsureDirs(dirs ...string) error

EnsureDirs creates all directories with 0o750 permissions.

func ExtractTar

func ExtractTar(dir string, r io.Reader) error

ExtractTar extracts flat tar entries into dir.

func FileHead added in v0.4.0

func FileHead(f *os.File, n int) ([]byte, error)

FileHead returns up to n bytes from offset 0 without moving the read position. Truncated at EOF, no error if shorter than n.

func FilterUnreferenced

func FilterUnreferenced(candidates []string, refs map[string]struct{}, exclude ...map[string]struct{}) []string

FilterUnreferenced returns the elements of candidates not present in refs or any of the optional exclude sets. Used by GC Resolve to compute deletions.

func GenerateID

func GenerateID() string

GenerateID returns a random 26-character crypto-secure base32 ID.

func InitNamedIndex

func InitNamedIndex[T any](items *map[string]*T, names *map[string]string)

InitNamedIndex initializes nil maps in a named index (Items + Names pattern).

func IsProcessAlive

func IsProcessAlive(pid int) bool

IsProcessAlive returns true if a process with the given PID currently exists. Uses kill(pid, 0) — no signal is sent, only existence is checked. EPERM means the process exists but we lack permission to signal it.

func IsRetryable

func IsRetryable(err error) bool

IsRetryable returns true for transient errors (connection failures, 5xx, 429).

func LookupCopy

func LookupCopy[T any](m map[string]*T, key string) (T, error)

LookupCopy returns a shallow copy at key. Pointer/slice/map fields inside T still alias the original — callers must not mutate them without deep-copying.

func Map added in v0.2.5

func Map[T, R any](ctx context.Context, items []T, fn func(ctx context.Context, idx int, item T) (R, error), concurrency ...int) ([]R, error)

Map runs fn for each item concurrently, returning results in input order. Fail-fast: the errgroup context is canceled on the first error, so in-flight callbacks see a canceled ctx and new ones are not started. An optional concurrency limit caps in-flight goroutines; zero or omitted means no limit.

func MapValues added in v0.3.9

func MapValues[K comparable, V, R any](m map[K]*V, fn func(*V) R) []R

MapValues projects every non-nil value in m through fn into a slice.

func MergeSets

func MergeSets[K comparable](sets ...map[K]struct{}) map[K]struct{}

MergeSets unions any number of set maps into a new set.

func NewSocketHTTPClient

func NewSocketHTTPClient(socketPath string) *http.Client

NewSocketHTTPClient creates an HTTP client that dials a Unix socket.

func NewSocketHTTPClientWithTimeout added in v0.3.1

func NewSocketHTTPClientWithTimeout(socketPath string, timeout time.Duration) *http.Client

NewSocketHTTPClientWithTimeout is like NewSocketHTTPClient but with a custom per-call Timeout. Use this for endpoints where the default HTTPTimeout is too tight (e.g. hypervisor snapshot/restore which transfer the entire guest memory synchronously and can take minutes on multi-GiB VMs or slow storage).

func PeekReader added in v0.3.9

func PeekReader(r io.Reader, n int) ([]byte, io.Reader, error)

PeekReader peeks up to n bytes and returns them along with a reader that re-emits the head followed by the rest of r. A short read at EOF is not an error — caller checks len(head).

func ReadJSONFile added in v0.4.0

func ReadJSONFile(path string, v any) error

ReadJSONFile loads path and unmarshals it into v.

func ReadPIDFile

func ReadPIDFile(path string) (int, error)

ReadPIDFile reads a PID integer from path.

func ReflinkCopy

func ReflinkCopy(dst, src string) error

ReflinkCopy copies a single file, preferring FICLONE (O(1) CoW on btrfs/xfs/bcachefs) and falling back to SparseCopy on any error.

func RemoveMatching

func RemoveMatching(ctx context.Context, dir string, match func(os.DirEntry) bool) []error

RemoveMatching scans dir and removes entries where match returns true. Returns a slice of errors for entries that could not be removed.

func ResolveRef

func ResolveRef[T any](items map[string]*T, names map[string]string, ref string, notFound error) (string, error)

ResolveRef resolves a ref (exact ID, name, or ID prefix ≥3 chars) to a full ID. Works with any Index that has an Items map and a Names map.

func ResolveRefs

func ResolveRefs[T any](items map[string]*T, names map[string]string, refs []string, notFound error) ([]string, error)

ResolveRefs batch-resolves refs to exact IDs, deduplicating results.

func RunQemuImg added in v0.3.9

func RunQemuImg(ctx context.Context, args ...string) error

RunQemuImg shells out to qemu-img and wraps any non-zero exit with the trimmed combined output. Use this for operations without meaningful stdout (create, resize, convert); for queries that need a clean stdout payload (e.g. `info --output=json`), call exec.CommandContext directly.

func ScanFileStems

func ScanFileStems(dir, suffix string) ([]string, error)

ScanFileStems returns the name-without-suffix of every file in dir whose name ends with suffix. Used by GC to enumerate on-disk blobs.

func ScanSubdirs

func ScanSubdirs(dir string) ([]string, error)

ScanSubdirs returns the names of all immediate subdirectories of dir. Used by GC to enumerate per-VM runtime and log directories.

func SparseCopy

func SparseCopy(dst, src string) error

SparseCopy copies src to dst preserving sparsity via SEEK_HOLE/SEEK_DATA. dst is created as a new file (truncated to src size, then only data segments written).

func SyncParentDir

func SyncParentDir(dir string) error

SyncParentDir fsyncs the directory containing the file to ensure the directory entry is persisted.

func TarDir

func TarDir(tw *tar.Writer, dir string) error

TarDir writes regular files in dir into tw as flat tar entries.

func TarDirStream

func TarDirStream(dir string, cleanup func()) io.ReadCloser

TarDirStream streams a directory as a tar archive via a pipe.

func TarDirStreamWithRemove

func TarDirStreamWithRemove(dir string) io.ReadCloser

TarDirStreamWithRemove streams a directory as tar and removes it after close.

func TerminateProcess

func TerminateProcess(ctx context.Context, pid int, binaryName, expectArg string, gracePeriod time.Duration) error

TerminateProcess verifies the PID belongs to binaryName (with optional cmdline arg check), then sends SIGTERM, waits up to gracePeriod, and falls back to SIGKILL.

func UUIDv5

func UUIDv5(name string) string

UUIDv5 generates a deterministic UUID v5 from the given name using the URL namespace. Compatible with the uuid_v5() bash function in os-image/start.sh.

func ValidFile

func ValidFile(path string) bool

ValidFile returns true if path is a regular file with size > 0.

func VerifyProcessCmdline

func VerifyProcessCmdline(pid int, binaryName, expectArg string) bool

VerifyProcessCmdline matches pid against binaryName + expectArg in /proc/<pid>/cmdline; falls back to IsProcessAlive on non-Linux.

func WaitFor

func WaitFor(ctx context.Context, timeout, interval time.Duration, check func() (done bool, err error)) error

WaitFor polls check at the given interval until it returns (true, nil), returns a non-nil error, or the timeout/context expires.

func WatchFile added in v0.2.6

func WatchFile(ctx context.Context, filePath string, debounce time.Duration) (<-chan struct{}, error)

WatchFile watches a file for changes using fsnotify on the parent directory.

Watch parent dir (temp-file + rename changes inode).

func WritePIDFile

func WritePIDFile(path string, pid int) error

WritePIDFile writes pid to path with 0600 permissions.

Types

type APIError

type APIError struct {
	Code    int
	Message string
}

APIError carries the HTTP status code from a REST API response.

func (*APIError) Error

func (e *APIError) Error() string

type BatchResult

type BatchResult[T any] struct {
	Succeeded []T
	Errors    []error
}

BatchResult holds the outcome of a best-effort batch operation.

func ForEach

func ForEach[T any](ctx context.Context, items []T, fn func(context.Context, T) error, concurrency ...int) BatchResult[T]

ForEach runs fn concurrently on each item, best-effort.

func (BatchResult[T]) Err

func (r BatchResult[T]) Err() error

Err returns the combined error from all failed operations.

type PipeStreamReader

type PipeStreamReader struct {
	*io.PipeReader
	// contains filtered or unexported fields
}

PipeStreamReader wraps a PipeReader with background error collection and cleanup.

func NewPipeStreamReader

func NewPipeStreamReader(pr *io.PipeReader, done <-chan error, cleanup func()) *PipeStreamReader

NewPipeStreamReader pairs pr with the producer's done channel so Close surfaces background errors and runs cleanup exactly once.

func (*PipeStreamReader) Close

func (r *PipeStreamReader) Close() error

Close drains the producer, runs cleanup, and returns any accumulated error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL