mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 03:59:13 +02:00
* New algorith to store update-buffers to file
* RowStateToByte and ByteToRowState * Start at the begin of a stream, after the automatic recognition of the stream has been used * Implemented TBufDataset.CompareBookmarks * Some update-buffer fixes * Fixed some warnings git-svn-id: trunk@12155 -
This commit is contained in:
parent
04d8ad3f17
commit
d1beccce83
@ -76,6 +76,10 @@ type
|
|||||||
- If UpdateKind is ukDelete it contains a bookmark to the record just after the deleted record
|
- If UpdateKind is ukDelete it contains a bookmark to the record just after the deleted record
|
||||||
}
|
}
|
||||||
BookmarkData : TBufBookmark;
|
BookmarkData : TBufBookmark;
|
||||||
|
{ DelBookMarkData:
|
||||||
|
- If UpdateKind is ukDelete it contains a bookmark to the deleted record, before it got deleted
|
||||||
|
}
|
||||||
|
DelBookmarkData : TBufBookmark;
|
||||||
{ OldValuesBuffer:
|
{ OldValuesBuffer:
|
||||||
- If UpdateKind is ukModify it contains a record-buffer which contains the old data
|
- If UpdateKind is ukModify it contains a record-buffer which contains the old data
|
||||||
- If UpdateKind is ukDelete it contains a record-buffer with the data of the deleted record
|
- If UpdateKind is ukDelete it contains a record-buffer with the data of the deleted record
|
||||||
@ -105,7 +109,6 @@ type
|
|||||||
TBufIndex = class(TObject)
|
TBufIndex = class(TObject)
|
||||||
private
|
private
|
||||||
FDataset : TBufDataset;
|
FDataset : TBufDataset;
|
||||||
|
|
||||||
protected
|
protected
|
||||||
function GetBookmarkSize: integer; virtual; abstract;
|
function GetBookmarkSize: integer; virtual; abstract;
|
||||||
function GetCurrentBuffer: Pointer; virtual; abstract;
|
function GetCurrentBuffer: Pointer; virtual; abstract;
|
||||||
@ -306,22 +309,25 @@ type
|
|||||||
TDatapacketReaderClass = class of TDatapacketReader;
|
TDatapacketReaderClass = class of TDatapacketReader;
|
||||||
TDataPacketReader = class(TObject)
|
TDataPacketReader = class(TObject)
|
||||||
FStream : TStream;
|
FStream : TStream;
|
||||||
|
protected
|
||||||
|
class function RowStateToByte(const ARowState : TRowState) : byte;
|
||||||
|
class function ByteToRowState(const AByte : Byte) : TRowState;
|
||||||
public
|
public
|
||||||
constructor create(AStream : TStream); virtual;
|
constructor create(AStream : TStream); virtual;
|
||||||
|
|
||||||
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
||||||
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); virtual; abstract;
|
||||||
procedure GetRecordUpdState(var AIsUpdate,AAddRecordBuffer,AIsFirstEntry : boolean); virtual; abstract;
|
function GetRecordRowState(out AUpdOrder : Integer) : TRowState; virtual; abstract;
|
||||||
procedure EndStoreRecord(const AChangeLog : TChangeLogEntryArr); virtual; abstract;
|
procedure EndStoreRecord; virtual; abstract;
|
||||||
function GetCurrentRecord : boolean; virtual; abstract;
|
function GetCurrentRecord : boolean; virtual; abstract;
|
||||||
procedure GotoNextRecord; virtual; abstract;
|
procedure GotoNextRecord; virtual; abstract;
|
||||||
function GetCurrentElement : pointer; virtual; abstract;
|
function GetCurrentElement : pointer; virtual; abstract;
|
||||||
procedure GotoElement(const AnElement : pointer); virtual; abstract;
|
procedure GotoElement(const AnElement : pointer); virtual; abstract;
|
||||||
procedure RestoreRecord(ADataset : TBufDataset); virtual; abstract;
|
procedure RestoreRecord(ADataset : TBufDataset); virtual; abstract;
|
||||||
procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); virtual; abstract;
|
procedure StoreRecord(ADataset : TBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); virtual; abstract;
|
||||||
procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); virtual; abstract;
|
procedure InitLoadRecords; virtual; abstract;
|
||||||
property Stream: TStream read FStream;
|
|
||||||
class function RecognizeStream(AStream : TStream) : boolean; virtual; abstract;
|
class function RecognizeStream(AStream : TStream) : boolean; virtual; abstract;
|
||||||
|
property Stream: TStream read FStream;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ TFpcBinaryDatapacketReader }
|
{ TFpcBinaryDatapacketReader }
|
||||||
@ -330,16 +336,15 @@ type
|
|||||||
public
|
public
|
||||||
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
|
procedure LoadFieldDefs(AFieldDefs : TFieldDefs); override;
|
||||||
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
|
procedure StoreFieldDefs(AFieldDefs : TFieldDefs); override;
|
||||||
procedure GetRecordUpdState(var AIsUpdate, AAddRecordBuffer,
|
function GetRecordRowState(out AUpdOrder : Integer) : TRowState; override;
|
||||||
AIsFirstEntry: boolean); override;
|
procedure EndStoreRecord; override;
|
||||||
procedure EndStoreRecord(const AChangeLog : TChangeLogEntryArr); override;
|
|
||||||
function GetCurrentRecord : boolean; override;
|
function GetCurrentRecord : boolean; override;
|
||||||
procedure GotoNextRecord; override;
|
procedure GotoNextRecord; override;
|
||||||
procedure GotoElement(const AnElement : pointer); override;
|
procedure GotoElement(const AnElement : pointer); override;
|
||||||
procedure InitLoadRecords(var AChangeLog : TChangeLogEntryArr); override;
|
procedure InitLoadRecords; override;
|
||||||
function GetCurrentElement: pointer; override;
|
function GetCurrentElement: pointer; override;
|
||||||
procedure RestoreRecord(ADataset : TBufDataset); override;
|
procedure RestoreRecord(ADataset : TBufDataset); override;
|
||||||
procedure StoreRecord(ADataset : TBufDataset; RowState : TRowState); override;
|
procedure StoreRecord(ADataset : TBufDataset; ARowState : TRowState; AUpdOrder : integer = 0); override;
|
||||||
class function RecognizeStream(AStream : TStream) : boolean; override;
|
class function RecognizeStream(AStream : TStream) : boolean; override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -385,7 +390,7 @@ type
|
|||||||
function GetIndexName: String;
|
function GetIndexName: String;
|
||||||
function LoadBuffer(Buffer : PChar): TGetResult;
|
function LoadBuffer(Buffer : PChar): TGetResult;
|
||||||
function GetFieldSize(FieldDef : TFieldDef) : longint;
|
function GetFieldSize(FieldDef : TFieldDef) : longint;
|
||||||
function GetRecordUpdateBuffer(const ABookmark : TBufBookmark) : boolean;
|
function GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false) : boolean;
|
||||||
function GetActiveRecordUpdateBuffer : boolean;
|
function GetActiveRecordUpdateBuffer : boolean;
|
||||||
procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
|
procedure ProcessFieldCompareStruct(AField: TField; var ACompareRec : TDBCompareRec);
|
||||||
procedure SetIndexFieldNames(const AValue: String);
|
procedure SetIndexFieldNames(const AValue: String);
|
||||||
@ -395,7 +400,7 @@ type
|
|||||||
function IntAllocRecordBuffer: PChar;
|
function IntAllocRecordBuffer: PChar;
|
||||||
procedure DoFilterRecord(var Acceptable: Boolean);
|
procedure DoFilterRecord(var Acceptable: Boolean);
|
||||||
procedure ParseFilter(const AFilter: string);
|
procedure ParseFilter(const AFilter: string);
|
||||||
procedure IntLoadFielddefsFromFile(const FileName: string);
|
procedure IntLoadFielddefsFromFile;
|
||||||
procedure IntLoadRecordsFromFile;
|
procedure IntLoadRecordsFromFile;
|
||||||
protected
|
protected
|
||||||
procedure UpdateIndexDefs; override;
|
procedure UpdateIndexDefs; override;
|
||||||
@ -466,6 +471,7 @@ type
|
|||||||
procedure LoadFromFile(AFileName: string = ''; Format: TDataPacketFormat = dfAny);
|
procedure LoadFromFile(AFileName: string = ''; Format: TDataPacketFormat = dfAny);
|
||||||
procedure SaveToFile(AFileName: string = ''; Format: TDataPacketFormat = dfBinary);
|
procedure SaveToFile(AFileName: string = ''; Format: TDataPacketFormat = dfBinary);
|
||||||
procedure CreateDataset;
|
procedure CreateDataset;
|
||||||
|
function CompareBookmarks(Bookmark1, Bookmark2: TBookmark): Longint; override;
|
||||||
|
|
||||||
property ChangeCount : Integer read GetChangeCount;
|
property ChangeCount : Integer read GetChangeCount;
|
||||||
property MaxIndexesCount : Integer read FMaxIndexesCount write SetMaxIndexesCount;
|
property MaxIndexesCount : Integer read FMaxIndexesCount write SetMaxIndexesCount;
|
||||||
@ -913,7 +919,7 @@ begin
|
|||||||
FFileStream := TFileStream.Create(FileName,fmOpenRead);
|
FFileStream := TFileStream.Create(FileName,fmOpenRead);
|
||||||
FDatasetReader := TFpcBinaryDatapacketReader.Create(FFileStream);
|
FDatasetReader := TFpcBinaryDatapacketReader.Create(FFileStream);
|
||||||
end;
|
end;
|
||||||
if assigned(FDatasetReader) then IntLoadFielddefsFromFile(FFileName);
|
if assigned(FDatasetReader) then IntLoadFielddefsFromFile;
|
||||||
CalcRecordSize;
|
CalcRecordSize;
|
||||||
|
|
||||||
FBRecordcount := 0;
|
FBRecordcount := 0;
|
||||||
@ -1516,21 +1522,30 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBufDataset.GetRecordUpdateBuffer(const ABookmark: TBufBookmark): boolean;
|
function TBufDataset.GetRecordUpdateBuffer(const ABookmark : TBufBookmark; IncludeDeleted : boolean = false; AFindNext : boolean = false): boolean;
|
||||||
|
|
||||||
var x : integer;
|
var x : integer;
|
||||||
|
StartBuf : integer;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
if AFindNext then
|
||||||
|
begin
|
||||||
|
inc(FCurrentUpdateBuffer);
|
||||||
|
StartBuf:=FCurrentUpdateBuffer;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
StartBuf := 0;
|
||||||
if (FCurrentUpdateBuffer >= length(FUpdateBuffer)) or not FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark) then
|
if (FCurrentUpdateBuffer >= length(FUpdateBuffer)) or not FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark) then
|
||||||
for x := 0 to high(FUpdateBuffer) do
|
for x := StartBuf to high(FUpdateBuffer) do
|
||||||
if FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].BookmarkData,@ABookmark) and
|
if FCurrentIndex.CompareBookmarks(@FUpdateBuffer[x].BookmarkData,@ABookmark) and
|
||||||
(FUpdateBuffer[x].UpdateKind<>ukDelete) then // The Bookmarkdata of a deleted record does not contain the deleted record, but the record thereafter
|
((FUpdateBuffer[x].UpdateKind<>ukDelete) or IncludeDeleted) then // The Bookmarkdata of a deleted record does not contain the deleted record, but the record thereafter
|
||||||
begin
|
begin
|
||||||
FCurrentUpdateBuffer := x;
|
FCurrentUpdateBuffer := x;
|
||||||
break;
|
break;
|
||||||
end;
|
end;
|
||||||
Result := (FCurrentUpdateBuffer < length(FUpdateBuffer)) and
|
Result := (FCurrentUpdateBuffer < length(FUpdateBuffer)) and
|
||||||
(FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark));
|
(FCurrentIndex.CompareBookmarks(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData,@ABookmark)) and
|
||||||
|
((FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind<>ukDelete) or IncludeDeleted) ;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
|
function TBufDataset.LoadBuffer(Buffer : PChar): TGetResult;
|
||||||
@ -1711,7 +1726,8 @@ begin
|
|||||||
// may arise. The 'delete' is placed in the update-buffer before the actual delete
|
// may arise. The 'delete' is placed in the update-buffer before the actual delete
|
||||||
// took place. This can lead into troubles, because other updates can depend on
|
// took place. This can lead into troubles, because other updates can depend on
|
||||||
// the record still being available.
|
// the record still being available.
|
||||||
if not GetActiveRecordUpdateBuffer or (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukModify) then
|
if not GetActiveRecordUpdateBuffer or
|
||||||
|
(FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukModify) then
|
||||||
begin
|
begin
|
||||||
FCurrentUpdateBuffer := length(FUpdateBuffer);
|
FCurrentUpdateBuffer := length(FUpdateBuffer);
|
||||||
SetLength(FUpdateBuffer,FCurrentUpdateBuffer+1);
|
SetLength(FUpdateBuffer,FCurrentUpdateBuffer+1);
|
||||||
@ -1719,15 +1735,15 @@ begin
|
|||||||
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := IntAllocRecordBuffer;
|
||||||
move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
move(RemRec^, FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
||||||
FreeRecordBuffer(RemRecBuf);
|
FreeRecordBuffer(RemRecBuf);
|
||||||
FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
||||||
end
|
end
|
||||||
else //with FIndexes[0] do
|
else //with FIndexes[0] do
|
||||||
begin
|
begin
|
||||||
FreeRecordBuffer(RemRecBuf);
|
FreeRecordBuffer(RemRecBuf);
|
||||||
FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
|
||||||
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
|
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukModify then
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil; //this 'disables' the updatebuffer
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := nil; //this 'disables' the updatebuffer
|
||||||
end;
|
end;
|
||||||
|
FCurrentIndex.StoreCurrentRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
||||||
|
FUpdateBuffer[FCurrentUpdateBuffer].DelBookmarkData := RemRecBookmrk;
|
||||||
|
|
||||||
dec(FBRecordCount);
|
dec(FBRecordCount);
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukDelete;
|
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind := ukDelete;
|
||||||
@ -2321,27 +2337,22 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TBufDataset.GetDatasetPacket(AWriter: TDataPacketReader);
|
procedure TBufDataset.GetDatasetPacket(AWriter: TDataPacketReader);
|
||||||
var i : integer;
|
var ScrollResult : TGetResult;
|
||||||
ScrollResult : TGetResult;
|
|
||||||
StoreDSState : TDataSetState;
|
StoreDSState : TDataSetState;
|
||||||
ABookMark : PBufBookmark;
|
ABookMark : PBufBookmark;
|
||||||
ATBookmark : TBufBookmark;
|
ATBookmark : TBufBookmark;
|
||||||
ChangeLog : array of TChangeLogEntry;
|
RowState : TRowState;
|
||||||
|
EntryNr : integer;
|
||||||
var RowState : TRowState;
|
StoreUpdBuf : integer;
|
||||||
RecUpdBuf: integer;
|
RunNr : integer;
|
||||||
EntryNr : integer;
|
|
||||||
ChangeLogStr : String;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FDatasetReader := AWriter;
|
FDatasetReader := AWriter;
|
||||||
try
|
try
|
||||||
|
//CheckActive;
|
||||||
// CheckActive;
|
|
||||||
ABookMark:=@ATBookmark;
|
ABookMark:=@ATBookmark;
|
||||||
FDatasetReader.StoreFieldDefs(FieldDefs);
|
FDatasetReader.StoreFieldDefs(FieldDefs);
|
||||||
|
|
||||||
SetLength(ChangeLog,length(FUpdateBuffer));
|
|
||||||
EntryNr:=1;
|
EntryNr:=1;
|
||||||
|
|
||||||
StoreDSState:=State;
|
StoreDSState:=State;
|
||||||
@ -2350,71 +2361,43 @@ begin
|
|||||||
while ScrollResult=grOK do
|
while ScrollResult=grOK do
|
||||||
begin
|
begin
|
||||||
FCurrentIndex.StoreCurrentRecIntoBookmark(ABookmark);
|
FCurrentIndex.StoreCurrentRecIntoBookmark(ABookmark);
|
||||||
if GetRecordUpdateBuffer(ABookmark^) and (FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind <> ukDelete) then
|
if GetRecordUpdateBuffer(ABookmark^,True) then
|
||||||
begin
|
begin
|
||||||
if FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind = ukInsert then
|
case FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind of
|
||||||
begin
|
ukModify : begin
|
||||||
RowState:=[rsvInserted];
|
FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
||||||
FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
FDatasetReader.StoreRecord(Self,[rsvOriginal],FCurrentUpdateBuffer);
|
||||||
with ChangeLog[FCurrentUpdateBuffer] do
|
RowState:=[rsvUpdated];
|
||||||
begin
|
end;
|
||||||
OrigEntry:=0;
|
ukDelete : begin
|
||||||
NewEntry:=EntryNr;
|
repeat
|
||||||
UpdateKind:=ukInsert;
|
StoreUpdBuf := FCurrentUpdateBuffer;
|
||||||
end;
|
RunNr := 0;
|
||||||
end
|
|
||||||
else // This is always ukModified
|
repeat
|
||||||
begin
|
inc(RunNr);
|
||||||
RowState:=[rsvOriginal];
|
Assert(FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind=ukDelete);
|
||||||
FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
FFilterBuffer:=FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer;
|
||||||
ChangeLog[FCurrentUpdateBuffer].OrigEntry:=EntryNr;
|
FDatasetReader.StoreRecord(Self,[rsvDeleted],FCurrentUpdateBuffer);
|
||||||
end;
|
RowState:=[];
|
||||||
|
until not GetRecordUpdateBuffer(FUpdateBuffer[FCurrentUpdateBuffer].DelBookmarkData,True,RunNr>1);
|
||||||
|
|
||||||
|
FCurrentUpdateBuffer:=StoreUpdBuf;
|
||||||
|
until not GetRecordUpdateBuffer(ABookmark^,True,True)
|
||||||
|
end;
|
||||||
|
end; { case }
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
|
||||||
FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
||||||
RowState:=[];
|
RowState:=[];
|
||||||
end;
|
FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
||||||
|
FDatasetReader.StoreRecord(Self,RowState,FCurrentUpdateBuffer);
|
||||||
|
|
||||||
FDatasetReader.StoreRecord(Self,RowState);
|
|
||||||
inc(EntryNr);
|
inc(EntryNr);
|
||||||
ScrollResult:=FCurrentIndex.ScrollForward;
|
ScrollResult:=FCurrentIndex.ScrollForward;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
for RecUpdBuf:=0 to length(FUpdateBuffer)-1 do with FUpdateBuffer[RecUpdBuf] do
|
|
||||||
begin
|
|
||||||
if UpdateKind = ukDelete then
|
|
||||||
begin
|
|
||||||
RowState:=[rsvDeleted];
|
|
||||||
FFilterBuffer:=FUpdateBuffer[RecUpdBuf].OldValuesBuffer;
|
|
||||||
FDatasetReader.StoreRecord(Self, RowState);
|
|
||||||
with ChangeLog[RecUpdBuf] do
|
|
||||||
begin
|
|
||||||
NewEntry:=EntryNr;
|
|
||||||
UpdateKind:=ukDelete;
|
|
||||||
end;
|
|
||||||
inc(EntryNr);
|
|
||||||
end
|
|
||||||
else if UpdateKind = ukModify then
|
|
||||||
begin
|
|
||||||
RowState:=[rsvUpdated];
|
|
||||||
FCurrentIndex.GotoBookmark(@BookmarkData);
|
|
||||||
FFilterBuffer:=FCurrentIndex.CurrentBuffer;
|
|
||||||
FDatasetReader.StoreRecord(Self, RowState);
|
|
||||||
with ChangeLog[RecUpdBuf] do
|
|
||||||
begin
|
|
||||||
NewEntry:=EntryNr;
|
|
||||||
UpdateKind:=ukModify;
|
|
||||||
end;
|
|
||||||
inc(EntryNr);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
RestoreState(StoreDSState);
|
RestoreState(StoreDSState);
|
||||||
|
|
||||||
FDatasetReader.EndStoreRecord(ChangeLog);
|
FDatasetReader.EndStoreRecord;
|
||||||
SetLength(ChangeLog,0);
|
|
||||||
|
|
||||||
finally
|
finally
|
||||||
FDatasetReader := nil;
|
FDatasetReader := nil;
|
||||||
end;
|
end;
|
||||||
@ -2427,7 +2410,10 @@ begin
|
|||||||
if GetRegisterDatapacketReader(AStream,format,APacketReaderReg) then
|
if GetRegisterDatapacketReader(AStream,format,APacketReaderReg) then
|
||||||
APacketReader := APacketReaderReg.ReaderClass.create(AStream)
|
APacketReader := APacketReaderReg.ReaderClass.create(AStream)
|
||||||
else if TFpcBinaryDatapacketReader.RecognizeStream(AStream) then
|
else if TFpcBinaryDatapacketReader.RecognizeStream(AStream) then
|
||||||
|
begin
|
||||||
|
AStream.Seek(0,soFromBeginning);
|
||||||
APacketReader := TFpcBinaryDatapacketReader.create(AStream)
|
APacketReader := TFpcBinaryDatapacketReader.create(AStream)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
DatabaseError(SStreamNotRecognised);
|
DatabaseError(SStreamNotRecognised);
|
||||||
try
|
try
|
||||||
@ -2472,7 +2458,16 @@ begin
|
|||||||
CreateFields;
|
CreateFields;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TBufDataset.IntLoadFielddefsFromFile(const FileName: string);
|
function TBufDataset.CompareBookmarks(Bookmark1, Bookmark2: TBookmark
|
||||||
|
): Longint;
|
||||||
|
begin
|
||||||
|
if FCurrentIndex.CompareBookmarks(Bookmark1,Bookmark2) then
|
||||||
|
Result := 0
|
||||||
|
else
|
||||||
|
Result := -1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TBufDataset.IntLoadFielddefsFromFile;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FDatasetReader.LoadFielddefs(FieldDefs);
|
FDatasetReader.LoadFielddefs(FieldDefs);
|
||||||
@ -2481,44 +2476,71 @@ end;
|
|||||||
|
|
||||||
procedure TBufDataset.IntLoadRecordsFromFile;
|
procedure TBufDataset.IntLoadRecordsFromFile;
|
||||||
|
|
||||||
|
var StoreState : TDataSetState;
|
||||||
var StoreState : TDataSetState;
|
EntryNr : integer;
|
||||||
ChangeLog : TChangeLogEntryArr;
|
AddRecordBuffer : boolean;
|
||||||
ChangeLogStr : string;
|
ARowState : TRowState;
|
||||||
ChangeLogInfo : TChangeLogInfoArr;
|
AUpdOrder : integer;
|
||||||
EntryNr : integer;
|
|
||||||
i : integer;
|
|
||||||
IsUpdate,
|
|
||||||
AddRecordBuffer,
|
|
||||||
IsFirstEntry : boolean;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
FDatasetReader.InitLoadRecords(ChangeLog);
|
FDatasetReader.InitLoadRecords;
|
||||||
EntryNr:=1;
|
EntryNr:=1;
|
||||||
StoreState:=SetTempState(dsFilter);
|
StoreState:=SetTempState(dsFilter);
|
||||||
SetLength(ChangeLogInfo,length(ChangeLog));
|
|
||||||
|
|
||||||
while FDatasetReader.GetCurrentRecord do
|
while FDatasetReader.GetCurrentRecord do
|
||||||
begin
|
begin
|
||||||
FDatasetReader.GetRecordUpdState(IsUpdate,AddRecordBuffer,IsFirstEntry);
|
ARowState := FDatasetReader.GetRecordRowState(AUpdOrder);
|
||||||
|
if rsvOriginal in ARowState then
|
||||||
if IsUpdate then
|
|
||||||
begin
|
begin
|
||||||
if IsFirstEntry then
|
if length(FUpdateBuffer) < (AUpdOrder+1) then
|
||||||
begin
|
SetLength(FUpdateBuffer,AUpdOrder+1);
|
||||||
for i := 0 to length(ChangeLog) -1 do
|
|
||||||
if ChangeLog[i].OrigEntry=EntryNr then break;
|
|
||||||
ChangeLogInfo[i].FirstChangeNode:=FDatasetReader.GetCurrentElement;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
for i := 0 to length(ChangeLog) -1 do
|
|
||||||
if ChangeLog[i].NewEntry=EntryNr then break;
|
|
||||||
ChangeLogInfo[i].SecondChangeNode:=FDatasetReader.GetCurrentElement;
|
|
||||||
end;
|
|
||||||
|
|
||||||
FIndexes[0].StoreSpareRecIntoBookmark(@ChangeLogInfo[i].Bookmark);
|
FCurrentUpdateBuffer:=AUpdOrder;
|
||||||
end;
|
|
||||||
|
FFilterBuffer:=IntAllocRecordBuffer;
|
||||||
|
fillchar(FFilterBuffer^,FNullmaskSize,0);
|
||||||
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := FFilterBuffer;
|
||||||
|
FDatasetReader.RestoreRecord(self);
|
||||||
|
|
||||||
|
FDatasetReader.GotoNextRecord;
|
||||||
|
if not FDatasetReader.GetCurrentRecord then
|
||||||
|
DatabaseError(SStreamNotRecognised);
|
||||||
|
ARowState := FDatasetReader.GetRecordRowState(AUpdOrder);
|
||||||
|
if rsvUpdated in ARowState then
|
||||||
|
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:= ukModify
|
||||||
|
else
|
||||||
|
DatabaseError(SStreamNotRecognised);
|
||||||
|
|
||||||
|
FFilterBuffer:=FIndexes[0].SpareBuffer;
|
||||||
|
FIndexes[0].StoreSpareRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
||||||
|
fillchar(FFilterBuffer^,FNullmaskSize,0);
|
||||||
|
|
||||||
|
FDatasetReader.RestoreRecord(self);
|
||||||
|
FIndexes[0].AddRecord(IntAllocRecordBuffer);
|
||||||
|
inc(FBRecordCount);
|
||||||
|
|
||||||
|
AddRecordBuffer:=False;
|
||||||
|
|
||||||
|
end
|
||||||
|
else if rsvDeleted in ARowState then
|
||||||
|
begin
|
||||||
|
if length(FUpdateBuffer) < (AUpdOrder+1) then
|
||||||
|
SetLength(FUpdateBuffer,AUpdOrder+1);
|
||||||
|
|
||||||
|
FCurrentUpdateBuffer:=AUpdOrder;
|
||||||
|
|
||||||
|
FFilterBuffer:=IntAllocRecordBuffer;
|
||||||
|
fillchar(FFilterBuffer^,FNullmaskSize,0);
|
||||||
|
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer := FFilterBuffer;
|
||||||
|
FDatasetReader.RestoreRecord(self);
|
||||||
|
|
||||||
|
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:= ukDelete;
|
||||||
|
FIndexes[0].StoreSpareRecIntoBookmark(@FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData);
|
||||||
|
|
||||||
|
AddRecordBuffer:=False;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
AddRecordBuffer:=True;
|
||||||
|
|
||||||
if AddRecordBuffer then
|
if AddRecordBuffer then
|
||||||
begin
|
begin
|
||||||
@ -2534,35 +2556,6 @@ begin
|
|||||||
inc(EntryNr);
|
inc(EntryNr);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Iterate through the ChangeLog list and add modifications to he update buffer
|
|
||||||
for i := 0 to length(ChangeLog)-1 do
|
|
||||||
begin
|
|
||||||
FCurrentUpdateBuffer:=Length(FUpdateBuffer);
|
|
||||||
setlength(FUpdateBuffer,FCurrentUpdateBuffer+1);
|
|
||||||
case ChangeLog[i].UpdateKind of
|
|
||||||
ukDelete : begin
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukDelete;
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
||||||
FDatasetReader.GotoElement(ChangeLogInfo[i].FirstChangeNode);
|
|
||||||
FDatasetReader.RestoreRecord(self);
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer:=IntAllocRecordBuffer;
|
|
||||||
move(findexes[0].SpareBuffer^,FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
|
||||||
end;
|
|
||||||
ukModify : begin
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukModify;
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
||||||
FDatasetReader.GotoElement(ChangeLogInfo[i].SecondChangeNode);
|
|
||||||
FDatasetReader.RestoreRecord(self);
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer:=IntAllocRecordBuffer;
|
|
||||||
move(findexes[0].SpareBuffer^,FUpdateBuffer[FCurrentUpdateBuffer].OldValuesBuffer^,FRecordSize);
|
|
||||||
end;
|
|
||||||
ukInsert : begin
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].UpdateKind:=ukInsert;
|
|
||||||
FUpdateBuffer[FCurrentUpdateBuffer].BookmarkData:=ChangeLogInfo[i].Bookmark;
|
|
||||||
FDatasetReader.GotoElement(ChangeLogInfo[i].FirstChangeNode);
|
|
||||||
end;
|
|
||||||
end; {case}
|
|
||||||
end;
|
|
||||||
RestoreState(StoreState);
|
RestoreState(StoreState);
|
||||||
FIndexes[0].SetToFirstRecord;
|
FIndexes[0].SetToFirstRecord;
|
||||||
FAllPacketsFetched:=True;
|
FAllPacketsFetched:=True;
|
||||||
@ -2820,6 +2813,7 @@ end;
|
|||||||
|
|
||||||
constructor TArrayBufIndex.Create(const ADataset: TBufDataset);
|
constructor TArrayBufIndex.Create(const ADataset: TBufDataset);
|
||||||
begin
|
begin
|
||||||
|
Inherited create(ADataset);
|
||||||
FInitialBuffers:=10000;
|
FInitialBuffers:=10000;
|
||||||
FGrowBuffer:=1000;
|
FGrowBuffer:=1000;
|
||||||
end;
|
end;
|
||||||
@ -2993,6 +2987,27 @@ end;
|
|||||||
|
|
||||||
{ TDataPacketReader }
|
{ TDataPacketReader }
|
||||||
|
|
||||||
|
class function TDataPacketReader.RowStateToByte(const ARowState: TRowState
|
||||||
|
): byte;
|
||||||
|
var RowStateInt : Byte;
|
||||||
|
begin
|
||||||
|
RowStateInt:=0;
|
||||||
|
if rsvOriginal in ARowState then RowStateInt := RowStateInt+1;
|
||||||
|
if rsvDeleted in ARowState then RowStateInt := RowStateInt+2;
|
||||||
|
if rsvInserted in ARowState then RowStateInt := RowStateInt+4;
|
||||||
|
if rsvUpdated in ARowState then RowStateInt := RowStateInt+8;
|
||||||
|
Result := RowStateInt;
|
||||||
|
end;
|
||||||
|
|
||||||
|
class function TDataPacketReader.ByteToRowState(const AByte: Byte): TRowState;
|
||||||
|
begin
|
||||||
|
result := [];
|
||||||
|
if (AByte and 1)=1 then Result := Result+[rsvOriginal];
|
||||||
|
if (AByte and 2)=2 then Result := Result+[rsvDeleted];
|
||||||
|
if (AByte and 4)=4 then Result := Result+[rsvInserted];
|
||||||
|
if (AByte and 8)=8 then Result := Result+[rsvUpdated];
|
||||||
|
end;
|
||||||
|
|
||||||
constructor TDataPacketReader.create(AStream: TStream);
|
constructor TDataPacketReader.create(AStream: TStream);
|
||||||
begin
|
begin
|
||||||
FStream := AStream;
|
FStream := AStream;
|
||||||
@ -3044,17 +3059,20 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.GetRecordUpdState(var AIsUpdate,
|
function TFpcBinaryDatapacketReader.GetRecordRowState(out AUpdOrder : Integer) : TRowState;
|
||||||
AAddRecordBuffer, AIsFirstEntry: boolean);
|
var Buf : byte;
|
||||||
begin
|
begin
|
||||||
AIsUpdate:=False;
|
Stream.Read(Buf,1);
|
||||||
AAddRecordBuffer:=True;
|
Result := ByteToRowState(Buf);
|
||||||
|
if Result<>[] then
|
||||||
|
Stream.ReadBuffer(AUpdOrder,sizeof(integer))
|
||||||
|
else
|
||||||
|
AUpdOrder := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.EndStoreRecord(
|
procedure TFpcBinaryDatapacketReader.EndStoreRecord;
|
||||||
const AChangeLog: TChangeLogEntryArr);
|
|
||||||
begin
|
begin
|
||||||
// inherited EndStoreRecord(AChangeLog);
|
// Do nothing
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpcBinaryDatapacketReader.GetCurrentRecord: boolean;
|
function TFpcBinaryDatapacketReader.GetCurrentRecord: boolean;
|
||||||
@ -3070,18 +3088,17 @@ end;
|
|||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.GotoElement(const AnElement: pointer);
|
procedure TFpcBinaryDatapacketReader.GotoElement(const AnElement: pointer);
|
||||||
begin
|
begin
|
||||||
// inherited GotoElement(AnElement);
|
// Do nothing
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.InitLoadRecords(
|
procedure TFpcBinaryDatapacketReader.InitLoadRecords;
|
||||||
var AChangeLog: TChangeLogEntryArr);
|
|
||||||
begin
|
begin
|
||||||
SetLength(AChangeLog,0);
|
// SetLength(AChangeLog,0);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TFpcBinaryDatapacketReader.GetCurrentElement: pointer;
|
function TFpcBinaryDatapacketReader.GetCurrentElement: pointer;
|
||||||
begin
|
begin
|
||||||
// Result:=inherited GetCurrentElement;
|
// Do nothing
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.RestoreRecord(ADataset: TBufDataset);
|
procedure TFpcBinaryDatapacketReader.RestoreRecord(ADataset: TBufDataset);
|
||||||
@ -3090,10 +3107,13 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TFpcBinaryDatapacketReader.StoreRecord(ADataset: TBufDataset;
|
procedure TFpcBinaryDatapacketReader.StoreRecord(ADataset: TBufDataset;
|
||||||
RowState: TRowState);
|
ARowState: TRowState; AUpdOrder : integer);
|
||||||
begin
|
begin
|
||||||
// Ugly because private members of ADataset are used...
|
// Ugly because private members of ADataset are used...
|
||||||
Stream.WriteByte($fe);
|
Stream.WriteByte($fe);
|
||||||
|
Stream.WriteByte(RowStateToByte(ARowState));
|
||||||
|
if ARowState<>[] then
|
||||||
|
Stream.WriteBuffer(AUpdOrder,sizeof(integer));
|
||||||
Stream.WriteBuffer(ADataset.GetCurrentBuffer^,ADataset.FRecordSize);
|
Stream.WriteBuffer(ADataset.GetCurrentBuffer^,ADataset.FRecordSize);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user