Changeset 2593
- Timestamp:
- 07/05/08 22:16:05 (3 months ago)
- Location:
- trunk/components
- Files:
-
- 4 modified
-
blitz/resources/omero/API.ice (modified) (1 diff)
-
blitz/resources/omero/Constants.ice (modified) (1 diff)
-
blitz/src/ome/services/blitz/impl/ServiceFactoryI.java (modified) (4 diffs)
-
tools/OmeroPy/src/omero/__init__.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/components/blitz/resources/omero/API.ice
r2522 r2593 596 596 597 597 /* 598 * Closes the service factory and all related services. 599 */ 600 void close(); 598 * Deprecated misnomer. 599 */ 600 ["deprecated:close() is deprecated. use closeOnDestroy() instead."] void close(); 601 602 /* 603 * Marks the session for closure rather than detachment, which will 604 * be triggered by the destruction of the Glacier2 connection via 605 * router.destroySession() 606 * 607 * Closing the session rather the detaching is more secure, since all 608 * resources are removed from the server and can safely be set once 609 * it is clear that a client is finished with those resources. 610 */ 611 void closeOnDestroy(); 612 613 /* 614 * Marks the session for detachment rather than closure, which will 615 * be triggered by the destruction of the Glacier2 connection via 616 * router.destroySession() 617 * 618 * This is the default and allows a lost session to be reconnected, 619 * at a slight security cost since the session will persist longer 620 * and can be used by others if the UUID is intercepted. 621 */ 622 void detachOnDestroy(); 601 623 602 624 // Session management 603 625 604 626 /* 605 627 * Returns a list of string ids for currently active services. This will -
trunk/components/blitz/resources/omero/Constants.ice
r2563 r2593 12 12 module omero { 13 13 module constants { 14 15 /* 16 * Key in the ImplicitContext which must be filled 17 * by all omero.client implementations. 18 */ 19 const string CLIENTUUID = "omero.client.uuid"; 14 20 15 21 /* -
trunk/components/blitz/src/ome/services/blitz/impl/ServiceFactoryI.java
r2592 r2593 145 145 final Map<String, Ice.Object> interactiveSlots; 146 146 147 /** 148 * The CLIENT_UUIDs for which a close should be invoked on this session. 149 */ 150 final Map<String, Boolean> closeUuids; 151 147 152 final Principal principal; 148 153 … … 172 177 // Setting up in memory store. 173 178 Ehcache cache = manager.inMemoryCache(p.getName()); 174 activeServants = getServantMap(ACTIVE_SERVANTS, cache); 175 interactiveSlots = getServantMap(INTERACTIVE_SLOTS, cache); 179 // TODO the getMap() method could be put in our own Cache class 180 activeServants = getMap(ACTIVE_SERVANTS, cache); 181 interactiveSlots = getMap(INTERACTIVE_SLOTS, cache); 182 closeUuids = getMap(CLOSE_UUIDS, cache); 176 183 } 177 184 178 185 static String ACTIVE_SERVANTS = "activeServants"; 179 186 static String INTERACTIVE_SLOTS = "interactiveSlots"; 180 181 private Map<String, Ice.Object> getServantMap(String key, Ehcache cache) { 182 Map<String, Ice.Object> ids; 187 static String CLOSE_UUIDS = "closeUuids"; 188 189 @SuppressWarnings("unchecked") 190 private <T> Map<String, T> getMap(String key, Ehcache cache) { 191 Map<String, T> ids; 183 192 if (!cache.isKeyInCache(key)) { 184 ids = new ConcurrentHashMap<String, Ice.Object>();193 ids = new ConcurrentHashMap<String, T>(); 185 194 cache.put(new Element(key, ids)); 186 195 } else { 187 ids = (Map<String, Ice.Object>) cache.get(key).getObjectValue();196 ids = (Map<String, T>) cache.get(key).getObjectValue(); 188 197 } 189 198 return ids; … … 464 473 } 465 474 475 public void detachOnDestroy(Ice.Current current) { 476 String key = current.ctx.get(omero.constants.CLIENTUUID.value); 477 closeUuids.remove(key); 478 } 479 480 @Deprecated 466 481 public void close(Ice.Current current) { 467 468 if (log.isInfoEnabled()) { 469 log.info(String.format("Closing %s session", this)); 470 } 471 472 // Cleaning up resources 473 474 // INTERACTIVE 475 Set<String> ipIds = interactiveSlots.keySet(); 476 for (String id : ipIds) { 477 InteractiveProcessorI ip = (InteractiveProcessorI) interactiveSlots 478 .get(id); 479 ip.stop(); 480 current.adapter.remove(Ice.Util.stringToIdentity(id)); 481 interactiveSlots.remove(id); 482 } 483 484 // SERVANTS 485 // Here we call the "close()" method on all methods which require that 486 // logic allowing the IceMethodInvoker to raise the 487 // UnregisterServantEvent, otherwise there is a recursive call back 488 // to close. 489 List<String> ids = activeServices(current); 490 for (String idString : ids) { 491 Ice.Identity id = Ice.Util.stringToIdentity(idString); 492 Ice.Object obj = current.adapter.find(id); 493 try { 494 if (obj instanceof StatefulServiceInterface) { 495 Method m = obj.getClass().getMethod("close", 496 Ice.Current.class); 497 Ice.Current __curr = new Ice.Current(); 498 __curr.id = id; 499 __curr.adapter = current.adapter; 500 __curr.operation = "close"; 501 __curr.mode = current.mode; // FIXME due to bug 502 // http://www.zeroc.com/forums/bug-reports/3348-ice-current-hashcode-can-throw-npe-null-enum.html 503 m.invoke(obj, __curr); 504 } else { 505 unregisterServant(id, current); 506 } 507 } catch (Exception e) { 508 log.error("Failure to close: " + idString + "=" + obj, e); 509 } 510 } 511 512 // All resources cleaned up to the best of our ability, 513 // now we can remove the current session. If an exception if thrown, 514 // there's not much we can do. 515 try { 516 current.adapter.remove(ServiceFactoryI.sessionId(principal 517 .getName())); 518 sessionManager.close(this.principal.getName()); 519 } catch (Throwable t) { 520 // FIXME 521 InternalException ie = new InternalException(t.getMessage()); 522 ie.setStackTrace(t.getStackTrace()); 523 } 482 closeOnDestroy(current); 483 } 484 485 public void closeOnDestroy(Ice.Current current) { 486 String key = current.ctx.get(omero.constants.CLIENTUUID.value); 487 closeUuids.put(key, Boolean.TRUE); 524 488 } 525 489 … … 531 495 */ 532 496 public void destroy(Ice.Current current) { 533 sessionManager.detach(this.principal.getName()); 497 498 // First detach and get the reference count. 499 int ref = sessionManager.detach(this.principal.getName()); 500 501 // If we are supposed to close, do only so if the ref count 502 // is < 1. 503 String key = current.ctx.get(omero.constants.CLIENTUUID.value); 504 if (key != null && ref < 1) { 505 506 ref = sessionManager.close(this.principal.getName()); 507 508 // If someone has attached since we called detach() above, do not 509 // destroy this session. 510 if (ref > 0) { 511 return; 512 } 513 514 if (log.isInfoEnabled()) { 515 log.info(String.format("Closing %s session", this)); 516 } 517 518 // Cleaning up resources 519 520 // INTERACTIVE 521 Set<String> ipIds = interactiveSlots.keySet(); 522 for (String id : ipIds) { 523 InteractiveProcessorI ip = (InteractiveProcessorI) interactiveSlots 524 .get(id); 525 ip.stop(); 526 current.adapter.remove(Ice.Util.stringToIdentity(id)); 527 interactiveSlots.remove(id); 528 } 529 530 // SERVANTS 531 // Here we call the "close()" method on all methods which require 532 // that 533 // logic allowing the IceMethodInvoker to raise the 534 // UnregisterServantEvent, otherwise there is a recursive call back 535 // to close. 536 List<String> ids = activeServices(current); 537 for (String idString : ids) { 538 Ice.Identity id = Ice.Util.stringToIdentity(idString); 539 Ice.Object obj = current.adapter.find(id); 540 try { 541 if (obj instanceof StatefulServiceInterface) { 542 Method m = obj.getClass().getMethod("close", 543 Ice.Current.class); 544 Ice.Current __curr = new Ice.Current(); 545 __curr.id = id; 546 __curr.adapter = current.adapter; 547 __curr.operation = "close"; 548 __curr.mode = current.mode; // FIXME due to bug 549 // http://www.zeroc.com/forums/bug-reports/3348-ice-current-hashcode-can-throw-npe-null-enum.html 550 m.invoke(obj, __curr); 551 } else { 552 unregisterServant(id, current); 553 } 554 } catch (Exception e) { 555 log.error("Failure to close: " + idString + "=" + obj, e); 556 } 557 } 558 559 // All resources cleaned up to the best of our ability, 560 // now we can remove the current session. If an exception if thrown, 561 // there's not much we can do. 562 try { 563 current.adapter.remove(ServiceFactoryI.sessionId(principal 564 .getName())); 565 } catch (Throwable t) { 566 // FIXME 567 InternalException ie = new InternalException(t.getMessage()); 568 ie.setStackTrace(t.getStackTrace()); 569 } 570 } 534 571 } 535 572 -
trunk/components/tools/OmeroPy/src/omero/__init__.py
r2592 r2593 18 18 from omero_ext import pysys 19 19 import omero_Constants_ice 20 import uuid 20 21 21 22 class client(object): … … 31 32 32 33 self.sf = None 33 self.ic = None 34 ic = Ice.initialize(args,id) 35 if not ic: 34 self.ic = Ice.initialize(args,id) 35 if not self.ic: 36 36 raise ClientError("Improper initialization") 37 # Register Object Factory 37 38 self.of = ObjectFactory() 38 self.of.registerObjectFactory(ic) 39 self.ic = ic 40 self.close_on_destroy = True 41 42 def closeOnDestroy(self): 43 """ 44 Closes the blitz session when destroyConnection() is called on exit. 45 This prevents other clients from attaching to the same blitz session, 46 and is more secure. 47 """ 48 self.close_on_destroy = True 49 50 def detachOnDestroy(self): 51 """ 52 Prevents the blitz session from being closed when destroyConnection() 53 is called. This will allow other clients to attach to the session for 54 distribtued work. This is less secure, but in many cases valuable. 55 """ 56 self.close_on_destroy = False 39 self.of.registerObjectFactory(self.ic) 40 # Define our unique identifier (used during close/detach) 41 self.ic.getImplicitContext().put(omero.constants.CLIENT_UUID, str(uuid.uuid4())) 57 42 58 43 def __del__(self): … … 60 45 self.destroyConnection() 61 46 except exceptions.Exception, e: 62 print " Error in__del__:" + str(e.__class__)47 print "Ignoring error in client.__del__:" + str(e.__class__) 63 48 64 49 def getCommunicator(self): … … 216 201 file.close() 217 202 218 def destroyConnection(self):203 def closeSession(self): 219 204 """ 220 205 Closes the Router connection created by createSession(). Due to a bug in Ice, 221 206 only one connection is allowed per communicator, so we also destroy the communicator. 222 207 """ 208 209 # If 'sf' exists we remove it. 210 if not hasattr(self, 'sf'): 211 self.sf = None 212 223 213 # If 'ic' does not exist we don't have anything to do 224 214 if not hasattr(self, 'ic') or not self.ic: 225 215 return 226 227 if self.close_on_destroy:228 self.closeSession()229 216 230 217 prx = self.ic.getDefaultRouter() … … 250 237 self.ic = None 251 238 252 def closeSession(self):253 """254 Call close on the session (ServiceFactoryPrx) which first decrements255 the reference count. If its reference count becomes 0, then the session256 will be removed from the server.257 """258 # If 'sf' does not exist we don't have a session at all259 if not hasattr(self, 'sf'):260 return261 # But even if we do have 'sf', the connection may have been lost and 'close' will fail262 try:263 try:264 self.sf.close()265 except:266 pass267 finally:268 self.sf = None269 270 239 def _env(self, method, *args): 271 240 """ Helper method to access session environment"""
