# -*- coding: iso-8859-1 -*-
-# Copyright (C) 2007-2022 CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
import SALOME__POA
import SALOME
+MY_CONTAINER_ENTRY_IN_GLBS = "my_container"
+
class Generic(SALOME__POA.GenericObj):
"""A Python implementation of the GenericObj CORBA IDL"""
def __init__(self,poa):
linecache.cache[nodeName]=0,None,code.split('\n'),nodeName
ccode=compile(code,nodeName,'exec')
self.context={}
- self.context["my_container"] = self.my_container
+ self.context[MY_CONTAINER_ENTRY_IN_GLBS] = self.my_container
exec(ccode, self.context)
def getContainer(self):
# default is 50 MB
SALOME_BIG_OBJ_ON_DISK_THRES_DFT = 50000000
+from ctypes import c_int
+TypeCounter = c_int
+
+def GetSizeOfTCnt():
+ return len( bytes(TypeCounter(0) ) )
+
+def GetObjectFromFile(fname):
+ with open(fname,"rb") as f:
+ cntb = f.read( GetSizeOfTCnt() )
+ cnt = TypeCounter.from_buffer_copy( cntb ).value
+ obj = pickle.load(f)
+ return obj,cnt
+
+def DumpInFile(obj,fname):
+ with open(fname,"wb") as f:
+ f.write( bytes( TypeCounter(1) ) )
+ f.write( obj )
+
+def IncrRefInFile(fname):
+ with open(fname,"rb") as f:
+ cntb = f.read( GetSizeOfTCnt() )
+ cnt = TypeCounter.from_buffer_copy( cntb ).value
+ with open(fname,"rb+") as f:
+ f.write( bytes( TypeCounter(cnt+1) ) )
+
+def DecrRefInFile(fname):
+ import os
+ with open(fname,"rb") as f:
+ cntb = f.read( GetSizeOfTCnt() )
+ cnt = TypeCounter.from_buffer_copy( cntb ).value
+ #
+ if cnt == 1:
+ os.unlink( fname )
+ else:
+ with open(fname,"rb+") as f:
+ f.write( bytes( TypeCounter(cnt-1) ) )
+
def GetBigObjectOnDiskThreshold():
import os
if SALOME_BIG_OBJ_ON_DISK_THRES_VAR in os.environ:
else:
return SALOME_BIG_OBJ_ON_DISK_THRES_DFT
+def ActivateProxyMecanismOrNot( sizeInByte ):
+ thres = GetBigObjectOnDiskThreshold()
+ if thres == -1:
+ return False
+ else:
+ return sizeInByte > thres
+
def GetBigObjectDirectory():
import os
if SALOME_FILE_BIG_OBJ_DIR not in os.environ:
:type objSerialized: bytes
"""
self._filename = fileName
+ # attribute _destroy is here to tell client side or server side
+ # only client side can be with _destroy set to True. server side due to risk of concurrency
+ # so pickled form of self must be done with this attribute set to False.
self._destroy = False
self.__dumpIntoFile(objSerialized)
def getDestroyStatus(self):
return self._destroy
+ def incrRef(self):
+ if self._destroy:
+ IncrRefInFile( self._filename )
+ else:
+ # should never happen !
+ RuntimeError("Invalid call to incrRef !")
+
+ def decrRef(self):
+ if self._destroy:
+ DecrRefInFile( self._filename )
+ else:
+ # should never happen !
+ RuntimeError("Invalid call to decrRef !")
+
def unlinkOnDestructor(self):
self._destroy = True
def __del__(self):
if self._destroy:
- import os
- os.unlink( self._filename )
+ DecrRefInFile( self._filename )
def getFileName(self):
return self._filename
def __dumpIntoFile(self, objSerialized):
- with open(self._filename,"wb") as f:
- f.write(objSerialized)
+ DumpInFile( objSerialized, self._filename )
def get(self):
- import pickle
- with open(self._filename,"rb") as f:
- return pickle.load(f)
+ obj, _ = GetObjectFromFile( self._filename )
+ return obj
def __float__(self):
return float( self.get() )
fullObj = BigObjectOnDiskBase.get(self)
return fullObj[ self._pos ]
+ def __getitem__(self, i):
+ return self.get()[i]
+
+ def __len__(self):
+ return len(self.get())
+
class BigObjectOnDiskSequence(BigObjectOnDiskBase):
def __init__(self, length, fileName, objSerialized):
BigObjectOnDiskBase.__init__(self, fileName, objSerialized)
def SpoolPickleObject( obj ):
import pickle
pickleObjInit = pickle.dumps( obj , pickle.HIGHEST_PROTOCOL )
- if len(pickleObjInit) < GetBigObjectOnDiskThreshold():
+ if not ActivateProxyMecanismOrNot( len(pickleObjInit) ):
return pickleObjInit
else:
if isinstance( obj, list):
return pickleProxy
def UnProxyObjectSimple( obj ):
+ """
+ Method to be called in Remote mode. Alterate the obj _status attribute.
+ Because the slave process does not participate in the reference counting
+ """
if isinstance(obj,BigObjectOnDiskBase):
+ obj.doNotTouchFile()
return obj.get()
elif isinstance( obj, list):
retObj = []
else:
return obj
-def UnProxyObject( obj ):
+def UnProxyObjectSimpleLocal( obj ):
+ """
+ Method to be called in Local mode. Do not alterate the PyObj counter
+ """
if isinstance(obj,BigObjectOnDiskBase):
- obj.doNotTouchFile()
return obj.get()
- if isinstance(obj,list) or isinstance(obj,tuple):
+ elif isinstance( obj, list):
+ retObj = []
for elt in obj:
- if isinstance(elt,BigObjectOnDiskBase):
- elt.doNotTouchFile()
- return obj
+ retObj.append( UnProxyObjectSimpleLocal(elt) )
+ return retObj
else:
return obj
linecache.cache[nodeName]=0,None,code.split('\n'),nodeName
self.ccode=compile(code,nodeName,'exec')
self.context={}
- self.context["my_container"] = self.my_container
+ self.context[MY_CONTAINER_ENTRY_IN_GLBS] = self.my_container
+
+ def __del__(self):
+ # force removal of self.context. Don t know why it s not done by default
+ self.removeAllVarsInContext()
+ pass
def getContainer(self):
return self.my_container
_,kws=pickle.loads(data)
for elt in kws:
# fetch real data if necessary
- kws[elt] = UnProxyObject( kws[elt] )
+ kws[elt] = UnProxyObjectSimple( kws[elt] )
self.context.update(kws)
except Exception:
exc_typ,exc_val,exc_fr=sys.exc_info()
def listAllVarsInContext(self):
import re
pat = re.compile("^__([a-z]+)__$")
- return [elt for elt in self.context if not pat.match(elt)]
+ return [elt for elt in self.context if not pat.match(elt) and elt != MY_CONTAINER_ENTRY_IN_GLBS]
def removeAllVarsInContext(self):
for elt in self.listAllVarsInContext():