Changeset 2596
- Timestamp:
- 07/05/08 22:16:06 (2 months ago)
- 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 11 11 import java.util.HashSet; 12 12 import java.util.List; 13 import java.util.Map; 13 14 import java.util.Set; 15 import java.util.concurrent.ConcurrentHashMap; 14 16 15 17 import ome.conditions.InternalException; … … 25 27 import ome.system.Principal; 26 28 import ome.system.Roles; 29 import omero.ApiUsageException; 27 30 import omero.constants.EVENT; 28 31 import omero.constants.GROUP; … … 71 74 protected final Set<String> sessionsForReaping = new HashSet<String>(); 72 75 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 73 83 public SessionManagerI(SecuritySystem secSys, 74 84 SessionManager sessionManager, Executor executor) { … … 102 112 103 113 try { 104 Ice.ObjectPrx _prx; 114 115 // Create the session for this ServiceFactory 105 116 Principal p = new Principal(userId, group, event); 106 117 ome.model.meta.Session s = sessionManager.create(p); 107 118 Principal sp = new Principal(s.getUuid(), group, event); 108 119 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)); 120 130 } else { 131 sessionToClientIds.get(s.getUuid()).add(session.clientId); 121 132 if (log.isDebugEnabled()) { 122 133 log.debug(String.format("Rejoined session %s for user %s", 123 134 id.name, userId)); 124 135 } 125 _prx = current.adapter.createProxy(id); 136 126 137 } 127 138 return Glacier2.SessionPrxHelper.uncheckedCast(_prx); 128 139 129 } catch ( RuntimeException t) {140 } catch (Exception t) { 130 141 ConvertToBlitzExceptionMessage convert = new ConvertToBlitzExceptionMessage( 131 142 this, t); … … 139 150 if (convert.to instanceof CannotCreateSessionException) { 140 151 throw (CannotCreateSessionException) convert.to; 152 } else if (convert.to instanceof ApiUsageException) { 153 ApiUsageException aue = (ApiUsageException) convert.to; 154 throw new CannotCreateSessionException(aue.message); 141 155 } 142 156 … … 158 172 159 173 // 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 } 161 181 Ice.Object obj = curr.adapter.find(id); 162 182 if (obj instanceof ServiceFactoryI) { 163 183 ServiceFactoryI sf = (ServiceFactoryI) obj; 164 sf.unregisterServant(Ice.Util.stringToIdentity(key), curr); 184 sf.unregisterServant(Ice.Util.stringToIdentity(key), 185 curr.adapter); 165 186 } 166 187 } else if (event instanceof DestroySessionMessage) { … … 180 201 * Unfortunately, that message does not have an {@link Ice.Current} instance 181 202 * 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} 182 208 */ 183 private void reapSessions(Ice.Current current) { 209 private void reapSessions(Ice.Current cantUseThisCurrent) { 210 Ice.ObjectAdapter adapter = cantUseThisCurrent.adapter; 184 211 synchronized (sessionsForReaping) { 185 212 List<String> ids = new ArrayList<String>(sessionsForReaping); 186 213 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); 195 229 } 196 sessionsForReaping.remove(id);197 } catch (Exception e) {198 log.error("Error reaping session " + id, e);199 230 } 200 231 } -
trunk/components/blitz/src/ome/services/blitz/impl/ServiceFactoryI.java
r2593 r2596 126 126 public final class ServiceFactoryI extends _ServiceFactoryDisp { 127 127 128 // STATIC 129 128 130 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 129 139 130 140 final SessionManager sessionManager; … … 145 155 final Map<String, Ice.Object> interactiveSlots; 146 156 147 /**148 * The CLIENT_UUIDs for which a close should be invoked on this session.149 */150 final Map<String, Boolean> closeUuids;151 152 157 final Principal principal; 153 158 … … 163 168 // ========================================================================= 164 169 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); 168 174 this.context = context; 169 175 this.sessionManager = manager; … … 180 186 activeServants = getMap(ACTIVE_SERVANTS, cache); 181 187 interactiveSlots = getMap(INTERACTIVE_SLOTS, cache); 182 closeUuids = getMap(CLOSE_UUIDS, cache);183 188 } 184 189 185 190 static String ACTIVE_SERVANTS = "activeServants"; 186 191 static String INTERACTIVE_SLOTS = "interactiveSlots"; 187 static String CLOSE_UUIDS = "closeUuids";188 192 189 193 @SuppressWarnings("unchecked") … … 474 478 475 479 public void detachOnDestroy(Ice.Current current) { 476 String key = current.ctx.get(omero.constants.CLIENTUUID.value); 477 closeUuids.remove(key); 480 doClose = false; 478 481 } 479 482 480 483 @Deprecated 481 484 public void close(Ice.Current current) { 482 closeOnDestroy(current);485 doClose = false; 483 486 } 484 487 485 488 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; 488 490 } 489 491 … … 501 503 // If we are supposed to close, do only so if the ref count 502 504 // is < 1. 503 String key = current.ctx.get(omero.constants.CLIENTUUID.value); 504 if (key != null && ref < 1) { 505 if (doClose && ref < 1) { 505 506 506 507 ref = sessionManager.close(this.principal.getName()); … … 512 513 } 513 514 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); 516 567 } 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()); 570 579 } 571 580 } … … 723 732 * to an {@link UnregisterServantMessage} 724 733 */ 725 public void unregisterServant(Ice.Identity id, Ice. Current current) {734 public void unregisterServant(Ice.Identity id, Ice.ObjectAdapter adapter) { 726 735 727 736 // Here we assume that if the "close()" call is required, that it has … … 730 739 // onApplicationEvent(). 731 740 // Otherwise, it is being called directly by SF.close(). 732 Ice.Object obj = current.adapter.remove(id);741 Ice.Object obj = adapter.remove(id); 733 742 Object removed = activeServants.remove(Ice.Util.identityToString(id)); 734 743 if (removed == null) { … … 748 757 } 749 758 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) { 751 771 Ice.Identity id = new Ice.Identity(); 752 id.category = "session ";772 id.category = "session-" + clientId; 753 773 id.name = uuid; 754 774 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; 755 793 } 756 794
