Files
StarPilot/openpilot/starpilot/saved_document.py
T
firestar5683 b06f37e2c7 Settings schema and storage contracts
Define persistent settings, typed schema fields and storage migrations before feature owners consume them. Keep calibration and parameter readers aligned with the shared data contracts.
2026-10-03 22:34:37 +00:00

65 lines
2.0 KiB
Python

"""One exact-source Params document replacement under the native Params lock."""
from collections.abc import Callable
from dataclasses import dataclass
import fcntl
import os
from pathlib import Path
import tempfile
from openpilot.starpilot.saved_source import read_saved
@dataclass(frozen=True)
class WriteResult:
committed: bool
verified: bool
def commit_exact(params, *, key: str, max_bytes: int, raw: bytes, expected: bytes | None,
authorized: Callable[[], bool], temp_prefix: str) -> WriteResult:
"""Stage outside the lock; recheck authority and source before replacement."""
if not authorized():
return WriteResult(False, False)
source, readable = read_saved(params, key, max_bytes)
if not readable or source != expected:
return WriteResult(False, False)
temporary = None
lock_fd = None
committed = False
try:
destination = Path(params.get_param_path(key))
root = destination.parent.parent
with tempfile.NamedTemporaryFile(prefix=temp_prefix, dir=root, delete=False) as stage:
temporary = stage.name
stage.write(raw)
stage.flush()
os.fsync(stage.fileno())
lock_fd = os.open(root / ".lock", os.O_CREAT | os.O_RDONLY, 0o775)
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
if not authorized():
return WriteResult(False, False)
source, readable = read_saved(params, key, max_bytes)
if not readable or source != expected or not authorized():
return WriteResult(False, False)
os.replace(temporary, destination)
temporary = None
committed = True
directory = os.open(destination.parent, os.O_RDONLY)
try:
os.fsync(directory)
finally:
os.close(directory)
observed, readable = read_saved(params, key, max_bytes)
return WriteResult(True, readable and observed == raw)
except (OSError, ValueError, TypeError):
return WriteResult(committed, False)
finally:
if lock_fd is not None:
os.close(lock_fd)
if temporary is not None:
try:
os.unlink(temporary)
except OSError:
pass