import ctypes
from typing import List
from ubse.models.ubs_engine_model_topo import UbsTopoNode, UbsTopoLink
from ubse.ffi.ubs_engine_exceptions import UbsError, UbsErrNullPointer, UbsEngineConnectionError, UbsEngineAuthError, \
UbsEngineTimeoutError, UbsEngineInternalError
from ubse.ffi.ubs_engine_binding_base import UbsEngineBindingBase
from ubse.ffi.ubs_engine_types import UbsTopoNodeT, UbsTopoLinkT
class UbsEngineBindingTopology(UbsEngineBindingBase):
"""拓扑相关接口"""
def __init__(self):
super().__init__()
self._setup_topo_functions()
def ubs_handle_topo_result(self, result: int, operation: str):
error_map = {
3: ("UBS_ERR_NULL_POINTER", UbsErrNullPointer),
1002: ("UBS_ENGINE_ERR_CONNECTION_FAILED", UbsEngineConnectionError),
1003: ("UBS_ENGINE_ERR_AUTH_FAILED", UbsEngineAuthError),
1004: ("UBS_ENGINE_ERR_TIMEOUT", UbsEngineTimeoutError),
1005: ("UBS_ENGINE_ERR_INTERNAL", UbsEngineInternalError)
}
if result != 0:
error_info = error_map.get(result, (f"error: {result}", UbsError))
raise error_info[1](f"{operation} failed: {error_info[0]}")
def ubs_topo_node_list(self) -> List[UbsTopoNode]:
"""查询全量节点信息"""
if not self.lib_ubse:
raise ConnectionError("Native library not loaded")
node_list_ptr = ctypes.POINTER(UbsTopoNodeT)()
node_count = ctypes.c_uint32(0)
try:
result = self.lib_ubse.ubs_topo_node_list(
ctypes.byref(node_list_ptr),
ctypes.byref(node_count)
)
self.ubs_handle_topo_result(result, "ubs_topo_node_list")
return self.convert_node_list(node_list_ptr, node_count.value)
finally:
self.safe_free_node_list(node_list_ptr)
def convert_node_list(self, node_list_ptr, node_count) -> List[UbsTopoNode]:
"""转换节点列表数据"""
if not node_list_ptr or node_count == 0:
return []
array_type = (UbsTopoNodeT * node_count)
node_list_array = ctypes.cast(node_list_ptr, ctypes.POINTER(array_type)).contents
return [UbsTopoNode.from_c_struct(node) for node in node_list_array]
def safe_free_node_list(self, node_list_ptr):
"""安全释放节点列表内存"""
if not node_list_ptr:
return
try:
if hasattr(self.lib_ubse, 'free'):
self.lib_ubse.free(node_list_ptr)
except Exception as e:
print(f"Warning: Failed to free node list memory: {e}")
def ubs_topo_node_local_get(self) -> UbsTopoNode:
"""查询本节点信息"""
if not self.lib_ubse:
raise ConnectionError("Native library not loaded")
local_node = UbsTopoNodeT()
try:
result = self.lib_ubse.ubs_topo_node_local_get(
ctypes.byref(local_node)
)
self.ubs_handle_topo_result(result, "ubs_topo_node_local_get")
return UbsTopoNode.from_c_struct(local_node)
except Exception as e:
print(f"Error getting local node info: {e}")
raise
def ubs_topo_link_list(self) -> List[UbsTopoLink]:
"""查询节点CPU拓扑连接列表"""
if not self.lib_ubse:
raise ConnectionError("Native library not loaded")
cpu_links_ptr = ctypes.POINTER(UbsTopoLinkT)()
link_count = ctypes.c_uint32(0)
try:
result = self.lib_ubse.ubs_topo_link_list(
ctypes.byref(cpu_links_ptr),
ctypes.byref(link_count)
)
self.ubs_handle_topo_result(result, "ubs_topo_link_list")
if not cpu_links_ptr or link_count.value == 0:
return []
link_models = []
for i in range(link_count.value):
link_ptr = ctypes.cast(
ctypes.addressof(cpu_links_ptr.contents) + i * ctypes.sizeof(UbsTopoLinkT),
ctypes.POINTER(UbsTopoLinkT)
)
link_models.append(UbsTopoLink.from_c_struct(link_ptr.contents))
return link_models
finally:
if cpu_links_ptr:
try:
self.lib_ubse.free(cpu_links_ptr)
except Exception as e:
print(f"Warning: Failed to free topology memory: {e}")
def _setup_topo_functions(self):
"""设置相关原型"""
self.lib_ubse.ubs_topo_link_list.argtypes = [
ctypes.POINTER(ctypes.POINTER(UbsTopoLinkT)),
ctypes.POINTER(ctypes.c_uint32)
]
self.lib_ubse.ubs_topo_link_list.restype = ctypes.c_int32
if hasattr(self.lib_ubse, 'free'):
self.lib_ubse.free.argtypes = [ctypes.c_void_p]
self.lib_ubse.free.restype = None