瀏覽代碼

* Retry opening session file on error (max 5 times)

git-svn-id: trunk@22070 -
michael 13 年之前
父節點
當前提交
3418ba156e
共有 1 個文件被更改,包括 81 次插入10 次删除
  1. 81 10
      packages/fcl-web/src/base/iniwebsession.pp

+ 81 - 10
packages/fcl-web/src/base/iniwebsession.pp

@@ -32,15 +32,17 @@ Type
     FSessionDir: String;
     FSessionDir: String;
     FTerminated :Boolean;
     FTerminated :Boolean;
     SID : String;
     SID : String;
-  private
-    procedure FreeIniFile;
+    procedure UpdateIniFile;
   Protected
   Protected
+    Function CreateIniFile(Const AFN : String) : TMemIniFile; virtual;
+    Procedure FreeIniFile;
     Procedure CheckSession;
     Procedure CheckSession;
     Function GetSessionID : String; override;
     Function GetSessionID : String; override;
     Function GetSessionVariable(VarName : String) : String; override;
     Function GetSessionVariable(VarName : String) : String; override;
     procedure SetSessionVariable(VarName : String; const AValue: String); override;
     procedure SetSessionVariable(VarName : String; const AValue: String); override;
     Property Cached : Boolean Read FCached Write FCached;
     Property Cached : Boolean Read FCached Write FCached;
     Property SessionDir : String Read FSessionDir Write FSessionDir;
     Property SessionDir : String Read FSessionDir Write FSessionDir;
+    Property IniFile : TMemIniFile Read FIniFile Write FIniFile;
   Public
   Public
     Destructor Destroy; override;
     Destructor Destroy; override;
     Procedure Terminate; override;
     Procedure Terminate; override;
@@ -82,6 +84,9 @@ Type
 Var
 Var
   IniWebSessionClass : TIniWebSessionClass = Nil;
   IniWebSessionClass : TIniWebSessionClass = Nil;
 
 
+Const
+  MaxIniCreate = 5;
+
 implementation
 implementation
 
 
 {$ifdef cgidebug}
 {$ifdef cgidebug}
@@ -235,10 +240,75 @@ begin
   Result:=SID;
   Result:=SID;
 end;
 end;
 
 
+Procedure TIniWebSession.UpdateIniFile;
+
+
+Var
+  ACount : Integer;
+  OK : Boolean;
+
+begin
+  ACount:=0;
+  OK:=False;
+  repeat
+    Inc(ACount);
+    try
+      TMemIniFile(FIniFile).UpdateFile;
+      OK:=True;
+    except
+      On E : EFCreateError do
+        begin
+        If ACount>MaxIniCreate then
+          Raise;
+        Sleep(20);
+        end;
+      On E : EFOpenError do
+        begin
+        If ACount>MaxIniCreate then
+          Raise;
+        Sleep(20);
+        end;
+      On E : Exception do
+        Raise;
+    end;
+  Until OK;
+end;
+
+function TIniWebSession.CreateIniFile(Const AFN: String): TMemIniFile;
+
+Var
+  ACount : Integer;
+
+begin
+  ACount:=0;
+  Result:=Nil;
+  repeat
+    Inc(ACount);
+    try
+      Result:=TMemIniFile.Create(AFN,False);
+    except
+      On E : EFCreateError do
+        begin
+        If ACount>MaxIniCreate then
+          Raise;
+        Sleep(20);
+        end;
+      On E : EFOpenError do
+        begin
+        If ACount>MaxIniCreate then
+          Raise;
+        Sleep(20);
+        end;
+      On E : Exception do
+        Raise;
+    end;
+  until (Result<>Nil);
+end;
+
 procedure TIniWebSession.FreeIniFile;
 procedure TIniWebSession.FreeIniFile;
 begin
 begin
   If Cached and Assigned(FIniFile) then
   If Cached and Assigned(FIniFile) then
-    TMemIniFile(FIniFile).UpdateFile;
+    UpdateIniFile;
   FreeAndNil(FIniFile);
   FreeAndNil(FIniFile);
 end;
 end;
 
 
@@ -265,7 +335,7 @@ begin
   CheckSession;
   CheckSession;
   FIniFile.WriteString(SData,VarName,AValue);
   FIniFile.WriteString(SData,VarName,AValue);
   If Not Cached then
   If Not Cached then
-    TMemIniFile(FIniFile).UpdateFile;
+    UpdateIniFile;
 end;
 end;
 
 
 destructor TIniWebSession.Destroy;
 destructor TIniWebSession.Destroy;
@@ -295,7 +365,7 @@ end;
 procedure TIniWebSession.InitSession(ARequest: TRequest; OnNewSession,OnExpired: TNotifyEvent);
 procedure TIniWebSession.InitSession(ARequest: TRequest; OnNewSession,OnExpired: TNotifyEvent);
 
 
 Var
 Var
-  S : String;
+  S,FN : String;
   SF : TIniSessionFactory;
   SF : TIniSessionFactory;
   
   
 begin
 begin
@@ -314,8 +384,9 @@ begin
   // have session cookie ?
   // have session cookie ?
   If (S<>'') then
   If (S<>'') then
     begin
     begin
-{$ifdef cgidebug}SendDebug('Reading ini file:'+S);{$endif}
-    FIniFile:=TMemIniFile.Create(IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+S);
+    FN:=IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+S;
+{$ifdef cgidebug}SendDebug('Reading ini file:'+FN);{$endif}
+    FIniFile:=CreateIniFile(FN);
     if SF.SessionExpired(FIniFile) then
     if SF.SessionExpired(FIniFile) then
       begin
       begin
       // Expire session.
       // Expire session.
@@ -335,14 +406,14 @@ begin
     GetSessionID;
     GetSessionID;
     S:=IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+SessionID;
     S:=IncludeTrailingPathDelimiter(SessionDir)+SF.SessionFilePrefix+SessionID;
 {$ifdef cgidebug}SendDebug('Creating new Ini file : '+S);{$endif}
 {$ifdef cgidebug}SendDebug('Creating new Ini file : '+S);{$endif}
-    FIniFile:=TMemIniFile.Create(S);
+    FIniFile:=CreateIniFile(S);
     FIniFile.WriteDateTime(SSession,KeyStart,Now);
     FIniFile.WriteDateTime(SSession,KeyStart,Now);
     FIniFile.WriteInteger(SSession,KeyTimeOut,Self.TimeOutMinutes);
     FIniFile.WriteInteger(SSession,KeyTimeOut,Self.TimeOutMinutes);
     FSessionStarted:=True;
     FSessionStarted:=True;
     end;
     end;
   FIniFile.WriteDateTime(SSession,KeyLast,Now);
   FIniFile.WriteDateTime(SSession,KeyLast,Now);
   If not FCached then
   If not FCached then
-    FIniFile.UpdateFile;
+    UpdateIniFile;
 {$ifdef cgidebug}SendMethodExit('TIniWebSession.InitSession');{$endif}
 {$ifdef cgidebug}SendMethodExit('TIniWebSession.InitSession');{$endif}
 end;
 end;
 
 
@@ -381,7 +452,7 @@ begin
   CheckSession;
   CheckSession;
   FIniFile.DeleteKey(SData,VariableName);
   FIniFile.DeleteKey(SData,VariableName);
   If Not Cached then
   If Not Cached then
-    TMemIniFile(FIniFile).UpdateFile;
+    UpdateIniFile;
 {$ifdef cgidebug}SendMethodExit('TIniWebSession.RemoveVariable');{$endif}
 {$ifdef cgidebug}SendMethodExit('TIniWebSession.RemoveVariable');{$endif}
 end;
 end;