Author | Sessions |
Walter Matte 20.02.2008 02:46:19
Registered user |
I have a rtcHTTPServer on a form, on a datamodule I have a rtcDataServerLink and three rtcDataProviders.
One of the rtcDataProviders OpenSession, with a KeepAlive for 3 minutes. I have a logout button on the form and if a user logs out I CloseSession. I have assigned a class to a Session.AsObject for each session I want to make sure this memory is release properly is the session does not close with logout. What I have seen is that if there are several dead sessions and I wait 5 or 10 minutes, these session are still there. It is not until another OpenSession is called that dead Sessions are freed, is that right? 1. When the user just closes the Browser how often and what triggers Session that are dead to be cleaned up?. (Closed) 2. If I shutdown the Server while sessions are still active I am getting an AV.... how can I wait or force sessions closed. Walter |
Danijel Tkalcec [RTC] 20.02.2008 10:50:32
Registered user |
Hi Walter,
You should never assign your own objects directly to Sessions, but only store native data types to sessions (integers, strings, rtcRecords, rtcArrays, ...). To link your external objects to sessions, you will need to implement your own mecnahisms to find these objects by ID and store only the ID inside the session. 1. Session cleanup is done when a new Session is locked, which means that memory from each closed session will be released the next time some user needs to work with another sessions. In the current implementation, the last session data is being released with the Session pool in the finalize section of the "rtcDataSrv" unit. And at that time, all your objects should already be destroyed. 2. Can you debug the server to see where exactly you are getting the AV? Is it inside one of RTCs units (if yes, where?) or somewhere inside your code? PS. There is an internal function in the "rtcDataSrv.pas" unit called "DoneSessions" which is used to destroy the Session pool, but it will NOT trigger any session events and should NOT be called directly. Regards, Danijel |
Walter Matte 20.02.2008 13:16:55
Registered user |
Danijel,
I will adjust my code and manage my objects in my own TObjectList and just keep a reference in the Session. This makes sense, and I was going to do this originally, but thought I could use the Session.AsObject, which worked fine except for the dead session not cleaning up my object. And I did decend the object from TrtcObject. It did the clean up when new Session is locked, but not when the server was shutdown. I'm sure the AV is in my code, it only happens when all my objects are not destoyed. So managing them myself with a reference in Sessions will resolve it. This is my first application with RTC and I am enjoying RTC. Reliable, Flexible... I just need to learn the tool better. Thanks. Sincerely, Walter |
Danijel Tkalcec [RTC] 20.02.2008 14:27:44
Registered user |
Hi Walter,
I'm glad you are enjoying RTC and hope you will find out and fix the problem with the AV at shutdown. Should you have any other questions or problems using the RTC SDK, let me know. Regards, Danijel |
Walter Matte 20.02.2008 15:53:36
Registered user |
Danijel,
// GET /webtime OpenSession; Session.KeepAlive:= 60 * 5; // seconds * minutes Response.Cookie['sid']:=Session.ID; // Create a Form, Keep Reference Inc(FmyFormId); Session.AsInteger['FormRef'] := FmyFormId; fidx := FmyFormList.Add(TfrmWebTime.Create(nil)); // TfrmWebTime is a TForm TfrmWebTime(FmyFormList.items[Session.AsInteger['fidx']]).Tag := FmyFormId; FdfmContent.TheForm := TfrmWebTime(FmyFormList.items[fidx]); FdfmContent.SessionID := Session.ID; FdfmContent.FormAction := Root + '/webtime'; html := FdfmContent.GetFormContent; Write(html); --------------------- When user logs out FORM POST FmyFormList.Delete(GetMyFormIdx(Session.AsInteger['FormRef'])); // GetMyFormIdx returns index to FmyFormList CloseSession(Session.ID); --------------------- Where can I put this when a Session is cleaned up because a User did not Logout but shut down the browse? FmyFormList.Delete(GetMyFormIdx(Session.AsInteger['FormRef'])); // GetMyFormIdx returns index to FmyFormList Or do I have to iterate through the Session list to find out what MyFormList I have and there is no Session to clean up MyFormList. Where and how should I do this? Walter |
Danijel Tkalcec [RTC] 20.02.2008 16:02:30
Registered user |
Hi Walter,
the "OnSessionClose" even will be fired when your session expires or when it is being cleaned up by the session garbage collector. If you have already clean up the session, there is nothing you should do there. To know if that is the case, you should use some session variable to remember your current state of the session, so you know about it and do not try to clean up your variables again. For example, in RTC Gateway, I use the boolean 'login' session variable. Here is the "OnSessionClose" event from the RTC Gateway ... procedure TrdServerModule.ServerModuleSessionClose(Sender: TRtcConnection); begin // Log the user out if there are no other active user sessions ... with TRtcDataServer(Sender) do if Session.asBoolean['login'] then begin xLog(Session.asString['user']+': Session expired'); // we will log the user out ONLY if he is logged in under the same ID if UserLoggedIn(Sender,Session.asString['user'], Session.asString['ID']) then if UserLogout(Sender,Session.asString['user'],Session.asString['pwd'],False) then begin xLog(Session.asString['user']+': LOGGED OUT'); DoTextEvent(Sender,FOnUserLogout,Session.asString['user']); end; Session.asBoolean['login']:=False; end; end; To make sure the same code isn't executed twice, when I am manually closing the session and logging out the user on his request, I set the 'login' variable to FALSE, so that the logout code isn't called twice. Regards, Danijel |
Walter Matte 20.02.2008 16:08:36
Registered user |
Danijel,
Thank you again. Walter |