1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 from __future__ import with_statement
30 __authors__ = [ "Jérôme Kieffer" ]
31 __contact__ = "jerome.kieffer@esrf.fr"
32 __license__ = "LGPLv3+"
33 __copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
34 __date__ = "20120228"
35
36 import os, tempfile
37 from EDLogging import EDLogging
38 from EDFactoryPluginStatic import EDFactoryPluginStatic
39 from EDUtilsPlatform import EDUtilsPlatform
40 from EDSession import EDSession
41 from EDUtilsPath import EDUtilsPath
42
43 TEMPDIR = tempfile.gettempdir()
44
45 if os.name in ["posix", "nt"]:
46 h5pyPath = os.path.join(EDUtilsPath.EDNA_HOME, "libraries", "H5Py-1.3.0", EDUtilsPlatform.architecture)
47 h5py = EDFactoryPluginStatic.preImport("h5py", _strPath=h5pyPath, _strForceVersion="1.8", _strMethodVersion="version.api_version")
48
49 if h5py is None:
50 BACKEND = "dict"
51 else:
52 BACKEND = "hdf5"
53 else:
54 BACKEND = "dict"
55 if BACKEND == "dict":
56 import pickle
57
58
59 -class EDShare(EDLogging, EDSession):
60 """
61 This class implements methods to share (large) arrays between plugins.
62
63 It is a Singleton
64 """
65 _instance = None
67 EDLogging.__init__(self)
68
69 self._backend = BACKEND
70 self._filename = None
71 self._storage = None
72 self._listKeys = []
73 self._dictAttrs = {}
74
75
77 """
78 Makes this class a SINGLETON
79 """
80 return self
81
83 """
84 getter for a key:
85 """
86 try:
87 unicode(key)
88 except UnicodeDecodeError:
89 self.ERROR("EDShare.__getitem__: Unicode Error %s" % key)
90 if self.isInitialized():
91 with self.locked():
92 if key in self._listKeys:
93 try:
94 value = self._storage[key]
95 except Exception:
96 value = None
97 self.ERROR("EDShare (exception): no such key %s" % key)
98 else:
99 value = None
100 self.ERROR("EDShare: no such key %s" % key)
101 else:
102 self.WARNING("EDShare is uninitialized: initializing")
103 self.initialize()
104 value = None
105 if value is not None:
106 return value[:]
107 get = __getitem__
108
109
111 """
112 setter for a key/value pair
113 @type key: string
114 @type value: int, float, or string ; one or many in lists or arrays (without mixing types)
115 """
116 if not self.isInitialized():
117 self.WARNING("EDShare is uninitialized: initializing")
118 self.initialize()
119 with self.locked():
120 if key in self._listKeys:
121 self.ERROR("EDShare: Redefinition of elements is forbidden key=%s, mean value=%s " % (key, value.mean()))
122 else:
123 self._listKeys.append(key)
124 self._storage[key] = value
125 self._dictAttrs[key] = {}
126 set = __setitem__
127
128
130 return (key in self._listKeys)
131 has_key = __contains__
132
133
145
160
161
163 return not((self._filename is None) and (self._storage is None))
164
165
167 """
168 Initialize EDShare to use this
169 """
170 with self.locked():
171 if filename is None:
172 if self._backend == "hdf5":
173 filename = "EDShare-%s.h5" % self.sessionId
174 if self._backend == "dict":
175 filename = "EDShare-%s.pickle" % self.sessionId
176 absFilename = os.path.abspath(os.path.join(directory, filename))
177
178 if not self.isInitialized():
179 self._filename = absFilename
180 if not os.path.isdir(directory):
181 os.makedirs(directory)
182 if (self._backend == "dict"):
183 if os.path.isfile(self._filename):
184 self._storage = pickle.load(open(self._filename))
185 self._listKeys = self._storage.keys()
186 if not isinstance(self._storage, dict):
187 self.ERROR("I did not load a dictionary ... resetting")
188 self._storage = {}
189 self._listKeys = []
190 else:
191 self._storage = {}
192 self._listKeys = []
193 elif (self._backend == "hdf5"):
194 self._storage = h5py.File(self._filename)
195 self._storage.visititems(self._analyseHDF5)
196 else:
197 self.ERROR("unrecognized backend !!!")
198 else:
199 if (absFilename != self._filename):
200 self.ERROR("EDShare was already initialized with backend %s on %s" % (self._backend, self._storage))
201
202
204 """
205 Write the content of the cache on the disk
206 """
207 with self.locked():
208 if self.isInitialized():
209 if self._backend == "hdf5":
210 if h5py.version.api_version_tuple < (1, 10):
211
212 self._storage.close()
213 self._storage = h5py.File(self._filename)
214 else:
215 self._storage.flush()
216 elif (self._backend == "dict"):
217 fileOut = open(self._filename, "w")
218 self._storage = pickle.dump(self._storage, fileOut)
219 fileOut.close()
220 else:
221 self.ERROR("EDShare: unrecognized backend !!!")
222 else:
223 self.ERROR("EDShare: Uninitialized !!!")
224
225
226 - def close(self, remove=False):
227 """
228 Method that closes the file and resets the cache.
229 if remove: delete the input file as well.
230
231 Useful for testing mainly
232 """
233 with self.locked():
234 if self.isInitialized():
235 if self._backend == "hdf5":
236 self._storage.close()
237 else:
238 self._storage.flush()
239 self._listKeys = []
240 self._storage = None
241 if remove:
242 os.unlink(self._filename)
243 self._filename = None
244 else:
245 self.ERROR("Closing a file that is uninitialized !!!")
246
247
249 """
250 Part of the recursive analysis of an HDF5 tree to retrieve all datasets.
251 Populates self._listKeys
252
253 @param name: name of the object itself (string)
254 @param obj: the h5py object itself
255 @return None
256 """
257 if isinstance(obj, h5py.Dataset):
258 self._listKeys.append(name)
259
260
262 """
263 Returns the list of
264 """
265 return self._listKeys
266
267
270 backend = property(get_backend)
271
272
274 return self._filename
275 filename = property(get_filename)
276
277
278
279 EDShare = EDShare()
280