From 264c4be96c02df590420c43e546467d2ad3d858b Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Wed, 3 Jan 2024 16:59:32 +0100 Subject: [PATCH] [EDF29150] : Logs are now centralized on node zero. --- idl/SALOME_Component.idl | 6 -- idl/SALOME_LogManager.idl | 2 +- src/Basics/PythonCppUtils.hxx | 1 + src/Container/Container_i.cxx | 15 --- src/Container/SALOME_Container.py | 19 ---- src/Container/SALOME_ContainerHelper.py | 114 +++++++++++++++++++-- src/Container/SALOME_Container_i.hxx | 1 - src/Container/SALOME_PyNode.py | 68 +++++++------ src/KERNEL_PY/__init__.py | 5 + src/Launcher/CMakeLists.txt | 1 + src/Launcher/KernelLauncher.cxx | 2 +- src/Launcher/SALOME_LogManager.cxx | 128 ++++++++++++++++++++---- src/Launcher/SALOME_LogManager.hxx | 29 ++++-- src/Launcher/SALOME_LogManager.py | 79 +++++++++++++++ 14 files changed, 369 insertions(+), 101 deletions(-) create mode 100644 src/Launcher/SALOME_LogManager.py diff --git a/idl/SALOME_Component.idl b/idl/SALOME_Component.idl index 5de885005..8c543d82b 100644 --- a/idl/SALOME_Component.idl +++ b/idl/SALOME_Component.idl @@ -190,12 +190,6 @@ module Engines void setVerbosity(in boolean activated, in string level); - //void addInfoOnLevel1(in long pos, in string key, in SALOME::vectorOfByte value); - - //void addInfoOnLevel2(in long pos0, in long pos1, in string key, in SALOME::vectorOfByte value); - - SALOME::vectorOfByte getAllInfo(); - //! Shutdown the Container process. void Shutdown(); diff --git a/idl/SALOME_LogManager.idl b/idl/SALOME_LogManager.idl index 9ef2fab96..23415c700 100644 --- a/idl/SALOME_LogManager.idl +++ b/idl/SALOME_LogManager.idl @@ -28,6 +28,7 @@ module Engines interface ContainerScriptExecPerfLog { void assign(in SALOME::vectorOfByte value); + SALOME::vectorOfByte getObj(); }; typedef sequence ListOfContainerScriptExecPerfLog; @@ -56,7 +57,6 @@ module Engines { ContainerPerfLog declareContainer(in string contInNS, in string logfile); ListOfContainerPerfLog listOfContainerLogs(); - SALOME::vectorOfByte getAllInfo(); }; }; diff --git a/src/Basics/PythonCppUtils.hxx b/src/Basics/PythonCppUtils.hxx index 8ef4904a2..93a3cfb59 100644 --- a/src/Basics/PythonCppUtils.hxx +++ b/src/Basics/PythonCppUtils.hxx @@ -36,6 +36,7 @@ public: AutoPyRef(PyObject *pyobj=nullptr):_pyobj(pyobj) { } ~AutoPyRef() { release(); } AutoPyRef(const AutoPyRef& other):_pyobj(other._pyobj) { if(_pyobj) Py_XINCREF(_pyobj); } + AutoPyRef(AutoPyRef&& other) = default; AutoPyRef& operator=(const AutoPyRef& other) { if(_pyobj==other._pyobj) return *this; release(); _pyobj=other._pyobj; Py_XINCREF(_pyobj); return *this; } operator PyObject *() { return _pyobj; } void set(PyObject *pyobj) { if(pyobj==_pyobj) return ; release(); _pyobj=pyobj; } diff --git a/src/Container/Container_i.cxx b/src/Container/Container_i.cxx index d83a20529..1362635a8 100644 --- a/src/Container/Container_i.cxx +++ b/src/Container/Container_i.cxx @@ -389,21 +389,6 @@ void Abstract_Engines_Container_i::setVerbosity(bool activated, const char *leve } } -SALOME::vectorOfByte *Abstract_Engines_Container_i::getAllInfo() -{ - AutoGIL gstate; - PyObject *result = PyObject_CallMethod(_pyCont, (char*)"getAllInfo",nullptr); - char *buffer = nullptr; - Py_ssize_t length = 0; - PyBytes_AsStringAndSize(result,&buffer,&length); - SALOME::vectorOfByte *ret = new SALOME::vectorOfByte; - ret->length(length); - for(auto i = 0 ; i < length ; ++i) - (*ret)[i] = buffer[i]; - Py_XDECREF(result); - return ret; -} - //============================================================================= //! Get container host name /*! diff --git a/src/Container/SALOME_Container.py b/src/Container/SALOME_Container.py index 1f4fa66e3..b609dcb49 100644 --- a/src/Container/SALOME_Container.py +++ b/src/Container/SALOME_Container.py @@ -47,7 +47,6 @@ from SALOME_utilities import * from Utils_Identity import getShortHostName from salome_utils import verbose from KernelBasis import VerbosityActivated -from SALOME_ContainerHelper import ScriptInfo #============================================================================= @@ -74,7 +73,6 @@ class SALOME_Container_i: self._poa = self._orb.resolve_initial_references("RootPOA") self._containerName = containerName self._logFileName = None - self._dbg_info = [] self._timeIntervalInMs = dftTimeIntervalInMs self._logm = None self._log = None @@ -161,11 +159,8 @@ class SALOME_Container_i: def create_pyscriptnode(self,nodeName,code): try: - self._dbg_info.append( ScriptInfo(nodeName) ) logscript = self._log.addScript(nodeName,code) node=SALOME_PyNode.PyScriptNode_i(nodeName,code,self._poa,self, logscript) - node.setIDInContainer(len(self._dbg_info)-1) - self.addInfoOnLevel1(node.getIDInContainer(),"code",code) id_o = self._poa.activate_object(node) comp_o = self._poa.id_to_reference(id_o) comp_iors = self._orb.object_to_string(comp_o) @@ -180,20 +175,6 @@ class SALOME_Container_i: if VerbosityActivated(): import salome_utils salome_utils.positionVerbosityOfLoggerRegardingState() - - def addInfoOnLevel1(self, pos, key, value): - setattr(self._dbg_info[pos],key,value) - - def addInfoOnLevel2(self, pos0, pos1, key, value): - setattr(self._dbg_info[pos0].execs[pos1],key,value) - - def addTimeInfoOnLevel2(self, pos0, pos1, key): - from datetime import datetime - self.addInfoOnLevel2(pos0, pos1, key,datetime.now()) - - def getAllInfo(self): - import pickle - return pickle.dumps( self._dbg_info ) def monitoringtimeresms(self): return self._timeIntervalInMs diff --git a/src/Container/SALOME_ContainerHelper.py b/src/Container/SALOME_ContainerHelper.py index 0d38486d0..c0dce572c 100644 --- a/src/Container/SALOME_ContainerHelper.py +++ b/src/Container/SALOME_ContainerHelper.py @@ -20,6 +20,8 @@ from collections import defaultdict +import pickle + class ScriptExecInfo: @classmethod def GetRepresentationOfTimeDelta(cls,endTime, startTime): @@ -48,6 +50,7 @@ class ScriptExecInfo: return "{} {}".format(m,UNITS[3]) def __init__(self): + self._measure_time_resolution_ms = None self._cpu_mem_during_exec = None self._start_exec_time = None self._end_exec_time = None @@ -59,6 +62,32 @@ class ScriptExecInfo: self._input_hdd_mem = None self._output_mem = 0 self._output_hdd_mem = None + self._start_pos_log = None + self._stop_pos_log = None + + @property + def measureTimeResolution(self): + return self._measure_time_resolution_ms + + @measureTimeResolution.setter + def measureTimeResolution(self, value): + self._measure_time_resolution_ms = value + + @property + def tracePosStart(self): + return self._start_pos_log + + @tracePosStart.setter + def tracePosStart(self,value): + self._start_pos_log = value + + @property + def tracePosStop(self): + return self._stop_pos_log + + @tracePosStop.setter + def tracePosStop(self,value): + self._stop_pos_log = value @property def CPUMemDuringExec(self): @@ -190,19 +219,42 @@ class ScriptExecInfo: return """start exec time = {self.startExecTime} end exec time = {self.endExecTime} exec_time = {self.execTimeStr} +Measure time resolution = {self.measureTimeResolution} ms CPU and mem monitoring = {self.CPUMemDuringExecStr} input unpickling and ev load from disk time = {self.inputTimeStr} output serialization and ev write to disk time = {self.outputTimeStr} input memory size before exec (MemoryPeak 2x) = {self.inputMemStr} input memory size from HDD = {self.inputHDDMemStr} output memory size after exec (MemoryPeak 2x) = {self.outputMemStr} -output memory size from HDD = {self.outputHDDMemStr}""".format(**locals()) +output memory size from HDD = {self.outputHDDMemStr} +Start position in log = {self.tracePosStart} +End position in log = {self.tracePosStop}""".format(**locals()) + +class ScriptExecInfoDeco: + def __init__(self, eff, father): + self._eff = eff + self._father = father + @property + def father(self): + return self._father + def get(self): + return self._eff + def __getitem__(self,i): + return self._eff[i] + def __str__(self): + return self._eff.__str__() + def __repr__(self): + return self._eff.__repr__() + def log(self): + with open(self.father.father.logfile,"rb") as f: + cont = f.read() + return cont[self._eff.tracePosStart:self._eff.tracePosStop].decode() class ScriptInfo: - def __init__(self, nodeName): - self._node_name = nodeName - self._code = "" - self._exec = defaultdict(ScriptExecInfo) + def __init__(self, scriptPtr): + self._node_name = scriptPtr.getName() + self._code = scriptPtr.getCode() + self._exec = [pickle.loads(elt.getObj()) for elt in scriptPtr.listOfExecs()] @property def execs(self): @@ -220,12 +272,62 @@ class ScriptInfo: def code(self,value): self._code = value + def __len__(self): + return len( self._exec ) + + def __getitem__(self,i): + return self._exec[i] + def __str__(self): - return """code = {self.code}\nexecs = {self.execs}""".format(**locals()) + return """name = {self.nodeName}\ncode = {self.code}\nexecs = {self.execs}""".format(**locals()) def __repr__(self): return """ScriptInfo \"{self.nodeName}\"""".format(**locals()) +class ScriptInfoDeco: + def __init__(self, eff, father): + self._eff = eff + self._father = father + @property + def father(self): + return self._father + def get(self): + return self._eff + def __getitem__(self,i): + return ScriptExecInfoDeco( self._eff[i], self ) + def __str__(self): + return self._eff.__str__() + def __repr__(self): + return self._eff.__repr__() + +class ContainerLogInfo: + def __init__(self,contLogPtr): + self._log_file = contLogPtr.getLogFile() + self._ns_entry = contLogPtr.getContainerEntryInNS() + self._scripts = [ScriptInfo(elt) for elt in contLogPtr.listOfScripts()] + + def log(self): + with open(self.logfile,"rb") as f: + cont = f.read() + return cont.decode() + + @property + def ns_entry(self): + return self._ns_entry + + @property + def logfile(self): + return self._log_file + + def __len__(self): + return len( self._scripts ) + + def __getitem__(self,i): + return ScriptInfoDeco( self._scripts[i], self) + + def __str__(self): + return """NS entry = {self.ns_entry} LogFile = {self.logfile}""".format(**locals()) + from abc import ABC, abstractmethod class InOutputObjVisitorAbstract(ABC): diff --git a/src/Container/SALOME_Container_i.hxx b/src/Container/SALOME_Container_i.hxx index 7f974bd5d..2e0099b8d 100644 --- a/src/Container/SALOME_Container_i.hxx +++ b/src/Container/SALOME_Container_i.hxx @@ -123,7 +123,6 @@ public: void monitoringtimeresms(CORBA::Long intervalInMs) override; void verbosity(bool& activated, CORBA::String_out level) override; void setVerbosity(bool activated, const char *level) override; - SALOME::vectorOfByte *getAllInfo() override; virtual void Shutdown(); char *getHostName(); diff --git a/src/Container/SALOME_PyNode.py b/src/Container/SALOME_PyNode.py index 52f3d5d98..d6d46668f 100644 --- a/src/Container/SALOME_PyNode.py +++ b/src/Container/SALOME_PyNode.py @@ -32,6 +32,7 @@ import SALOME import logging import os import sys +from SALOME_ContainerHelper import ScriptExecInfo MY_CONTAINER_ENTRY_IN_GLBS = "my_container" @@ -487,6 +488,17 @@ class SeqByteReceiver: iStart = iEnd; iEnd = min(iStart + EFF_CHUNK_SIZE,size) return data_for_split_case +class LogOfCurrentExecutionSession: + def __init__(self, handleToCentralizedInst): + self._remote_handle = handleToCentralizedInst + self._current_instance = ScriptExecInfo() + + def addInfoOnLevel2(self, key, value): + setattr(self._current_instance,key,value) + + def finalizeAndPushToMaster(self): + self._remote_handle.assign( pickle.dumps( self._current_instance ) ) + class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): """The implementation of the PyScriptNode CORBA IDL that executes a script""" def __init__(self, nodeName,code,poa,my_container,logscript): @@ -500,24 +512,9 @@ class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): self.ccode=compile(code,nodeName,'exec') self.context={} self.context[MY_CONTAINER_ENTRY_IN_GLBS] = self.my_container - self._pos = None - self._current_exec = 0 self._log_script = logscript self._current_execution_session = None sys.stdout.flush() ; sys.stderr.flush() # flush to correctly capture log per execution session - - #start of non remote callable methods - - def setIDInContainer(self, pos): - """ - Method that store the rank of creation of self inside Container instance - """ - self._pos = pos - - def getIDInContainer(self): - return self._pos - - #end of non remote callable methods def __del__(self): # force removal of self.context. Don t know why it s not done by default @@ -587,22 +584,21 @@ class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): def executeFirst(self,argsin): """ Same than first part of self.execute to reduce memory peak.""" try: - #self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"tracePosStart",) - self._current_execution_session = self._log_script.addExecutionSession() + self.beginOfCurrentExecutionSession() data = None - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"startInputTime") + self.addTimeInfoOnLevel2("startInputTime") if True: # to force call of SeqByteReceiver's destructor argsInPy = SeqByteReceiver( argsin ) data = argsInPy.data() - self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"inputMem",len(data)) + self.addInfoOnLevel2("inputMem",len(data)) _,kws=pickle.loads(data) vis = InOutputObjVisitor() for elt in kws: # fetch real data if necessary kws[elt] = UnProxyObjectSimple( kws[elt],vis) - self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"inputHDDMem",vis) + self.addInfoOnLevel2("inputHDDMem",vis) self.context.update(kws) - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"endInputTime") + self.addTimeInfoOnLevel2("endInputTime") except Exception: exc_typ,exc_val,exc_fr=sys.exc_info() l=traceback.format_exception(exc_typ,exc_val,exc_fr) @@ -613,16 +609,17 @@ class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): """ Same than second part of self.execute to reduce memory peak.""" import sys try: - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"startExecTime") + self.addTimeInfoOnLevel2("startExecTime") ## + self.addInfoOnLevel2("measureTimeResolution",self.my_container_py.monitoringtimeresms()) monitoringParams = LaunchMonitoring( self.my_container_py.monitoringtimeresms() ) exec(self.ccode, self.context) cpumeminfo = StopMonitoring( ) ## - self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"CPUMemDuringExec",cpumeminfo) + self.addInfoOnLevel2("CPUMemDuringExec",cpumeminfo) del monitoringParams - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"endExecTime") - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"startOutputTime") + self.addTimeInfoOnLevel2("endExecTime") + self.addTimeInfoOnLevel2("startOutputTime") argsout=[] for arg in outargsname: if arg not in self.context: @@ -639,9 +636,10 @@ class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): retObj = self.poa.id_to_reference(id_o) ret.append( retObj._narrow( SALOME.SenderByte ) ) outputMem += len(argPickle) - self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"outputMem",outputMem) - self.my_container_py.addInfoOnLevel2(self.getIDInContainer(),self._current_exec,"outputHDDMem",vis) - self.my_container_py.addTimeInfoOnLevel2(self.getIDInContainer(),self._current_exec,"endOutputTime") + self.addInfoOnLevel2("outputMem",outputMem) + self.addInfoOnLevel2("outputHDDMem",vis) + self.addTimeInfoOnLevel2("endOutputTime") + self.endOfCurrentExecutionSession() return ret except Exception: exc_typ,exc_val,exc_fr=sys.exc_info() @@ -684,3 +682,17 @@ class PyScriptNode_i (Engines__POA.PyScriptNode,Generic): l=traceback.format_exception(exc_typ,exc_val,exc_fr) raise SALOME.SALOME_Exception(SALOME.ExceptionStruct(SALOME.BAD_PARAM,"".join(l),"PyScriptNode: %s" %self.nodeName,0)) pass + + def beginOfCurrentExecutionSession(self): + self._current_execution_session = LogOfCurrentExecutionSession( self._log_script.addExecutionSession() ) + + def endOfCurrentExecutionSession(self): + self._current_execution_session.finalizeAndPushToMaster() + self._current_execution_session = None + + def addInfoOnLevel2(self, key, value): + self._current_execution_session.addInfoOnLevel2(key, value) + + def addTimeInfoOnLevel2(self, key): + from datetime import datetime + self._current_execution_session.addInfoOnLevel2(key,datetime.now()) diff --git a/src/KERNEL_PY/__init__.py b/src/KERNEL_PY/__init__.py index 7c052ae65..1adfba2a3 100644 --- a/src/KERNEL_PY/__init__.py +++ b/src/KERNEL_PY/__init__.py @@ -268,6 +268,7 @@ def salome_init_without_session(path=None, embedded=False, iorfakensfile=None): esm = KernelLauncher.GetExternalServer() # idem for logm logm = KernelLauncher.myLogManager() + type(logm).Fetch = LogManagerFetch # import KernelLogger naming_service.Register(KernelLogger.myLogger(),"/Logger") @@ -450,5 +451,9 @@ def ContainerManagerSetOverrideEnvForContainersSimple(self,env): envEff = [ Engines.KeyValPairString(key=k,val=v) for k,v in env ] return self.SetOverrideEnvForContainers( envEff ) +def LogManagerFetch(self): + import SALOME_ContainerHelper + return [SALOME_ContainerHelper.ContainerLogInfo(elt) for elt in self.listOfContainerLogs()] + #to expose all objects to pydoc __all__=dir() diff --git a/src/Launcher/CMakeLists.txt b/src/Launcher/CMakeLists.txt index 0a11fa419..caa851941 100644 --- a/src/Launcher/CMakeLists.txt +++ b/src/Launcher/CMakeLists.txt @@ -144,6 +144,7 @@ SET(COMMON_HEADERS_HXX SET(LAUNCHER_PYTHON_SCRIPTS launcher_proxy.py + SALOME_LogManager.py ) SET(KernelLauncher_HEADERS KernelLauncher.hxx KernelLauncher.i) diff --git a/src/Launcher/KernelLauncher.cxx b/src/Launcher/KernelLauncher.cxx index c04805d21..ba5db8085 100644 --- a/src/Launcher/KernelLauncher.cxx +++ b/src/Launcher/KernelLauncher.cxx @@ -94,7 +94,7 @@ std::string GetLogManagerInstance() // SALOME_CPythonHelper *cPyh(SALOME_CPythonHelper::Singleton()); SALOME_Fake_NamingService *ns = new SALOME_Fake_NamingService; - SALOME_LogManager *esm(new SALOME_LogManager(cPyh,orb,safePOA,ns)); + SALOME_LogManager *esm(new SALOME_LogManager(orb,safePOA,ns)); esm->_remove_ref(); // CORBA::Object_var esmPtr = safePOA->servant_to_reference(esm); diff --git a/src/Launcher/SALOME_LogManager.cxx b/src/Launcher/SALOME_LogManager.cxx index 1aea17de8..f55a618eb 100644 --- a/src/Launcher/SALOME_LogManager.cxx +++ b/src/Launcher/SALOME_LogManager.cxx @@ -16,12 +16,10 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // -// Author : Anthony GEAY (EDF R&D) #include "SALOME_LogManager.hxx" #include "SALOME_Fake_NamingService.hxx" #include "SALOME_ContainerManager.hxx" -#include "SALOME_CPythonHelper.hxx" #ifndef WIN32 #include @@ -38,6 +36,18 @@ const char SALOME_LogManager::NAME_IN_NS[]="/LogManager"; +static std::vector FromPyToCpp(PyObject *obj) +{ + std::vector ret; + char *buffer = nullptr; + Py_ssize_t length = 0; + PyBytes_AsStringAndSize(obj,&buffer,&length); + ret.resize(length); + for(auto i = 0 ; i < length ; ++i) + ret[i] = buffer[i]; + return ret; +} + PortableServer::POA_var SALOME_ContainerScriptExecPerfLog::getPOA() { return father()->getPOA(); @@ -45,7 +55,50 @@ PortableServer::POA_var SALOME_ContainerScriptExecPerfLog::getPOA() void SALOME_ContainerScriptExecPerfLog::assign(const SALOME::vectorOfByte& value) { + auto sz = value.length(); + _data.resize( sz ); + for(auto i = 0 ; i < sz ; ++i) + _data[i] = value[i]; + // + AutoPyRef s( this->end( ) ); + // + _data = FromPyToCpp(s); +} + +SALOME::vectorOfByte *SALOME_ContainerScriptExecPerfLog::getObj() +{ + SALOME::vectorOfByte_var ret = new SALOME::vectorOfByte; + auto length = this->_data.size(); + ret->length(length); + for(auto i = 0 ; i < length ; ++i) + ret[i] = _data[i]; + return ret._retn(); +} +void SALOME_ContainerScriptExecPerfLog::start() +{ + AutoGIL gstate; + PyObject *result = PyObject_CallMethod(pyObj(),(char*)"start","",nullptr); + if (PyErr_Occurred()) + { + std::string error("can not start"); + PyErr_Print(); + THROW_SALOME_CORBA_EXCEPTION(error.c_str(),SALOME::INTERNAL_ERROR); + } +} + +AutoPyRef SALOME_ContainerScriptExecPerfLog::end() +{ + AutoGIL gstate; + //https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue + AutoPyRef result(PyObject_CallMethod(pyObj(),(char*)"end","y#",_data.data(),_data.size(),nullptr) ) ; + if (PyErr_Occurred()) + { + std::string error("can not end"); + PyErr_Print(); + THROW_SALOME_CORBA_EXCEPTION(error.c_str(),SALOME::INTERNAL_ERROR); + } + return result; } ///// @@ -73,12 +126,29 @@ Engines::ContainerScriptExecPerfLog_ptr SALOME_ContainerScriptPerfLog::addExecut CORBA::Object_var executionPtr(getPOA()->id_to_reference(id)); Engines::ContainerScriptExecPerfLog_var executionPtr2 = Engines::ContainerScriptExecPerfLog::_narrow(executionPtr); _sessions.push_back( executionPtr2 ); - return executionPtr2; + { + AutoGIL gstate; + PyObject *result = PyObject_CallMethod(pyObj(),(char*)"addExecution","",nullptr); + if (PyErr_Occurred()) + { + std::string error("can not addExecution"); + PyErr_Print(); + THROW_SALOME_CORBA_EXCEPTION(error.c_str(),SALOME::INTERNAL_ERROR); + } + execution->setPyObj( result ); + } + execution->start(); + return executionPtr2._retn(); } Engines::ListOfContainerScriptExecPerfLog *SALOME_ContainerScriptPerfLog::listOfExecs() { - + Engines::ListOfContainerScriptExecPerfLog_var ret = new Engines::ListOfContainerScriptExecPerfLog; + auto sz = this->_sessions.size(); + ret->length(sz); + for(auto i = 0 ; i < sz ; ++i) + ret[i] = this->_sessions[i]; + return ret._retn(); } ///// @@ -96,7 +166,18 @@ Engines::ContainerScriptPerfLog_ptr SALOME_ContainerPerfLog::addScript(const cha CORBA::Object_var scriptPtr(getPOA()->id_to_reference(id)); Engines::ContainerScriptPerfLog_var scriptPtr2 = Engines::ContainerScriptPerfLog::_narrow(scriptPtr); _scripts.push_back( scriptPtr2 ); - return scriptPtr2; + { + AutoGIL gstate; + PyObject *result = PyObject_CallMethod(pyObj(),(char*)"addScript","",nullptr); + if (PyErr_Occurred()) + { + std::string error("can not addScript"); + PyErr_Print(); + THROW_SALOME_CORBA_EXCEPTION(error.c_str(),SALOME::INTERNAL_ERROR); + } + script->setPyObj( result ); + } + return scriptPtr2._retn(); } Engines::ListOfContainerScriptPerfLog *SALOME_ContainerPerfLog::listOfScripts() @@ -121,23 +202,23 @@ char *SALOME_ContainerPerfLog::getContainerEntryInNS() ///// -SALOME_LogManager::SALOME_LogManager(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, PortableServer::POA_var poa,SALOME_NamingService_Abstract *ns):_pyHelper(pyHelper),_poa(poa) +SALOME_LogManager::SALOME_LogManager(CORBA::ORB_ptr orb, PortableServer::POA_var poa,SALOME_NamingService_Abstract *ns):_poa(poa) { _NS.reset(ns); PortableServer::ObjectId_var id(_poa->activate_object(this)); CORBA::Object_var obj(_poa->id_to_reference(id)); Engines::LogManager_var refPtr(Engines::LogManager::_narrow(obj)); _NS->Register(refPtr,NAME_IN_NS); -} - -SALOME::vectorOfByte *SALOME_LogManager::getAllInfo() -{ - auto length = 2; - SALOME::vectorOfByte *ret = new SALOME::vectorOfByte; - ret->length(length); - for(auto i = 0 ; i < length ; ++i) - (*ret)[i] = 1; - return ret; + { + AutoGIL gstate; + std::ostringstream myCommand; + myCommand << "mylogmanager = SALOME_LogManager.SALOME_LogManagerHelper()"; + PyRun_SimpleString("import SALOME_LogManager"); + PyRun_SimpleString((char*)myCommand.str().c_str()); + PyObject *mainmod = PyImport_AddModule("__main__"); + PyObject *globals = PyModule_GetDict(mainmod); + _pyLogManager = PyDict_GetItemString(globals, "mylogmanager"); + } } Engines::ContainerPerfLog_ptr SALOME_LogManager::declareContainer(const char *contInNS, const char *logfile) @@ -148,7 +229,18 @@ Engines::ContainerPerfLog_ptr SALOME_LogManager::declareContainer(const char *co cont->_remove_ref(); Engines::ContainerPerfLog_var contPtr2 = Engines::ContainerPerfLog::_narrow(contPtr); _containers.push_back( contPtr2 ); - return contPtr2; + { + AutoGIL gstate; + PyObject *result = PyObject_CallMethod(_pyLogManager,(char*)"declareContainer","ss",contInNS,logfile,nullptr); + if (PyErr_Occurred()) + { + std::string error("can not declareContainer"); + PyErr_Print(); + THROW_SALOME_CORBA_EXCEPTION(error.c_str(),SALOME::INTERNAL_ERROR); + } + cont->setPyObj( result ); + } + return contPtr2._retn(); } Engines::ListOfContainerPerfLog *SALOME_LogManager::listOfContainerLogs() @@ -157,6 +249,8 @@ Engines::ListOfContainerPerfLog *SALOME_LogManager::listOfContainerLogs() std::size_t len( this->_containers.size() ); ret->length( len ); for(std::size_t i = 0 ; i < len ; ++i) + { ret[i] = this->_containers[i]; + } return ret._retn(); } diff --git a/src/Launcher/SALOME_LogManager.hxx b/src/Launcher/SALOME_LogManager.hxx index 373924659..81c587669 100644 --- a/src/Launcher/SALOME_LogManager.hxx +++ b/src/Launcher/SALOME_LogManager.hxx @@ -21,7 +21,11 @@ #include "SALOME_Launcher_defs.hxx" -#include +#include "Python.h" + +#include "PythonCppUtils.hxx" +#include "Utils_CorbaException.hxx" +#include "SALOMEconfig.h" #include CORBA_SERVER_HEADER(SALOME_LogManager) @@ -30,7 +34,6 @@ #include class SALOME_NamingService_Abstract; -class SALOME_CPythonHelper; class SALOME_LogManager; class SALOME_ContainerPerfLog; class SALOME_ContainerScriptPerfLog; @@ -40,10 +43,18 @@ class SALOMELAUNCHER_EXPORT SALOME_ContainerScriptExecPerfLog : public POA_Engin public: SALOME_ContainerScriptExecPerfLog(SALOME_ContainerScriptPerfLog *father):_father(father) { } SALOME_ContainerScriptPerfLog *father() const { return _father; } + void setPyObj(PyObject *obj) { _pyExecutionLog.set(obj); } + PyObject *pyObj() { return _pyExecutionLog.get(); } PortableServer::POA_var getPOA(); void assign(const SALOME::vectorOfByte& value) override; + SALOME::vectorOfByte *getObj() override; +public: + void start(); + AutoPyRef end(); private: + AutoPyRef _pyExecutionLog; SALOME_ContainerScriptPerfLog *_father = nullptr; + std::vector _data; }; class SALOMELAUNCHER_EXPORT SALOME_ContainerScriptPerfLog : public POA_Engines::ContainerScriptPerfLog @@ -51,12 +62,15 @@ class SALOMELAUNCHER_EXPORT SALOME_ContainerScriptPerfLog : public POA_Engines:: public: SALOME_ContainerScriptPerfLog(SALOME_ContainerPerfLog *father, const std::string& name, const std::string& code):_father(father),_name(name),_code(code) { } SALOME_ContainerPerfLog *father() const { return _father; } + void setPyObj(PyObject *obj) { _pyScriptLog.set(obj); } + PyObject *pyObj() { return _pyScriptLog.get(); } PortableServer::POA_var getPOA(); Engines::ContainerScriptExecPerfLog_ptr addExecutionSession() override; Engines::ListOfContainerScriptExecPerfLog *listOfExecs() override; char *getCode() override; char *getName() override; private: + AutoPyRef _pyScriptLog; SALOME_ContainerPerfLog *_father = nullptr; std::string _name; std::string _code; @@ -68,12 +82,15 @@ class SALOMELAUNCHER_EXPORT SALOME_ContainerPerfLog : public POA_Engines::Contai public: SALOME_ContainerPerfLog(SALOME_LogManager *father, const std::string& nameInNS, const std::string& logFile):_father(father),_name_in_ns(nameInNS),_log_file(logFile) { } SALOME_LogManager *father() const { return _father; } + void setPyObj(PyObject *obj) { _pyContLog.set(obj); } + PyObject *pyObj() { return _pyContLog.get(); } PortableServer::POA_var getPOA(); char *getLogFile() override; char *getContainerEntryInNS() override; Engines::ContainerScriptPerfLog_ptr addScript(const char *name, const char *code) override; Engines::ListOfContainerScriptPerfLog *listOfScripts() override; private: + AutoPyRef _pyContLog; SALOME_LogManager *_father = nullptr; std::string _name_in_ns; std::string _log_file; @@ -83,16 +100,14 @@ private: class SALOMELAUNCHER_EXPORT SALOME_LogManager : public POA_Engines::LogManager { public: - SALOME_LogManager(const SALOME_CPythonHelper *pyHelper, CORBA::ORB_ptr orb, PortableServer::POA_var poa, SALOME_NamingService_Abstract *ns = nullptr); + SALOME_LogManager(CORBA::ORB_ptr orb, PortableServer::POA_var poa, SALOME_NamingService_Abstract *ns = nullptr); PortableServer::POA_var getPOA() { return _poa; } + PyObject *pyHelper() const { return _pyLogManager; } virtual ~SALOME_LogManager() = default; - SALOME::vectorOfByte *getAllInfo() override; Engines::ContainerPerfLog_ptr declareContainer(const char *contInNS, const char *logfile) override; Engines::ListOfContainerPerfLog *listOfContainerLogs() override; - public: - const SALOME_CPythonHelper *getPyHelper() const { return _pyHelper; } private: - const SALOME_CPythonHelper *_pyHelper = nullptr; + PyObject *_pyLogManager = nullptr; std::unique_ptr _NS; PortableServer::POA_var _poa; std::vector _containers; diff --git a/src/Launcher/SALOME_LogManager.py b/src/Launcher/SALOME_LogManager.py new file mode 100644 index 000000000..6e30a380d --- /dev/null +++ b/src/Launcher/SALOME_LogManager.py @@ -0,0 +1,79 @@ +# -*- coding: iso-8859-1 -*- +# Copyright (C) 2024 CEA, EDF +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# +# See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +# + +import os +import sys +import pickle +from SALOME_ContainerHelper import ScriptExecInfo + +class SALOME_ContainerScriptExecPerfLog: + def __init__(self, father): + self._father = father + self._start_pos = None + self._stop_pos = None + + @property + def father(self): + return self._father + + def end(self,s): + obj = pickle.loads(s) + self._stop_pos = os.path.getsize( self.father.father.logfilename ) + setattr(obj,"tracePosStop",self._stop_pos) + setattr(obj,"tracePosStart",self._start_pos) + return pickle.dumps(obj) + + def start(self): + self._start_pos = os.path.getsize( self.father.father.logfilename ) + +class SALOME_ContainerScriptPerfLog: + def __init__(self, father): + self._father = father + + @property + def father(self): + return self._father + + def addExecution(self): + return SALOME_ContainerScriptExecPerfLog(self) + +class SALOME_ContainerPerfLog: + def __init__(self,contInNS,logfile): + self._container_in_ns = contInNS + self._log_filename = logfile + + @property + def logfilename(self): + return self._log_filename + + @property + def father(self): + return self._father + + def addScript(self): + return SALOME_ContainerScriptPerfLog(self) + +class SALOME_LogManagerHelper: + def __init__(self): + pass + + def declareContainer(self, contInNS,logfile): + inst = SALOME_ContainerPerfLog(contInNS,logfile) + return inst -- 2.39.2