Package omero :: Module clients
[hide private]
[frames] | no frames]

Source Code for Module omero.clients

  1  #!/usr/bin/env python 
  2  """ 
  3   
  4     Copyright 2009 Glencoe Software, Inc. All rights reserved. 
  5     Use is subject to license terms supplied in LICENSE.txt 
  6   
  7  """ 
  8   
  9  __save__ = __name__ 
 10  __name__ = 'omero' 
 11  try: 
 12      api = __import__('omero.api') 
 13      model = __import__('omero.model') 
 14      util = __import__('omero.util') 
 15      sys = __import__('omero.sys') 
 16      import omero.all 
 17  finally: 
 18      __name__ = __save__ 
 19      del __save__ 
 20   
 21  sys = __import__("sys") 
 22  import exceptions, traceback, threading, logging 
 23  import Ice, Glacier2, Glacier2_Router_ice 
 24  import omero_ext.uuid as uuid # see ticket:3774 
 25   
26 -class BaseClient(object):
27 """ 28 Central client-side blitz entry point, and should be in sync with OmeroJava's omero.client 29 and OmeroCpp's omero::client. 30 31 Typical usage includes:: 32 33 client = omero.client() # Uses --Ice.Config argument or ICE_CONFIG variable 34 client = omero.client(host = host) # Defines "omero.host" 35 client = omero.client(host = host, port = port) # Defines "omero.host" and "omero.port" 36 37 For more information, see: 38 39 - U{https://trac.openmicroscopy.org.uk/omero/wiki/ClientDesign} 40 41 """ 42
43 - def __init__(self, args = None, id = None, \ 44 host = None, port = None, pmap = None):
45 """ 46 Constructor which takes one sys.argv-style list, one initialization 47 data, one host string, one port integer, and one properties map, in 48 that order. *However*, to simplify use, we reassign values based on 49 their type with a warning printed. A cleaner approach is to use named 50 parameters. 51 :: 52 c1 = omero.client(None, None, "host", myPort) # Correct 53 c2 = omero.client(host = "host", port = myPort) # Correct 54 c3 = omero.client("host", myPort) # Works with warning 55 56 Both "Ice" and "omero" prefixed properties will be parsed. 57 58 Defines the state variables:: 59 __previous : InitializationData from any previous communicator, if any 60 Used to re-initialization the client post-closeSession() 61 62 __ic : communicator. Nullness => init() needed on createSession() 63 64 __sf : current session. Nullness => createSession() needed. 65 66 __resources: if non-null, hs access to this client instance and will 67 periodically call sf.keepAlive(None) in order to keep any 68 session alive. This can be enabled either via the omero.keep_alive 69 configuration property, or by calling the enableKeepAlive() method. 70 Once enabled, the period cannot be adjusted during a single 71 session. 72 73 Modifying these variables outside of the accessors can lead to 74 undefined behavior. 75 76 Equivalent to all OmeroJava and OmeroCpp constructors 77 """ 78 79 # Setting all protected values to prevent AttributeError 80 self.__agent = "OMERO.py" #: See setAgent 81 self.__insecure = False 82 self.__previous = None 83 self.__ic = None 84 self.__oa = None 85 self.__sf = None 86 self.__uuid = None 87 self.__resources = None 88 self.__lock = threading.RLock() 89 90 # Logging 91 self.__logger = logging.getLogger("omero.client") 92 logging.basicConfig() # Does nothing if already configured 93 94 # Reassigning based on argument type 95 96 args, id, host, port, pmap = self._repair(args, id, host, port, pmap) 97 98 # Copying args since we don't really want them edited 99 if not args: 100 args = [] 101 else: 102 # See ticket:5516 To prevent issues on systems where the base 103 # class of path.path is unicode, we will encode all unicode 104 # strings here. 105 for idx, arg in enumerate(args): 106 if isinstance(arg, unicode): 107 arg = arg.encode("utf-8") 108 args[idx] = arg 109 110 # Equiv to multiple constructors. ####################### 111 if id == None: 112 id = Ice.InitializationData() 113 114 if id.properties == None: 115 id.properties = Ice.createProperties(args) 116 117 id.properties.parseCommandLineOptions("omero", args); 118 if host: 119 id.properties.setProperty("omero.host", str(host)) 120 if not port: 121 port = id.properties.getPropertyWithDefault("omero.port",\ 122 str(omero.constants.GLACIER2PORT)) 123 id.properties.setProperty("omero.port", str(port)) 124 if pmap: 125 for k,v in pmap.items(): 126 id.properties.setProperty(str(k), str(v)) 127 128 self._initData(id)
129
130 - def _repair(self, args, id, host, port, pmap):
131 """ 132 Takes the 5 arguments passed to the __init__ method 133 and attempts to re-order them based on their types. 134 This allows for simplified usage without parameter 135 names. 136 """ 137 types = [list, Ice.InitializationData, str, int, dict] 138 original = [args, id, host, port, pmap] 139 repaired = [None, None, None, None, None] 140 141 # Check all to see if valid 142 valid = True 143 for i in range(0, len(types)): 144 if None != original[i] and not isinstance(original[i], types[i]): 145 valid = False 146 break 147 if valid: 148 return original 149 150 # Now try to find corrections. 151 for i in range(0, len(types)): 152 found = None 153 for j in range(0, len(types)): 154 if isinstance(original[j], types[i]): 155 if not found: 156 found = original[j] 157 else: 158 raise omero.ClientError("Found two arguments of same type: " + str(types[i])) 159 if found: 160 repaired[i] = found 161 return repaired
162
163 - def _initData(self, id):
164 """ 165 Initializes the current client via an Ice.InitializationData 166 instance. This is called by all of the constructors, but may 167 also be called on createSession(name, pass) if a previous 168 call to closeSession() has nulled the Ice.Communicator. 169 """ 170 171 if not id: 172 raise omero.ClientError("No initialization data provided."); 173 174 # Strictly necessary for this class to work 175 id.properties.setProperty("Ice.ImplicitContext", "Shared") 176 id.properties.setProperty("Ice.ACM.Client", "0") 177 id.properties.setProperty("Ice.RetryIntervals", "-1") 178 id.properties.setProperty("Ice.Default.EndpointSelection", "Ordered") 179 id.properties.setProperty("Ice.Default.PreferSecure", "1") 180 id.properties.setProperty("Ice.Plugin.IceSSL" , "IceSSL:createIceSSL") 181 id.properties.setProperty("IceSSL.Ciphers" , "ADH") 182 id.properties.setProperty("IceSSL.VerifyPeer" , "0") 183 184 # Setting MessageSizeMax 185 messageSize = id.properties.getProperty("Ice.MessageSizeMax") 186 if not messageSize or len(messageSize) == 0: 187 id.properties.setProperty("Ice.MessageSizeMax", str(omero.constants.MESSAGESIZEMAX)) 188 189 # Setting ConnectTimeout 190 self.parseAndSetInt(id, "Ice.Override.ConnectTimeout",\ 191 omero.constants.CONNECTTIMEOUT) 192 193 # Endpoints set to tcp if not present 194 endpoints = id.properties.getProperty("omero.ClientCallback.Endpoints") 195 if not endpoints or len(endpoints) == 0: 196 id.properties.setProperty("omero.ClientCallback.Endpoints", "tcp") 197 198 # ThreadPool to 5 if not present 199 threadpool = id.properties.getProperty("omero.ClientCallback.ThreadPool.Size") 200 if not threadpool or len(threadpool) == 0: 201 id.properties.setProperty("omero.ClientCallback.ThreadPool.Size", str(omero.constants.CLIENTTHREADPOOLSIZE)) 202 203 # Port, setting to default if not present 204 port = self.parseAndSetInt(id, "omero.port",\ 205 omero.constants.GLACIER2PORT) 206 207 # Default Router, set a default and then replace 208 router = id.properties.getProperty("Ice.Default.Router") 209 if not router or len(router) == 0: 210 router = str(omero.constants.DEFAULTROUTER) 211 host = id.properties.getPropertyWithDefault("omero.host", """<"omero.host" not set>""") 212 router = router.replace("@omero.port@", str(port)) 213 router = router.replace("@omero.host@", str(host)) 214 id.properties.setProperty("Ice.Default.Router", router) 215 216 # Dump properties 217 dump = id.properties.getProperty("omero.dump") 218 if len(dump) > 0: 219 m = self.getPropertyMap(id.properties) 220 keys = list(m.keys()) 221 keys.sort() 222 for key in keys: 223 print "%s=%s" % (key, m[key]) 224 225 self.__lock.acquire() 226 try: 227 if self.__ic: 228 raise omero.ClientError("Client already initialized") 229 230 try: 231 self.__ic = Ice.initialize(id) 232 except Ice.EndpointParseException: 233 msg = "No host specified. " 234 msg += "Use omero.client(HOSTNAME), ICE_CONFIG, or similar." 235 raise omero.ClientError(msg) 236 237 if not self.__ic: 238 raise omero.ClientError("Improper initialization") 239 240 # Register Object Factory 241 self.of = ObjectFactory() 242 self.of.registerObjectFactory(self.__ic) 243 for of in omero.rtypes.ObjectFactories.values(): 244 of.register(self.__ic) 245 246 # Define our unique identifier (used during close/detach) 247 self.__uuid = str(uuid.uuid4()) 248 ctx = self.__ic.getImplicitContext() 249 if not ctx: 250 raise omero.ClientError("Ice.ImplicitContext not set to Shared") 251 ctx.put(omero.constants.CLIENTUUID, self.__uuid) 252 253 # ticket:2951 - sending user group 254 group = id.properties.getPropertyWithDefault("omero.group", "") 255 if group: 256 ctx.put("omero.group", group) 257 258 # Register the default client callback 259 self.__oa = self.__ic.createObjectAdapter("omero.ClientCallback") 260 cb = BaseClient.CallbackI(self.__ic, self.__oa) 261 self.__oa.add(cb, self.__ic.stringToIdentity("ClientCallback/%s" % self.__uuid)) 262 self.__oa.activate() 263 finally: 264 self.__lock.release()
265
266 - def setAgent(self, agent):
267 """ 268 Sets the omero.model.Session#getUserAgent() string for 269 this client. Every session creation will be passed this argument. Finding 270 open sesssions with the same agent can be done via 271 omero.api.ISessionPrx#getMyOpenAgentSessions(String). 272 """ 273 self.__agent = agent
274
275 - def isSecure(self):
276 """ 277 Specifies whether or not this client was created via a call to 278 createClient with a boolean of False. If insecure, then all 279 remote calls will use the insecure connection defined by the server. 280 """ 281 return not self.__insecure
282
283 - def createClient(self, secure):
284 """ 285 Creates a possibly insecure omero.client instance and calls joinSession 286 using the current getSessionId value. If secure is False, then first the 287 "omero.router.insecure" configuration property is retrieved from the server 288 and used as the value of "Ice.Default.Router" for the new client. Any exception 289 thrown during creation is passed on to the caller. 290 """ 291 props = self.getPropertyMap() 292 if not secure: 293 insecure = self.getSession().getConfigService().getConfigValue("omero.router.insecure") 294 if insecure is not None and insecure != "": 295 props["Ice.Default.Router"] = insecure 296 else: 297 self.__logger.warn("Could not retrieve \"omero.router.insecure\"") 298 299 nClient = omero.client(props) 300 nClient.__insecure = not secure 301 nClient.setAgent("%s;secure=%s" % (self.__agent, secure)) 302 nClient.joinSession(self.getSessionId()) 303 return nClient
304
305 - def __del__(self):
306 """ 307 Calls closeSession() and ignores any exceptions. 308 309 Equivalent to close() in OmeroJava or omero::client::~client() 310 """ 311 try: 312 self.closeSession() 313 except exceptions.Exception, e: 314 self.__logger.warning("Ignoring error in client.__del__:" + str(e.__class__))
315
316 - def getCommunicator(self):
317 """ 318 Returns the Ice.Communicator for this instance or throws 319 an exception if None. 320 """ 321 self.__lock.acquire() 322 try: 323 if not self.__ic: 324 raise omero.ClientError("No Ice.Communicator active; call createSession() or create a new client instance") 325 return self.__ic 326 finally: 327 self.__lock.release()
328
329 - def getAdapter(self):
330 """ 331 Returns the Ice.ObjectAdapter for this instance or throws 332 an exception if None. 333 """ 334 self.__lock.acquire() 335 try: 336 if not self.__oa: 337 raise omero.ClientError("No Ice.ObjectAdapter active; call createSession() or create a new client instance") 338 return self.__oa 339 finally: 340 self.__lock.release()
341
342 - def getSession(self):
343 """ 344 Returns the current active session or throws an exception if none has been 345 created since the last closeSession() 346 """ 347 self.__lock.acquire() 348 try: 349 sf = self.__sf 350 if not sf: 351 raise omero.ClientError("No session available") 352 return sf 353 finally: 354 self.__lock.release()
355
356 - def getSessionId(self):
357 """ 358 Returns the UUID for the current session without making a remote call. 359 Uses getSession() internally and will throw an exception if no session 360 is active. 361 """ 362 return self.getSession().ice_getIdentity().name
363
364 - def getImplicitContext(self):
365 """ 366 Returns the Ice.ImplicitContext which defines what properties 367 will be sent on every method invocation. 368 """ 369 return self.getCommunicator().getImplicitContext()
370
371 - def getProperties(self):
372 """ 373 Returns the active properties for this instance 374 """ 375 self.__lock.acquire() 376 try: 377 return self.__ic.getProperties() 378 finally: 379 self.__lock.release()
380
381 - def getProperty(self, key):
382 """ 383 Returns the property for the given key or "" if none present 384 """ 385 return self.getProperties().getProperty(key)
386
387 - def getPropertyMap(self, properties = None):
388 """ 389 Returns all properties which are prefixed with "omero." or "Ice." 390 """ 391 if properties is None: 392 properties = self.getProperties() 393 394 rv = dict() 395 for prefix in ["omero","Ice"]: 396 for k,v in properties.getPropertiesForPrefix(prefix).items(): 397 rv[k] = v 398 return rv
399
400 - def joinSession(self, session):
401 """ 402 Uses the given session uuid as name 403 and password to rejoin a running session 404 """ 405 return self.createSession(session, session)
406
407 - def createSession(self, username=None, password=None):
408 """ 409 Performs the actual logic of logging in, which is done via the 410 getRouter(). Disallows an extant ServiceFactoryPrx, and 411 tries to re-create a null Ice.Communicator. A null or empty 412 username will throw an exception, but an empty password is allowed. 413 """ 414 import omero 415 416 self.__lock.acquire() 417 try: 418 419 # Checking state 420 421 if self.__sf: 422 raise omero.ClientError("Session already active. Create a new omero.client or closeSession()") 423 424 if not self.__ic: 425 if not self.__previous: 426 raise omero.ClientError("No previous data to recreate communicator.") 427 self._initData(self.__previous) 428 self.__previous = None 429 430 # Check the required properties 431 432 if not username: 433 username = self.getProperty("omero.user") 434 elif isinstance(username,omero.RString): 435 username = username.val 436 437 if not username or len(username) == 0: 438 raise omero.ClientError("No username specified") 439 440 if not password: 441 password = self.getProperty("omero.pass") 442 elif isinstance(password,omero.RString): 443 password = password.val 444 445 if not password: 446 raise omero.ClientError("No password specified") 447 448 # Acquire router and get the proxy 449 prx = None 450 retries = 0 451 while retries < 3: 452 reason = None 453 if retries > 0: 454 self.__logger.warning(\ 455 "%s - createSession retry: %s"% (reason, retries) ) 456 try: 457 ctx = dict(self.getImplicitContext().getContext()) 458 ctx[omero.constants.AGENT] = self.__agent 459 prx = self.getRouter(self.__ic).createSession(username, password, ctx) 460 break 461 except omero.WrappedCreateSessionException, wrapped: 462 if not wrapped.concurrency: 463 raise wrapped # We only retry concurrency issues. 464 reason = "%s:%s" % (wrapped.type, wrapped.reason) 465 retries = retries + 1 466 except Ice.ConnectTimeoutException, cte: 467 reason = "Ice.ConnectTimeoutException:%s" % str(cte) 468 retries = retries + 1 469 470 if not prx: 471 raise omero.ClientError("Obtained null object prox") 472 473 # Check type 474 self.__sf = omero.api.ServiceFactoryPrx.uncheckedCast(prx) 475 if not self.__sf: 476 raise omero.ClientError("Obtained object proxy is not a ServiceFactory") 477 478 # Configure keep alive 479 keep_alive = self.__ic.getProperties().getPropertyWithDefault("omero.keep_alive", "-1") 480 try: 481 i = int(keep_alive) 482 self.enableKeepAlive(i) 483 except: 484 pass 485 486 # Set the client callback on the session 487 # and pass it to icestorm 488 try: 489 id = self.__ic.stringToIdentity("ClientCallback/%s" % self.__uuid ) 490 raw = self.__oa.createProxy(id) 491 self.__sf.setCallback(omero.api.ClientCallbackPrx.uncheckedCast(raw)) 492 #self.__sf.subscribe("/public/HeartBeat", raw) 493 except: 494 self.__del__() 495 raise 496 497 # Set the session uuid in the implicit context 498 self.getImplicitContext().put(omero.constants.SESSIONUUID, self.getSessionId()) 499 500 return self.__sf 501 finally: 502 self.__lock.release()
503
504 - def enableKeepAlive(self, seconds):
505 """ 506 Resets the "omero.keep_alive" property on the current 507 Ice.Communicator which is used on initialization to determine 508 the time-period between Resource checks. If no __resources 509 instance is available currently, one is also created. 510 """ 511 512 self.__lock.acquire() 513 try: 514 # A communicator must be configured! 515 ic = self.getCommunicator() 516 # Setting this here guarantees that after closeSession() 517 # the next createSession() will use the new value despite 518 # what was in the configuration file 519 ic.getProperties().setProperty("omero.keep_alive", str(seconds)) 520 521 # If it's not null, then there's already an entry for keeping 522 # any existing session alive 523 if self.__resources == None and seconds > 0: 524 self.__resources = omero.util.Resources(seconds) 525 class Entry: 526 def __init__(self, c): 527 self.c = c
528 def cleanup(self): pass 529 def check(self): 530 sf = self.c._BaseClient__sf 531 ic = self.c._BaseClient__ic 532 if sf != None: 533 try: 534 sf.keepAlive(None) 535 except exceptions.Exception, e: 536 if ic != None: 537 ic.getLogger().warning("Proxy keep alive failed.") 538 return False 539 return True
540 self.__resources.add(Entry(self)) 541 finally: 542 self.__lock.release() 543
544 - def getRouter(self, comm):
545 """ 546 Acquires the default router, and throws an exception 547 if it is not of type Glacier2.Router. Also sets the 548 Ice.ImplicitContext on the router proxy. 549 """ 550 prx = comm.getDefaultRouter() 551 if not prx: 552 raise omero.ClientError("No default router found.") 553 router = Glacier2.RouterPrx.uncheckedCast(prx) 554 if not router: 555 raise omero.ClientError("Error obtaining Glacier2 router") 556 557 # For whatever reason, we have to set the context 558 # on the router context here as well 559 router = router.ice_context(comm.getImplicitContext().getContext()) 560 return router
561
562 - def sha1(self, filename):
563 """ 564 Calculates the local sha1 for a file. 565 """ 566 try: 567 from hashlib import sha1 as sha_new 568 except ImportError: 569 from sha import new as sha_new 570 digest = sha_new() 571 file = open(filename, 'rb') 572 try: 573 while True: 574 block = file.read(1024) 575 if not block: 576 break 577 digest.update(block) 578 finally: 579 file.close() 580 return digest.hexdigest()
581
582 - def upload(self, filename, name = None, path = None, 583 type = None, ofile = None, block_size = 1024):
584 """ 585 Utility method to upload a file to the server. 586 """ 587 if not self.__sf: 588 raise omero.ClientError("No session. Use createSession first.") 589 590 import os, types 591 if not filename or not isinstance(filename, types.StringType): 592 raise omero.ClientError("Non-null filename must be provided") 593 594 if not os.path.exists(filename): 595 raise omero.ClientError("File does not exist: " + filename) 596 597 from path import path as __path__ 598 filepath = __path__(filename) 599 file = open(filename, 'rb') 600 try: 601 602 size = os.path.getsize(file.name) 603 if block_size > size: 604 block_size = size 605 606 if not ofile: 607 ofile = omero.model.OriginalFileI() 608 609 ofile.size = omero.rtypes.rlong(size) 610 ofile.sha1 = omero.rtypes.rstring(self.sha1(file.name)) 611 612 abspath = filepath.normpath().abspath() 613 if not ofile.name: 614 if name: 615 ofile.name = omero.rtypes.rstring(name) 616 else: 617 ofile.name = omero.rtypes.rstring(str(abspath.basename())) 618 619 if not ofile.path: 620 ofile.path = omero.rtypes.rstring(str(abspath.dirname())+os.path.sep) 621 622 if not ofile.mimetype: 623 if type: 624 # ofile.mimetype = 'application/octet-stream' by default 625 ofile.mimetype = omero.rtypes.rstring(type) 626 627 # Disabled with group permissions #1434 628 # if permissions: 629 # ofile.details.permissions = permissions 630 631 up = self.__sf.getUpdateService() 632 ofile = up.saveAndReturnObject(ofile) 633 634 prx = self.__sf.createRawFileStore() 635 try: 636 prx.setFileId(ofile.id.val) 637 prx.truncate(size) # ticket:2337 638 offset = 0 639 while True: 640 block = file.read(block_size) 641 if not block: 642 break 643 prx.write(block, offset, len(block)) 644 offset += len(block) 645 finally: 646 prx.close() 647 finally: 648 file.close() 649 650 return ofile
651
652 - def download(self, ofile, filename = None, block_size = 1024*1024, filehandle = None):
653 prx = self.__sf.createRawFileStore() 654 try: 655 if not ofile or not ofile.id: 656 raise omero.ClientError("No file to download") 657 ofile = self.__sf.getQueryService().get("OriginalFile", ofile.id.val) 658 659 if block_size > ofile.size.val: 660 block_size = ofile.size.val 661 662 prx.setFileId(ofile.id.val) 663 664 size = ofile.size.val 665 offset = 0 666 667 if filehandle is None: 668 if filename is None: 669 raise omero.ClientError("no filename or filehandle specified") 670 filehandle = open(filename, 'wb') 671 else: 672 if filename: 673 raise omero.ClientError("filename and filehandle specified.") 674 675 try: 676 while (offset+block_size) < size: 677 filehandle.write(prx.read(offset, block_size)) 678 offset += block_size 679 filehandle.write(prx.read(offset, (size-offset))) 680 finally: 681 if filename: 682 filehandle.close() 683 finally: 684 prx.close()
685
686 - def getStatefulServices(self):
687 """ 688 Returns all active StatefulServiceInterface proxies. This can 689 be used to call close before calling setSecurityContext. 690 """ 691 rv = [] 692 sf = self.sf 693 services = sf.activeServices() 694 for srv in services: 695 try: 696 prx = sf.getByName(srv) 697 prx = omero.api.StatefulServiceInterfacePrx.checkedCast(prx) 698 if prx is not None: 699 rv.append(prx) 700 except: 701 self.__logger.warn("Error looking up proxy: %s" % srv, exc_info=1) 702 return rv
703
704 - def closeSession(self):
705 """ 706 Closes the Router connection created by createSession(). Due to a bug in Ice, 707 only one connection is allowed per communicator, so we also destroy the communicator. 708 """ 709 710 self.__lock.acquire() 711 try: 712 self.__sf = None 713 714 oldOa = self.__oa 715 self.__oa = None 716 717 oldIc = self.__ic 718 self.__ic = None 719 720 # Only possible if improperly configured. 721 if not oldIc: 722 return 723 724 if oldOa: 725 try: 726 oldOa.deactivate() 727 except exceptions.Exception, e: 728 self.__logger.warning("While deactivating adapter: " + str(e.message)) 729 730 self.__previous = Ice.InitializationData() 731 self.__previous.properties = oldIc.getProperties().clone() 732 733 oldR = self.__resources 734 self.__resources = None 735 if oldR != None: 736 try: 737 oldR.cleanup() 738 except exceptions.Exception, e: 739 oldIc.getLogger().warning( 740 "While cleaning up resources: " + str(e)) 741 742 try: 743 try: 744 self.getRouter(oldIc).destroySession() 745 except Glacier2.SessionNotExistException: 746 # ok. We don't want it to exist 747 pass 748 except Ice.ConnectionLostException: 749 # ok. Exception will always be thrown 750 pass 751 except Ice.ConnectionRefusedException: 752 # ok. Server probably went down 753 pass 754 except Ice.ConnectTimeoutException: 755 # ok. Server probably went down 756 pass 757 # Possible other items to handle/ignore: 758 # * Ice.DNSException 759 finally: 760 oldIc.destroy() 761 del oldIc._impl # WORKAROUND ticket:2007 762 763 finally: 764 self.__lock.release()
765 766
767 - def killSession(self):
768 """ 769 Calls ISession.closeSession(omero.model.Session) until 770 the returned reference count is greater than zero. The 771 number of invocations is returned. If ISession.closeSession() 772 cannot be called, -1 is returned. 773 """ 774 775 s = omero.model.SessionI() 776 s.uuid = omero.rtypes.rstring(self.getSessionId()) 777 try: 778 svc = self.sf.getSessionService() 779 except: 780 self.__logger.warning("Cannot get session service for killSession. Using closeSession") 781 self.closeSession() 782 return -1; 783 784 count = 0 785 try: 786 r = 1 787 while r > 0: 788 count += 1 789 r = svc.closeSession(s) 790 except omero.RemovedSessionException: 791 pass 792 except: 793 self.__logger.warning("Unknown exception while closing all references", exc_info = True) 794 795 # Now the server-side session is dead, call closeSession() 796 self.closeSession() 797 return count
798 799 # Environment Methods 800 # =========================================================== 801
802 - def _env(self, _unwrap, method, *args):
803 """ Helper method to access session environment""" 804 session = self.getSession() 805 if not session: 806 raise omero.ClientError("No session active") 807 a = session.getAdminService() 808 u = self.getSessionId() 809 s = session.getSessionService() 810 m = getattr(s, method) 811 rv = apply(m, (u,)+args) 812 if callable(_unwrap): 813 rv = _unwrap(rv) # Passed in function 814 elif _unwrap: 815 rv = omero.rtypes.unwrap(rv) # Default method 816 return rv
817
818 - def getInput(self, key, unwrap=False):
819 """ 820 Retrieves an item from the "input" shared (session) memory. 821 """ 822 return self._env(unwrap, "getInput", key)
823
824 - def getOutput(self, key, unwrap=False):
825 """ 826 Retrieves an item from the "output" shared (session) memory. 827 """ 828 return self._env(unwrap, "getOutput", key)
829 830
831 - def setInput(self, key, value):
832 """ 833 Sets an item in the "input" shared (session) memory under the given name. 834 """ 835 self._env(False, "setInput", key, value)
836
837 - def setOutput(self, key, value):
838 """ 839 Sets an item in the "output" shared (session) memory under the given name. 840 """ 841 self._env(False, "setOutput", key, value)
842
843 - def getInputKeys(self):
844 """ 845 Returns a list of keys for all items in the "input" shared (session) memory 846 """ 847 return self._env(False, "getInputKeys")
848
849 - def getOutputKeys(self):
850 """ 851 Returns a list of keys for all items in the "output" shared (session) memory 852 """ 853 return self._env(False, "getOutputKeys")
854
855 - def getInputs(self, unwrap=False):
856 """ 857 Returns all items in the "input" shared (session) memory 858 """ 859 return self._env(unwrap, "getInputs")
860
861 - def getOutputs(self, unwrap=False):
862 """ 863 Returns all items in the "output" shared (session) memory 864 """ 865 return self._env(unwrap, "getOutputKeys")
866 # 867 # Misc. 868 # 869
870 - def parseAndSetInt(self, data, key, newValue):
871 currentValue = data.properties.getProperty(key) 872 if not currentValue or len(currentValue) == 0: 873 newStr = str(newValue) 874 data.properties.setProperty(key, newStr) 875 currentValue = newStr 876 return currentValue
877
878 - def __getattr__(self, name):
879 """ 880 Compatibility layer, which allows calls to getCommunicator() and getSession() 881 to be called via self.ic and self.sf 882 """ 883 if name == "ic": 884 return self.getCommunicator() 885 elif name == "sf": 886 return self.getSession() 887 elif name == "adapter": 888 return self.getAdapter() 889 else: 890 raise AttributeError("Unknown property: " + name)
891 892 # 893 # Callback 894 #
895 - def _getCb(self):
896 if not self.__oa: 897 raise omero.ClientError("No session active; call createSession()") 898 obj = self.__oa.find(self.ic.stringToIdentity("ClientCallback/%s" % self.__uuid)) 899 if not isinstance(obj, BaseClient.CallbackI): 900 raise omero.ClientError("Cannot find CallbackI in ObjectAdapter") 901 return obj
902
903 - def onHeartbeat(self, myCallable):
904 self._getCb().onHeartbeat = myCallable
905
906 - def onSessionClosed(self, myCallable):
907 self._getCb().onSessionClosed = myCallable
908
909 - def onShutdownIn(self, myCallable):
910 self._getCb().onShutdownIn = myCallable
911
912 - class CallbackI(omero.api.ClientCallback):
913 """ 914 Implemention of ClientCallback which will be added to 915 any Session which this instance creates. Note: this client 916 should avoid all interaction with the {@link client#lock} since it 917 can lead to deadlocks during shutdown. See: ticket:1210 918 """ 919 920 # 921 # Default callbacks 922 #
923 - def _noop(self):
924 pass
925 - def _closeSession(self):
926 try: 927 self.oa.deactivate(); 928 except exceptions.Exception, e: 929 sys.err.write("On session closed: " + str(e))
930
931 - def __init__(self, ic, oa):
932 self.ic = ic 933 self.oa = oa 934 self.onHeartbeat = self._noop 935 self.onShutdownIn = self._noop 936 self.onSessionClosed = self._noop
937 - def execute(self, myCallable, action):
938 try: 939 myCallable() 940 # self.ic.getLogger().trace("ClientCallback", action + " run") 941 except: 942 try: 943 self.ic.getLogger().error("Error performing %s" % action) 944 except: 945 print "Error performing %s" % action
946
947 - def requestHeartbeat(self, current = None):
948 self.execute(self.onHeartbeat, "heartbeat")
949 - def shutdownIn(self, milliseconds, current = None):
950 self.execute(self.onShutdownIn, "shutdown")
951 - def sessionClosed(self, current = None):
952 self.execute(self.onSessionClosed, "sessionClosed")
953 954 # 955 # Other 956 # 957 958 import util.FactoryMap
959 -class ObjectFactory(Ice.ObjectFactory):
960 """ 961 Responsible for instantiating objects during deserialization. 962 """ 963
964 - def __init__(self, pmap = util.FactoryMap.map()):
965 self.__m = pmap
966
967 - def registerObjectFactory(self, ic):
968 for key in self.__m: 969 if not ic.findObjectFactory(key): 970 ic.addObjectFactory(self,key)
971
972 - def create(self, type):
973 generator = self.__m[type] 974 if generator == None: 975 raise omero.ClientError("Unknown type:"+type) 976 return generator.next()
977
978 - def destroy(self):
979 # Nothing to do 980 pass
981