• R/O
  • SSH
  • HTTPS

dzlargetextview: Commit


Commit MetaInfo

Revision266 (tree)
Zeit2016-05-30 02:45:34
Autortwm

Log Message

* Bugfix: The last block was never written if no other block was accessed after writing to it
* Now writes the count in the last Int64 of the file, after the last block, meaning the file will always be n*blocksize+SizeOf(Int64) long. This is checked when opening the file. If it is true, the Count is read from the file and the list is immediately available for use. Otherwise FCount must be set by other means.

Ändern Zusammenfassung

Diff

--- trunk/src/u_Int64ListFile.pas (revision 265)
+++ trunk/src/u_Int64ListFile.pas (revision 266)
@@ -11,8 +11,12 @@
1111 u_dzFileUtils;
1212
1313 type
14+ ///<summary>
15+ /// A list of Int64 items backed by a file. It can grow beyond memory size
16+ /// theoretically up to MaxInt64/SizeOf(Int64) items
17+ /// (tested up to 790 million entries). </summary>
1418 TInt64ListFile = class
15- private
19+ protected
1620 FTempDir: IUniqueTempDir;
1721 FBuffer: array[0..1023] of Int64;
1822 FOffset: Int64;
@@ -21,8 +25,11 @@
2125 function GetItems(_Idx: Int64): Int64;
2226 procedure SetItems(_Idx: Int64; const _Value: Int64);
2327 procedure AssureBufferFor(_Idx: integer);
28+ procedure WriteBufferToFile;
29+ procedure ReadBufferFromFile;
2430 public
25- constructor Create(_fn: string = '');
31+ constructor Create(const _fn: string); overload;
32+ constructor Create; overload;
2633 destructor Destroy; override;
2734 function Add(_Value: Int64): Int64;
2835 property Items[_Idx: Int64]: Int64 read GetItems write SetItems;
@@ -36,25 +43,47 @@
3643
3744 { TInt64ListFile }
3845
39-constructor TInt64ListFile.Create(_fn: string);
46+constructor TInt64ListFile.Create(const _fn: string);
47+var
48+ Size: Int64;
4049 begin
4150 inherited Create;
42- if _fn = '' then begin
43- FTempDir := TFileSystem.CreateUniqueTempDir();
44- _fn := FTempDir.PathBS + 'index.dat';
45- end;
4651 FTempFile := TdzFile.Create(_fn);
4752 FTempFile.AccessMode := faReadWrite;
4853 FTempFile.ShareMode := fsNoSharing;
49- FTempFile.CreateDisposition := fcCreateFailIfExists;
54+ FTempFile.CreateDisposition := fcOpenCreateIfNotExists;
5055 FTempFile.Open;
51- ZeroMemory(@FBuffer, SizeOf(FBuffer));
5256 FOffset := 0;
57+ Size := FTempFile.Size;
58+ if (Size > 0) and (Size mod SizeOf(FBuffer) = SizeOf(FCount)) then begin
59+ FTempFile.Seek(-SizeOf(FCount), soEnd);
60+ FTempFile.ReadBuffer(FCount, SizeOf(FCount));
61+ Assert(Size div SizeOf(Int64) - 1 >= FCount);
62+ end;
63+ ReadBufferFromFile;
5364 end;
5465
66+constructor TInt64ListFile.Create;
67+begin
68+ FTempDir := TFileSystem.CreateUniqueTempDir();
69+ Create(FTempDir.PathBS + 'temp' + '.In64');
70+end;
71+
5572 destructor TInt64ListFile.Destroy;
73+var
74+ SizeMod: Int64;
5675 begin
57- FreeAndNil(FTempFile);
76+ if Assigned(FTempFile) then begin
77+ if FCount > 0 then
78+ WriteBufferToFile;
79+ SizeMod := FTempFile.Size mod SizeOf(FBuffer);
80+ if SizeMod = SizeOf(FCount) then
81+ FTempFile.Seek(-SizeOf(FCount), soEnd)
82+ else if SizeMod = SizeOf(FCount) then
83+ FTempFile.Seek(0, soEnd);
84+ FTempFile.WriteBuffer(FCount, SizeOf(FCount));
85+ FreeAndNil(FTempFile);
86+ end;
5887 inherited;
5988 end;
6089
@@ -66,17 +95,29 @@
6695 Inc(FCount);
6796 end;
6897
98+procedure TInt64ListFile.ReadBufferFromFile;
99+begin
100+ if FOffset * SizeOf(Int64) + SizeOf(FBuffer) <= FTempFile.Size then begin
101+ FTempFile.Position := FOffset * SizeOf(Int64);
102+ FTempFile.ReadBuffer(FBuffer, SizeOf(FBuffer));
103+ end else
104+ ZeroMemory(@FBuffer, SizeOf(FBuffer));
105+end;
106+
107+procedure TInt64ListFile.WriteBufferToFile;
108+begin
109+ if FOffset >= 0 then begin
110+ FTempFile.Position := FOffset * SizeOf(Int64);
111+ FTempFile.WriteBuffer(FBuffer, SizeOf(FBuffer));
112+ end;
113+end;
114+
69115 procedure TInt64ListFile.AssureBufferFor(_Idx: integer);
70116 begin
71117 if (_Idx < FOffset) or (_Idx >= FOffset + Length(FBuffer)) then begin
72- FTempFile.Position := FOffset * SizeOf(Int64);
73- FTempFile.WriteBuffer(FBuffer, SizeOf(FBuffer));
118+ WriteBufferToFile;
74119 FOffset := (_Idx div Length(FBuffer)) * Length(FBuffer);
75- if FOffset * SizeOf(Int64) < FTempFile.Size then begin
76- FTempFile.Position := FOffset * SizeOf(Int64);
77- FTempFile.ReadBuffer(FBuffer, SizeOf(FBuffer));
78- end else
79- ZeroMemory(@FBuffer, SizeOf(FBuffer));
120+ ReadBufferFromFile;
80121 end;
81122 end;
82123
Show on old repository browser