Pinned — one process's hold on a sealed object; eviction never takes a held object.
One rule: the index changes only on an explicit call. Pinned() takes the
hold and release() (or leaving the with block) lets it go; nothing runs
from a finalizer. A pin dropped unreleased is noted on its scratch and let go
at the next explicit call — another pin taken or released, or an eviction —
and a process that dies holding pins is reclaimed by reconcile through its
liveness lock.
Pinned
A hold on one sealed object; the object stays until every hold is gone.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| class Pinned:
"""A hold on one sealed object; the object stays until every hold is gone."""
__slots__ = ("__weakref__", "_finalizer", "_scratch", "hash", "path")
def __init__(self, scratch: Scratch, hash: ContentHash) -> None:
"""Take one more hold on ``hash`` for this scratch's owner."""
self.hash = hash
self.path = scratch.object_dir(hash)
self._scratch = scratch
with scratch.database.transaction() as db:
release_leaked(scratch, db)
pins.acquire(db, hash, scratch.liveness.pid, scratch.liveness.boot)
self._finalizer = weakref.finalize(self, scratch.leaked_pins.append, hash)
self._finalizer.atexit = False
def release(self) -> None:
"""Let go of the hold; a second call does nothing."""
if not self._finalizer.detach() or self._scratch.closed:
return
with self._scratch.database.transaction() as db:
pins.release(db, self.hash, self._scratch.liveness.boot)
release_leaked(self._scratch, db)
def __enter__(self) -> Pinned:
"""Hold the object for the block."""
return self
def __exit__(self, *_: object) -> None:
"""Release the hold."""
self.release()
def __repr__(self) -> str:
"""``Pinned(<hex>)``."""
return f"Pinned({self.hash.hex})"
|
__enter__()
Hold the object for the block.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def __enter__(self) -> Pinned:
"""Hold the object for the block."""
return self
|
__exit__(*_)
Release the hold.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def __exit__(self, *_: object) -> None:
"""Release the hold."""
self.release()
|
__init__(scratch, hash)
Take one more hold on hash for this scratch's owner.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def __init__(self, scratch: Scratch, hash: ContentHash) -> None:
"""Take one more hold on ``hash`` for this scratch's owner."""
self.hash = hash
self.path = scratch.object_dir(hash)
self._scratch = scratch
with scratch.database.transaction() as db:
release_leaked(scratch, db)
pins.acquire(db, hash, scratch.liveness.pid, scratch.liveness.boot)
self._finalizer = weakref.finalize(self, scratch.leaked_pins.append, hash)
self._finalizer.atexit = False
|
__repr__()
Pinned(<hex>).
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def __repr__(self) -> str:
"""``Pinned(<hex>)``."""
return f"Pinned({self.hash.hex})"
|
release()
Let go of the hold; a second call does nothing.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def release(self) -> None:
"""Let go of the hold; a second call does nothing."""
if not self._finalizer.detach() or self._scratch.closed:
return
with self._scratch.database.transaction() as db:
pins.release(db, self.hash, self._scratch.liveness.boot)
release_leaked(self._scratch, db)
|
release_leaked(scratch, db)
Let go of every hold dropped unreleased since the last explicit call.
Source code in capturegraph-lib/capturegraph/recipes/scratch/store/pinned.py
| def release_leaked(scratch: Scratch, db: sqlite3.Connection) -> None:
"""Let go of every hold dropped unreleased since the last explicit call."""
leaked = scratch.leaked_pins
while leaked:
pins.release(db, leaked.popleft(), scratch.liveness.boot)
|