* 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:
joost 2008-11-17 22:05:00 +00:00
parent 04d8ad3f17
commit d1beccce83

View File

@ -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;