Skip to content

Commit

Permalink
ConnectionQueueCount and ConnectionFactoryLogger (#4)
Browse files Browse the repository at this point in the history
ConnectionQueueCount and ConnectionFactoryLogger
  • Loading branch information
glprog authored Nov 9, 2019
1 parent 3e47290 commit aa68589
Show file tree
Hide file tree
Showing 10 changed files with 559 additions and 266 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,4 @@ backup/
heap.trc
log.txt
MiniRESTSQLTest.xml
/unittest/SQL/logPool.txt
4 changes: 2 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ module.exports = function(grunt) {
tasks: ['bgShell:sql']
},
sql_fpc: {
files: ['**/*.pas'],
files: ['*.pas', 'unittest/SQL/*.pas'],
tasks: ['bgShell:sql_fpc']
},
orm: {
Expand All @@ -74,5 +74,5 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');

grunt.registerTask('default', ['watch:server']);

grunt.registerTask('test_sql_fpc', ['bgShell:sql_fpc']);
};
273 changes: 201 additions & 72 deletions MiniREST.SQL.Base.pas
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ TMiniRESTSQLConnectionFactoryBase = class abstract(TInterfacedObject, IMiniRES
strict private
FConnectionsToNotifyFree: TList;
protected
FConnectionFactoryEventLogger: IMiniRESTSQLConnectionFactoryEventLogger;
{$IFNDEF FPC}
FSemaphore: TLightweightSemaphore;
FQueue: TQueue<IMiniRESTSQLConnection>;
Expand All @@ -35,26 +36,33 @@ TMiniRESTSQLConnectionFactoryBase = class abstract(TInterfacedObject, IMiniRES
procedure RemoveConnectionToNotifyFree(AConnection: IMiniRESTSQLConnection);
procedure ReleaseConnection(AConnection: IMiniRESTSQLConnection); virtual;
function InternalGetconnection: IMiniRESTSQLConnection; virtual; abstract;
procedure LogConnectionPoolEvent(const AMessage: string);
public
constructor Create(const AConnectionCount: Integer);
constructor Create(const AConnectionCount: Integer); overload;
constructor Create(AParams: IMiniRESTSQLConnectionFactoryParams); overload;
destructor Destroy; override;
function GetConnection: IMiniRESTSQLConnection;
function GetConnection: IMiniRESTSQLConnection; overload;
function GetObject: TObject;
function GetConnectionsCount: Integer; virtual; abstract;
function GetQueueCount: Integer; virtual; abstract;
function GetConnection(const AIdentifier: string): IMiniRESTSQLConnection; overload;
end;

{ TMiniRESTSQLConnectionBase }

TMiniRESTSQLConnectionBase = class abstract(TInterfacedObject, IMiniRESTSQLConnection)
strict private
FOwner : TObject;
FOwner: TObject;
FConnectionID: Integer;
protected
FName: string;
FEstaNoPool: Boolean;
function _Release: Integer; {$IFNDEF WINDOWS}cdecl{$ELSE}stdcall{$ENDIF};
function GetObject: TObject; virtual; abstract;
procedure SetOwner(AOwner: Pointer);
public
constructor Create(AOwner : IMiniRESTSQLConnectionFactory);
constructor Create(AOwner: IMiniRESTSQLConnectionFactory); overload;
constructor Create(AParams: IMiniRESTSQLConnectionParams); overload;
procedure StartTransaction; virtual; abstract;
procedure Commit; virtual; abstract;
procedure Rollback; virtual; abstract;
Expand All @@ -67,6 +75,7 @@ TMiniRESTSQLConnectionBase = class abstract(TInterfacedObject, IMiniRESTSQLCon
function Execute(const ACommand: string; AParams: array of IMiniRESTSQLParam): Integer; virtual; abstract;
function GetDatabaseInfo: IMiniRESTSQLDatabaseInfo; virtual; abstract;
function InTransaction: Boolean; virtual; abstract;
function GetConnectionID: Integer;
end;

TMiniRESTSQLPrimaryKeyInfo = class(TInterfacedObject, IMiniRESTSQLPrimaryKeyInfo)
Expand Down Expand Up @@ -105,26 +114,44 @@ TMiniRESTSQLColumnInfo = class(TInterfacedObject, IMiniRESTSQLColumnInfo)
function GetName: string;
end;

TMiniRESTSQLConnectionParams = class(TInterfacedObject, IMiniRESTSQLConnectionParams)
private
FConnectionFactory: IMiniRESTSQLConnectionFactory;
FConnectionID: Integer;
public
//class function New: IMiniRESTSQLConnectionParams;
function GetConnectionFactory: IMiniRESTSQLConnectionFactory;
procedure SetConnectionFactory(AConnectionFactory: IMiniRESTSQLConnectionFactory);
function GetConnectionID: Integer;
procedure SetConnectionID(const AID: Integer);
end;

TMiniRESTSQLConnectionFactoryParams = class(TInterfacedObject, IMiniRESTSQLConnectionFactoryParams)
private
FConnectionCount: Integer;
FConnectionFactoryEventLogger: IMiniRESTSQLConnectionFactoryEventLogger;
public
function GetConnectionsCount: Integer;
procedure SetConnectionsCount(const ACount: Integer);
function GetObject: TObject;
function GetConnectionFactoryEventLogger: IMiniRESTSQLConnectionFactoryEventLogger;
procedure SetConnectionFactoryEventLogger(ALogger: IMiniRESTSQLConnectionFactoryEventLogger);
end;

implementation

var
gConnectionIDCounter: Integer;

{ TMiniRESTSQLConnectionFactoryBase }

constructor TMiniRESTSQLConnectionFactoryBase.Create(const AConnectionCount: Integer);
var
LParams: IMiniRESTSQLConnectionFactoryParams;
begin
FConnectionsCount := AConnectionCount;
{$IFNDEF FPC}
FSemaphore := TLightweightSemaphore.Create(AConnectionCount, AConnectionCount);
FQueue := TQueue<IMiniRESTSQLConnection>.Create;
{$ELSE}
FAvailableConnections := AConnectionCount;
FQueue := TFPGInterfacedObjectList<IMiniRESTSQLConnection>.Create;
FConnectionGetEvent := RTLEventCreate;
FConnectionReleaseEvent := RTLEventCreate;
RTLeventSetEvent(FConnectionGetEvent);
RTLeventSetEvent(FConnectionReleaseEvent);
{$ENDIF}
FCriticalSection := TCriticalSection.Create;
FConnectionsToNotifyFree := TList.Create;
LParams := TMiniRESTSQLConnectionFactoryParams.Create;
LParams.SetConnectionsCount(AConnectionCount);
Create(LParams);
end;

destructor TMiniRESTSQLConnectionFactoryBase.Destroy;
Expand All @@ -151,56 +178,8 @@ destructor TMiniRESTSQLConnectionFactoryBase.Destroy;
end;

function TMiniRESTSQLConnectionFactoryBase.GetConnection: IMiniRESTSQLConnection;
var
LConnection: IMiniRESTSQLConnection;
begin
{$IFNDEF FPC}
FSemaphore.Acquire;
FCriticalSection.Enter;
try

if FQueue.Count = 0 then
begin
LConnection := InternalGetconnection.SetName('Connection' + IntToStr(FConnectionCounter));
Inc(FConnectionCounter);
Result := LConnection;
end
else
begin
Result := FQueue.Dequeue;
end;
TMiniRESTSQLConnectionBase(Result).FEstaNoPool := False;

finally
FSemaphore.Release(1);
FCriticalSection.Leave;
end;
{$IFEND}
{$IFDEF FPC}
if InterlockedDecrement(FAvailableConnections) < 0 then
begin
RTLeventResetEvent(FConnectionReleaseEvent);
RTLeventWaitFor(FConnectionReleaseEvent);
end;
RTLeventWaitFor(FConnectionGetEvent);
try
if (FConnectionCounter < FConnectionsCount) then
begin
LConnection := InternalGetconnection.SetName('Connection' + IntToStr(FConnectionCounter));
Inc(FConnectionCounter);
Result := LConnection;
end
else
begin
LConnection := FQueue.Last;
Result := FQueue.Extract(LConnection);
end;

TMiniRESTSQLConnectionBase(Result.GetObject).FEstaNoPool := False;
finally
RTLeventSetEvent(FConnectionGetEvent);
end;
{$IFEND}
Result := GetConnection('');
end;

function TMiniRESTSQLConnectionFactoryBase.GetObject: TObject;
Expand Down Expand Up @@ -228,12 +207,15 @@ procedure TMiniRESTSQLConnectionFactoryBase.ReleaseConnection(

constructor TMiniRESTSQLConnectionBase.Create(
AOwner: IMiniRESTSQLConnectionFactory);
var
LID: Integer;
LParams: IMiniRESTSQLConnectionParams;
begin
FOwner := nil;
FOwner := AOwner.GetObject;
//TMiniRESTSQLConnectionFactoryBase(AOwner)
//.FConnectionsToNotifyFree.Add(Self);
TMiniRESTSQLConnectionFactoryBase(AOwner.GetObject).AddConnectionToNotifyFree(Self);
LID := InterLockedIncrement(gConnectionIDCounter);
LParams := TMiniRESTSQLConnectionParams.Create;
LParams.SetConnectionFactory(AOwner);
LParams.SetConnectionID(LID);
Create(LParams);
end;

function TMiniRESTSQLConnectionBase.GetName: string;
Expand Down Expand Up @@ -349,4 +331,151 @@ procedure TMiniRESTSQLConnectionFactoryBase.RemoveConnectionToNotifyFree(AConnec
FConnectionsToNotifyFree.Remove(AConnection.GetObject);
end;

procedure TMiniRESTSQLConnectionFactoryBase.LogConnectionPoolEvent(const AMessage: string);
begin
if FConnectionFactoryEventLogger = nil then
Exit;
FConnectionFactoryEventLogger.LogPoolEvent(AMessage);
end;

function TMiniRESTSQLConnectionFactoryBase.GetConnection(const AIdentifier: string): IMiniRESTSQLConnection;
var
LConnection: IMiniRESTSQLConnection;
begin
{$IFNDEF FPC}
FSemaphore.Acquire;
FCriticalSection.Enter;
try

if FQueue.Count = 0 then
begin
LConnection := InternalGetconnection.SetName('Connection' + IntToStr(FConnectionCounter));
Inc(FConnectionCounter);
Result := LConnection;
end
else
begin
Result := FQueue.Dequeue;
end;
TMiniRESTSQLConnectionBase(Result).FEstaNoPool := False;

finally
FSemaphore.Release(1);
FCriticalSection.Leave;
end;
{$IFEND}
{$IFDEF FPC}
if InterlockedDecrement(FAvailableConnections) < 0 then
begin
RTLeventResetEvent(FConnectionReleaseEvent);
RTLeventWaitFor(FConnectionReleaseEvent);
end;
RTLeventWaitFor(FConnectionGetEvent);
try
if (FConnectionCounter < FConnectionsCount) then
begin
LConnection := InternalGetconnection.SetName('Connection' + IntToStr(FConnectionCounter) + ' ' + AIdentifier);
Inc(FConnectionCounter);
Result := LConnection;
end
else
begin
LConnection := FQueue.Last;
Result := FQueue.Extract(LConnection);
end;

TMiniRESTSQLConnectionBase(Result.GetObject).FEstaNoPool := False;
LogConnectionPoolEvent(Format('GET CONNECTION %d - %s', [Result.GetConnectionID, Result.GetName]));
finally
RTLeventSetEvent(FConnectionGetEvent);
end;
{$IFEND}
end;

function TMiniRESTSQLConnectionBase.GetConnectionID: Integer;
begin
Result := FConnectionID;
end;

procedure TMiniRESTSQLConnectionParams.SetConnectionFactory(AConnectionFactory: IMiniRESTSQLConnectionFactory);
begin
FConnectionFactory := AConnectionFactory;
end;

function TMiniRESTSQLConnectionParams.GetConnectionFactory: IMiniRESTSQLConnectionFactory;
begin
Result := FConnectionFactory;
end;

function TMiniRESTSQLConnectionParams.GetConnectionID: Integer;
begin
Result := FConnectionID;
end;

procedure TMiniRESTSQLConnectionParams.SetConnectionID(const AID: Integer);
begin
FConnectionID := AID;
end;

constructor TMiniRESTSQLConnectionBase.Create(AParams: IMiniRESTSQLConnectionParams);
begin
FOwner := nil;
FOwner := AParams.GetConnectionFactory.GetObject;
FConnectionID := AParams.GetConnectionID;

TMiniRESTSQLConnectionFactoryBase(FOwner).AddConnectionToNotifyFree(Self);
end;

function TMiniRESTSQLConnectionFactoryParams.GetConnectionsCount: Integer;
begin
Result := FConnectionCount;
end;

procedure TMiniRESTSQLConnectionFactoryParams.SetConnectionsCount(const ACount: Integer);
begin
FConnectionCount := ACount;
end;

// class function TMiniRESTSQLConnectionFactoryParams.New: IMiniRESTSQLConnectionFactoryParams;
// begin
// Result := Create;
// end;

constructor TMiniRESTSQLConnectionFactoryBase.Create(AParams: IMiniRESTSQLConnectionFactoryParams);
begin
FConnectionsCount := AParams.GetConnectionsCount;
{$IFNDEF FPC}
FSemaphore := TLightweightSemaphore.Create(FConnectionsCount, FConnectionsCount);
FQueue := TQueue<IMiniRESTSQLConnection>.Create;
{$ELSE}
FAvailableConnections := FConnectionsCount;
FQueue := TFPGInterfacedObjectList<IMiniRESTSQLConnection>.Create;
FConnectionGetEvent := RTLEventCreate;
FConnectionReleaseEvent := RTLEventCreate;
RTLeventSetEvent(FConnectionGetEvent);
RTLeventSetEvent(FConnectionReleaseEvent);
{$ENDIF}
FCriticalSection := TCriticalSection.Create;
FConnectionsToNotifyFree := TList.Create;
FConnectionFactoryEventLogger := AParams.GetConnectionFactoryEventLogger;
end;

function TMiniRESTSQLConnectionFactoryParams.GetObject: TObject;
begin
Result := Self;
end;

function TMiniRESTSQLConnectionFactoryParams.GetConnectionFactoryEventLogger: IMiniRESTSQLConnectionFactoryEventLogger;
begin
Result := FConnectionFactoryEventLogger;
end;

procedure TMiniRESTSQLConnectionFactoryParams.SetConnectionFactoryEventLogger(ALogger: IMiniRESTSQLConnectionFactoryEventLogger);
begin
FConnectionFactoryEventLogger := ALogger;
end;

initialization
gConnectionIDCounter := 0;

end.
Loading

0 comments on commit aa68589

Please sign in to comment.