Documentation
¶
Overview ¶
Package lastgood keeps the last good generation of magpie's own state files (accounts, sign-ins, providers, settings) and reads it back when the file itself can't be read.
A Windows machine that went down mid-write left logins.json and plugin-auth.json at their full length with every byte zero (#1505). magpie then read no accounts, and its next write made that final. Here a file that is there but not valid is unknown, never empty: before each write the file there now is kept as <file>.bak when it is valid, or copied aside as <file>.bad-<time> when it isn't, and a read of a file that isn't valid gives the .bak's contents instead, noted for the GUI and the log.
Index ¶
- Variables
- func Bak(path string) string
- func Fallback(path string, bad []byte, valid Valid) ([]byte, error)
- func Into[T any](b []byte) bool
- func JSON(b []byte) bool
- func Keep(path string, valid Valid, perm fs.FileMode) error
- func KeepBad(path string, b []byte) (string, error)
- func KeepUnparsed(path string, parses Valid) error
- func Noted(path, why string)
- func Read(path string, valid Valid) ([]byte, error)
- func Reset()
- type Note
- type UnreadableError
- type Valid
Constants ¶
This section is empty.
Variables ¶
var ErrUnreadable = errors.New("unreadable")
ErrUnreadable is a file that is there but neither it nor its .bak is valid: unknown, never empty.
Functions ¶
func Fallback ¶
Fallback is Read for a caller that read path itself and found bad (its contents, or nil when only its parse said so): the .bak's contents when they are valid, noted, else an *UnreadableError.
func Into ¶ added in v0.1.1247
Into is a file that unmarshals into a T: what a reader that takes any other file as empty can read. `[]` is valid JSON but not a map, so a reader of a map would see nothing in it.
func JSON ¶
JSON is a file that holds one JSON value: a file of zero bytes, empty or whitespace only, or cut short is not.
func Keep ¶
Keep is called before path is replaced, under the lock its writer holds: the file there now, when valid, becomes the last good generation, path.bak, written to the disk before path is; one that isn't valid is copied aside (path.bad-<time>) and the .bak left as it is, so a file that can't be read is never written over before a copy of it is kept. A file not there needs neither. An error stops the write: the file there couldn't be read, or a bad one couldn't be kept.
func KeepBad ¶
KeepBad copies b, path's contents that aren't valid, aside as path.bad-<time> and gives that name. Two bad files within one second are both kept (.bad-<time>-2, …); the same bad bytes kept already, under any time, are not kept again.
func KeepUnparsed ¶ added in v0.1.1247
KeepUnparsed is called before path is written over, by a writer whose reader takes a file that doesn't parse (parses false) as empty: such a file is copied aside (KeepBad) first, so the write of what was read as empty doesn't lose what it held. A file not there, or empty, needs nothing. An error stops the write: the file there couldn't be read, or couldn't be kept.
func Noted ¶
func Noted(path, why string)
Noted records a recovery another process made (the plugin host's of plugin-auth.json).
func Read ¶
Read gives path's contents when they are valid. A file there that isn't gives its .bak's contents, when that is valid, and the recovery is noted (Recovered). A file not there is fs.ErrNotExist, its .bak not looked at: a crash leaves a file renamed over as it was or as it became, never gone, so one gone was removed on purpose. Anything else is an *UnreadableError, or the error that stopped the read.
Types ¶
type Note ¶
type Note struct {
File string `json:"file"` // the file's name: logins.json
Path string `json:"path"`
Why string `json:"why"` // what was wrong with it
Bak time.Time `json:"bak"` // when the .bak was written
At time.Time `json:"at"`
}
A Note is one file read back from its last good generation.
type UnreadableError ¶
UnreadableError says which file, and why it didn't read.
func (*UnreadableError) Error ¶
func (e *UnreadableError) Error() string
func (*UnreadableError) Unwrap ¶
func (e *UnreadableError) Unwrap() []error