Source code for eon.process_id

"""Content-addressed process ids (xxHash).

Process table rows and procdata files are keyed by integer ids. A counter
based on ``len(procs)`` freezes when duplicate ids collapse the dict; a
counter based on ``max(id)+1`` still couples identity to registration
order and external table rewrites.

Instead, seed the id from a stable xxh64 of the process payload (saddle
geometry bytes, barrier tag, direction). Geometric uniqueness remains
``find_repeat``; the hash only assigns free keys that do not depend on
table length. Rare collisions (or an already-occupied pure-content hash)
are resolved by salting until free.
"""

from __future__ import annotations

from typing import Union

import xxhash

BytesLike = Union[bytes, bytearray, memoryview, str]


def _as_bytes(part: BytesLike) -> bytes:
    if isinstance(part, str):
        return part.encode("utf-8")
    if isinstance(part, memoryview):
        return part.tobytes()
    if isinstance(part, bytearray):
        return bytes(part)
    return part


[docs] def process_id_from_parts(*parts: BytesLike, salt: int = 0) -> int: """xxh64 over *parts* (null-separated), optionally salted. Returns a non-negative 63-bit int so it is safe as a dict key and as the ``%d`` field in processtable / ``procdata/*_%d.*`` paths. """ h = xxhash.xxh64() for part in parts: h.update(_as_bytes(part)) h.update(b"\0") if salt: h.update(salt.to_bytes(8, "little", signed=False)) return h.intdigest() & 0x7FFFFFFFFFFFFFFF
[docs] def allocate_unique_process_id( occupied: dict | set | None, *parts: BytesLike, max_salts: int = 1024, ) -> int: """Return a content-addressed id not already in *occupied*. Salt 0 is the pure content hash. If that id is already present (true re-registration of the same payload, or an xxh64 collision), salt until free. Raises if *max_salts* is exhausted. """ keys = occupied if occupied is not None else () for salt in range(max_salts): pid = process_id_from_parts(*parts, salt=salt) if pid not in keys: return pid raise RuntimeError( "unable to allocate a free xxh64 process id after %d salts" % max_salts )