Archived
This forum has been archived. Please start a new discussion on GitHub.
Glacier2: sessions vs callbacks
in Help Center
Hi,
I have some questions regarding Glacier2 sessions and client callbacks coexistence.
My flow is like following:
1. On some stage when my iPhone client moved to background, attempt to call client's callback object throws ObjectNotExistException.
According to Ice Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
Please explain this behaviour.
2. Client app is resumed and would like to know whether its session is still alive. For this purpose it calls ice_ping on session object that throws ObjectNotExistException though the session is still alive. I'd expect something like ConnectionLostException, otherwise ice_ping should return normally. Please explain.
3. Now client tries to re-establish session. As stated in Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
My Environment:
Server: C# + ICE 3.4.2 on Windows (Vista, Server 2008)
Client: Ice Touch 1.2.0
I have some questions regarding Glacier2 sessions and client callbacks coexistence.
My flow is like following:
1. On some stage when my iPhone client moved to background, attempt to call client's callback object throws ObjectNotExistException.
According to Ice Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
In my case session's destroy method is not called.In that case <if the server regularly calls back to the client>, Glacier2 will automatically destroy the session if a failure occurs while forwarding a server callback to the client
Please explain this behaviour.
2. Client app is resumed and would like to know whether its session is still alive. For this purpose it calls ice_ping on session object that throws ObjectNotExistException though the session is still alive. I'd expect something like ConnectionLostException, otherwise ice_ping should return normally. Please explain.
3. Now client tries to re-establish session. As stated in Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
What exactly SessionManager is expected to do? Should it call (it will be a nested call?) to previously saved SessionControlPrx destroy method, and after that create a new session?The create operations may be called with information that identifies an existing session. For example, this can occur when a client loses its connection to the router but its previous session has not yet expired (and therefore the router has not yet invoked destroy on its Session proxy). A session manager implementation must be prepared to handle this situation.
My Environment:
Server: C# + ICE 3.4.2 on Windows (Vista, Server 2008)
Client: Ice Touch 1.2.0
0
Comments
-
Hi,Hi,
I have some questions regarding Glacier2 sessions and client callbacks coexistence.
My flow is like following:
1. On some stage when my iPhone client moved to background, attempt to call client's callback object throws ObjectNotExistException.
According to Ice Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
In my case session's destroy method is not called.
Please explain this behaviour.
2. Client app is resumed and would like to know whether its session is still alive. For this purpose it calls ice_ping on session object that throws ObjectNotExistException though the session is still alive. I'd expect something like ConnectionLostException, otherwise ice_ping should return normally. Please explain.
The destroy method should be called if the session gets destroyed as a result of the failure of a server to client invocation and ice_ping on the session object shouldn't fail with Ice::ObjectNotExistException if the session is still alive. Did you try enabling some tracing on Glacier2 to investigate why it doesn't behave as expected? You can for instance enable the following properties:- Glacier2.Trace.Session=1
- Glacier2.Trace.Client.Reject=1
3. Now client tries to re-establish session. As stated in Manual (Glacier2 Session Management - Ice 3.4 - ZeroC):
What exactly SessionManager is expected to do? Should it call (it will be a nested call?) to previously saved SessionControlPrx destroy method, and after that create a new session?
Calling destroy on the session control object is useful to destroy an active session. If your session manager implementation already knows that the session was destroyed (the session destroy method was called), it doesn't need to call it.
Cheers,
Benoit.0 -
Thanks for fast response.
Unfortunately I still don't get it
1.The destroy method should be called if the session gets destroyed as a result of the failure of a server to client invocation
Or Glacier2 is supposed to destroy client's session on Ice.ConnectionLostException only?
2.ice_ping on the session object shouldn't fail with Ice::ObjectNotExistException if the session is still alivepublic override Glacier2.SessionPrx create(string userId, Glacier2.SessionControlPrx control, Ice.Current current__) { Ice.Identity userSessionId = new Ice.Identity(userId, strSessionType); Ice.ObjectPrx prx = null; ... if (null == current__.adapter.find(userSessionId)) { prx = current__.adapter.add(new UserSessionI(userId), userSessionId); } else // "existing session" case { prx = current__.adapter.createProxy(userSessionId); } return Glacier2.SessionPrxHelper.uncheckedCast(prx); }
Session's destroy looks pretty standard:public override void destroy(Ice.Current current__) { trace("destroy called for userId=" + userId_); ... current__.adapter.remove(current__.id); }
Now, client creates a new session before previous one get expired. He receives a proxy to existing session servant and starts working normally until the servant will be destroyed by Glacier2 due to expiration of previous session.
I've tried to change it as following:public override Glacier2.SessionPrx create(string userId, Glacier2.SessionControlPrx control, Ice.Current current__) { Ice.Identity userSessionId = new Ice.Identity(userId, strSessionType); Ice.ObjectPrx prx = null; if (null != current__.adapter.find(userSessionId)) // "existing session" case { trace("Existing session found for userId=" + userId); Glacier2.SessionControlPrx currentControl = getSessionControl(userId); currentControl.destroy(); trace("Existing session destroyed for userId=" + userId); } if (null == current__.adapter.find(userSessionId)) { prx = current__.adapter.add(new UserSessionI(userId), userSessionId); setSessionControl(userId, control); trace("New session created for userId=" + userId); return Glacier2.SessionPrxHelper.uncheckedCast(prx); } else // "still existing session" case { trace("Cleanup failed for userId=" + userId); return null; } }
Unfortunately it doesn't work - though currentControl.destroy() is called I receive "Cleanup failed".
What's wrong with this implementation?
How "existing session" situation should be handled properly if Ice.Identity based on userId?0 -
Hi Alex,
An Ice::ObjectNotExistException doesn't necessarily indicate a communication failure with the client. It might just mean that the invocation failed because no servant was registered for the object identity from the proxy.
The Glacier2::Session::destroy() method is called asynchronously when you call destroy() on the session control object. So when the destroy session control invocation returns, it doesn't necessarily mean that your session destroy method was called (yet). You'll need to add some synchronization if you really want to keep using the user ID for the session identity. Something like the above should work:// Session destroy method public override void destroy(Ice.Current current__) { trace("destroy called for userId=" + userId_); ... current__.adapter.remove(current__.id); sessionManager.sessionDestroyed(); } // Session Manager public void sessionDestroyed() { lock(this) { System.Threading.Monitor.PulseAll(this) } }; public override Glacier2.SessionPrx create(string userId, Glacier2.SessionControlPrx control, Ice.Current current__) { Ice.Identity userSessionId = new Ice.Identity(userId, strSessionType); Ice.ObjectPrx prx = null; if (null != current__.adapter.find(userSessionId)) // "existing session" case { trace("Existing session found for userId=" + userId); Glacier2.SessionControlPrx currentControl = getSessionControl(userId); currentControl.destroy(); trace("Existing session destroyed for userId=" + userId); // Wait for Session.destroy() call while(null != current__.adapter.find(userSessionId)) { lock(this) { System.Threading.Monitor.Wait(this); } } } prx = current__.adapter.add(new UserSessionI(userId), userSessionId); setSessionControl(userId, control); trace("New session created for userId=" + userId); return Glacier2.SessionPrxHelper.uncheckedCast(prx); }
I recommend adding timeouts however to make sure to not wait indefinitely if something goes wrong between your server and Glacier2.
Cheers,
Benoit.0