📄 dbtxn.pas
字号:
//
// Database Transactions Interface & Implementation
//
// This module is used by DCOM clients to create database transactions.
// Its a considerable improvement over Prexim V1.1 which actually locked
// entire request threads to perform database transactions. In this new method
// the DCOM client simply calls TransactionIn to add items to a transaction.
// Once the transaction needs committing, it calls CommitTransaction. This
// will then pass off the transaction list to a request thread which will
// perform the committal in one go.
//
// There are some things to consider when using this method. The most important
// is that the request threads have to support it by knowing if a request
// is part of a transaction yet to be committed (RequestInRec.prep_txn) or
// part of a transaction actually being committed now (RequestInRec.commit_txn)
// If a request is part of a transaction yet to be committed then the request
// thread will check the request and return any results, e.g. key values, but
// will not actually update the RDBMS. When the request is actually being
// committed it will take values from the RequestInRec that it would not
// normally use, e.g. the key values previously created by the preparatory
// call.
//
// (c) Chicony Software 2001
//
// When Who Why
// --------- --- ------------------------------------------------------------
// 2001.6.7 century Initial version
//
unit dbtxn;
interface
uses syncobjs, Windows, Messages, Classes, SysUtils,
// Prexim modules
PreximV2Constants_TLB, reqint, reqthread;
//
// This is the class the DCOM clients use to create and commit database
// transactions
//
type
TTransactionInterface = class
public
function TransactionIn(reqin: RequestInRec): Integer;
function CommitTransaction(var errcode:Integer; var errmsg: String;
var erritem: Integer; const audit_user, audit_location: WideString): Integer;
function RollbackTransaction: Integer;
function TransactionItems: Integer;
constructor Create;
procedure Free;
private
t_TxnList: TList; // List of items in database transaction
end;
implementation
uses FrontEnd;
//
// Class creation
//
constructor TTransactionInterface.Create;
begin
t_TxnList:=TList.Create;
inherited Create;
end;
//
// Class destruction
//
procedure TTransactionInterface.Free;
begin
if Self=nil then Exit;
RollbackTransaction;
if t_TxnList<>nil then t_TxnList.Free;
Destroy;
end;
//
// Returns number of items in transaction list
// Else negative number on error
//
function TTransactionInterface.TransactionItems: Integer;
begin
if Self=nil then Result:= -1
else if t_TxnList=nil then Result:= -2
else Result:=t_TxnList.Count;
end;
//
// Place a database transaction statement onto the queue
// Simply added to the end of the existing queue
//
// Args: transaction item to add to queue
//
// Returns: GE_OK on success, else error
//
function TTransactionInterface.TransactionIn(reqin: RequestInRec): Integer;
var txnin: PRequestInRec;
begin
// Simply add it to the queue
try
New(txnin);
txnin^:=reqin;
t_TxnList.Add(txnin);
Result:=Integer(GE_OK);
except on E:Exception do begin
Result:=Integer(GE_EXCEPTION);
FrontEnd.g_LogFiles.LogErrMessage('TransactionIn', 'Exception:'+e.message, Result, self);
end;
end;
end;
//
// Rollback the transaction
// Simply free up the queue
//
// Returns: GE_OK on success,
// else error (serious, as the list cannot be recreated)
//
function TTransactionInterface.RollbackTransaction: Integer;
var txnin: PRequestInRec;
begin
// First we'll try the correct method of freeing & removing each
// item in the list one by one
try
while t_TxnList.Count > 0 do begin
txnin:=t_TxnList.First;
t_TxnList.Remove(txnin);
Dispose(txnin);
end;
Result:=GE_OK;
Exit;
except
// Ignore - we will try another method
end;
// If the fails we have to resort to freeing the list itself
// and re-creating an empty list - this would cause a memory leak
// to occur, but we have no choice
try
t_TxnList.Free;
except
// Ignore
end;
try
t_TxnList:=TList.Create;
FrontEnd.g_LogFiles.LogErrMessage('RollbackTransaction', 'Unable to cleanly free transaction list', Integer(GE_EXCEPTION), self);
Result:=GE_OK;
except on E:Exception do begin
// Serious problem
Result:=Integer(GE_EXCEPTION);
FrontEnd.g_LogFiles.LogErrMessage('RollbackTransaction', 'Unable to create new transaction list. Exception:'+E.Message, Result, self);
end;
end;
end;
//
// Commit the transaction
// Simply send the items in the queue to a request thread
//
// Args: errcode is set to an error value on error (same as result value)
// errmsg is set to an error message on error
// erritem is set to the item which failed in the transaction (first
// item is number 1 - set to zero if no errors occured)
// user committing transaction
// location of user committing transaction
//
// Returns: >0 on success
// else error (see errcode & errmsg)
//
function TTransactionInterface.CommitTransaction(var errcode: Integer;
var errmsg: String; var erritem: Integer;
const audit_user, audit_location: WideString): Integer;
var reqin: RequestInRec;
reqout: RequestOutRec;
begin
// Send to request thread
reqin.req_type:=REQUEST_T_COMMIT_TRANSACTION;
reqin.txn_list:=t_TxnList;
reqin.audit_user:=audit_user;
reqin.audit_location:=audit_location;
if not g_RequestInterface.RequestSync(FALSE, TRUE, reqin, reqout) then begin
// Timed out
errmsg:='The request timed-out at the server';
errcode:=Integer(GE_TIMED_OUT);
Result:=errcode;
RollbackTransaction;
Exit;
end;
// Return results
erritem:=reqout.out_count;
errcode:=reqout.int_result;
errmsg:=reqout.errmsg;
Result:=errcode;
// Free list
RollbackTransaction;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -