summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: 9cd5e07)
raw | patch | inline | side by side (parent: 9cd5e07)
author | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 15 Apr 2016 11:29:42 +0000 (14:29 +0300) | ||
committer | Ketmar Dark <ketmar@ketmar.no-ip.org> | |
Fri, 15 Apr 2016 11:30:37 +0000 (14:30 +0300) |
src/sfs/sfs.pas | patch | blob | history |
diff --git a/src/sfs/sfs.pas b/src/sfs/sfs.pas
index 7588ae7fc7bfad89bb544866293272e1dffe887c..eaabb964a9e0bb9f55a8f952deabbd9ecf29b8fc 100644 (file)
--- a/src/sfs/sfs.pas
+++ b/src/sfs/sfs.pas
// ïîñëå èñïîëüçîâàíèÿ, íàòóðàëüíî, èòåðàòîð íàäî ãðîõíóòü %-)
function SFSFileList (const dataFileName: TSFSString): TSFSFileList;
+// çàïðåòèòü îñâîáîæäåíèå âðåìåííûõ òîìîâ (ìîæíî âûçûâàòü ðåêóðñèâíî)
+procedure sfsGCDisable ();
+
+// ðàçðåøèòü îñâîáîæäåíèå âðåìåííûõ òîìîâ (ìîæíî âûçûâàòü ðåêóðñèâíî)
+procedure sfsGCEnable ();
+
+// for completeness sake
+procedure sfsGCCollect ();
+
+
function SFSReplacePathDelims (const s: TSFSString; newDelim: TSFSChar): TSFSString;
// èãíîðèðóåò ðåãèñòð ñèìâîëîâ
function SFSStrEqu (const s0, s1: TSFSString): Boolean;
var
factories: TObjectList; // TSFSVolumeFactory
volumes: TObjectList; // TVolumeInfo
+ gcdisabled: Integer = 0; // >0: disabled
+
+
+procedure sfsGCCollect ();
+var
+ f, c: Integer;
+ vi: TVolumeInfo;
+ used: Boolean;
+begin
+ // collect garbage
+ f := 0;
+ while f < volumes.Count do
+ begin
+ vi := TVolumeInfo(volumes[f]);
+ if vi = nil then continue;
+ if (not vi.fPermanent) and (vi.fVolume.fRC = 0) and (vi.fOpenedFilesCount = 0) then
+ begin
+ // this volume probably can be removed
+ used := false;
+ c := volumes.Count-1;
+ while not used and (c >= 0) do
+ begin
+ if (c <> f) and (volumes[c] <> nil) then
+ begin
+ used := (TVolumeInfo(volumes[c]).fStream = vi.fStream);
+ if not used then used := (TVolumeInfo(volumes[c]).fVolume.fFileStream = vi.fStream);
+ if used then break;
+ end;
+ Dec(c);
+ end;
+ if not used then
+ begin
+ {$IFDEF SFS_VOLDEBUG}writeln('000: destroying volume "', TVolumeInfo(volumes[f]).fPackName, '"');{$ENDIF}
+ volumes.extract(vi); // remove from list
+ vi.Free; // and kill
+ f := 0;
+ continue;
+ end;
+ end;
+ Inc(f); // next volume
+ end;
+end;
+
+procedure sfsGCDisable ();
+begin
+ Inc(gcdisabled);
+end;
+
+procedure sfsGCEnable ();
+begin
+ Dec(gcdisabled);
+ if gcdisabled <= 0 then
+ begin
+ gcdisabled := 0;
+ sfsGCCollect();
+ end;
+end;
// ðàçáèòü èìÿ ôàéëà íà ÷àñòè: ïðåôèêñ ôàéëîâîé ñèñòåìû, èìÿ ôàéëà äàííûõ,
if fOwner <> nil then
begin
Dec(fOwner.fOpenedFilesCount);
- if not fOwner.fPermanent and (fOwner.fOpenedFilesCount < 1) then
+ if (gcdisabled = 0) and not fOwner.fPermanent and (fOwner.fOpenedFilesCount < 1) then
begin
f := volumes.IndexOf(fOwner);
if f <> -1 then
begin
- {$IFDEF SFS_VOLDEBUG}writeln('destroying volume "', TVolumeInfo(volumes[f]).fPackName, '"');{$ENDIF}
+ {$IFDEF SFS_VOLDEBUG}writeln('001: destroying volume "', TVolumeInfo(volumes[f]).fPackName, '"');{$ENDIF}
volumes[f] := nil; // this will destroy the volume
end;
end;
if fVolume <> nil then Dec(fVolume.fRC);
Dec(TVolumeInfo(volumes[f]).fOpenedFilesCount);
// óáü¸ì çàïèñü, åñëè îíà âðåìåííàÿ, è â íåé íåò áîëüøå íè÷åãî îòêðûòîãî
- if not TVolumeInfo(volumes[f]).fPermanent and (TVolumeInfo(volumes[f]).fOpenedFilesCount < 1) then
+ if (gcdisabled = 0) and not TVolumeInfo(volumes[f]).fPermanent and (TVolumeInfo(volumes[f]).fOpenedFilesCount < 1) then
begin
- {$IFDEF SFS_VOLDEBUG}writeln('destroying volume "', TVolumeInfo(volumes[f]).fPackName, '"');{$ENDIF}
+ {$IFDEF SFS_VOLDEBUG}writeln('002: destroying volume "', TVolumeInfo(volumes[f]).fPackName, '"');{$ENDIF}
volumes[f] := nil;
end;
inherited Destroy();
except
FreeAndNil(st);
// óäàëèì íåèñïîëüçóåìûé âðåìåííûé òîì.
- if not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[result] := nil;
+ if (gcdisabled = 0) and not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[result] := nil;
raise;
end;
// óðà. îòêðûëè ôàéë. êèäàåì â âîçäóõ ÷åï÷èêè, ïðîäîëæàåì ðàçâëå÷åíèå.
ps := TOwnedPartialStream.Create(vi, result, 0, result.Size, true);
except
result.Free();
- if not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[f] := nil;
+ if (gcdisabled = 0) and not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[f] := nil;
result := CheckDisk(); // îáëîì ñ datafile, ïðîâåðèì äèñê
if result = nil then raise ESFSError.Create('file not found: "'+fName+'"');
exit;
result := TSFSFileList.Create(vi.fVolume);
Inc(vi.fVolume.fRC);
except
- if not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[f] := nil;
+ if (gcdisabled = 0) and not vi.fPermanent and (vi.fOpenedFilesCount < 1) then volumes[f] := nil;
end;
end;