• Views
  • Iteration Report
  • My Iteration Report
  •  
OMERO.server
  • Login
  • Help/Guide
  • About Trac
  • Preferences
  • Wiki
  • Timeline
  • Roadmap
  • Browse Source
  • View Tickets
  • Search

Context Navigation

  • ← Previous Changeset
  • Next Changeset →

Changeset 2593

Show
Ignore:
Timestamp:
07/05/08 22:16:05 (3 months ago)
Author:
jmoore
Message:

ticket:1018 - Second attempt at improving OmeroSessions in blitz

This tries to keep up with an individual client via a uuid set
on the client side. This may also be sub-optimal. A better idea
may be using individual ServiceFactory instances which talk to
the same session (in which case only the SessionManager? need be
distributed)

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  
    596596 
    597597        /* 
    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(); 
    601623 
    602624        // Session management 
    603          
     625 
    604626        /* 
    605627         * Returns a list of string ids for currently active services. This will 
  • trunk/components/blitz/resources/omero/Constants.ice

    r2563 r2593  
    1212module omero { 
    1313  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"; 
    1420 
    1521    /* 
  • trunk/components/blitz/src/ome/services/blitz/impl/ServiceFactoryI.java

    r2592 r2593  
    145145    final Map<String, Ice.Object> interactiveSlots; 
    146146 
     147    /** 
     148     * The CLIENT_UUIDs for which a close should be invoked on this session. 
     149     */ 
     150    final Map<String, Boolean> closeUuids; 
     151 
    147152    final Principal principal; 
    148153 
    … …  
    172177        // Setting up in memory store. 
    173178        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); 
    176183    } 
    177184 
    178185    static String ACTIVE_SERVANTS = "activeServants"; 
    179186    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; 
    183192        if (!cache.isKeyInCache(key)) { 
    184             ids = new ConcurrentHashMap<String, Ice.Object>(); 
     193            ids = new ConcurrentHashMap<String, T>(); 
    185194            cache.put(new Element(key, ids)); 
    186195        } else { 
    187             ids = (Map<String, Ice.Object>) cache.get(key).getObjectValue(); 
     196            ids = (Map<String, T>) cache.get(key).getObjectValue(); 
    188197        } 
    189198        return ids; 
    … …  
    464473    } 
    465474 
     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 
    466481    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); 
    524488    } 
    525489 
    … …  
    531495     */ 
    532496    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        } 
    534571    } 
    535572 
  • trunk/components/tools/OmeroPy/src/omero/__init__.py

    r2592 r2593  
    1818from omero_ext import pysys 
    1919import omero_Constants_ice 
     20import uuid 
    2021 
    2122class client(object): 
    … …  
    3132 
    3233        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: 
    3636            raise ClientError("Improper initialization") 
     37        # Register Object Factory 
    3738        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())) 
    5742 
    5843    def __del__(self): 
    … …  
    6045            self.destroyConnection() 
    6146        except exceptions.Exception, e: 
    62             print "Error in __del__:" + str(e.__class__) 
     47            print "Ignoring error in client.__del__:" + str(e.__class__) 
    6348 
    6449    def getCommunicator(self): 
    … …  
    216201            file.close() 
    217202 
    218     def destroyConnection(self): 
     203    def closeSession(self): 
    219204        """ 
    220205        Closes the Router connection created by createSession(). Due to a bug in Ice, 
    221206        only one connection is allowed per communicator, so we also destroy the communicator. 
    222207        """ 
     208 
     209        # If 'sf' exists we remove it. 
     210        if not hasattr(self, 'sf'): 
     211            self.sf = None 
     212 
    223213        # If 'ic' does not exist we don't have anything to do 
    224214        if not hasattr(self, 'ic') or not self.ic: 
    225215            return 
    226  
    227         if self.close_on_destroy: 
    228             self.closeSession() 
    229216 
    230217        prx = self.ic.getDefaultRouter() 
    … …  
    250237        self.ic = None 
    251238 
    252     def closeSession(self): 
    253         """ 
    254         Call close on the session (ServiceFactoryPrx) which first decrements 
    255         the reference count. If its reference count becomes 0, then the session 
    256         will be removed from the server. 
    257         """ 
    258         # If 'sf' does not exist we don't have a session at all 
    259         if not hasattr(self, 'sf'): 
    260             return 
    261         # But even if we do have 'sf', the connection may have been lost and 'close' will fail 
    262         try: 
    263             try: 
    264                 self.sf.close() 
    265             except: 
    266                 pass 
    267         finally: 
    268             self.sf = None 
    269  
    270239    def _env(self, method, *args): 
    271240        """ Helper method to access session environment""" 

Download in other formats:

  • Unified Diff
  • Zip Archive

Trac Powered

Powered by Trac 0.11
By Edgewall Software.

Visit the Trac open source project at
http://trac.edgewall.org/