?? myldbpage.pas
字號:
unit MYLDBPage;
{$I MYLDBVer.inc}
interface
uses Classes, Windows, Math,
// MYLDBoluteDatabase units
{$IFDEF DEBUG_LOG}
MYLDBDebug,
{$ENDIF}
MYLDBExcept,
MYLDBMemory,
MYLDBConst,
MYLDBTypes;
type
TMYLDBPageManager = class;
TMYLDBSortedPageList = class;
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBPage
//
////////////////////////////////////////////////////////////////////////////////
TMYLDBPageTableStateInfo = packed record
TableState: Integer;
IsTableStateValueAssigned: Boolean;
end;
TMYLDBPage = class(TObject)
private
LPageManager: TMYLDBPageManager;
FPageNo: TMYLDBPageNo;
FPageBuffer: TMYLDBPageBuffer;
FOwnBuffer: Boolean;
FIsDirty: Boolean;
FUseCount: Integer;
FParentList: TMYLDBSortedPageList;
FSessionID: TMYLDBSessionID;
FReloaded: Boolean;
FEncryptionEnabled: Boolean;
FTableStates: array of TMYLDBPageTableStateInfo;
function GetPageHeader: PMYLDBDiskPageHeader;
function GetPageHeaderSize: Integer;
function GetPageData: TMYLDBPageBuffer;
function GetPageDataSize: Integer;
function GetPageSize: Integer;
procedure InitHeader;
public
constructor Create(PageManager: TMYLDBPageManager);
destructor Destroy; override;
procedure ClearPageBuffer;
procedure AllocPageBuffer;
procedure FreeAndNilPageBuffer;
procedure EnlargePageBuffer(NewSize: Integer);
procedure Synchronize;
function GetTableState(SessionID: TMYLDBSessionID; var TableState: Integer): Boolean;
procedure SetTableState(SessionID: TMYLDBSessionID; TableState: Integer);
property PageNo: TMYLDBPageNo read FPageNo write FPageNo;
property PageSize: Integer read GetPageSize;
property PageBuffer: TMYLDBPageBuffer read FPageBuffer write FPageBuffer;
property OwnBuffer: Boolean read FOwnBuffer write FOwnBuffer;
property IsDirty: Boolean read FIsDirty write FIsDirty;
property UseCount: Integer read FUseCount write FUseCount;
property PageManager: TMYLDBPageManager read LPageManager write LPageManager;
property PageHeader: PMYLDBDiskPageHeader read GetPageHeader;
property PageHeaderSize: Integer read GetPageHeaderSize;
property PageData: TMYLDBPageBuffer read GetPageData;
property PageDataSize: Integer read GetPageDataSize;
property ParentList: TMYLDBSortedPageList read FParentList write FParentList;
property SessionID: TMYLDBSessionID read FSessionID write FSessionID;
property Reloaded: Boolean read FReloaded write FReloaded;
property EncryptionEnabled: Boolean read FEncryptionEnabled write FEncryptionEnabled;
end;// TMYLDBPage
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBPageController
//
////////////////////////////////////////////////////////////////////////////////
TMYLDBPageController = class(TObject)
private
LPage: TMYLDBPage;
protected
procedure SetPageNo(Value: TMYLDBPageNo);
function GetPageNo: TMYLDBPageNo;
function GetPageSize: Integer;
procedure SetPageBuffer(Value: TMYLDBPageBuffer);
function GetPageBuffer: TMYLDBPageBuffer;
procedure SetOwnBuffer(Value: Boolean);
function GetOwnBuffer: Boolean;
procedure SetIsDirty(Value: Boolean);
function GetIsDirty: Boolean;
procedure SetUseCount(Value: Integer);
function GetUseCount: Integer;
function GetPageManager: TMYLDBPageManager;
function GetPageData: TMYLDBPageBuffer;
function GetPageDataSize: Integer;
public
procedure EnlargePageBuffer(NewSize: Integer);
property Page: TMYLDBPage read LPage write LPage;
property PageNo: TMYLDBPageNo read GetPageNo write SetPageNo;
property PageSize: Integer read GetPageSize;
property PageBuffer: TMYLDBPageBuffer read GetPageBuffer write SetPageBuffer;
property OwnBuffer: Boolean read GetOwnBuffer write SetOwnBuffer;
property IsDirty: Boolean read GetIsDirty write SetIsDirty;
property UseCount: Integer read GetUseCount write SetUseCount;
property PageManager: TMYLDBPageManager read GetPageManager;
property PageData: TMYLDBPageBuffer read GetPageData;
property PageDataSize: Integer read GetPageDataSize;
end;// TMYLDBPageController
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBSortedPageList
//
////////////////////////////////////////////////////////////////////////////////
TMYLDBPageElement = record
Page: TMYLDBPage;
LRUCount: Int64;
end;
TMYLDBSortedPageList = class(TObject)
private
KeyItems: array of integer;
ItemCount: integer;
AllocBy: integer;
deAllocBy: integer;
MaxAllocBy: integer;
AllocItemCount: integer;
LRUCount: Int64;
LRULastFound: Integer;
function FindPositionForInsert(key: Integer) : Integer;
function FindPosition(key: Integer): Integer;
procedure InsertByPosition(ItemNo, key: integer; var value: TMYLDBPageElement);
procedure DeleteByPosition(ItemNo: integer);
public
ValueItems: array of TMYLDBPageElement;
constructor Create(size: integer=0);
procedure SetSize(newSize: integer);
function Find(key: Integer): TMYLDBPage;
procedure Insert(Page: TMYLDBPage);
procedure Delete(PageNo: integer);
procedure Clear;
function FirstByLRU: TMYLDBPage;
function NextByLRU: TMYLDBPage;
procedure UpdateLRU(Page: TMYLDBPage);
property Count: Integer read ItemCount;
end;//TMYLDBSortedPageList
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBPageManager
//
////////////////////////////////////////////////////////////////////////////////
TMYLDBSessionPageInfo = record
SessionID: TMYLDBSessionID;
DirtyPages: TMYLDBSortedPageList;
AddedPageNumbers: TMYLDBPagesArray;
RemovedPageNumbers: TMYLDBPagesArray;
end;
TMYLDBPageManager = class (TObject)
protected
FCSect: TRTLCriticalSection;
FCacheCapacity: Integer;
FSharedPages: TMYLDBSortedPageList; // pages shared between all sessions
FSessions: array of TMYLDBSessionPageInfo;
FPageSize: Word;
FPageHeaderSize: Word;
FPageDataSize: Word;
FPageCount: TMYLDBPageNo;
FMultiUser: Boolean;
procedure Lock;
procedure Unlock;
function AddNewSession(SessionID: TMYLDBSessionID): Integer;
function FindSession(SessionID: TMYLDBSessionID; var SessionNo: Integer): Boolean;
function FindPage(Pages: TMYLDBSortedPageList; PageNo: TMYLDBPageNo; var Page: TMYLDBPage): Boolean;
procedure RemovePageIfExists(Pages: TMYLDBSortedPageList; PageNo: TMYLDBPageNo);
function GetPageCount: TMYLDBPageNo; virtual;
function IsSafeNotToSyncPage(SessionID: TMYLDBSessionID; Page: TMYLDBPage): Boolean; virtual;
procedure UpdatePageTableState(SessionID: TMYLDBSessionID; Page: TMYLDBPage); virtual;
public
procedure LoadFromStream(Stream: TStream); virtual;
procedure SaveToStream(Stream: TStream); virtual;
procedure InternalAddPage(aPage: TMYLDBPage); virtual; abstract;
procedure InternalRemovePage(PageNo: TMYLDBPageNo); virtual; abstract;
function InternalReadPage(aPage: TMYLDBPage): Boolean; virtual; abstract;
procedure InternalWritePage(aPage: TMYLDBPage); virtual; abstract;
constructor Create;
destructor Destroy; override;
function AddPage(SessionID: TMYLDBSessionID; PageType: TMYLDBPageTypeID): TMYLDBPage;
procedure RemovePage(SessionID: TMYLDBSessionID; PageNo: TMYLDBPageNo); virtual;
function GetPage(SessionID: TMYLDBSessionID; PageNo: TMYLDBPageNo;
PageType: TMYLDBPageTypeID; SynchronizeAllowed: Boolean = True): TMYLDBPage; virtual;
procedure PutPage(aPage: TMYLDBPage);
procedure ApplyChanges(SessionID: TMYLDBSessionID); virtual;
procedure CancelChanges(SessionID: TMYLDBSessionID);
property PageSize: Word read FPageSize;
property PageHeaderSize: Word read FPageHeaderSize;
property PageDataSize: Word read FPageDataSize;
property PageCount: TMYLDBPageNo read GetPageCount;
property MultiUser: Boolean read FMultiUser write FMultiUser;
end; // TMYLDBPageManager
implementation
uses MYLDBBTree, MYLDBBaseEngine, MYLDBDiskEngine;
////////////////////////////////////////////////////////////////////////////////
//
// TMYLDBPage
//
////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// GetPageHEader
//------------------------------------------------------------------------------
function TMYLDBPage.GetPageHeader: PMYLDBDiskPageHeader;
begin
Result := PMYLDBDiskPageHeader(FPageBuffer);
end; // GetPageHeader
//------------------------------------------------------------------------------
// GetPageData
//------------------------------------------------------------------------------
function TMYLDBPage.GetPageHeaderSize: Integer;
begin
Result := LPageManager.PageHeaderSize;
end;//GetPageHeaderSize
//------------------------------------------------------------------------------
// GetPageData
//------------------------------------------------------------------------------
function TMYLDBPage.GetPageData: TMYLDBPageBuffer;
begin
Result := TMYLDBPageBuffer(FPageBuffer + PageHeaderSize);
end;//GetPageData
//------------------------------------------------------------------------------
// GetPageDataSize
//------------------------------------------------------------------------------
function TMYLDBPage.GetPageDataSize: Integer;
begin
Result := PageSize - PageHeaderSize;
end;//GetPageDataSize
//------------------------------------------------------------------------------
// GetPageSize
//------------------------------------------------------------------------------
function TMYLDBPage.GetPageSize: Integer;
begin
Result := LPageManager.PageSize;
end;// GetPageSize
//------------------------------------------------------------------------------
// InitHeader
//------------------------------------------------------------------------------
procedure TMYLDBPage.InitHeader;
var
i:integer;
begin
// PageHeader.Signature := MYLDBDiskPageSignature;
for i:=0 to 3 do
PageHeader.Signature[i] := MYLDBDiskPageSignature[i];
PageHeader.State := 0;
PageHeader.PageType := ptUnknown;
PageHeader.NextPageNo := INVALID_PAGE_NO;
PageHeader.CRC32 := 0;
PageHeader.CRCType := 0;
PageHeader.HashType := 0;
PageHeader.Cipherype := 0;
PageHeader.MACType := 0;
PageHeader.ObjectID := INVALID_OBJECT_ID;
PageHeader.RecordID.PageNo := INVALID_PAGE_NO;
PageHeader.RecordID.PageItemNo := 0;
end;//InitHeader
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
constructor TMYLDBPage.Create(PageManager: TMYLDBPageManager);
begin
LPageManager := PageManager;
FPageBuffer := nil;
FPageNo := INVALID_PAGE_NO;
FOwnBuffer := True;
FIsDirty := False;
FUseCount := 0;
FReloaded := False;
FEncryptionEnabled := True;
end;// Create
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
destructor TMYLDBPage.Destroy;
begin
if (FOwnBuffer) then
FreeAndNilPageBuffer;
end;// Destroy
//------------------------------------------------------------------------------
// ClearPageBuffer
//------------------------------------------------------------------------------
procedure TMYLDBPage.ClearPageBuffer;
begin
FillChar(FPageBuffer^,PageSize,00);
end;// ClearPageBuffer
//------------------------------------------------------------------------------
// AllocPageBuffer
//------------------------------------------------------------------------------
procedure TMYLDBPage.AllocPageBuffer;
begin
//FPageBuffer := MemoryManager.GetMem(PageSize);
FPageBuffer := MemoryManager.AllocMem(PageSize);
InitHeader;
end;// AllocPageBuffer
//------------------------------------------------------------------------------
// FreeAndNilPageBuffer
//------------------------------------------------------------------------------
procedure TMYLDBPage.FreeAndNilPageBuffer;
begin
if (FPageBuffer <> nil) then
MemoryManager.FreeAndNillMem(FPageBuffer);
end;// FreeAndNilPageBuffer
//------------------------------------------------------------------------------
// EnlargePageBuffer
//------------------------------------------------------------------------------
procedure TMYLDBPage.EnlargePageBuffer(NewSize: Integer);
var
NewBuffer: PChar;
begin
if (FPageBuffer = nil) then
raise EMYLDBException.Create(20038, ErrorAInvalidPageBuffer);
if (NewSize < PageSize) then
raise EMYLDBException.Create(20039, ErrorAInvalidPageModification);
if (FOwnBuffer) then
MemoryManager.ReallocMem(FPageBuffer, NewSize)
else
begin
NewBuffer := MemoryManager.AllocMem(NewSize);
Move(FPageBuffer^, NewBuffer^, PageSize);
FPageBuffer := NewBuffer;
FOwnBuffer := True;
end;
end;// EnlargePageBuffer
//------------------------------------------------------------------------------
// Synchronize
//------------------------------------------------------------------------------
procedure TMYLDBPage.Synchronize;
{$IFDEF FILE_SERVER_VERSION}
var
NewState: Integer;
{$ENDIF}
begin
{$IFDEF FILE_SERVER_VERSION}
if (LPageManager is TMYLDBDiskPageManager) then
if (LPageManager.MultiUser) then
begin
NewState := TMYLDBDiskPageManager(LPageManager).InternalReadPageState(PageNo);
if ((NewState <> DELETED_PAGE_STATE) and (PageHeader^.State <> NewState)) then
LPageManager.InternalReadPage(Self)
else
PageHeader^.State := NewState;
end;
{$ENDIF}
end;// Synchronize
//------------------------------------------------------------------------------
// GetTableState
//------------------------------------------------------------------------------
function TMYLDBPage.GetTableState(SessionID: TMYLDBSessionID; var TableState: Integer): Boolean;
var
Index: Integer;
begin
Index := SessionID - MIN_SESSION_ID;
if (Index < Length(FTableStates)) then
begin
Result := FTableStates[Index].IsTableStateValueAssigned;
TableState := FTableStates[Index].TableState;
end
else
Result := False;
end;// GetTableState
//------------------------------------------------------------------------------
// SetTableState
//------------------------------------------------------------------------------
procedure TMYLDBPage.SetTableState(SessionID: TMYLDBSessionID; TableState: Integer);
var
Index: Integer;
OldLength: Integer;
i: Integer;
begin
Index := SessionID - MIN_SESSION_ID;
if (Index >= Length(FTableStates)) then
begin
OldLength := Length(FTableStates);
SetLength(FTableStates, Index+1);
for i:= OldLength to Index-1 do
FTableStates[Index].IsTableStateValueAssigned := False;
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -