mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
b38832e251
Move the epoch inside the storage_provider, this allows us to make the storage_provider_factory to return an async context manager. This way we can simplify the locking for the daemon, but forces the CLI project commands to deal with async code.
123 lines
3.5 KiB
Python
123 lines
3.5 KiB
Python
#
|
|
# This file is distributed under the MIT License. See LICENSE.md for details.
|
|
#
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Buffer
|
|
from contextlib import asynccontextmanager
|
|
from datetime import datetime
|
|
from typing import AsyncGenerator, Iterable, Mapping
|
|
|
|
from revng import __version__ as revng_version
|
|
from revng.pypeline.container import ConfigurationId
|
|
from revng.pypeline.model import ModelPathSet
|
|
from revng.pypeline.object import ObjectID
|
|
from revng.pypeline.task.task import ObjectDependencies
|
|
|
|
from .file_provider import FileRequest
|
|
from .storage_provider import ContainerLocation, FileStorageEntry, InvalidatedObjects, ProjectID
|
|
from .storage_provider import ProjectMetadata, SavePointsRange, StorageProvider
|
|
from .storage_provider import StorageProviderFactory
|
|
from .util import compute_hash
|
|
|
|
|
|
class NullStorageProviderFactory(StorageProviderFactory):
|
|
def __init__(self, url: str):
|
|
assert url == "null://"
|
|
|
|
@classmethod
|
|
def scheme(cls) -> str:
|
|
return "null"
|
|
|
|
@asynccontextmanager
|
|
async def get(
|
|
self,
|
|
project_id: ProjectID | None,
|
|
token: str | None,
|
|
cache_dir: str | None,
|
|
) -> AsyncGenerator[StorageProvider]:
|
|
yield NullStorageProvider()
|
|
|
|
|
|
class NullStorageProvider(StorageProvider):
|
|
"""The /dev/null of storage providers. It stores nothing and caches nothing.
|
|
It just keeps track of the model, project ID, and last change time as those
|
|
are required by the interface.
|
|
"""
|
|
|
|
def __init__(self):
|
|
self.model = b""
|
|
self.last_change = datetime.now()
|
|
|
|
def has(
|
|
self,
|
|
location: ContainerLocation,
|
|
keys: Iterable[ObjectID],
|
|
) -> Iterable[ObjectID]:
|
|
return []
|
|
|
|
def get(
|
|
self,
|
|
location: ContainerLocation,
|
|
keys: Iterable[ObjectID],
|
|
) -> Mapping[ObjectID, bytes]:
|
|
assert not keys, "NullStorageProvider does not support get operation."
|
|
return {}
|
|
|
|
def add_dependencies(
|
|
self,
|
|
savepoint_range: SavePointsRange,
|
|
configuration_id: ConfigurationId,
|
|
deps: ObjectDependencies,
|
|
) -> None:
|
|
self.last_change = datetime.now()
|
|
|
|
def put(
|
|
self,
|
|
location: ContainerLocation,
|
|
values: Mapping[ObjectID, Buffer],
|
|
) -> None:
|
|
self.last_change = datetime.now()
|
|
|
|
def invalidate(self, invalidation_list: ModelPathSet) -> InvalidatedObjects:
|
|
self.last_change = datetime.now()
|
|
return {}
|
|
|
|
def get_epoch(self) -> int:
|
|
return 0
|
|
|
|
def get_model(self) -> tuple[bytes, int]:
|
|
return (self.model, self.get_epoch())
|
|
|
|
def set_model(self, new_model: bytes):
|
|
self.model = new_model
|
|
self.last_change = datetime.now()
|
|
return 0
|
|
|
|
def metadata(self) -> ProjectMetadata:
|
|
"""
|
|
Fetch metadata about the current project
|
|
"""
|
|
return ProjectMetadata(
|
|
last_change=self.last_change,
|
|
revng_version=revng_version,
|
|
)
|
|
|
|
def prune_objects(self):
|
|
"""
|
|
Prunes all the objects (except metadata) from storage
|
|
"""
|
|
|
|
def put_files_in_storage(self, files: list[FileStorageEntry]) -> list[str]:
|
|
result = []
|
|
for file in files:
|
|
if file.path is not None:
|
|
result.append(compute_hash(file.path))
|
|
elif file.contents is not None:
|
|
result.append(compute_hash(file.contents))
|
|
return result
|
|
|
|
def get_files_from_storage(self, requests: list[FileRequest]) -> dict[str, bytes]:
|
|
raise ValueError("Unsupported")
|