Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# SPDX-License-Identifier: Apache-2.0

import pytest

from vaccel import Config


@pytest.fixture
def test_data():
return {
"plugins": "libvaccel-exec.so",
"log_level": 4,
"log_file": "vaccel.log",
"profiling_enabled": True,
"version_ignore": True,
}


def test_config_default():
config = Config()
assert config.plugins == "libvaccel-noop.so"
assert config.log_level == 1
assert config.log_file is None
assert not config.profiling_enabled
assert not config.version_ignore


def test_config_with_data(test_data):
config = Config(
plugins=test_data["plugins"],
log_level=test_data["log_level"],
log_file=test_data["log_file"],
profiling_enabled=test_data["profiling_enabled"],
version_ignore=test_data["version_ignore"],
)
assert config.plugins == test_data["plugins"]
assert config.log_level == test_data["log_level"]
assert config.log_file == test_data["log_file"]
assert config.profiling_enabled == test_data["profiling_enabled"]
assert config.version_ignore == test_data["version_ignore"]
28 changes: 28 additions & 0 deletions tests/test_vaccel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# SPDX-License-Identifier: Apache-2.0

import vaccel
from vaccel import Config


def test_bootstrap_default():
vaccel.bootstrap()


def test_bootstrap_with_config():
config = Config()
vaccel.bootstrap(config)


def test_cleanup():
vaccel.cleanup()


def test_bootstrap_default_and_cleanup():
vaccel.bootstrap()
vaccel.cleanup()


def test_bootstrap_with_config_and_cleanup():
config = Config()
vaccel.bootstrap(config)
vaccel.cleanup()
5 changes: 5 additions & 0 deletions vaccel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,20 @@

from ._version import __version__
from .arg import Arg
from .config import Config
from .op import OpType
from .resource import Resource, ResourceType
from .session import Session
from .vaccel import bootstrap, cleanup

__all__ = [
"Arg",
"Config",
"OpType",
"Resource",
"ResourceType",
"Session",
"__version__",
"bootstrap",
"cleanup",
]
148 changes: 148 additions & 0 deletions vaccel/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# SPDX-License-Identifier: Apache-2.0

"""Interface to the `struct vaccel_config` C object."""

from ._c_types import CStr, CType
from ._libvaccel import ffi, lib
from .error import FFIError


class Config(CType):
"""Wrapper for the `struct vaccel_config` C object.

Manages the creation and initialization of a C `struct vaccel_config` and
provides access to it through Python properties.

Inherits:
CType: Abstract base class for defining C data types.

Attributes:
_plugins (str): Colon-separated list of plugin names to load.
_log_level (int): Logging verbosity level (1-4).
_log_file (str | None): Path to the log file, or None to disable file
logging.
_profiling_enabled (bool): Whether profiling is enabled.
_version_ignore (bool): Whether to ignore version mismatches.
"""

def __init__(
self,
plugins: str = "libvaccel-noop.so",
log_level: int = 1,
log_file: str | None = None,
*,
profiling_enabled: bool = False,
version_ignore: bool = False,
):
"""Initializes a new `Config` object.

Args:
plugins (str): Colon-separated list of plugin names to load.
log_level (int): Logging level (1=ERROR, 4=DEBUG).
log_file (str | None): Path to log file or None to disable logging
to file.
profiling_enabled (bool): Enable or disable profiling.
version_ignore (bool): Ignore version mismatches if True.
"""
self._plugins = str(plugins)
self._log_level = log_level
self._log_file = log_file
self._profiling_enabled = profiling_enabled
self._version_ignore = version_ignore
self._c_obj_ptr = None
super().__init__()

def _init_c_obj(self):
"""Initializes the underlying C `struct vaccel_config` object.

Raises:
FFIError: If config initialization fails.
"""
log_file = (
self._log_file.encode() if self._log_file is not None else ffi.NULL
)
self._c_obj_ptr = ffi.new("struct vaccel_config **")
ret = lib.vaccel_config_new(
self._c_obj_ptr,
self._plugins.encode(),
self._log_level,
log_file,
self._profiling_enabled,
self._version_ignore,
)
if ret != 0:
raise FFIError(ret, "Could not initialize config")

self._c_obj = self._c_obj_ptr[0]
self._c_size = ffi.sizeof("struct vaccel_config")

@property
def value(self) -> ffi.CData:
"""Returns the value of the underlying C struct.

Returns:
The dereferenced 'struct vaccel_config`
"""
return self._c_obj[0]

def _del_c_obj(self):
"""Deletes the underlying `struct vaccel_config` C object.

Raises:
FFIError: If resource deletion fails.
"""
if self._c_obj:
ret = lib.vaccel_config_delete(self._c_obj)
if ret != 0:
raise FFIError(ret, "Could not delete resource")
self._c_obj = None

def __del__(self):
self._del_c_obj()

@property
def plugins(self) -> str:
"""The configured plugins.

Returns:
The config's plugins.
"""
return CStr.from_c_obj(self._c_obj.plugins).value

@property
def log_level(self) -> int:
"""The configured log level.

Returns:
The config's log level.
"""
return int(self._c_obj.log_level)

@property
def log_file(self) -> str | None:
"""The configured log file.

Returns:
The config's log file.
"""
if self._c_obj.log_file == ffi.NULL:
return None
return CStr.from_c_obj(self._c_obj.log_file).value

@property
def profiling_enabled(self) -> bool:
"""If profiling is enabled or disabled.

Returns:
True if profiling is enabled.
"""
return bool(self._c_obj.profiling_enabled)

@property
def version_ignore(self) -> bool:
"""Whether a plugin/vAccel version mismatch is ignored.

Returns:
True if version mismatch is ignored.
"""
return bool(self._c_obj.version_ignore)
42 changes: 42 additions & 0 deletions vaccel/vaccel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# SPDX-License-Identifier: Apache-2.0

"""Interface to common vaccel C functions."""

import atexit

from ._libvaccel import lib
from .config import Config
from .error import FFIError


def bootstrap(config: Config | None = None) -> None:
"""Initializes the vAccel library.

Args:
config (Config | None): A configuration object for the library. If None,
defaults are used.

Raises:
FFIError: If the C operation fails.
"""
if config is None:
ret = lib.vaccel_bootstrap()
else:
ret = lib.vaccel_bootstrap_with_config(config._c_ptr)
if ret != 0:
raise FFIError(ret, "Could not bootstrap vAccel library")


@atexit.register
def cleanup() -> None:
"""Cleans up the vAccel library resources.

This function is called automatically at program exit, but can also be
invoked explicitly if needed.

Raises:
FFIError: If the C operation fails.
"""
ret = lib.vaccel_cleanup()
if ret != 0:
raise FFIError(ret, "Could not cleanup vAccel library objects")