Package MDSplus :: Module connection
[frames] | no frames]

Source Code for Module MDSplus.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   
11 -class Connection(object):
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
26 - def __inspect__(self,value):
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
61 - def __getAnswer__(self):
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
111 - def __init__(self,hostspec):
112 self.socket=self.__ConnectToMds(hostspec) 113 if self.socket == -1: 114 raise Exception,"Error connecting to %s" % (hostspec,) 115 self.hostspec=hostspec
116
117 - def __processGetMany__(cls):
118 try: 119 cls.GetMany(value=Data.getTdiVar("__getManyIn__").deserialize()).execute().serialize().setTdiVar("__getManyOut__") 120 except Exception,e: 121 print e 122 raise
123 __processGetMany__=classmethod(__processGetMany__) 124
125 - def __processPutMany__(cls):
126 try: 127 cls.PutMany(value=Data.getTdiVar("__putManyIn__").deserialize()).execute().serialize().setTdiVar("__putManyOut__") 128 except Exception,e: 129 print e 130 raise
131 __processPutMany__=classmethod(__processPutMany__) 132 133
134 - def __sendArg__(self,value,idx,num):
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
144 - def closeTree(self,*args):
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
160 - def getMany(self):
161 """Return instance of a Connection.GetMany class. See the Connection.GetMany documentation for further information.""" 162 return Connection.GetMany(connection=self)
163
164 - def openTree(self,tree,shot):
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
198 - def putMany(self):
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
223 - def setDefault(self,path):
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
234 - class GetMany(List):
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):
260 """GetMany instance initialization.""" 261 if value is not None: 262 List.__init__(self,value) 263 self.connection=connection 264 self.result=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
278 - def execute(self):
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
332 - def remove(self,name):
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
344 - class PutMany(List):
345 """Build list of put instructions.""" 346
347 - def __init__(self,value=None,connection=None):
348 """Instance initialization""" 349 if value is not None: 350 List.__init__(self,value) 351 self.connection=connection 352 self.result=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
380 - def execute(self):
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
433 - def remove(self,node):
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