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

Source Code for Module omero.clients

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