📄 absdiskengine.pas
字号:
unit ABSDiskEngine;
interface
{$I ABSVer.inc}
uses SysUtils, Classes, Windows, Math,
// AbsoluteDatabase units
{$IFDEF DEBUG_LOG}
ABSDebug,
{$ENDIF}
{$IFNDEF D5H}
ABSD4Routines,
{$ENDIF}
ABSExcept,
ABSBase,
ABSBaseEngine,
ABSBTree,
ABSMemory,
ABSPage,
ABSCompression,
ABSExpressions,
ABSSecurity,
ABSCipher,
ABSConverts,
ABSTypes,
ABSConst;
type
// forward decls
TABSDiskPageManager = class;
TABSDiskTableData = class;
TABSSystemDirectory = class;
TABSActiveSessionsFile = class;
TABSTableListFile = class;
TABSTableLocksFile = class;
TABSInternalDBDirectAccessFile = class;
TABSInternalDBTransactedAccessFile = class;
TABSDatabaseTableLockManager = class;
////////////////////////////////////////////////////////////////////////////////
//
// TABSDiskDatabaseData
//
////////////////////////////////////////////////////////////////////////////////
TABSDiskDatabaseData = class (TABSDatabaseData)
private
FSystemDir: TABSSystemDirectory;
FActiveSessionsFile: TABSActiveSessionsFile;
FTableListFile: TABSTableListFile;
FPassword: TABSPassword;
FMaxSessionCount: Integer;
FPageSize: Integer;
FPageCountInExtent: Integer;
FTableLockManager: TABSDatabaseTableLockManager;
FSingleUserConnected: Boolean;
procedure OpenDatabase(Session: TABSBaseSession; Exclusive: Boolean;
var RepairNeeded: Boolean);
procedure CloseDatabase;
function GetPassword: PABSPassword;
function GetEncrypted: Boolean;
protected
procedure AddTable(
TableID: TABSTableID;
TableName: String;
MetadataFilePageNo,
MostUpdatedFilePageNo,
LocksFilePageNo: TABSPageNo
);
procedure RemoveTable(TableName: String);
procedure OpenTable(
TableName: String;
out TableID: TABSTableID;
out MetadataFilePageNo: TABSPageNo;
out MostUpdatedFilePageNo: TABSPageNo;
out LocksFilePageNo: TABSPageNo
);
procedure RenameTable(TableName, NewTableName: String);
public
constructor Create;
destructor Destroy; override;
// create table data
function CreateTableData(Cursor: TABSCursor): TABSTableData; override;
// database operations
procedure CreateDatabase; override;
procedure ConnectSession(Session: TABSBaseSession); override;
procedure DisconnectSession(Session: TABSBaseSession); override;
procedure FreeIfNoSessionsConnected; override;
procedure GetTablesList(List: TStrings); override;
// database operations
procedure TruncateDatabase;
function GetDBFileConnectionsCount: Integer;
// lock tables (virtual object)
procedure LockTables;
// unlock tables (virtual object)
procedure UnlockTables;
procedure Commit(SessionID: TABSSessionID; DoFlushBuffers: Boolean=True); override;
procedure Rollback(SessionID: TABSSessionID); override;
procedure FlushBuffers; override;
function GetNewObjectId: TABSObjectID; override;
function GetSuppressDBHeaderErrors: Boolean;
procedure SetSuppressDBHeaderErrors(Value: boolean);
public
property Password: PABSPassword read GetPassword;
property Encrypted: Boolean read GetEncrypted;
property MaxSessionCount: Integer read FMaxSessionCount write FMaxSessionCount;
property PageSize: Integer read FPageSize write FPageSize;
property PageCountInExtent: Integer read FPageCountInExtent write FPageCountInExtent;
end; // TABSDiskDatabaseData
////////////////////////////////////////////////////////////////////////////////
//
// TABSSmallRecordPage
//
////////////////////////////////////////////////////////////////////////////////
TABSSmallRecordPage = class(TObject)
private
LPage: TABSPage;
FRecordBufferSize: Integer;
FMaxRecordsOnPage: Integer;
FRecordDataOffset: Integer;
function FindUnusedRecordSlot(var SlotNo: Integer): Boolean;
function GetRecordCount: TABSRecordNo;
public
constructor Create(Page: TABSPage; RecordBufferSize: Integer;
MaxRecordsOnPage: Integer);
procedure AddRecord(RecordBuffer: PChar; var RecordID: TABSRecordID);
function UpdateRecord(RecordBuffer: PChar; RecordID: TABSRecordID): Boolean;
function DeleteRecord(RecordID: TABSRecordID): Boolean;
function GetRecordBuffer(RecordID: TABSRecordID; RecordBuffer: PChar): Boolean;
// navigation inside page
procedure GetFirstRecordID(var RecordID: TABSRecordID);
procedure GetLastRecordID(var RecordID: TABSRecordID);
function GetNextRecordID(var RecordID: TABSRecordID): Boolean;
function GetPriorRecordID(var RecordID: TABSRecordID): Boolean;
procedure GetRecordID(RecNoOnPage: Integer; var RecordID: TABSRecordID);
procedure GetRecNoOnPage(RecordID: TABSRecordID; var RecNoOnPage: Integer);
property RecordCount: TABSRecordNo read GetRecordCount;
end;// TABSSmallRecordPage
////////////////////////////////////////////////////////////////////////////////
//
// TABSDiskRecordManager
//
////////////////////////////////////////////////////////////////////////////////
TABSDiskRecordManager = class(TABSBaseRecordManager)
private
FRecordPageIndex: TABSBTreeRecordPageIndex;
LPageManager: TABSPageManager;
LFieldManager: TABSBaseFieldManager;
LMostUpdatedFile: TABSInternalDBTransactedAccessFile;
FMaxRecordsOnPage: Integer;
FLastAutoIncValues: array of Int64;
FDiskRecordBufferSize: Integer;
FTempDiskRecordBuffer: PChar;
LTableData: TABSDiskTableData;
function IsRecordPageValid(Page: TABSPage): Boolean;
procedure GetFirstRecord(SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo);
procedure GetLastRecord(SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo);
procedure GetNextRecord(SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo);
procedure GetPriorRecord(SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo);
procedure GetCurrentRecord(SessionID: TABSSessionID;
var NavigationInfo: TABSNavigationInfo);
public
constructor Create(PageManager: TABSPageManager;
FieldManager: TABSBaseFieldManager; MostUpdatedFile: TABSInternalDBTransactedAccessFile;
TableData: TABSDiskTableData);
destructor Destroy; override;
procedure Init(RecordBufferSize: Integer; DiskRecordBufferSize: Integer;
FieldCount: Integer);
procedure LoadMostUpdated(Buf: PChar; var Offset: Integer);
procedure SaveMostUpdated(Buf: PChar; var Offset: Integer);
procedure LoadMetadata(Stream: TStream);
procedure SaveMetadata(Stream: TStream);
procedure CreateRecordPageIndex;
procedure Empty(SessionID: TABSSessionID); override;
procedure Delete(SessionID: TABSSessionID);
// add record and return its number
function AddRecord(SessionID: TABSSessionID; RecordBuffer: TABSRecordBuffer; var RecordID: TABSRecordID): Boolean; override;
// update record, return true if record was updated, false if record was deleted
function UpdateRecord(SessionID: TABSSessionID; RecordBuffer: TABSRecordBuffer; RecordID: TABSRecordID): Boolean; override;
// delete record, return true if record was deleted, false if record was deleted earlier
function DeleteRecord(SessionID: TABSSessionID; var RecordID: TABSRecordID): Boolean; override;
procedure GetRecordBuffer(SessionID: TABSSessionID; var NavigationInfo: TABSNavigationInfo); override;
// return 0,1, or -1 if (1 = 2), (1 > 2) or (1 < 2)
function CompareRecordID(RecordID1: TABSRecordID; RecordID2: TABSRecordID): Integer; override;
// return record no
function GetApproximateRecNo(SessionID: TABSSessionID; RecordID: TABSRecordID): TABSRecordNo; override;
procedure SetRecNo(SessionID: TABSSessionID; RecNo: TABSRecordNo; var RecordID: TABSRecordID);
procedure GetRecNo(SessionID: TABSSessionID; RecordID: TABSRecordID; var RecNo: TABSRecordNo);
procedure RebuildRecordPageIndex(SessionID: TABSSessionID);
procedure ValidateRecordPageIndex(SessionID: TABSSessionID);
property RecordPageIndex: TABSBTreeRecordPageIndex read FRecordPageIndex;
end;// TABSDiskRecordManager
////////////////////////////////////////////////////////////////////////////////
//
// TABSSmallBlobPage
//
////////////////////////////////////////////////////////////////////////////////
TABSSmallBlobPage = class(TObject)
protected
LPage: TABSPage;
procedure SetBlobCount(Value: Integer);
function GetBlobCount: Integer;
function BlobHeader(Index: Integer): PABSDiskBlobHeader;
function BlobData(Index: Integer): PChar;
function GetNewBlobID: Word;
public
constructor Create(Page: TABSPage);
procedure AddBlob(BlobCache: PABSDiskBLOBCache;
var PageItemID: TABSPageItemID);
procedure DeleteBlob(PageItemID: TABSPageItemID; var BlobSize: Integer);
procedure ReadBlob(BlobCache: PABSDiskBLOBCache;
PageItemID: TABSPageItemID);
property BlobCount: Integer read GetBlobCount write SetBlobCount;
end;// TABSSmallBlobPage
////////////////////////////////////////////////////////////////////////////////
//
// TABSDiskBlobManager
//
////////////////////////////////////////////////////////////////////////////////
TABSDiskBlobManager = class(TObject)
private
LPageManager: TABSPageManager;
LFieldManager: TABSBaseFieldManager;
LRecordManager: TABSBaseRecordManager;
FBlobCacheList: TList;
FBlobPageIndex: TABSBTreeBlobPageIndex;
procedure GetBlobInfo(RecordBuffer: TABSRecordBuffer;
FieldNo: Integer;
var PageItemID: TABSPageItemID;
var BlobCache: PABSDiskBLOBCache);
procedure SetBlobInfo(RecordBuffer: TABSRecordBuffer;
FieldNo: Integer; PageItemID: TABSPageItemID);
procedure CreateBlobCache(RecordBuffer: TABSRecordBuffer; FieldNo: Integer;
var BlobCache: PABSDiskBLOBCache);
procedure FreeBlobCache(RecordBuffer: TABSRecordBuffer; FieldNo: Integer;
ForceClear: Boolean = False);
procedure StreamToBlobCache(Stream: TABSStream; BlobCache: PABSDiskBLOBCache);
procedure BlobCacheToStream(BlobCache: PABSDiskBLOBCache; Stream: TStream);
// blob <-> disk pages
procedure ReadBlobHeader(SessionID: TABSSessionID; PageItemID: TABSPageItemID;
var BlobHeader: TABSDiskBlobHeader;
BlobCache: PABSDiskBLOBCache);
procedure WriteBlobHeader(SessionID: TABSSessionID;
BlobHeader: TABSDiskBlobHeader; var PageItemID: TABSPageItemID);
procedure ReadBlobData(
// in
SessionID: TABSSessionID;
PageItemID: TABSPageItemID;
BlobHeader: TABSDiskBlobHeader;
BlobDataPageList: TABSIntegerArray;
// out
BlobCache: PABSDiskBLOBCache);
procedure ReadBlobDataPageList(
// in
SessionID: TABSSessionID;
PageItemID: TABSPageItemID;
const PageListLink: TABSPageListLink;
// out
BlobDataPageList: TABSIntegerArray;
BlobDataPageListPages: TABSIntegerArray);
procedure ReadLinkToBlobDataPageList(
SessionID: TABSSessionID;
PageItemID: TABSPageItemID;
var PageListLink: TABSPageListLink);
procedure ReadMultiPagesBlob(SessionID: TABSSessionID;
PageItemID: TABSPageItemID; BlobHeader: TABSDiskBlobHeader;
BlobCache: PABSDiskBLOBCache);
procedure WriteBlobData(
// in
SessionID: TABSSessionID;
BlobCache: PABSDiskBLOBCache; PageItemID: TABSPageItemID;
BlobHeader: TABSDiskBlobHeader;
// out
var LastPageNo: TABSPageNo; var LastPageOffset: Word;
BlobDataPageList: TABSIntegerArray);
procedure WriteBlobDataPageList(
// in
SessionID: TABSSessionID;
PageItemID: TABSPageItemID;
BlobHeader: TABSDiskBlobHeader;
LastPageNo: TABSPageNo; LastPageOffset: Word;
BlobDataPageList: TABSIntegerArray;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -