• 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 2596

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

ticket:1018 - Working solution (needs concurrency testing)

Each ServiceFactory instance now keeps track of its clientId.

This solution uses a managed map in SessionManagerI to
make up for the missing ObjectAdapter.findAll() method.

Location:
trunk/components/blitz/src/ome/services/blitz
Files:
2 modified

  • fire/SessionManagerI.java (modified) (7 diffs)
  • impl/ServiceFactoryI.java (modified) (10 diffs)

Legend:

Unmodified
Added
Removed
  • trunk/components/blitz/src/ome/services/blitz/fire/SessionManagerI.java

    r2382 r2596  
    1111import java.util.HashSet; 
    1212import java.util.List; 
     13import java.util.Map; 
    1314import java.util.Set; 
     15import java.util.concurrent.ConcurrentHashMap; 
    1416 
    1517import ome.conditions.InternalException; 
    … …  
    2527import ome.system.Principal; 
    2628import ome.system.Roles; 
     29import omero.ApiUsageException; 
    2730import omero.constants.EVENT; 
    2831import omero.constants.GROUP; 
    … …  
    7174    protected final Set<String> sessionsForReaping = new HashSet<String>(); 
    7275 
     76    /** 
     77     * An internal mapping to all {@link ServiceFactoryI} instances for a given 
     78     * session since there is no method on {@link Ice.ObjectAdapter} to retrieve 
     79     * all servants. 
     80     */ 
     81    protected final Map<String, Set<String>> sessionToClientIds = new ConcurrentHashMap<String, Set<String>>(); 
     82 
    7383    public SessionManagerI(SecuritySystem secSys, 
    7484            SessionManager sessionManager, Executor executor) { 
    … …  
    102112 
    103113        try { 
    104             Ice.ObjectPrx _prx; 
     114 
     115            // Create the session for this ServiceFactory 
    105116            Principal p = new Principal(userId, group, event); 
    106117            ome.model.meta.Session s = sessionManager.create(p); 
    107118            Principal sp = new Principal(s.getUuid(), group, event); 
    108119 
    109             Ice.Identity id = ServiceFactoryI.sessionId(s.getUuid()); 
    110             Ice.Object servant = current.adapter.find(id); 
    111             if (servant == null) { 
    112                 ServiceFactoryI session = new ServiceFactoryI(context, 
    113                         sessionManager, executor, sp, CPTORS); 
    114  
    115                 _prx = current.adapter.add(session, id); 
    116                 if (log.isDebugEnabled()) { 
    117                     log.debug(String.format("Created session %s for user %s", 
    118                             id.name, userId)); 
    119                 } 
     120            // Create the ServiceFactory 
     121            ServiceFactoryI session = new ServiceFactoryI(current, context, 
     122                    sessionManager, executor, sp, CPTORS); 
     123 
     124            Ice.Identity id = session.sessionId(s.getUuid()); 
     125            Ice.ObjectPrx _prx = current.adapter.add(session, id); 
     126            if (!sessionToClientIds.containsKey(s.getUuid())) { 
     127                sessionToClientIds.put(s.getUuid(), new HashSet<String>()); 
     128                log.debug(String.format("Created session %s for user %s", 
     129                        id.name, userId)); 
    120130            } else { 
     131                sessionToClientIds.get(s.getUuid()).add(session.clientId); 
    121132                if (log.isDebugEnabled()) { 
    122133                    log.debug(String.format("Rejoined session %s for user %s", 
    123134                            id.name, userId)); 
    124135                } 
    125                 _prx = current.adapter.createProxy(id); 
     136 
    126137            } 
    127138            return Glacier2.SessionPrxHelper.uncheckedCast(_prx); 
    128139 
    129         } catch (RuntimeException t) { 
     140        } catch (Exception t) { 
    130141            ConvertToBlitzExceptionMessage convert = new ConvertToBlitzExceptionMessage( 
    131142                    this, t); 
    … …  
    139150            if (convert.to instanceof CannotCreateSessionException) { 
    140151                throw (CannotCreateSessionException) convert.to; 
     152            } else if (convert.to instanceof ApiUsageException) { 
     153                ApiUsageException aue = (ApiUsageException) convert.to; 
     154                throw new CannotCreateSessionException(aue.message); 
    141155            } 
    142156 
    … …  
    158172 
    159173            // And unregister the service if possible 
    160             Ice.Identity id = ServiceFactoryI.sessionId(curr.id.category); 
     174            Ice.Identity id; 
     175            try { 
     176                id = ServiceFactoryI.sessionId(curr, curr.id.category); 
     177            } catch (ApiUsageException e) { 
     178                throw new RuntimeException( 
     179                        "Could not unregister servant: could not create session id"); 
     180            } 
    161181            Ice.Object obj = curr.adapter.find(id); 
    162182            if (obj instanceof ServiceFactoryI) { 
    163183                ServiceFactoryI sf = (ServiceFactoryI) obj; 
    164                 sf.unregisterServant(Ice.Util.stringToIdentity(key), curr); 
     184                sf.unregisterServant(Ice.Util.stringToIdentity(key), 
     185                        curr.adapter); 
    165186            } 
    166187        } else if (event instanceof DestroySessionMessage) { 
    … …  
    180201     * Unfortunately, that message does not have an {@link Ice.Current} instance 
    181202     * and so reaping must happen asynchronously. 
     203     *  
     204     * @param cantUseThisCurrent 
     205     *            a current from another method invocation which is not usable 
     206     *            for reaping the given sessions except to get the current 
     207     *            {@link Ice.ObjectAdapter} 
    182208     */ 
    183     private void reapSessions(Ice.Current current) { 
     209    private void reapSessions(Ice.Current cantUseThisCurrent) { 
     210        Ice.ObjectAdapter adapter = cantUseThisCurrent.adapter; 
    184211        synchronized (sessionsForReaping) { 
    185212            List<String> ids = new ArrayList<String>(sessionsForReaping); 
    186213            for (String id : ids) { 
    187                 try { 
    188                     Ice.Identity iid = ServiceFactoryI.sessionId(id); 
    189                     Ice.Object obj = current.adapter.find(iid); 
    190                     if (obj == null) { 
    191                         log.debug(id + " already removed."); 
    192                     } else { 
    193                         ServiceFactoryI sf = (ServiceFactoryI) obj; 
    194                         sf.close(current); 
     214                for (String clientId : sessionToClientIds.get(id)) { 
     215                    try { 
     216                        Ice.Identity iid = ServiceFactoryI.sessionId(clientId, 
     217                                id); 
     218                        Ice.Object obj = adapter.find(iid); 
     219                        if (obj == null) { 
     220                            log.debug(id + " already removed."); 
     221                        } else { 
     222                            ServiceFactoryI sf = (ServiceFactoryI) obj; 
     223                            sf.doDestroy(adapter); 
     224                        } 
     225                        sessionsForReaping.remove(id); 
     226                    } catch (Exception e) { 
     227                        log.error("Error reaping session " + id 
     228                                + " from client " + clientId, e); 
    195229                    } 
    196                     sessionsForReaping.remove(id); 
    197                 } catch (Exception e) { 
    198                     log.error("Error reaping session " + id, e); 
    199230                } 
    200231            } 
  • trunk/components/blitz/src/ome/services/blitz/impl/ServiceFactoryI.java

    r2593 r2596  
    126126public final class ServiceFactoryI extends _ServiceFactoryDisp { 
    127127 
     128    // STATIC 
     129 
    128130    private final static Log log = LogFactory.getLog(ServiceFactoryI.class); 
     131 
     132    // PRIVATE STATE 
     133 
     134    boolean doClose = false; 
     135 
     136    public final String clientId; 
     137 
     138    // SHARED STATE 
    129139 
    130140    final SessionManager sessionManager; 
    … …  
    145155    final Map<String, Ice.Object> interactiveSlots; 
    146156 
    147     /** 
    148      * The CLIENT_UUIDs for which a close should be invoked on this session. 
    149      */ 
    150     final Map<String, Boolean> closeUuids; 
    151  
    152157    final Principal principal; 
    153158 
    … …  
    163168    // ========================================================================= 
    164169 
    165     public ServiceFactoryI(OmeroContext context, SessionManager manager, 
    166             Executor executor, Principal p, 
    167             List<HardWiredInterceptor> interceptors) { 
     170    public ServiceFactoryI(Ice.Current current, OmeroContext context, 
     171            SessionManager manager, Executor executor, Principal p, 
     172            List<HardWiredInterceptor> interceptors) throws ApiUsageException { 
     173        this.clientId = clientId(current); 
    168174        this.context = context; 
    169175        this.sessionManager = manager; 
    … …  
    180186        activeServants = getMap(ACTIVE_SERVANTS, cache); 
    181187        interactiveSlots = getMap(INTERACTIVE_SLOTS, cache); 
    182         closeUuids = getMap(CLOSE_UUIDS, cache); 
    183188    } 
    184189 
    185190    static String ACTIVE_SERVANTS = "activeServants"; 
    186191    static String INTERACTIVE_SLOTS = "interactiveSlots"; 
    187     static String CLOSE_UUIDS = "closeUuids"; 
    188192 
    189193    @SuppressWarnings("unchecked") 
    … …  
    474478 
    475479    public void detachOnDestroy(Ice.Current current) { 
    476         String key = current.ctx.get(omero.constants.CLIENTUUID.value); 
    477         closeUuids.remove(key); 
     480        doClose = false; 
    478481    } 
    479482 
    480483    @Deprecated 
    481484    public void close(Ice.Current current) { 
    482         closeOnDestroy(current); 
     485        doClose = false; 
    483486    } 
    484487 
    485488    public void closeOnDestroy(Ice.Current current) { 
    486         String key = current.ctx.get(omero.constants.CLIENTUUID.value); 
    487         closeUuids.put(key, Boolean.TRUE); 
     489        doClose = true; 
    488490    } 
    489491 
    … …  
    501503        // If we are supposed to close, do only so if the ref count 
    502504        // is < 1. 
    503         String key = current.ctx.get(omero.constants.CLIENTUUID.value); 
    504         if (key != null && ref < 1) { 
     505        if (doClose && ref < 1) { 
    505506 
    506507            ref = sessionManager.close(this.principal.getName()); 
    … …  
    512513            } 
    513514 
    514             if (log.isInfoEnabled()) { 
    515                 log.info(String.format("Closing %s session", this)); 
     515            doDestroy(current.adapter); 
     516 
     517        } 
     518    } 
     519 
     520    /** 
     521     * Performs the actual cleanup operation. Since {@link #destroy()} is called 
     522     * non-discriminantly by the router, even when a client has just died, we 
     523     * have this internal method for handling the actual closing of resources. 
     524     */ 
     525    public void doDestroy(Ice.ObjectAdapter adapter) { 
     526 
     527        if (log.isInfoEnabled()) { 
     528            log.info(String.format("Closing %s session", this)); 
     529        } 
     530 
     531        // Cleaning up resources 
     532 
     533        // INTERACTIVE 
     534        Set<String> ipIds = interactiveSlots.keySet(); 
     535        for (String id : ipIds) { 
     536            InteractiveProcessorI ip = (InteractiveProcessorI) interactiveSlots 
     537                    .get(id); 
     538            ip.stop(); 
     539            adapter.remove(Ice.Util.stringToIdentity(id)); 
     540            interactiveSlots.remove(id); 
     541        } 
     542 
     543        // SERVANTS 
     544        // Here we call the "close()" method on all methods which require 
     545        // that 
     546        // logic allowing the IceMethodInvoker to raise the 
     547        // UnregisterServantEvent, otherwise there is a recursive call back 
     548        // to close. 
     549        List<String> ids = activeServices(); 
     550        for (String idString : ids) { 
     551            Ice.Identity id = Ice.Util.stringToIdentity(idString); 
     552            Ice.Object obj = adapter.find(id); 
     553            try { 
     554                if (obj instanceof StatefulServiceInterface) { 
     555                    Method m = obj.getClass().getMethod("close", 
     556                            Ice.Current.class); 
     557                    Ice.Current __curr = new Ice.Current(); 
     558                    __curr.id = id; 
     559                    __curr.adapter = adapter; 
     560                    __curr.operation = "close"; 
     561                    m.invoke(obj, __curr); 
     562                } else { 
     563                    unregisterServant(id, adapter); 
     564                } 
     565            } catch (Exception e) { 
     566                log.error("Failure to close: " + idString + "=" + obj, e); 
    516567            } 
    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             } 
     568        } 
     569 
     570        // All resources cleaned up to the best of our ability, 
     571        // now we can remove the current session. If an exception if thrown, 
     572        // there's not much we can do. 
     573        try { 
     574            adapter.remove(sessionId(principal.getName())); 
     575        } catch (Throwable t) { 
     576            // FIXME 
     577            InternalException ie = new InternalException(t.getMessage()); 
     578            ie.setStackTrace(t.getStackTrace()); 
    570579        } 
    571580    } 
    … …  
    723732     * to an {@link UnregisterServantMessage} 
    724733     */ 
    725     public void unregisterServant(Ice.Identity id, Ice.Current current) { 
     734    public void unregisterServant(Ice.Identity id, Ice.ObjectAdapter adapter) { 
    726735 
    727736        // Here we assume that if the "close()" call is required, that it has 
    … …  
    730739        // onApplicationEvent(). 
    731740        // Otherwise, it is being called directly by SF.close(). 
    732         Ice.Object obj = current.adapter.remove(id); 
     741        Ice.Object obj = adapter.remove(id); 
    733742        Object removed = activeServants.remove(Ice.Util.identityToString(id)); 
    734743        if (removed == null) { 
    … …  
    748757    } 
    749758 
    750     public static Ice.Identity sessionId(String uuid) { 
     759    // Id Helpers 
     760    // ========================================================================= 
     761    // Used for naming service factory instances and creating Ice.Identities 
     762    // from Ice.Currents, etc. 
     763 
     764    public static Ice.Identity sessionId(Ice.Current current, String uuid) 
     765            throws ApiUsageException { 
     766        String clientId = clientId(current); 
     767        return sessionId(clientId, uuid); 
     768    } 
     769 
     770    public static Ice.Identity sessionId(String clientId, String uuid) { 
    751771        Ice.Identity id = new Ice.Identity(); 
    752         id.category = "session"; 
     772        id.category = "session-" + clientId; 
    753773        id.name = uuid; 
    754774        return id; 
     775 
     776    } 
     777 
     778    public Ice.Identity sessionId(String uuid) { 
     779        return sessionId(clientId, uuid); 
     780    } 
     781 
     782    public static String clientId(Ice.Current current) throws ApiUsageException { 
     783        String clientId = null; 
     784        if (current.ctx != null) { 
     785            clientId = current.ctx.get(omero.constants.CLIENTUUID.value); 
     786        } 
     787        if (clientId == null) { 
     788            throw new ApiUsageException(null, null, "No " 
     789                    + omero.constants.CLIENTUUID.value 
     790                    + " key provided in context."); 
     791        } 
     792        return clientId; 
    755793    } 
    756794 

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/