Help us shape the future of Go! Take the 2026 Go Developer Survey

dblock

package
v0.20.3 Latest Latest
Warning

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

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package dblock is the one-Studio-per-database rule of the weft command (B7-fix): `weft studio` and `weft dev` hold an exclusive lock on <db>.lock, beside a SQLite database file, for as long as they serve it, taken before the port policy runs. A second start on the same file — at the same moment, or from another directory whose discovery file names another Studio — cannot take it and is refused.

The lock is the operating system's, on an open file: flock(2) on unix (LOCK_EX|LOCK_NB), LockFileEx on Windows. Either is released by the kernel when the holding process's last descriptor closes — on a clean exit, and equally when the process is killed or crashes — so a stale lock never outlives its Studio and needs no cleanup. The file itself stays (removing it would race the next taker): Acquire empties it the moment it takes the lock, so a crashed holder's words never name the new one, and the holder writes its {url, pid} once it serves. A refused start reads them only under ReadHolder's rules: the file 0600 and this user's (unix), a loopback IP url and a live pid — anything else names nobody.

One file, one lock: the caller passes the database path with its symlinks resolved (cmd/weft does). Hard links, and two spellings of one name on a case-insensitive filesystem, are not detected.

Only a database with a file has a lock: ":memory:" and ClickHouse (a server shared by design) are out of scope. On a platform with neither flock nor LockFileEx the lock is a no-op.

Index

Constants

This section is empty.

Variables

View Source
var ErrHeld = errors.New("dblock: held")

ErrHeld is Acquire's error when another process (or another handle of this one) holds the lock.

View Source
var ErrNotRegular = errors.New("dblock: the lock file is not a regular file")

ErrNotRegular is Acquire's error when <db>.lock is not a regular file — a symlink planted there, a FIFO, a directory: never followed, truncated or chmodded.

Functions

func Path

func Path(dbPath string) string

Path is the lock file beside dbPath.

Types

type Holder

type Holder struct {
	URL string `json:"url"`
	PID int    `json:"pid"`
}

Holder is what the lock file says about the Studio holding it.

func ReadHolder

func ReadHolder(dbPath string) (Holder, bool)

ReadHolder is the holder the lock file beside dbPath names; ok false when it names none — not written yet, released, unreadable — or names one not to be trusted: a file that is not a regular one of mode 0600 owned by this user (unix; Windows skips the owner check), a url whose host is not a loopback IP (the holder is handed the database's token), or a pid not running (a crashed holder's leftover).

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

Lock is a held lock on <db>.lock.

func Acquire

func Acquire(dbPath string) (*Lock, error)

Acquire takes the lock beside dbPath without waiting: ErrHeld when it is held, ErrNotRegular when <db>.lock is not a regular file, another error when the file cannot be opened.

A planted symlink is never followed: unix opens with O_NOFOLLOW (the open fails on a symlink), and on every platform the opened handle is then checked against the path's own Lstat — a regular file, the same one — before it is truncated or chmodded. Windows has no O_NOFOLLOW; the check after the open is its guard: a symlink there when the handle was taken fails it, and one swapped in after it changes nothing, since Truncate and Chmod act on the handle (the regular file checked), never on the name. On unix a file with more than one link is refused too: a hard link planted at the path to another file (another user's or the database's own) is never truncated or chmodded. Windows does not check (a hard link there needs write access to the target already).

func (*Lock) Release

func (l *Lock) Release()

Release gives the lock up (closing the file). Nil-safe, idempotent.

func (*Lock) SetHolder

func (l *Lock) SetHolder(h Holder)

SetHolder records the holder's url and pid in the lock file (best effort: the lock holds regardless).

Jump to

Keyboard shortcuts

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