Package MDSplus ::
Module connection
|
|
1 import ctypes as _C
2 import numpy as _N
3 from _descriptor import descriptor,descriptor_a
4 from _mdsshr import _load_library,MdsException,MdsGetMsg
5 from mdsdata import makeData,Data
6 from mdsscalar import Scalar
7 from mdsarray import Array
8 from _mdsdtypes import *
9 from apd import List,Dictionary
10
12 """Implements an MDSip connection to an MDSplus server"""
13 __MdsIpShr=_load_library('MdsIpShr')
14 __ConnectToMds=__MdsIpShr.ConnectToMds
15 __ConnectToMds.argtypes=[_C.c_char_p]
16 __MdsOpen=__MdsIpShr.MdsOpen
17 __MdsOpen.argtypes=[_C.c_int,_C.c_char_p,_C.c_int]
18 __GetAnswerInfoTS=__MdsIpShr.GetAnswerInfoTS
19 __GetAnswerInfoTS.argtypes=[_C.c_int,_C.POINTER(_C.c_ubyte),_C.POINTER(_C.c_ushort),_C.POINTER(_C.c_ubyte),
20 _C.c_void_p,_C.POINTER(_C.c_ulong),_C.POINTER(_C.c_void_p),_C.POINTER(_C.c_void_p)]
21 __mdsipFree=__MdsIpShr.MdsIpFree
22 __mdsipFree.argtypes=[_C.c_void_p]
23 __SendArg=__MdsIpShr.SendArg
24 __SendArg.argtypes=[_C.c_int,_C.c_ubyte,_C.c_ubyte,_C.c_ubyte,_C.c_ushort,_C.c_ubyte,_C.c_void_p, _C.c_void_p]
25
27 """Internal routine used in determining characteristics of the value"""
28 d=descriptor(value)
29 if d.dtype==DTYPE_DSC:
30 if d.pointer.contents.dclass == 4:
31 a=_C.cast(d.pointer,_C.POINTER(descriptor_a)).contents
32 dims=list()
33 if a.dimct == 1:
34 dims.append(a.arsize/a.length)
35 else:
36 for i in range(a.dimct):
37 dims.append(a.coeff_and_bounds[i])
38 dtype=a.dtype
39 length=a.length
40 dims=_N.array(dims,dtype=_N.uint32)
41 dimct=a.dimct
42 pointer=a.pointer
43 else:
44 raise MdsException,"Error handling argument of type %s" % (type(value),)
45 else:
46 length=d.length
47 dtype=d.dtype
48 dims=_N.array(0,dtype=_N.uint32)
49 dimct=0
50 pointer=d.pointer
51 if dtype == DTYPE_FLOAT:
52 dtype = DTYPE_F
53 elif dtype == DTYPE_DOUBLE:
54 dtype = DTYPE_D
55 elif dtype == DTYPE_FLOAT_COMPLEX:
56 dtype = DTYPE_FC
57 elif dtype == DTYPE_DOUBLE_COMPLEX:
58 dtype = DTYPE_DC
59 return {'dtype':dtype,'length':length,'dimct':dimct,'dims':dims,'address':pointer}
60
62 dtype=_C.c_ubyte(0)
63 length=_C.c_ushort(0)
64 ndims=_C.c_ubyte(0)
65 dims=_N.array([0,0,0,0,0,0,0,0],dtype=_N.uint32)
66 numbytes=_C.c_ulong(0)
67 ans=_C.c_void_p(0)
68 mem=_C.c_void_p(0)
69 status=self.__GetAnswerInfoTS(self.socket,dtype,length,ndims,dims.ctypes.data,numbytes,_C.pointer(ans),_C.pointer(mem))
70 dtype=dtype.value
71 if dtype == DTYPE_F:
72 dtype = DTYPE_FLOAT
73 elif dtype == DTYPE_D:
74 dtype = DTYPE_DOUBLE
75 elif dtype == DTYPE_FC:
76 dtype = DTYPE_FLOAT_COMPLEX
77 elif dtype == DTYPE_DC:
78 dtype = DTYPE_DOUBLE_COMPLEX
79 if ndims.value == 0:
80 val=descriptor()
81 val.dtype=dtype
82 val.dclass=1
83 val.length=length.value
84 val.pointer=_C.cast(ans,_C.POINTER(descriptor))
85 ans=val.value
86 else:
87 val=descriptor_a()
88 val.dtype=dtype
89 val.dclass=4
90 val.length=length.value
91 val.pointer=ans
92 val.scale=0
93 val.digits=0
94 val.aflags=0
95 val.dimct=ndims.value
96 val.arsize=numbytes.value
97 val.a0=val.pointer
98 if val.dimct > 1:
99 val.coeff=1
100 for i in range(val.dimct):
101 val.coeff_and_bounds[i]=int(dims[i])
102 ans=val.value
103 if not ((status & 1) == 1):
104 if mem.value is not None:
105 self.__mdsipFree(mem)
106 raise MdsException,MdsGetMsg(status)
107 if mem.value is not None:
108 self.__mdsipFree(mem)
109 return ans
110
112 self.socket=self.__ConnectToMds(hostspec)
113 if self.socket == -1:
114 raise Exception,"Error connecting to %s" % (hostspec,)
115 self.hostspec=hostspec
116
123 __processGetMany__=classmethod(__processGetMany__)
124
131 __processPutMany__=classmethod(__processPutMany__)
132
133
135 """Internal routine to send argument to mdsip server"""
136 val=makeData(value)
137 if not isinstance(val,Scalar) and not isinstance(val,Array):
138 val=makeData(val.data())
139 valInfo=self.__inspect__(val)
140 status=self.__SendArg(self.socket,idx,valInfo['dtype'],num,valInfo['length'],valInfo['dimct'],valInfo['dims'].ctypes.data,valInfo['address'])
141 if not ((status & 1)==1):
142 raise MdsException,MdsGetMsg(status)
143
145 """Close an MDSplus tree on the remote server
146 @param args: you can optionally include a tree and shot number if omitted all trees open are closed.
147 @type args: str and int
148 @rtype: None
149 """
150 if len(args) == 0:
151 exp="TreeClose()"
152 elif len(args) == 2:
153 exp="TreeClose($,$)"
154 else:
155 raise TypeError,"closeTree takes zero or two arguments (%d given)" % (len(args),)
156 status=self.value(exp,arglist=args)
157 if not ((status & 1)==1):
158 raise MdsException,MdsGetMsg(status)
159
161 """Return instance of a Connection.GetMany class. See the Connection.GetMany documentation for further information."""
162 return Connection.GetMany(connection=self)
163
165 """Open an MDSplus tree on a remote server
166 @param tree: Name of tree
167 @type tree: str
168 @param shot: shot number
169 @type shot: int
170 @rtype: None
171 """
172 status=self.value("TreeOpen($,$)",tree,shot)
173 if not ((status & 1)==1):
174 raise MdsException,MdsGetMsg(status)
175
176 - def put(self,node,exp,*args):
177 """Put data into a node in an MDSplus tree
178 @param node: Node name, relative or full path. Include double backslashes in string if node name includes one.
179 @type node: str
180 @param exp: TDI expression with placeholders for any optional args.
181 @type exp: str
182 @param args: optional arguments to be inserted for the placeholders in the expression.
183 @type args: Data
184 @rtype: None
185 """
186 num=len(args)+3
187 idx=0
188 pargs=[node,exp]
189 putexp="TreePut($,$"
190 for i in range(len(args)):
191 putexp=putexp+",$"
192 pargs.append(args[i])
193 putexp=putexp+")"
194 status=self.value(putexp,arglists=pargs)
195 if not ((status & 1)==1):
196 raise MdsException,MdsGetMsg(status)
197
199 """Return an instance of a Connection.PutMany class. See the Connection.PutMany documentation for further information."""
200 return Connection.PutMany(connection=self)
201
202 - def value(self,exp,*args,**kwargs):
203 """Evaluate and expression on the remote server
204 @param exp: TDI expression to be evaluated
205 @type exp: str
206 @param args: optional arguments to be inserted for the placeholders in the expression.
207 @type args: Data
208 @param kwargs: Used for internal purposes
209 @return: result of evaluating the expression on the remote server
210 @rtype: Scalar or Array
211 """
212 if 'arglist' in kwargs:
213 args=kwargs['arglist']
214 num=len(args)+1
215 idx=0
216 self.__sendArg__(exp,idx,num)
217 for arg in args:
218 idx=idx+1
219 self.__sendArg__(arg,idx,num)
220 return self.__getAnswer__()
221
222
224 """Change the current default tree location on the remote server
225 @param path: Tree node path to be the new default location.
226 @type path: str
227 @rtype: None
228 """
229 status=self.value("TreeSetDefault($)",path)
230 if not ((status & 1)==1):
231 raise MdsException,MdsGetMsg(status)
232
233
235 """Build a list of expressions to evaluate
236
237 To reduce the number of network transactions between you and the remote system you can
238 use the GetMany class to specify a list of expressions to be evaluated and then
239 send that list to the remote system in one network transation. The remote system will
240 then evaluate all of the expressions and return the answer in one response.
241
242 To use the GetMany class you can create an instance using the getMany() method of a
243 Connection instance. You then use the GetMany.append(name,expression[,args]) method
244 to add expressions to the list. Once the list is complete you then use the GetMany.execute()
245 method to execute the expressions on the remote host and retrieve the answers. This will
246 return a dictionary instance with the names assigned to the expressions as the key. Each
247 name will have a dictionary instance containing the result of the execution of the expression.
248 If this dictionary has an 'error' key then its value will be an error string, otherwise
249 the dictionary should have a 'value' key containing the result.
250
251 The GetMany instance can be executed multiple times. For instance, if you want to get the
252 same information from many different trees you could use the Connection.openTeee(tree,shot)
253 method between executions of the same GetMany instance.
254
255 NOTE: MDSplus can currently only address objects less than 4 gigabytes. Therefore the
256 maximum size of the expression list with arguments and the result dictionary is approximately 4 gigatypes.
257 """
258
259 - def __init__(self,value=None,connection=None):
265
266 - def append(self,name,exp,*args):
267 """Append expression to the list.
268 @param name: name to assign to the expression for identifying it in the result dictionary.
269 @type name: str
270 @param exp: expression to be evaluated with placeholders for optional arguments
271 @type exp: str
272 @param args: optional arguments to replace placeholders in the expression
273 @type args: Data
274 @rtype: None
275 """
276 super(Connection.GetMany,self).append(Dictionary({'name':str(name),'exp':str(exp),'args':args}))
277
279 """Execute the list. Send the list to the remote server for evaluation and return the answer as a dict instance."""
280 if self.connection is None:
281 self.result=Dictionary()
282 for val in self:
283 name=val['name']
284 try:
285 self.result[name]=Dictionary({'value':Data.execute('data('+val['exp']+')',tuple(val['args']))})
286 except Exception,e:
287 self.result[name]=Dictionary({'error':str(e)})
288 return self.result
289 else:
290 ans=self.connection.value("public __getManyIn__=$,Py('Connection.__processGetMany__()'),public __getManyOut__",self.serialize())
291 if isinstance(ans,str):
292 raise Exception("Error fetching data: "+ans)
293 self.result=ans.deserialize()
294 return self.result
295
296 - def get(self,name):
297 """Get the result of an expression identified by name from the last invokation of the execute() method.
298 @param name: name associated with an expression.
299 @type name: str
300 @return: result of the expression evaluation.
301 @rtype: Scalar or Array
302 """
303 if self.result is None:
304 raise Exception,"GetMany has not yet been executed. Use the execute() method on this object first."
305 if 'value' in self.result[name]:
306 return self.result[name]['value']
307 else:
308 raise Exception,self.result[name]['error']
309
310 - def insert(self,beforename, name,exp,*args):
311 """Insert an expression in the list before the one named in the beforename argument.
312 @param beforename: Insert the expression before this one
313 @type beforename: str
314 @param name: Name to associate with the result of this expression
315 @type name: str
316 @param exp: TDI expression to be evaluated with optional placeholders for the arguments
317 @type expression: str
318 @param args: Optional arguments to replace placeholders in the expression
319 @type args: Data
320 @rtype: None
321 """
322 d=Dictionary({'name':name,'exp':str(exp),'args':args})
323 n = 0
324 for item in self:
325 if item['name'] == beforename:
326 super(Connection.GetMany,self).insert(n,d)
327 return
328 else:
329 n=n+1
330 raise Exception,"Item %s not found in list" % (beforename,)
331
333 """Remove first occurrence of expression identified by its name from the list.
334 @param name: Name of expression to be removed.
335 @type name: str
336 @rtype: None
337 """
338 for item in self:
339 if item['name'] == name:
340 super(Connection.GetMany,self).remove(item)
341 return
342 raise Exception,"Item %s not found in list" % (name,)
343
345 """Build list of put instructions."""
346
347 - def __init__(self,value=None,connection=None):
353
354 - def append(self,node,exp,*args):
355 """Append node data information
356 @param node: Node name where to store the data
357 @type node: str
358 @param exp: TDI expression to be stored in node with optional placeholders for arguments
359 @type exp: str
360 @param args: optional arguments to replace placeholders in expression
361 @type args: Data
362 @rtype: None
363 """
364 super(Connection.PutMany,self).append(Dictionary({'node':str(node),'exp':str(exp),'args':args}))
365
366 - def get(self,node):
367 """Return the status of the put for this node. Anything other than 'Success' will raise an exception.
368 @param node: Node name. Must match exactly the node name used in the append() or insert() methods.
369 @type node: str
370 @result: The string 'Success' otherwise an exception is raised.
371 @rtype: str
372 """
373 if self.result is None:
374 raise Exception,"PutMany has not yet been executed. Use the execute() method on this object first."
375 if self.result[node] != "Success":
376 raise MdsException,self.result[node]
377 else:
378 return self.result[node]
379
381 """Execute the PutMany by sending the instructions to the remote server. The remote server will attempt to
382 put the data in each of the nodes listed and after completion return a dict instance of the status of each put.
383 @return: dict instance with status of each put. The key of the result will be the node name.
384 """
385 if self.connection is None:
386 self.result=Dictionary()
387 for val in self:
388 node=val['node']
389 try:
390 exp='TreePut($,$'
391 args=[node,val['exp']]
392 for i in range(len(val['args'])):
393 exp=exp+',$'
394 args.append(val['args'][i])
395 exp=exp+')'
396 status=Data.execute(exp,tuple(args))
397 if (status & 1) == 1:
398 self.result[node]='Success'
399 else:
400 self.result[node]=MdsGetMsg(status)
401 except Exception,e:
402 self.result[node]=str(e)
403 return self.result
404 else:
405 ans=self.connection.value("public __putManyIn__=$,Py('Connection.__processPutMany__()'),public __putManyOut__",self.serialize())
406 if isinstance(ans,str):
407 raise Exception("Error putting any data: "+ans)
408 self.result=ans.deserialize()
409 return self.result
410
411 - def insert(self,beforenode, node,exp,*args):
412 """Insert put data before node in list specified by beforenode
413 @param beforenode: Name of node in list to insert this put data information.
414 @type beforenode: str
415 @param node: Node name to put data into
416 @type node: str
417 @param exp: TDI expression to store in node with optional placeholders for arguments
418 @type exp: str
419 @param args: Optional arguments to replace placeholders in expression
420 @type args: Data
421 @rtype: None
422 """
423 d=Dictionary({'node':str(node),'exp':str(exp),'args':args})
424 n = 0
425 for item in self:
426 if item['node'] == beforenode:
427 super(Connection.PutMany,self).insert(n,d)
428 return
429 else:
430 n=n+1
431 raise Exception,"Node %s not found in list" % (str(beforenode),)
432
434 """Remove the node from the list.
435 @param node: node name to remove from list. Must match exactly the node name used in the append() or insert() methods.
436 @type node: str
437 @rtype: None
438 """
439 for item in self:
440 if item['node'] == node:
441 super(Connection.PutMany,self).remove(item)
442 return
443 raise Exception,"Node %s not found in list" % (node,)
444