ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/nongui/IBXServices.pas
Revision: 266
Committed: Wed Dec 26 18:34:32 2018 UTC (5 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 91377 byte(s)
Log Message:
Fixes Merged

File Contents

# Content
1 {************************************************************************}
2 { }
3 { Borland Delphi Visual Component Library }
4 { InterBase Express core components }
5 { }
6 { Copyright (c) 1998-2000 Inprise Corporation }
7 { }
8 { InterBase Express is based in part on the product }
9 { Free IB Components, written by Gregory H. Deatz for }
10 { Hoagland, Longo, Moran, Dunst & Doukas Company. }
11 { Free IB Components is used under license. }
12 { }
13 { The contents of this file are subject to the InterBase }
14 { Public License Version 1.0 (the "License"); you may not }
15 { use this file except in compliance with the License. You }
16 { may obtain a copy of the License at http://www.Inprise.com/IPL.html }
17 { Software distributed under the License is distributed on }
18 { an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either }
19 { express or implied. See the License for the specific language }
20 { governing rights and limitations under the License. }
21 { The Original Code was created by InterBase Software Corporation }
22 { and its successors. }
23 { Portions created by Inprise Corporation are Copyright (C) Inprise }
24 { Corporation. All Rights Reserved. }
25 { Contributor(s): Jeff Overcash }
26 { }
27 { IBX For Lazarus (Firebird Express) }
28 { Contributor: Tony Whyman, MWA Software http://www.mwasoftware.co.uk }
29 { Portions created by MWA Software are copyright McCallum Whyman }
30 { Associates Ltd 2011 - 2018 }
31 { }
32 {************************************************************************}
33
34 unit IBXServices;
35
36 {$mode objfpc}{$H+}
37
38 interface
39
40 uses
41 Classes, SysUtils, DB, IB, IBDatabase, IBTypes, IBSQLMonitor, IBExternals, memds;
42
43 type
44 TIBXCustomService = class;
45 TIBXControlService = class;
46 TIBXServicesConnection = class;
47
48 IIBXServicesClient = interface
49 procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string);
50 procedure OnBeforeDisconnect(Sender: TIBXServicesConnection);
51 end;
52
53 TSecContextAction = (scRaiseError, scReconnect);
54
55 TIBXServicesLoginEvent = procedure(Service: TIBXServicesConnection; var aServerName: string; LoginParams: TStrings) of object;
56 TIBXServicesSecContextEvent = procedure(Service: TIBXServicesConnection; var aAction: TSecContextAction) of object;
57
58 { TIBXServicesConnection }
59
60 TIBXServicesConnection = class(TIBXMonitoredConnection)
61 private
62 FDatabase: TIBDatabase;
63 FFirebirdAPI: IFirebirdAPI;
64 FConnectString: string;
65 FFirebirdLibraryPathName: TIBFileName;
66 FOnSecurityContextException: TIBXServicesSecContextEvent;
67 FParams: TStrings;
68 FIBXServices: array of IIBXServicesClient;
69 FOnLogin: TIBXServicesLoginEvent;
70 FService: IServiceManager;
71 FPortNo: string;
72 FServerName: string;
73 FProtocol: TProtocol;
74 FServerVersionNo: array [1..4] of integer;
75 FExpectedDB: string;
76 FWireCompression: boolean;
77 procedure CheckActive;
78 procedure CheckInactive;
79 procedure CheckServerName;
80 function GenerateSPB(sl: TStrings): ISPB;
81 function GetFirebirdAPI: IFirebirdAPI;
82 function GetServerVersionNo(index: integer): integer;
83 function GetSPBConstName(action: byte): string;
84 procedure HandleException(Sender: TObject);
85 procedure HandleSecContextException(Sender: TIBXControlService; var action: TSecContextAction);
86 function Login(var aServerName: string; LoginParams: TStrings): Boolean;
87 procedure ParamsChanging(Sender: TObject);
88 procedure SetConnectString(AValue: string);
89 procedure SetFirebirdLibraryPathName(AValue: TIBFileName);
90 procedure SetParams(AValue: TStrings);
91 procedure SetPortNo(AValue: string);
92 procedure SetProtocol(AValue: TProtocol);
93 procedure SetServerName(AValue: string);
94 protected
95 procedure DoConnect; override;
96 procedure DoDisconnect; override;
97 function GetConnected: Boolean; override;
98 function GetDataset(Index : longint) : TDataset; override;
99 function GetDataSetCount : Longint; override;
100 procedure ReadState(Reader: TReader); override;
101 procedure RegisterIntf(intf: IIBXServicesClient);
102 procedure UnRegisterIntf(intf: IIBXServicesClient);
103 public
104 constructor Create(AOwner: TComponent); override;
105 destructor Destroy; override;
106 procedure ConnectUsing(aDatabase: TIBDatabase);
107 {Copies database parameters as give in the DBParams to the Services connection
108 omitting any parameters not appropriate for Services API. Typically, the
109 DBParams are TIBDatabase.Params}
110 procedure SetDBParams(DBParams: TStrings);
111 property FirebirdAPI: IFirebirdAPI read GetFirebirdAPI;
112 property ServerVersionNo[index: integer]: integer read GetServerVersionNo;
113 property ServiceIntf: IServiceManager read FService;
114 published
115 property Connected;
116 property ConnectString: string read FConnectString write SetConnectString;
117 property FirebirdLibraryPathName: TIBFileName read FFirebirdLibraryPathName
118 write SetFirebirdLibraryPathName;
119 property LoginPrompt default True;
120 property Protocol: TProtocol read FProtocol write SetProtocol default Local;
121 property PortNo: string read FPortNo write SetPortNo;
122 property Params: TStrings read FParams write SetParams;
123 property ServerName: string read FServerName write SetServerName;
124 property TraceFlags;
125 property WireCompression: boolean read FWireCompression write FWireCompression;
126 property AfterConnect;
127 property AfterDisconnect;
128 property BeforeConnect;
129 property BeforeDisconnect;
130 property OnLogin: TIBXServicesLoginEvent read FOnLogin write FOnLogin;
131 property OnSecurityContextException: TIBXServicesSecContextEvent read FOnSecurityContextException
132 write FOnSecurityContextException;
133 end;
134
135 { TIBXCustomService }
136
137 TIBXCustomService = class(TIBXMonitoredService,IIBXServicesClient)
138 private
139 FSRB: ISRB;
140 FSQPB: ISQPB;
141 FServiceQueryResults: IServiceQueryResults;
142 FServicesConnection: TIBXServicesConnection;
143 procedure CheckActive;
144 function GetSQPB: ISQPB;
145 function GetSRB: ISRB;
146 procedure SetServicesConnection(AValue: TIBXServicesConnection);
147 protected
148 procedure Clear; virtual;
149 procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string); virtual;
150 procedure OnBeforeDisconnect(Sender: TIBXServicesConnection); virtual;
151 procedure InternalServiceQuery(RaiseExceptionOnError: boolean=true);
152 procedure DoServiceQuery; virtual;
153 procedure Notification( AComponent: TComponent; Operation: TOperation); override;
154 property SRB: ISRB read GetSRB;
155 property SQPB: ISQPB read GetSQPB;
156 property ServiceQueryResults: IServiceQueryResults read FServiceQueryResults;
157 public
158 constructor Create(AOwner: TComponent); override;
159 destructor Destroy; override;
160 procedure Assign(Source: TPersistent); override;
161 published
162 property ServicesConnection: TIBXServicesConnection read FServicesConnection
163 write SetServicesConnection;
164 property TraceFlags;
165 end;
166
167 { TDatabaseInfo }
168
169 TDatabaseInfo = class
170 public
171 NoOfAttachments: Integer;
172 NoOfDatabases: Integer;
173 DbName: array of string;
174 constructor Create;
175 destructor Destroy; override;
176 end;
177
178 { TConfigFileData }
179
180 TConfigFileData = class
181 public
182 ConfigFileValue: array of integer;
183 ConfigFileKey: array of integer;
184 constructor Create;
185 destructor Destroy; override;
186 end;
187
188 { TConfigParams }
189
190 TConfigParams = class
191 public
192 ConfigFileData: TConfigFileData;
193 ConfigFileParams: array of string;
194 BaseLocation: string;
195 LockFileLocation: string;
196 MessageFileLocation: string;
197 SecurityDatabaseLocation: string;
198 constructor Create;
199 destructor Destroy; override;
200 end;
201
202 TVersionInfo = class
203 ServerVersion: String;
204 ServerImplementation: string;
205 ServiceVersion: Integer;
206 end;
207
208 { TIBXServerProperties }
209
210 TIBXServerProperties = class(TIBXCustomService)
211 private
212 FDatabaseInfo: TDatabaseInfo;
213 FVersionInfo: TVersionInfo;
214 FConfigParams: TConfigParams;
215 function GetConfigParams: TConfigParams;
216 function GetDatabaseInfo: TDatabaseInfo;
217 function GetVersionInfo: TVersionInfo;
218 protected
219 procedure Clear; override;
220 public
221 property DatabaseInfo: TDatabaseInfo read GetDatabaseInfo;
222 property VersionInfo: TVersionInfo read GetVersionInfo;
223 property ConfigParams: TConfigParams read GetConfigParams;
224 end;
225
226 { TIBXControlService }
227
228 TIBXControlService = class(TIBXCustomService)
229 private
230 FDatabaseName: string;
231 FAction: TSecContextAction;
232 FLastStartSRB: ISRB;
233 function GetIsServiceRunning: Boolean;
234 procedure HandleSecContextErr;
235 procedure CallSecContextException;
236 procedure SetDatabaseName(AValue: string);
237 protected
238 procedure DatabaseNameChanged; virtual;
239 procedure OnAfterConnect(Sender: TIBXServicesConnection; aDatabaseName: string); override;
240 procedure AddDBNameToSRB;
241 procedure CheckServiceNotRunning;
242 procedure InternalServiceStart;
243 procedure DoServiceQuery; override;
244 procedure SetServiceStartOptions; virtual;
245 procedure ServiceStart; virtual;
246 property DatabaseName: string read FDatabaseName write SetDatabaseName;
247 public
248 procedure Assign(Source: TPersistent); override;
249 property IsServiceRunning : Boolean read GetIsServiceRunning;
250 end;
251
252 TIBXOnGetNextLine = procedure(Sender: TObject; var Line: string) of object;
253
254 { TIBXControlAndQueryService }
255
256 TIBXControlAndQueryService = class (TIBXControlService)
257 private
258 FEof: Boolean;
259 FSendBytes: integer;
260 FOnGetNextLine: TIBXOnGetNextLine;
261 FServiceStarted: boolean;
262 FDataSets: TList;
263 protected
264 function GetNextLine : String;
265 function GetNextChunk : String;
266 procedure ServiceStart; override;
267 function ReceiveNextChunk(stream: TStream): integer;
268 function SendNextChunk(stream: TStream; var line: String): integer;
269 procedure DoOnGetNextLine(Line: string);
270 procedure OnBeforeDisconnect(Sender: TIBXServicesConnection); override;
271 procedure Notification( AComponent: TComponent; Operation: TOperation); override;
272 procedure RegisterDataSet(aDataSet: TDataSet);
273 procedure UnRegisterDataSet(aDataSet: TDataSet);
274 public
275 constructor Create(aOwner: TComponent); override;
276 destructor Destroy; override;
277 procedure Execute(OutputLog: TStrings); virtual;
278 property Eof: boolean read FEof;
279 published
280 property OnGetNextLine: TIBXOnGetNextLine read FOnGetNextLine write FOnGetNextLine;
281 end;
282
283 { TIBXLogService }
284
285 TIBXLogService = class(TIBXControlAndQueryService)
286 protected
287 procedure SetServiceStartOptions; override;
288 end;
289
290 TDBShutdownMode = (Forced, DenyTransaction, DenyAttachment);
291
292 { TIBXConfigService }
293
294 TIBXConfigService = class(TIBXControlService)
295 public
296 procedure ShutdownDatabase (Options: TDBShutdownMode; Wait: Integer);
297 procedure SetSweepInterval (Value: Integer);
298 procedure SetDBSqlDialect (Value: Integer);
299 procedure SetPageBuffers (Value: Integer);
300 procedure ActivateShadow;
301 procedure BringDatabaseOnline;
302 procedure SetReserveSpace (Value: Boolean);
303 procedure SetAsyncMode (Value: Boolean);
304 procedure SetReadOnly (Value: Boolean);
305 procedure SetNoLinger;
306 published
307 property DatabaseName;
308 end;
309
310 TStatOption = (DataPages, HeaderPages, IndexPages, SystemRelations);
311 TStatOptions = set of TStatOption;
312
313 { TIBXStatisticalService }
314
315 TIBXStatisticalService = class(TIBXControlAndQueryService)
316 private
317 FOptions: TStatOptions;
318 protected
319 procedure SetServiceStartOptions; override;
320 published
321 property DatabaseName;
322 property Options: TStatOptions read FOptions write FOptions;
323 end;
324
325 TBackupStatsOption = (bsTotalTime,bsTimeDelta,bsPageReads,bsPageWrites);
326 TBackupStatsOptions = set of TBackupStatsOption;
327
328 { TIBXBackupRestoreService }
329
330 TIBXBackupRestoreService = class(TIBXControlAndQueryService)
331 private
332 FStatisticsRequested: TBackupStatsOptions;
333 FVerbose: Boolean;
334 protected
335 procedure SetServiceStartOptions; override;
336 property Verbose : Boolean read FVerbose write FVerbose default False;
337 property StatisticsRequested: TBackupStatsOptions read FStatisticsRequested write FStatisticsRequested;
338 published
339 end;
340
341 TBackupOption = (IgnoreChecksums, IgnoreLimbo, MetadataOnly, NoGarbageCollection,
342 OldMetadataDesc, NonTransportable, ConvertExtTables, NoDBTriggers);
343 TBackupOptions = set of TBackupOption;
344
345 { TIBXBackupService }
346
347 TIBXBackupService = class (TIBXBackupRestoreService)
348 private
349 FOptions: TBackupOptions;
350 FBlockingFactor: Integer;
351 protected
352 procedure SetServiceStartOptions; override;
353 procedure SetBackupTarget; virtual; abstract;
354 published
355 property BlockingFactor: Integer read FBlockingFactor write FBlockingFactor;
356 property DatabaseName;
357 property Options : TBackupOptions read FOptions write FOptions;
358 end;
359
360 { TIBXClientSideBackupService }
361
362 TIBXClientSideBackupService = class(TIBXBackupService)
363 protected
364 procedure Execute(OutputLog: TStrings); override;
365 procedure SetBackupTarget; override;
366 public
367 procedure BackupToStream(S: TStream; var BytesWritten: integer);
368 procedure BackupToFile(aFileName: string; var BytesWritten: integer);
369 end;
370
371 { TIBXServerSideBackupService }
372
373 TIBXServerSideBackupService = class(TIBXBackupService)
374 private
375 FBackupFiles: TStrings;
376 procedure SetBackupFile(const Value: TStrings);
377 protected
378 procedure SetBackupTarget; override;
379 public
380 constructor Create(AOwner: TComponent); override;
381 destructor Destroy; override;
382 {Use inherited Execute method to perform backup}
383 published
384 { a name=value pair of filename and length }
385 property BackupFiles: TStrings read FBackupFiles write SetBackupFile;
386 property StatisticsRequested;
387 property Verbose;
388 end;
389
390 TRestoreOption = (DeactivateIndexes, NoShadow, NoValidityCheck, OneRelationAtATime,
391 Replace, CreateNewDB, UseAllSpace, RestoreMetaDataOnly);
392
393 TRestoreOptions = set of TRestoreOption;
394
395 { TIBXRestoreService }
396
397 TIBXRestoreService = class (TIBXBackupRestoreService)
398 private
399 FDatabaseFiles: TStrings;
400 FOptions: TRestoreOptions;
401 FPageSize: Integer;
402 FPageBuffers: Integer;
403 procedure SetDatabaseFiles(const Value: TStrings);
404 protected
405 procedure DatabaseNameChanged; override;
406 procedure SetServiceStartOptions; override;
407 procedure SetArchiveSource; virtual; abstract;
408 public
409 constructor Create(AOwner: TComponent); override;
410 destructor Destroy; override;
411 published
412 { a name=value pair of filename and length }
413 property DatabaseFiles: TStrings read FDatabaseFiles write SetDatabaseFiles;
414 property PageSize: Integer read FPageSize write FPageSize;
415 property PageBuffers: Integer read FPageBuffers write FPageBuffers;
416 property Options : TRestoreOptions read FOptions write FOptions default [CreateNewDB];
417 property StatisticsRequested;
418 property Verbose;
419 end;
420
421 { TIBXClientSideRestoreService }
422
423 TIBXClientSideRestoreService = class(TIBXRestoreService)
424 protected
425 procedure Execute(OutputLog: TStrings); override;
426 procedure SetArchiveSource; override;
427 public
428 procedure RestoreFromStream(S: TStream; OutputLog: TStrings);
429 procedure RestoreFromFile(aFileName: string; OutputLog: TStrings);
430 procedure RestoreFromFiles(FileList: TStrings; OutputLog: TStrings);
431 end;
432
433 { TIBXServerSideRestoreService }
434
435 TIBXServerSideRestoreService = class(TIBXRestoreService)
436 private
437 FBackupFiles: TStrings;
438 procedure SetBackupFiles(const Value: TStrings);
439 protected
440 procedure SetArchiveSource; override;
441 public
442 constructor Create(AOwner: TComponent); override;
443 destructor Destroy; override;
444 {use inherited Execute method to perform restore}
445 published
446 property BackupFiles: TStrings read FBackupFiles write SetBackupFiles;
447 end;
448
449 { TIBXOnlineValidationService }
450
451 TIBXOnlineValidationService = class(TIBXControlAndQueryService)
452 private
453 FExcludeIndexes: string;
454 FExcludeTables: string;
455 FIncludeIndexes: string;
456 FIncludeTables: string;
457 FLockTimeout: integer;
458 protected
459 procedure SetServiceStartOptions; override;
460 procedure ServiceStart; override;
461 public
462 constructor Create(AOwner: TComponent); override;
463 published
464 property IncludeTables: string read FIncludeTables write FIncludeTables;
465 property ExcludeTables: string read FExcludeTables write FExcludeTables;
466 property IncludeIndexes: string read FIncludeIndexes write FIncludeIndexes;
467 property ExcludeIndexes: string read FExcludeIndexes write FExcludeIndexes;
468 property LockTimeout: integer read FLockTimeout write FLockTimeout default 10;
469 property DatabaseName;
470 end;
471
472 TValidateOption = (CheckDB, IgnoreChecksum, KillShadows, MendDB,
473 SweepDB, ValidateDB, ValidateFull);
474 TValidateOptions = set of TValidateOption;
475
476 { TIBXValidationService }
477
478 TIBXValidationService = class(TIBXControlAndQueryService)
479 private
480 FOptions: TValidateOptions;
481 protected
482 procedure SetServiceStartOptions; override;
483 public
484 {use inherited Execute method to perform validation}
485 published
486 property DatabaseName;
487 property Options: TValidateOptions read FOptions write FOptions;
488 end;
489
490 TUserInfo = class
491 public
492 UserName: string;
493 FirstName: string;
494 MiddleName: string;
495 LastName: string;
496 GroupID: Integer;
497 UserID: Integer;
498 AdminRole: boolean;
499 end;
500
501 TSecurityAction = (ActionAddUser, ActionDeleteUser, ActionModifyUser, ActionDisplayUser);
502 TSecurityModifyParam = (ModifyFirstName, ModifyMiddleName, ModifyLastName, ModifyUserId,
503 ModifyGroupId, ModifyPassword, ModifyAdminRole);
504 TSecurityModifyParams = set of TSecurityModifyParam;
505
506 { TIBXSecurityService }
507
508 TIBXSecurityService = class(TIBXControlAndQueryService)
509 private
510 FAdminRole: boolean;
511 FUserID: Integer;
512 FGroupID: Integer;
513 FFirstName: string;
514 FUserName: string;
515 FPassword: string;
516 FSQLRole: string;
517 FLastName: string;
518 FMiddleName: string;
519 FUserInfo: array of TUserInfo;
520 FSecurityAction: TSecurityAction;
521 FModifyParams: TSecurityModifyParams;
522 procedure ClearParams;
523 procedure SetAdminRole(AValue: boolean);
524 procedure SetSecurityAction (Value: TSecurityAction);
525 procedure SetFirstName (Value: String);
526 procedure SetMiddleName (Value: String);
527 procedure SetLastName (Value: String);
528 procedure SetPassword (Value: String);
529 procedure SetUserId (Value: Integer);
530 procedure SetGroupId (Value: Integer);
531
532 procedure FetchUserInfo;
533 function GetUserInfo(Index: Integer): TUserInfo;
534 function GetUserInfoCount: Integer;
535
536 protected
537 procedure Execute(OutputLog: TStrings); override;
538 procedure Loaded; override;
539 procedure SetServiceStartOptions; override;
540 property SecurityAction: TSecurityAction read FSecurityAction
541 write SetSecurityAction;
542 public
543 constructor Create(AOwner: TComponent); override;
544 destructor Destroy; override;
545 procedure DisplayUsers;
546 procedure DisplayUser(aUserName: string);
547 procedure AddUser;
548 procedure DeleteUser;
549 procedure ModifyUser;
550 function HasAdminRole: boolean;
551 procedure SetAutoAdmin(Value: Boolean);
552 property UserInfo[Index: Integer]: TUserInfo read GetUserInfo;
553 property UserInfoCount: Integer read GetUserInfoCount;
554
555 published
556 property SQlRole : string read FSQLRole write FSQLrole;
557 property UserName : string read FUserName write FUserName;
558 property FirstName : string read FFirstName write SetFirstName;
559 property MiddleName : string read FMiddleName write SetMiddleName;
560 property LastName : string read FLastName write SetLastName;
561 property UserID : Integer read FUserID write SetUserID;
562 property GroupID : Integer read FGroupID write SetGroupID;
563 property Password : string read FPassword write setPassword;
564 property AdminRole: boolean read FAdminRole write SetAdminRole;
565 end;
566
567 TTransactionGlobalAction = (CommitGlobal, RollbackGlobal, RecoverTwoPhaseGlobal,
568 NoGlobalAction);
569 TTransactionState = (LimboState, CommitState, RollbackState, UnknownState);
570 TTransactionAdvise = (CommitAdvise, RollbackAdvise, UnknownAdvise);
571 TTransactionAction = (CommitAction, RollbackAction);
572
573 TLimboTransactionInfo = class
574 public
575 MultiDatabase: Boolean;
576 ID: Integer;
577 HostSite: String;
578 RemoteSite: String;
579 RemoteDatabasePath: String;
580 State: TTransactionState;
581 Advise: TTransactionAdvise;
582 Action: TTransactionAction;
583 end;
584
585 { TIBXLimboTransactionResolutionService }
586
587 TIBXLimboTransactionResolutionService = class(TIBXControlAndQueryService)
588 private
589 FLimboTransactionInfo: array of TLimboTransactionInfo;
590 FGlobalAction: TTransactionGlobalAction;
591 function GetLimboTransactionInfo(index: integer): TLimboTransactionInfo;
592 function GetLimboTransactionInfoCount: integer;
593 function FetchLimboTransactionInfo: integer;
594
595 protected
596 procedure SetServiceStartOptions; override;
597 public
598 destructor Destroy; override;
599 procedure Clear; override;
600 procedure Execute(OutputLog: TStrings); override;
601 property LimboTransactionInfo[Index: integer]: TLimboTransactionInfo read GetLimboTransactionInfo;
602 property LimboTransactionInfoCount: Integer read GetLimboTransactionInfoCount;
603
604 published
605 property DatabaseName;
606 property GlobalAction: TTransactionGlobalAction read FGlobalAction
607 write FGlobalAction;
608
609 end;
610
611 TRequiredSources = class of TIBXControlAndQueryService;
612
613 { TIBXServicesDataSet }
614
615 TIBXServicesDataSet = class(TMemDataSet)
616 private
617 FSource: TIBXControlAndQueryService;
618 procedure SetSource(AValue: TIBXControlAndQueryService);
619 protected
620 FRequiredSource: TRequiredSources;
621 procedure DoBeforeClose; override;
622 procedure Notification( AComponent: TComponent; Operation: TOperation); override;
623 public
624 destructor Destroy; override;
625 published
626 property Source: TIBXControlAndQueryService read FSource write SetSource;
627 end;
628
629 { TIBXServicesUserList }
630
631 TIBXServicesUserList = class(TIBXServicesDataSet)
632 private
633 FLoading: boolean;
634 protected
635 procedure DoBeforePost; override;
636 procedure DoAfterInsert; override;
637 procedure DoAfterPost; override;
638 procedure DoAfterOpen; override;
639 procedure InternalDelete; override;
640 public
641 constructor Create(AOwner:TComponent); override;
642 end;
643
644 { TIBXServicesLimboTransactionsList }
645
646 TIBXServicesLimboTransactionsList = class(TIBXServicesDataSet)
647 private
648 FLoading: boolean;
649 protected
650 procedure DoBeforeInsert; override;
651 procedure DoAfterOpen; override;
652 procedure DoAfterPost; override;
653 procedure DoBeforePost; override;
654 public
655 constructor Create(AOwner:TComponent); override;
656 procedure Delete; override;
657 procedure FixErrors(GlobalAction: TTransactionGlobalAction; OutputLog: TStrings);
658 end;
659
660 implementation
661
662 uses FBMessages, IBUtils, RegExpr, CustApp, IBErrorCodes;
663
664 const
665 SPBPrefix = 'isc_spb_';
666 isc_spb_last_spb_constant = 13;
667 SPBConstantNames: array[1..isc_spb_last_spb_constant] of String = (
668 'user_name',
669 'sys_user_name',
670 'sys_user_name_enc',
671 'password',
672 'password_enc',
673 'command_line',
674 'db_name',
675 'verbose',
676 'options',
677 'connect_timeout',
678 'dummy_packet_interval',
679 'sql_role_name',
680 'expected_db'
681 );
682
683 SPBConstantValues: array[1..isc_spb_last_spb_constant] of Integer = (
684 isc_spb_user_name,
685 isc_spb_sys_user_name,
686 isc_spb_sys_user_name_enc,
687 isc_spb_password,
688 isc_spb_password_enc,
689 isc_spb_command_line,
690 isc_spb_dbname,
691 isc_spb_verbose,
692 isc_spb_options,
693 isc_spb_connect_timeout,
694 isc_spb_dummy_packet_interval,
695 isc_spb_sql_role_name,
696 isc_spb_expected_db
697 );
698
699 { TIBXClientSideRestoreService }
700
701 procedure TIBXClientSideRestoreService.Execute(OutputLog: TStrings);
702 begin
703 // Do nothing
704 end;
705
706 procedure TIBXClientSideRestoreService.SetArchiveSource;
707 begin
708 SRB.Add(isc_spb_bkp_file).AsString := 'stdin';
709 end;
710
711 procedure TIBXClientSideRestoreService.RestoreFromStream(S: TStream;
712 OutputLog: TStrings);
713 var line: string;
714 begin
715 ServiceStart;
716 try
717 while not Eof do
718 begin
719 SendNextChunk(S,line);
720 if line <> '' then
721 begin
722 DoOnGetNextLine(line);
723 if OutputLog <> nil then
724 OutputLog.Add(line);
725 end;
726 end;
727 finally
728 while IsServiceRunning do; {flush}
729 end;
730 end;
731
732 procedure TIBXClientSideRestoreService.RestoreFromFile(aFileName: string;
733 OutputLog: TStrings);
734 var F: TFileStream;
735 begin
736 F := TFileStream.Create(aFileName,fmOpenRead);
737 try
738 RestoreFromStream(F,OutputLog)
739 finally
740 F.Free;
741 end;
742 end;
743
744 procedure TIBXClientSideRestoreService.RestoreFromFiles(FileList: TStrings;
745 OutputLog: TStrings);
746 var i: integer;
747 F: TFileStream;
748 line: string;
749 begin
750 ServiceStart;
751 for i := 0 to FileList.Count - 1 do
752 begin
753 F := TFileStream.Create(FileList[i],fmOpenRead);
754 try
755 while Eof do
756 begin
757 SendNextChunk(F,line);
758 if line <> '' then
759 begin
760 DoOnGetNextLine(line);
761 if OutputLog <> nil then
762 OutputLog.Add(line);
763 end;
764 end;
765 finally
766 F.Free;
767 while IsServiceRunning do; {flush}
768 FEof := false;
769 end;
770 end;
771 end;
772
773 { TIBXClientSideBackupService }
774
775 procedure TIBXClientSideBackupService.Execute(OutputLog: TStrings);
776 begin
777 //Do nothing
778 end;
779
780 procedure TIBXClientSideBackupService.SetBackupTarget;
781 begin
782 SRB.Add(isc_spb_bkp_file).AsString := 'stdout';
783 end;
784
785 procedure TIBXClientSideBackupService.BackupToStream(S: TStream;
786 var BytesWritten: integer);
787 var InitialSize: integer;
788 begin
789 InitialSize := S.Size;
790 ServiceStart;
791 while not Eof do
792 ReceiveNextChunk(S);
793 BytesWritten := S.Size - InitialSize;
794 end;
795
796 procedure TIBXClientSideBackupService.BackupToFile(aFileName: string;
797 var BytesWritten: integer);
798 var F: TFileStream;
799 begin
800 F := TFileStream.Create(aFileName,fmCreate);
801 try
802 BackupToStream(F,BytesWritten);
803 finally
804 F.Free;
805 end;
806 end;
807
808 { TIBXServicesLimboTransactionsList }
809
810 procedure TIBXServicesLimboTransactionsList.DoBeforeInsert;
811 begin
812 inherited DoBeforeInsert;
813 if not FLoading then
814 IBError(ibxeNoLimboTransactionInsert,[nil]);
815 end;
816
817 procedure TIBXServicesLimboTransactionsList.DoAfterOpen;
818
819 function TypeToStr(MultiDatabase: boolean): string;
820 begin
821 if MultiDatabase then
822 Result := 'Multi DB'
823 else
824 Result := 'Single DB';
825 end;
826
827 function StateToStr(State: TTransactionState): string;
828 begin
829 case State of
830 LimboState:
831 Result := 'Limbo';
832 CommitState:
833 Result := 'Commit';
834 RollbackState:
835 Result := 'Rollback';
836 else
837 Result := 'Unknown';
838 end;
839 end;
840
841 function AdviseToStr(Advise: TTransactionAdvise): string;
842 begin
843 case Advise of
844 CommitAdvise:
845 Result := 'Commit';
846 RollbackAdvise:
847 Result := 'Rollback';
848 else
849 Result := 'Unknown';
850 end;
851 end;
852
853 function ActionToStr(anAction: TTransactionAction): string;
854 begin
855 case anAction of
856 CommitAction:
857 Result := 'Commit';
858 RollbackAction:
859 Result := 'Rollback';
860 end;
861 end;
862
863 var i: integer;
864 begin
865 if FLoading then Exit;
866 FLoading := true;
867 with FSource as TIBXLimboTransactionResolutionService do
868 try
869 for i := 0 to LimboTransactionInfoCount - 1 do
870 with LimboTransactionInfo[i] do
871 begin
872 Append;
873 FieldByName('TransactionID').AsInteger := ID;
874 FieldByName('TransactionType').AsString := TypeToStr(MultiDatabase);
875 FieldByName('HostSite').AsString := HostSite;
876 FieldByName('RemoteSite').AsString := RemoteSite;
877 FieldByName('DatabasePath').AsString := RemoteDatabasePath;
878 FieldByName('State').AsString := StateToStr(State);
879 FieldByName('RecommendedAction').AsString := AdviseToStr(Advise);
880 FieldByName('RequestedAction').AsString := ActionToStr(Action);
881 Post;
882 end;
883 finally
884 FLoading := false;
885 end;
886 inherited DoAfterOpen;
887 end;
888
889 procedure TIBXServicesLimboTransactionsList.DoAfterPost;
890 begin
891 if not FLoading then
892 inherited DoAfterPost;
893 end;
894
895 procedure TIBXServicesLimboTransactionsList.DoBeforePost;
896 var i: integer;
897 begin
898 inherited DoBeforePost;
899 if FLoading then Exit;
900 with FSource as TIBXLimboTransactionResolutionService do
901 for i := 0 to LimboTransactionInfoCount - 1 do
902 with LimboTransactionInfo[i] do
903 begin
904 if ID = FieldByName('TransactionID').AsInteger then
905 begin
906 if FieldByName('RequestedAction').AsString = 'Commit' then
907 Action := CommitAction
908 else
909 if FieldByName('RequestedAction').AsString = 'Rollback' then
910 Action := RollbackAction;
911 break;
912 end;
913 end;
914 end;
915
916
917 constructor TIBXServicesLimboTransactionsList.Create(AOwner: TComponent);
918 var i: integer;
919 begin
920 inherited Create(AOwner);
921 FRequiredSource := TIBXLimboTransactionResolutionService;
922 with FieldDefs do
923 if Count = 0 then
924 begin
925 Add('TransactionID',ftInteger);
926 Add('TransactionType',ftString,16);
927 Add('HostSite',ftString,256);
928 Add('RemoteSite',ftString,256);
929 Add('DatabasePath',ftString,256);
930 Add('State',ftString,32);
931 Add('RecommendedAction',ftString,32);
932 Add('RequestedAction',ftString,32);
933 for i := 0 to Count - 2 do
934 Items[i].Attributes := Items[i].Attributes + [faReadOnly];
935 end;
936 end;
937
938 procedure TIBXServicesLimboTransactionsList.Delete;
939 begin
940 //Do nothing
941 end;
942
943 procedure TIBXServicesLimboTransactionsList.FixErrors(
944 GlobalAction: TTransactionGlobalAction; OutputLog: TStrings);
945 begin
946 if State = dsEdit then Post;
947 (FSource as TIBXLimboTransactionResolutionService).GlobalAction := GlobalAction;
948 (FSource as TIBXLimboTransactionResolutionService).Execute(OutputLog);
949 Active := false;
950 Active := true;
951 end;
952
953 { TIBXServicesUserList }
954
955 procedure TIBXServicesUserList.DoBeforePost;
956 procedure SetParams;
957 begin
958 with FSource as TIBXSecurityService do
959 begin
960 UserID := FieldByName('UserID').AsInteger;
961 GroupID := FieldByName('GroupID').AsInteger;
962 UserName := FieldByName('SEC$USER_NAME').AsString;
963 FirstName := FieldByName('SEC$FIRST_NAME').AsString;
964 MiddleName := FieldByName('SEC$MIDDLE_NAME').AsString;
965 LastName := FieldByName('SEC$LAST_NAME').AsString;
966 if not FieldByName('SEC$PASSWORD').IsNull then
967 Password := FieldByName('SEC$PASSWORD').AsString;
968 AdminRole := FieldByName('SEC$ADMIN').AsBoolean;
969 end;
970 end;
971
972 begin
973 inherited DoBeforePost;
974 if FLoading then Exit;
975 case State of
976 dsEdit:
977 begin
978 SetParams;
979 (FSource as TIBXSecurityService).ModifyUser;
980 end;
981 dsInsert:
982 begin
983 SetParams;
984 (FSource as TIBXSecurityService).AddUser;
985 end;
986 end;
987 end;
988
989 procedure TIBXServicesUserList.DoAfterInsert;
990 begin
991 FieldByName('UserID').AsInteger := 0;
992 FieldByName('GroupID').AsInteger := 0;
993 FieldByName('SEC$PASSWORD').Clear;
994 FieldByName('SEC$ADMIN').AsBoolean := false;
995 inherited DoAfterInsert;
996 end;
997
998 procedure TIBXServicesUserList.DoAfterPost;
999 begin
1000 {Refresh}
1001 if not FLoading then
1002 begin
1003 inherited DoAfterPost;
1004 with FSource as TIBXSecurityService do
1005 begin
1006 DisplayUser(FieldByName('SEC$USER_NAME').AsString);
1007 if UserInfoCount > 0 then
1008 with UserInfo[0] do
1009 begin
1010 FieldByName('UserID').AsInteger := UserID;
1011 FieldByName('GroupID').AsInteger := GroupID;
1012 FieldByName('SEC$USER_NAME').AsString := UserName;
1013 FieldByName('SEC$FIRST_NAME').AsString := FirstName;
1014 FieldByName('SEC$MIDDLE_NAME').AsString := MiddleName;
1015 FieldByName('SEC$LAST_NAME').AsString := LastName;
1016 FieldByName('SEC$PASSWORD').Clear;
1017 FieldByName('SEC$ADMIN').AsBoolean := AdminRole;
1018 end;
1019 end;
1020 end;
1021 end;
1022
1023 procedure TIBXServicesUserList.DoAfterOpen;
1024 var i: integer;
1025 Buf: TStringList;
1026 begin
1027 buf := TStringList.Create; {Used to sort user info}
1028 try
1029 with FSource as TIBXSecurityService do
1030 begin
1031 buf.Sorted := true;
1032 DisplayUsers;
1033 FLoading := true;
1034 try
1035 for i := 0 to UserInfoCount - 1 do
1036 buf.AddObject(UserInfo[i].UserName,UserInfo[i]);
1037
1038 for i := 0 to buf.Count - 1 do
1039 with TUserInfo(buf.Objects[i]) do
1040 begin
1041 Append;
1042 FieldByName('UserID').AsInteger := UserID;
1043 FieldByName('GroupID').AsInteger := GroupID;
1044 FieldByName('SEC$USER_NAME').AsString := UserName;
1045 FieldByName('SEC$FIRST_NAME').AsString := FirstName;
1046 FieldByName('SEC$MIDDLE_NAME').AsString := MiddleName;
1047 FieldByName('SEC$LAST_NAME').AsString := LastName;
1048 FieldByName('SEC$PASSWORD').Clear;
1049 FieldByName('SEC$ADMIN').AsBoolean := AdminRole;
1050 Post;
1051 end;
1052 finally
1053 FLoading := false;
1054 end;
1055 end;
1056 finally
1057 Buf.Free;
1058 end;
1059 inherited DoAfterOpen;
1060 end;
1061
1062 procedure TIBXServicesUserList.InternalDelete;
1063 begin
1064 with FSource as TIBXSecurityService do
1065 begin
1066 UserName := FieldByName('SEC$USER_NAME').AsString;
1067 DeleteUser;
1068 end;
1069 inherited InternalDelete;
1070 end;
1071
1072 constructor TIBXServicesUserList.Create(AOwner: TComponent);
1073 begin
1074 inherited Create(AOwner);
1075 FRequiredSource := TIBXSecurityService;
1076 with FieldDefs do
1077 if Count = 0 then
1078 begin
1079 Add('UserID',ftInteger);
1080 Add('GroupID',ftInteger);
1081 Add('SEC$USER_NAME',ftString,31);
1082 Add('SEC$FIRST_NAME',ftString,32);
1083 Add('SEC$MIDDLE_NAME',ftString,32);
1084 Add('SEC$LAST_NAME',ftString,32);
1085 Add('SEC$PASSWORD',ftString,32);
1086 Add('SEC$ADMIN',ftBoolean);
1087 end;
1088 end;
1089
1090 { TIBXServicesDataSet }
1091
1092 procedure TIBXServicesDataSet.SetSource(AValue: TIBXControlAndQueryService);
1093 begin
1094 if FSource = AValue then Exit;
1095 if (AValue <> nil) and not (AValue is FRequiredSource) then
1096 IBError(ibxeNotRequiredDataSetSource,[AValue.ClassName]);
1097 if FSource <> nil then
1098 begin
1099 FSource.UnRegisterDataSet(self);
1100 RemoveFreeNotification(FSource);
1101 end;
1102 FSource := AValue;
1103 if FSource <> nil then
1104 begin
1105 FSource.RegisterDataSet(self);
1106 FreeNotification(FSource);
1107 end;
1108 end;
1109
1110 procedure TIBXServicesDataSet.DoBeforeClose;
1111 begin
1112 if csDestroying in ComponentState then Exit;
1113 if State in [dsEdit,dsInsert] then Post;
1114 Clear(false);
1115 inherited DoBeforeClose;
1116 end;
1117
1118 procedure TIBXServicesDataSet.Notification(AComponent: TComponent;
1119 Operation: TOperation);
1120 begin
1121 inherited Notification(AComponent, Operation);
1122 if (Operation = opRemove) and (AComponent = FSource) then
1123 FSource := nil;
1124 end;
1125
1126 destructor TIBXServicesDataSet.Destroy;
1127 begin
1128 Source := nil;
1129 inherited Destroy;
1130 end;
1131
1132 { TIBXLimboTransactionResolutionService }
1133
1134 function TIBXLimboTransactionResolutionService.GetLimboTransactionInfo(
1135 index: integer): TLimboTransactionInfo;
1136 begin
1137 if index < GetLimboTransactionInfoCount then
1138 Result := FLimboTransactionInfo[index]
1139 else
1140 Result := nil;
1141 end;
1142
1143 function TIBXLimboTransactionResolutionService.GetLimboTransactionInfoCount: integer;
1144 begin
1145 Result := Length(FLimboTransactionInfo);
1146 if Result = 0 then
1147 Result := FetchLimboTransactionInfo;
1148 end;
1149
1150 procedure TIBXLimboTransactionResolutionService.SetServiceStartOptions;
1151 var i: integer;
1152 begin
1153 SRB.Add(isc_action_svc_repair);
1154 AddDBNameToSRB;
1155 if Length(FLimboTransactionInfo) = 0 then
1156 SRB.Add(isc_spb_options).AsInteger := isc_spb_rpr_list_limbo_trans
1157 else
1158 {Fixing existing transactions}
1159 begin
1160 case FGlobalAction of
1161 NoGlobalAction:
1162 begin
1163 for i := 0 to LimboTransactionInfoCount - 1 do
1164 begin
1165 if (FLimboTransactionInfo[i].Action = CommitAction) then
1166 SRB.Add(isc_spb_rpr_commit_trans).AsInteger := FLimboTransactionInfo[i].ID
1167 else
1168 SRB.Add(isc_spb_rpr_rollback_trans).AsInteger := FLimboTransactionInfo[i].ID;
1169 end;
1170 end;
1171
1172 CommitGlobal:
1173 begin
1174 for i := 0 to LimboTransactionInfoCount - 1 do
1175 SRB.Add(isc_spb_rpr_commit_trans).AsInteger := FLimboTransactionInfo[i].ID;
1176 end;
1177
1178 RollbackGlobal:
1179 begin
1180 for i := 0 to LimboTransactionInfoCount - 1 do
1181 SRB.Add(isc_spb_rpr_rollback_trans).AsInteger := FLimboTransactionInfo[i].ID;
1182 end;
1183
1184 RecoverTwoPhaseGlobal:
1185 begin
1186 for i := 0 to LimboTransactionInfoCount - 1 do
1187 SRB.Add(isc_spb_rpr_recover_two_phase).AsInteger := FLimboTransactionInfo[i].ID;
1188 end;
1189 end;
1190 end;
1191 end;
1192
1193 destructor TIBXLimboTransactionResolutionService.Destroy;
1194 begin
1195 Clear;
1196 inherited Destroy;
1197 end;
1198
1199 procedure TIBXLimboTransactionResolutionService.Clear;
1200 var
1201 i : Integer;
1202 begin
1203 for i := 0 to High(FLimboTransactionInfo) do
1204 FLimboTransactionInfo[i].Free;
1205 SetLength(FLimboTransactionInfo,0);
1206 end;
1207
1208
1209 function TIBXLimboTransactionResolutionService.FetchLimboTransactionInfo: integer;
1210
1211 procedure NextLimboTransaction(index: integer);
1212 begin
1213 SetLength(FLimboTransactionInfo, index+1);
1214 FLimboTransactionInfo[index] := TLimboTransactionInfo.Create;
1215 { if no advice commit as default }
1216 FLimboTransactionInfo[index].Advise := UnknownAdvise;
1217 FLimboTransactionInfo[index].Action:= CommitAction;
1218 end;
1219
1220 var
1221 i,j, k: Integer;
1222 begin
1223 Clear;
1224 Result := 0;
1225 ServiceStart;
1226 SRB.Add(isc_info_svc_limbo_trans);
1227 InternalServiceQuery;
1228
1229 k := -1;
1230 for i := 0 to FServiceQueryResults.Count - 1 do
1231 with FServiceQueryResults[i] do
1232 case getItemType of
1233 isc_info_svc_limbo_trans:
1234 begin
1235 if FServiceQueryResults[i].Count = 0 then continue;
1236 NextLimboTransaction(0);
1237 for j := 0 to FServiceQueryResults[i].Count - 1 do
1238 begin
1239 with FServiceQueryResults[i][j] do
1240 begin
1241 case getItemType of
1242 isc_spb_single_tra_id:
1243 begin
1244 Inc(k);
1245 if k > 0 then
1246 NextLimboTransaction(k);
1247 FLimboTransactionInfo[k].MultiDatabase := False;
1248 FLimboTransactionInfo[k].ID := AsInteger;
1249 end;
1250
1251 isc_spb_multi_tra_id:
1252 begin
1253 Inc(k);
1254 if k > 0 then
1255 NextLimboTransaction(k);
1256 FLimboTransactionInfo[k].MultiDatabase := True;
1257 FLimboTransactionInfo[k].ID := AsInteger;
1258 end;
1259
1260 isc_spb_tra_host_site:
1261 FLimboTransactionInfo[k].HostSite := AsString;
1262
1263 isc_spb_tra_state:
1264 case AsByte of
1265 isc_spb_tra_state_limbo:
1266 FLimboTransactionInfo[k].State := LimboState;
1267
1268 isc_spb_tra_state_commit:
1269 FLimboTransactionInfo[k].State := CommitState;
1270
1271 isc_spb_tra_state_rollback:
1272 FLimboTransactionInfo[k].State := RollbackState;
1273
1274 else
1275 FLimboTransactionInfo[k].State := UnknownState;
1276 end;
1277
1278 isc_spb_tra_remote_site:
1279 FLimboTransactionInfo[k].RemoteSite := AsString;
1280
1281 isc_spb_tra_db_path:
1282 FLimboTransactionInfo[k].RemoteDatabasePath := AsString;
1283
1284 isc_spb_tra_advise:
1285 with FLimboTransactionInfo[k] do
1286 begin
1287 case (AsByte) of
1288 isc_spb_tra_advise_commit:
1289 begin
1290 Advise := CommitAdvise;
1291 Action:= CommitAction;
1292 end;
1293
1294 isc_spb_tra_advise_rollback:
1295 begin
1296 Advise := RollbackAdvise;
1297 Action := RollbackAction;
1298 end;
1299
1300 else
1301 Advise := UnknownAdvise;
1302 end;
1303 end;
1304
1305 else
1306 IBError(ibxeOutputParsingError, [getItemType]);
1307 end;
1308 end;
1309 end;
1310 end;
1311 else
1312 IBError(ibxeOutputParsingError, [getItemType]);
1313 end;
1314 Result := Length(FLimboTransactionInfo);
1315 end;
1316
1317 procedure TIBXLimboTransactionResolutionService.Execute(OutputLog: TStrings);
1318 begin
1319 if Length(FLimboTransactionInfo) > 0 then
1320 begin
1321 ServiceStart; {Fix is implicit in non-zero list of Limbo transactions}
1322 while not Eof do
1323 OutputLog.Add(GetNextLine);
1324 while IsServiceRunning do;
1325 Clear;
1326 end;
1327 end;
1328
1329 { TIBXSecurityService }
1330
1331 constructor TIBXSecurityService.Create(AOwner: TComponent);
1332 begin
1333 inherited Create(AOwner);
1334 FModifyParams := [];
1335 end;
1336
1337 destructor TIBXSecurityService.Destroy;
1338 var
1339 i : Integer;
1340 begin
1341 for i := 0 to High(FUserInfo) do
1342 FUserInfo[i].Free;
1343 FUserInfo := nil;
1344 inherited Destroy;
1345 end;
1346
1347 procedure TIBXSecurityService.Execute(OutputLog: TStrings);
1348 begin
1349 //Do nothing
1350 end;
1351
1352 procedure TIBXSecurityService.FetchUserInfo;
1353 var
1354 i, j, k: Integer;
1355 begin
1356 SRB.Add(isc_info_svc_get_users);
1357 InternalServiceQuery;
1358
1359 for i := 0 to High(FUserInfo) do
1360 FUserInfo[i].Free;
1361 for i := 0 to FServiceQueryResults.Count - 1 do
1362 with FServiceQueryResults[i] do
1363 begin
1364 case getItemType of
1365 isc_info_svc_get_users:
1366 begin
1367 SetLength(FUserInfo,1);
1368 k := 0;
1369 FUserInfo[0] := TUserInfo.Create;
1370 FUserInfo[0].UserName := '';
1371 for j := 0 to FServiceQueryResults[i].Count - 1 do
1372 begin
1373 with FServiceQueryResults[i][j] do
1374 case getItemType of
1375 isc_spb_sec_username:
1376 begin
1377 if FUserInfo[k].UserName <> '' then
1378 begin
1379 Inc(k);
1380 SetLength(FUserInfo,k+1);
1381 if FUserInfo[k] = nil then
1382 FUserInfo[k] := TUserInfo.Create;
1383 end;
1384 FUserInfo[k].UserName := AsString;
1385 end;
1386
1387 isc_spb_sec_firstname:
1388 FUserInfo[k].FirstName := AsString;
1389
1390 isc_spb_sec_middlename:
1391 FUserInfo[k].MiddleName := AsString;
1392
1393 isc_spb_sec_lastname:
1394 FUserInfo[k].LastName := AsString;
1395
1396 isc_spb_sec_userId:
1397 FUserInfo[k].UserId := AsInteger;
1398
1399 isc_spb_sec_groupid:
1400 FUserInfo[k].GroupID := AsInteger;
1401
1402 isc_spb_sec_admin:
1403 FUserInfo[k].AdminRole := AsInteger <> 0;
1404
1405 else
1406 IBError(ibxeOutputParsingError, [getItemType]);
1407 end;
1408 end;
1409 end;
1410 else
1411 IBError(ibxeOutputParsingError, [getItemType]);
1412 end;
1413 end;
1414 end;
1415
1416 function TIBXSecurityService.GetUserInfo(Index: Integer): TUserInfo;
1417 begin
1418 if Index <= High(FUSerInfo) then
1419 result := FUserInfo[Index]
1420 else
1421 result := nil;
1422 end;
1423
1424 function TIBXSecurityService.GetUserInfoCount: Integer;
1425 begin
1426 Result := Length(FUserInfo);
1427 end;
1428
1429 procedure TIBXSecurityService.AddUser;
1430 begin
1431 SecurityAction := ActionAddUser;
1432 ServiceStart;
1433 while IsServiceRunning do;
1434 end;
1435
1436 procedure TIBXSecurityService.DeleteUser;
1437 begin
1438 SecurityAction := ActionDeleteUser;
1439 ServiceStart;
1440 while IsServiceRunning do;
1441 end;
1442
1443 procedure TIBXSecurityService.DisplayUsers;
1444 begin
1445 SecurityAction := ActionDisplayUser;
1446 ClearParams;
1447 FUserName := '';
1448 ServiceStart;
1449 FetchUserInfo;
1450 end;
1451
1452 procedure TIBXSecurityService.DisplayUser(aUserName: string);
1453 begin
1454 SecurityAction := ActionDisplayUser;
1455 ClearParams;
1456 FUserName := aUserName;
1457 ServiceStart;
1458 FetchUserInfo;
1459 end;
1460
1461 procedure TIBXSecurityService.ModifyUser;
1462 begin
1463 SecurityAction := ActionModifyUser;
1464 ServiceStart;
1465 while IsServiceRunning do;
1466 end;
1467
1468 function TIBXSecurityService.HasAdminRole: boolean;
1469 begin
1470 CheckActive;
1471 with ServicesConnection do
1472 Result := (ServerVersionNo[1] > 2) or
1473 ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] = 5));
1474 end;
1475
1476 procedure TIBXSecurityService.SetAutoAdmin(Value: Boolean);
1477 begin
1478 CheckActive;
1479 {only available for Firebird 2.5 and later}
1480 with ServicesConnection do
1481 if (ServerVersionNo[1] < 2) or
1482 ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] < 5)) then Exit;
1483 if Value then
1484 SRB.Add(isc_action_svc_set_mapping)
1485 else
1486 SRB.Add(isc_action_svc_drop_mapping);
1487 InternalServiceStart;
1488 while IsServiceRunning do;
1489 end;
1490
1491 procedure TIBXSecurityService.SetSecurityAction (Value: TSecurityAction);
1492 begin
1493 FSecurityAction := Value;
1494 if Value = ActionDeleteUser then
1495 ClearParams;
1496 end;
1497
1498 procedure TIBXSecurityService.ClearParams;
1499 begin
1500 FModifyParams := [];
1501 FFirstName := '';
1502 FMiddleName := '';
1503 FLastName := '';
1504 FGroupID := 0;
1505 FUserID := 0;
1506 FPassword := '';
1507 end;
1508
1509 procedure TIBXSecurityService.SetAdminRole(AValue: boolean);
1510 begin
1511 FAdminRole := AValue;
1512 Include (FModifyParams, ModifyAdminRole);
1513 end;
1514
1515 procedure TIBXSecurityService.SetFirstName (Value: String);
1516 begin
1517 FFirstName := Value;
1518 Include (FModifyParams, ModifyFirstName);
1519 end;
1520
1521 procedure TIBXSecurityService.SetMiddleName (Value: String);
1522 begin
1523 FMiddleName := Value;
1524 Include (FModifyParams, ModifyMiddleName);
1525 end;
1526
1527 procedure TIBXSecurityService.SetLastName (Value: String);
1528 begin
1529 FLastName := Value;
1530 Include (FModifyParams, ModifyLastName);
1531 end;
1532
1533 procedure TIBXSecurityService.SetPassword (Value: String);
1534 begin
1535 FPassword := Value;
1536 Include (FModifyParams, ModifyPassword);
1537 end;
1538
1539 procedure TIBXSecurityService.SetUserId (Value: Integer);
1540 begin
1541 FUserId := Value;
1542 Include (FModifyParams, ModifyUserId);
1543 end;
1544
1545 procedure TIBXSecurityService.SetGroupId (Value: Integer);
1546 begin
1547 FGroupId := Value;
1548 Include (FModifyParams, ModifyGroupId);
1549 end;
1550
1551 procedure TIBXSecurityService.Loaded;
1552 begin
1553 inherited Loaded;
1554 ClearParams;
1555 end;
1556
1557 procedure TIBXSecurityService.SetServiceStartOptions;
1558 var
1559 Len: UShort;
1560
1561 begin
1562 case FSecurityAction of
1563 ActionDisplayUser:
1564 begin
1565 if HasAdminRole then
1566 SRB.Add(isc_action_svc_display_user_adm) {Firebird 2.5 and later only}
1567 else
1568 SRB.Add(isc_action_svc_display_user);
1569 if UserName <> '' then
1570 SRB.Add(isc_spb_sec_username).AsString := UserName;
1571 end;
1572
1573 ActionAddUser:
1574 begin
1575 if ( Pos(' ', FUserName) > 0 ) then
1576 IBError(ibxeStartParamsError, [nil]);
1577 Len := Length(FUserName);
1578 if (Len = 0) then
1579 IBError(ibxeStartParamsError, [nil]);
1580 SRB.Add(isc_action_svc_add_user);
1581 SRB.Add(isc_spb_sec_username).AsString := FUserName;
1582 if FSQLRole <> '' then
1583 SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1584 SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1585 SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1586 SRB.Add(isc_spb_sec_password).AsString := FPassword;
1587 SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1588 SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1589 SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1590 if HasAdminRole then
1591 SRB.Add(isc_spb_sec_admin).AsInteger := ord(FAdminRole);
1592 end;
1593
1594 ActionDeleteUser:
1595 begin
1596 Len := Length(FUserName);
1597 if (Len = 0) then
1598 IBError(ibxeStartParamsError, [nil]);
1599 SRB.Add(isc_action_svc_delete_user);
1600 SRB.Add(isc_spb_sec_username).AsString := FUserName;
1601 if FSQLRole <> '' then
1602 SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1603 end;
1604
1605 ActionModifyUser:
1606 begin
1607 Len := Length(FUserName);
1608 if (Len = 0) then
1609 IBError(ibxeStartParamsError, [nil]);
1610 SRB.Add(isc_action_svc_modify_user);
1611 SRB.Add(isc_spb_sec_username).AsString := FUserName;
1612 if FSQLRole <> '' then
1613 SRB.Add(isc_spb_sql_role_name).AsString := FSQLRole;
1614 if (ModifyUserId in FModifyParams) then
1615 SRB.Add(isc_spb_sec_userid).AsInteger := FUserID;
1616 if (ModifyGroupId in FModifyParams) then
1617 SRB.Add(isc_spb_sec_groupid).AsInteger := FGroupID;
1618 if (ModifyPassword in FModifyParams) then
1619 SRB.Add(isc_spb_sec_password).AsString := FPassword;
1620 if (ModifyFirstName in FModifyParams) then
1621 SRB.Add(isc_spb_sec_firstname).AsString := FFirstName;
1622 if (ModifyMiddleName in FModifyParams) then
1623 SRB.Add(isc_spb_sec_middlename).AsString := FMiddleName;
1624 if (ModifyLastName in FModifyParams) then
1625 SRB.Add(isc_spb_sec_lastname).AsString := FLastName;
1626 if (ModifyAdminRole in FModifyParams) and HasAdminRole then
1627 begin
1628 if FAdminRole then
1629 SRB.Add(isc_spb_sec_admin).AsInteger := 1
1630 else
1631 SRB.Add(isc_spb_sec_admin).AsInteger := 0;
1632 end;
1633 end;
1634 end;
1635 ClearParams;
1636 end;
1637
1638
1639 { TIBXValidationService }
1640
1641 procedure TIBXValidationService.SetServiceStartOptions;
1642 var
1643 param: Integer;
1644 begin
1645 SRB.Add(isc_action_svc_repair);
1646 AddDBNAmeToSRB;
1647
1648 param := 0;
1649 if (SweepDB in Options) then
1650 param := param or isc_spb_rpr_sweep_db;
1651 if (ValidateDB in Options) then
1652 param := param or isc_spb_rpr_validate_db;
1653
1654 if (CheckDB in Options) then
1655 param := param or isc_spb_rpr_check_db;
1656 if (IgnoreChecksum in Options) then
1657 param := param or isc_spb_rpr_ignore_checksum;
1658 if (KillShadows in Options) then
1659 param := param or isc_spb_rpr_kill_shadows;
1660 if (MendDB in Options) then
1661 param := param or isc_spb_rpr_mend_db;
1662 if (ValidateFull in Options) then
1663 begin
1664 param := param or isc_spb_rpr_full;
1665 if not (MendDB in Options) then
1666 param := param or isc_spb_rpr_validate_db;
1667 end;
1668 if param > 0 then
1669 SRB.Add(isc_spb_options).AsInteger := param;
1670 end;
1671
1672 { TIBXOnlineValidationService }
1673
1674 procedure TIBXOnlineValidationService.SetServiceStartOptions;
1675 begin
1676 SRB.Add(isc_action_svc_validate);
1677 AddDBNameToSRB;
1678 if IncludeTables <> '' then
1679 SRB.Add(isc_spb_val_tab_incl).AsString := IncludeTables;
1680 if ExcludeTables <> '' then
1681 SRB.Add(isc_spb_val_tab_excl).AsString := ExcludeTables;
1682 if IncludeIndexes <> '' then
1683 SRB.Add(isc_spb_val_idx_incl).AsString := IncludeIndexes;
1684 if ExcludeIndexes <> '' then
1685 SRB.Add(isc_spb_val_idx_excl).AsString := ExcludeIndexes;
1686 if LockTimeout <> 0 then
1687 SRB.Add(isc_spb_val_lock_timeout).AsInteger := LockTimeout;
1688 end;
1689
1690 constructor TIBXOnlineValidationService.Create(AOwner: TComponent);
1691 begin
1692 inherited Create(AOwner);
1693 FLockTimeout := 10;
1694 end;
1695
1696 procedure TIBXOnlineValidationService.ServiceStart;
1697 begin
1698 CheckActive;
1699 {Firebird 2.5 and later}
1700 with ServicesConnection do
1701 if (ServerVersionNo[1] < 2) or
1702 ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] < 5)) then
1703 IBError(ibxeServiceUnavailable,[]);
1704 inherited ServiceStart;
1705 end;
1706
1707 { TIBXServerSideRestoreService }
1708
1709 procedure TIBXServerSideRestoreService.SetBackupFiles(const Value: TStrings);
1710 begin
1711 FBackupFiles.Assign(Value);
1712 end;
1713
1714 procedure TIBXServerSideRestoreService.SetArchiveSource;
1715 var i: integer;
1716 begin
1717 for i := 0 to FBackupFiles.Count - 1 do
1718 begin
1719 if (Trim(FBackupFiles[i]) = '') then continue;
1720 if (Pos('=', FBackupFiles[i]) <> 0) then {mbcs ok}
1721 begin
1722 SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles.Names[i];
1723 SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(FBackupFiles.ValueFromIndex[i]);
1724 end
1725 else
1726 SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles[i];
1727 end
1728 end;
1729
1730 constructor TIBXServerSideRestoreService.Create(AOwner: TComponent);
1731 begin
1732 inherited Create(AOwner);
1733 FBackupFiles := TStringList.Create;
1734 end;
1735
1736 destructor TIBXServerSideRestoreService.Destroy;
1737 begin
1738 if assigned(FBackupFiles) then FBackupFiles.Free;
1739 inherited Destroy;
1740 end;
1741
1742 { TIBXRestoreService }
1743
1744 procedure TIBXRestoreService.SetDatabaseFiles(const Value: TStrings);
1745 begin
1746 FDatabaseFiles.Assign(Value);
1747 end;
1748
1749 procedure TIBXRestoreService.DatabaseNameChanged;
1750 begin
1751 inherited DatabaseNameChanged;
1752 DatabaseFiles.Clear;
1753 DatabaseFiles.Add(DatabaseName);
1754 end;
1755
1756 procedure TIBXRestoreService.SetServiceStartOptions;
1757 var
1758 param: Integer;
1759 i: integer;
1760 begin
1761 SRB.Add(isc_action_svc_restore);
1762 inherited SetServiceStartOptions;
1763
1764 param := 0;
1765 if (DeactivateIndexes in Options) then
1766 param := param or isc_spb_res_deactivate_idx;
1767 if (NoShadow in Options) then
1768 param := param or isc_spb_res_no_shadow;
1769 if (NoValidityCheck in Options) then
1770 param := param or isc_spb_res_no_validity;
1771 if (OneRelationAtATime in Options) then
1772 param := param or isc_spb_res_one_at_a_time;
1773 if (Replace in Options) then
1774 param := param or isc_spb_res_replace;
1775 if (CreateNewDB in Options) then
1776 param := param or isc_spb_res_create;
1777 if (UseAllSpace in Options) then
1778 param := param or isc_spb_res_use_all_space;
1779 if (RestoreMetaDataOnly in Options) then
1780 param := param or isc_spb_res_metadata_only;
1781 SRB.Add(isc_spb_options).AsInteger := param;
1782
1783 if FPageSize > 0 then
1784 SRB.Add(isc_spb_res_page_size).AsInteger := FPageSize;
1785 if FPageBuffers > 0 then
1786 SRB.Add(isc_spb_res_buffers).AsInteger := FPageBuffers;
1787
1788 SetArchiveSource;
1789
1790 if FDatabaseFiles.Count > 0 then
1791 FDatabaseName := FDatabaseFiles[0]; {needed if an isc_sec_context error}
1792 for i := 0 to FDatabaseFiles.Count - 1 do
1793 begin
1794 if (Trim(FDatabaseFiles[i]) = '') then continue;
1795 if (Pos('=', FDatabaseFiles[i]) <> 0) then {mbcs ok}
1796 begin
1797 SRB.Add(isc_spb_dbname).AsString := FDatabaseFiles.Names[i];
1798 SRB.Add(isc_spb_res_length).AsInteger := StrToInt(FDatabaseFiles.ValueFromIndex[i]);
1799 end
1800 else
1801 SRB.Add(isc_spb_dbname).AsString := FDatabaseFiles[i];
1802 end;
1803 end;
1804
1805 constructor TIBXRestoreService.Create(AOwner: TComponent);
1806 begin
1807 inherited Create(AOwner);
1808 FDatabaseFiles := TStringList.Create;
1809 Include (FOptions, CreateNewDB);
1810 end;
1811
1812 destructor TIBXRestoreService.Destroy;
1813 begin
1814 if FDatabaseFiles <> nil then FDatabaseFiles.Free;
1815 inherited Destroy;
1816 end;
1817
1818 { TIBXServerSideBackupService }
1819
1820 procedure TIBXServerSideBackupService.SetBackupFile(const Value: TStrings);
1821 begin
1822 FBackupFiles.Assign(Value);
1823 end;
1824
1825 procedure TIBXServerSideBackupService.SetBackupTarget;
1826 var i: integer;
1827 begin
1828 for i := 0 to FBackupFiles.Count - 1 do
1829 begin
1830 if (Trim(FBackupFiles[i]) = '') then
1831 continue;
1832 if (Pos('=', FBackupFiles[i]) <> 0) then
1833 begin {mbcs ok}
1834 SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles.Names[i];
1835 SRB.Add(isc_spb_bkp_length).AsInteger := StrToInt(FBackupFiles.ValueFromIndex[i]);
1836 end
1837 else
1838 SRB.Add(isc_spb_bkp_file).AsString := FBackupFiles[i];
1839 end;
1840 end;
1841
1842 constructor TIBXServerSideBackupService.Create(AOwner: TComponent);
1843 begin
1844 inherited Create(AOwner);
1845 FBackupFiles := TStringList.Create;
1846 end;
1847
1848 destructor TIBXServerSideBackupService.Destroy;
1849 begin
1850 if assigned(FBackupFiles) then FBackupFiles.Free;
1851 inherited Destroy;
1852 end;
1853
1854 { TIBXBackupService }
1855
1856 procedure TIBXBackupService.SetServiceStartOptions;
1857 var
1858 param: Integer;
1859 begin
1860 SRB.Add(isc_action_svc_backup);
1861 AddDBNameToSRB;
1862 inherited SetServiceStartOptions;
1863
1864 param := 0;
1865 if (IgnoreChecksums in Options) then
1866 param := param or isc_spb_bkp_ignore_checksums;
1867 if (IgnoreLimbo in Options) then
1868 param := param or isc_spb_bkp_ignore_limbo;
1869 if (MetadataOnly in Options) then
1870 param := param or isc_spb_bkp_metadata_only;
1871 if (NoGarbageCollection in Options) then
1872 param := param or isc_spb_bkp_no_garbage_collect;
1873 if (OldMetadataDesc in Options) then
1874 param := param or isc_spb_bkp_old_descriptions;
1875 if (NonTransportable in Options) then
1876 param := param or isc_spb_bkp_non_transportable;
1877 if (ConvertExtTables in Options) then
1878 param := param or isc_spb_bkp_convert;
1879 {Firebird 2.5 and later}
1880 with ServicesConnection do
1881 if (ServerVersionNo[1] > 2) or
1882 ((ServerVersionNo[1] = 2) and (ServerVersionNo[2] = 5)) then
1883 begin
1884 if (NoDBTriggers in Options) then
1885 param := param or isc_spb_bkp_no_triggers;
1886 end;
1887 SRB.Add(isc_spb_options).AsInteger := param;
1888
1889 if FBlockingFactor > 0 then
1890 SRB.Add(isc_spb_bkp_factor).AsInteger := FBlockingFactor;
1891 SetBackupTarget;
1892 end;
1893
1894 { TIBXBackupRestoreService }
1895
1896 procedure TIBXBackupRestoreService.SetServiceStartOptions;
1897 var options: string;
1898 begin
1899 if Verbose then
1900 SRB.Add(isc_spb_verbose);
1901
1902 with ServicesConnection do
1903 {Firebird 2.5.5 and later}
1904 if (ServerVersionNo[1] < 2) or
1905 ((ServerVersionNo[1] = 2) and ((ServerVersionNo[2] < 5) or
1906 ((ServerVersionNo[2] = 5) and (ServerVersionNo[3] < 5)))) then Exit;
1907
1908 if StatisticsRequested <> [] then
1909 begin
1910 options := '';
1911 if bsTotalTime in StatisticsRequested then
1912 options += 'T';
1913 if bsTimeDelta in StatisticsRequested then
1914 options += 'D';
1915 if bsPageReads in StatisticsRequested then
1916 options += 'R';
1917 if bsPageWrites in StatisticsRequested then
1918 options += 'W';
1919 SRB.Add(isc_spb_bkp_stat).AsString := options;
1920 end;
1921 end;
1922
1923
1924 { TIBXStatisticalService }
1925
1926 procedure TIBXStatisticalService.SetServiceStartOptions;
1927 var param: integer;
1928 begin
1929 SRB.Add(isc_action_svc_db_stats);
1930 AddDBNameToSRB;
1931
1932 param := 0;
1933 if (DataPages in Options) then
1934 param := param or isc_spb_sts_data_pages;
1935 if (HeaderPages in Options) then
1936 param := param or isc_spb_sts_hdr_pages;
1937 if (IndexPages in Options) then
1938 param := param or isc_spb_sts_idx_pages;
1939 if (SystemRelations in Options) then
1940 param := param or isc_spb_sts_sys_relations;
1941 SRB.Add(isc_spb_options).AsInteger := param;
1942 end;
1943
1944 { TIBXConfigService }
1945
1946 procedure TIBXConfigService.ShutdownDatabase(Options: TDBShutdownMode;
1947 Wait: Integer);
1948 begin
1949 SRB.Add(isc_action_svc_properties);
1950 AddDBNameToSRB;
1951 if (Options = Forced) then
1952 SRB.Add(isc_spb_prp_shutdown_db).AsInteger := Wait
1953 else if (Options = DenyTransaction) then
1954 SRB.Add(isc_spb_prp_deny_new_transactions).AsInteger := Wait
1955 else
1956 SRB.Add(isc_spb_prp_deny_new_attachments).AsInteger := Wait;
1957 InternalServiceStart;
1958 while IsServiceRunning do;
1959 end;
1960
1961 procedure TIBXConfigService.SetSweepInterval(Value: Integer);
1962 begin
1963 CheckActive;
1964 SRB.Add(isc_action_svc_properties);
1965 AddDBNameToSRB;
1966 SRB.Add(isc_spb_prp_sweep_interval).AsInteger := Value;
1967 InternalServiceStart;
1968 while IsServiceRunning do;
1969 end;
1970
1971 procedure TIBXConfigService.SetDBSqlDialect(Value: Integer);
1972 begin
1973 SRB.Add(isc_action_svc_properties);
1974 AddDBNameToSRB;
1975 SRB.Add(isc_spb_prp_set_sql_dialect).AsInteger := Value;
1976 InternalServiceStart;
1977 while IsServiceRunning do;
1978 end;
1979
1980 procedure TIBXConfigService.SetPageBuffers(Value: Integer);
1981 begin
1982 SRB.Add(isc_action_svc_properties);
1983 AddDBNameToSRB;
1984 SRB.Add(isc_spb_prp_page_buffers).AsInteger := Value;
1985 InternalServiceStart;
1986 while IsServiceRunning do;
1987 end;
1988
1989 procedure TIBXConfigService.ActivateShadow;
1990 begin
1991 SRB.Add(isc_action_svc_properties);
1992 AddDBNameToSRB;
1993 SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_activate;
1994 InternalServiceStart;
1995 while IsServiceRunning do;
1996 end;
1997
1998 procedure TIBXConfigService.BringDatabaseOnline;
1999 begin
2000 SRB.Add(isc_action_svc_properties);
2001 AddDBNameToSRB;
2002 SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_db_online;
2003 InternalServiceStart;
2004 while IsServiceRunning do;
2005 end;
2006
2007 procedure TIBXConfigService.SetReserveSpace(Value: Boolean);
2008 begin
2009 SRB.Add(isc_action_svc_properties);
2010 AddDBNameToSRB;
2011 with SRB.Add(isc_spb_prp_reserve_space) do
2012 if Value then
2013 AsByte := isc_spb_prp_res
2014 else
2015 AsByte := isc_spb_prp_res_use_full;
2016 InternalServiceStart;
2017 while IsServiceRunning do;
2018 end;
2019
2020 procedure TIBXConfigService.SetAsyncMode(Value: Boolean);
2021 begin
2022 SRB.Add(isc_action_svc_properties);
2023 AddDBNameToSRB;
2024 with SRB.Add(isc_spb_prp_write_mode) do
2025 if Value then
2026 AsByte := isc_spb_prp_wm_async
2027 else
2028 AsByte := isc_spb_prp_wm_sync;
2029 InternalServiceStart;
2030 while IsServiceRunning do;
2031 end;
2032
2033 procedure TIBXConfigService.SetReadOnly(Value: Boolean);
2034 begin
2035 SRB.Add(isc_action_svc_properties);
2036 AddDBNameToSRB;
2037 with SRB.Add(isc_spb_prp_access_mode) do
2038 if Value then
2039 AsByte := isc_spb_prp_am_readonly
2040 else
2041 AsByte := isc_spb_prp_am_readwrite;
2042 InternalServiceStart;
2043 while IsServiceRunning do;
2044 end;
2045
2046 procedure TIBXConfigService.SetNoLinger;
2047 begin
2048 SRB.Add(isc_action_svc_properties);
2049 AddDBNameToSRB;
2050 SRB.Add(isc_spb_options).AsInteger := isc_spb_prp_nolinger;
2051 InternalServiceStart;
2052 while IsServiceRunning do;
2053 end;
2054
2055 { TIBXLogService }
2056
2057 procedure TIBXLogService.SetServiceStartOptions;
2058 begin
2059 SRB.Add(isc_action_svc_get_ib_log);
2060 end;
2061
2062 { TIBXControlAndQueryService }
2063
2064 function TIBXControlAndQueryService.GetNextLine: String;
2065 var
2066 i: Integer;
2067 begin
2068 Result := '';
2069 if (FEof = True) then
2070 Exit;
2071 if not FServiceStarted then
2072 IBError(ibxeServiceNotStarted,[nil]);
2073
2074 SRB.Add(isc_info_svc_line);
2075 InternalServiceQuery;
2076
2077 for i := 0 to FServiceQueryResults.Count - 1 do
2078 with FServiceQueryResults[i] do
2079 begin
2080 case getItemType of
2081 isc_info_svc_line:
2082 Result := AsString;
2083 else
2084 IBError(ibxeOutputParsingError, [getItemType]);
2085 end;
2086 end;
2087 FEof := Result = '';
2088 Result := Trim(Result);
2089 DoOnGetNextLine(Result);
2090 if FEof then
2091 FServiceStarted := false;
2092 end;
2093
2094 function TIBXControlAndQueryService.GetNextChunk: String;
2095 var
2096 i: Integer;
2097 begin
2098 if (FEof = True) then
2099 begin
2100 Result := '';
2101 exit;
2102 end;
2103 if not FServiceStarted then
2104 IBError(ibxeServiceNotStarted,[nil]);
2105
2106 SRB.Add(isc_info_svc_to_eof);
2107 InternalServiceQuery;
2108
2109 FEof := True;
2110 for i := 0 to FServiceQueryResults.Count - 1 do
2111 with FServiceQueryResults[i] do
2112 begin
2113 case getItemType of
2114 isc_info_svc_to_eof:
2115 Result := AsString;
2116
2117 isc_info_truncated:
2118 FEof := False;
2119 else
2120 IBError(ibxeOutputParsingError, [getItemType]);
2121 end;
2122 end;
2123 if FEof then
2124 FServiceStarted := false;
2125 end;
2126
2127 procedure TIBXControlAndQueryService.ServiceStart;
2128 begin
2129 FEof := false;
2130 FSendBytes := 0;
2131 inherited ServiceStart;
2132 FServiceStarted := true;
2133 end;
2134
2135 function TIBXControlAndQueryService.ReceiveNextChunk(stream: TStream): integer;
2136 var
2137 i: Integer;
2138 TimeOut: boolean;
2139 begin
2140 Result := 0;
2141 TimeOut := false;
2142 if (FEof = True) then
2143 Exit;
2144 if not FServiceStarted then
2145 IBError(ibxeServiceNotStarted,[nil]);
2146
2147 SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2148 SRB.Add(isc_info_svc_to_eof);
2149 InternalServiceQuery;
2150
2151 FEof := True;
2152 for i := 0 to FServiceQueryResults.Count - 1 do
2153 with FServiceQueryResults[i] do
2154 begin
2155 case getItemType of
2156 isc_info_svc_to_eof:
2157 begin
2158 Result := CopyTo(stream,0);
2159 FEof := (Result = 0) and not TimeOut;
2160 end;
2161
2162 isc_info_truncated:
2163 FEof := False;
2164
2165 isc_info_svc_timeout:
2166 begin
2167 FEof := False;
2168 TimeOut := true;
2169 end
2170
2171 else
2172 IBError(ibxeOutputParsingError, [getItemType]);
2173 end;
2174 end;
2175 if FEof then
2176 FServiceStarted := false;
2177 end;
2178
2179 function TIBXControlAndQueryService.SendNextChunk(stream: TStream;
2180 var line: String): integer;
2181 var
2182 i: Integer;
2183 begin
2184 Result := 0;
2185 line := '';
2186 if (FEof = True) then
2187 Exit;
2188
2189 if not FServiceStarted then
2190 IBError(ibxeServiceNotStarted,[nil]);
2191
2192 SRB.Add(isc_info_svc_line);
2193 SRB.Add(isc_info_svc_stdin);
2194
2195 SQPB.Add(isc_info_svc_timeout).AsInteger := 1;
2196 if FSendBytes > 0 then
2197 Result := SQPB.Add(isc_info_svc_line).CopyFrom(stream,FSendBytes);
2198 try
2199 InternalServiceQuery;
2200 except
2201 FSendBytes := 0;
2202 raise;
2203 end;
2204
2205 FSendBytes := 0;
2206 for i := 0 to FServiceQueryResults.Count - 1 do
2207 with FServiceQueryResults[i] do
2208 begin
2209 case getItemType of
2210 isc_info_svc_line:
2211 line := AsString;
2212
2213 isc_info_svc_stdin:
2214 FSendBytes := AsInteger;
2215
2216 isc_info_svc_timeout,
2217 isc_info_data_not_ready:
2218 {ignore};
2219 else
2220 IBError(ibxeOutputParsingError, [getItemType]);
2221 end;
2222 end;
2223 FEOF := (FSendBytes = 0) and (line = '');
2224 if FEof then
2225 FServiceStarted := false;
2226 end;
2227
2228 procedure TIBXControlAndQueryService.DoOnGetNextLine(Line: string);
2229 begin
2230 if assigned(FOnGetNextLine) then
2231 OnGetNextLine(self,Line);
2232 end;
2233
2234 procedure TIBXControlAndQueryService.OnBeforeDisconnect(
2235 Sender: TIBXServicesConnection);
2236 var i: integer;
2237 begin
2238 inherited OnBeforeDisconnect(Sender);
2239 for i := 0 to FDataSets.Count - 1 do
2240 TDataSet(FDataSets[i]).Active := false;
2241 end;
2242
2243 procedure TIBXControlAndQueryService.Notification(AComponent: TComponent;
2244 Operation: TOperation);
2245 begin
2246 inherited Notification(AComponent, Operation);
2247 if (Operation = opRemove) and (AComponent is TDataSet) then
2248 FDataSets.Remove(AComponent);
2249 end;
2250
2251 procedure TIBXControlAndQueryService.RegisterDataSet(aDataSet: TDataSet);
2252 begin
2253 if FDataSets.IndexOf(aDataset) = -1 then
2254 begin
2255 FDataSets.Add(aDataSet);
2256 FreeNotification(ADataSet);
2257 end;
2258 end;
2259
2260 procedure TIBXControlAndQueryService.UnRegisterDataSet(aDataSet: TDataSet);
2261 begin
2262 FDataSets.Remove(aDataSet);
2263 RemoveFreeNotification(aDataset);
2264 end;
2265
2266 constructor TIBXControlAndQueryService.Create(aOwner: TComponent);
2267 begin
2268 inherited Create(aOwner);
2269 FDataSets := TList.Create;
2270 end;
2271
2272 destructor TIBXControlAndQueryService.Destroy;
2273 begin
2274 inherited Destroy;
2275 if assigned(FDataSets) then FDataSets.Free;
2276 end;
2277
2278 procedure TIBXControlAndQueryService.Execute(OutputLog: TStrings);
2279 begin
2280 ServiceStart;
2281 try
2282 while not Eof do
2283 if OutputLog <> nil then
2284 OutputLog.Add(GetNextLine)
2285 else
2286 GetNextLine;
2287 finally
2288 while IsServiceRunning do; {flush}
2289 end;
2290 end;
2291
2292 { TIBXControlService }
2293
2294 function TIBXControlService.GetIsServiceRunning: Boolean;
2295 begin
2296 Result := (ServicesConnection <> nil) and (ServicesConnection.Connected);
2297 if Result then
2298 begin
2299 SRB.Add(isc_info_svc_running);
2300 InternalServiceQuery(false);
2301 Result := (FServiceQueryResults <> nil) and (FServiceQueryResults.Count > 0) and
2302 (FServiceQueryResults[0].getItemType = isc_info_svc_running) and
2303 (FServiceQueryResults[0].AsInteger = 1);
2304 end;
2305 end;
2306
2307 procedure TIBXControlService.HandleSecContextErr;
2308 begin
2309 FAction := scRaiseError;
2310 if MainThreadID = TThread.CurrentThread.ThreadID then
2311 CallSecContextException
2312 else
2313 TThread.Synchronize(TThread.CurrentThread,@CallSecContextException);
2314 end;
2315
2316 procedure TIBXControlService.CallSecContextException;
2317 begin
2318 ServicesConnection.HandleSecContextException(self,FAction)
2319 end;
2320
2321 procedure TIBXControlService.SetDatabaseName(AValue: string);
2322 begin
2323 if FDatabaseName = AValue then Exit;
2324 CheckServiceNotRunning;
2325 FDatabaseName := AValue;
2326 DatabaseNameChanged;
2327 end;
2328
2329 procedure TIBXControlService.DatabaseNameChanged;
2330 begin
2331 //Do nothing
2332 end;
2333
2334 procedure TIBXControlService.OnAfterConnect(Sender: TIBXServicesConnection;
2335 aDatabaseName: string);
2336 begin
2337 inherited OnAfterConnect(Sender,aDatabaseName);
2338 if aDatabaseName <> '' then
2339 DatabaseName := aDatabaseName;
2340 end;
2341
2342 procedure TIBXControlService.AddDBNameToSRB;
2343 begin
2344 if FDatabaseName = '' then
2345 IBError(ibxeStartParamsError, [nil]);
2346 SRB.Add(isc_spb_dbname).AsString := FDatabaseName;
2347 end;
2348
2349 procedure TIBXControlService.CheckServiceNotRunning;
2350 begin
2351 if IsServiceRunning then
2352 IBError(ibxeServiceRunning,[nil]);
2353 end;
2354
2355 procedure TIBXControlService.InternalServiceStart;
2356 var done: boolean;
2357 theError: EIBInterBaseError;
2358 begin
2359 if SRB = nil then
2360 IBError(ibxeStartParamsError, [nil]);
2361
2362 FLastStartSRB := SRB;
2363 done := false;
2364 theError := nil;
2365 try
2366 repeat
2367 CheckActive;
2368 done := ServicesConnection.ServiceIntf.Start(SRB,false);
2369 if not done then
2370 begin
2371 theError := EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus);
2372 if theError.IBErrorCode = isc_sec_context then
2373 begin
2374 HandleSecContextErr;
2375 if FAction = scRaiseError then
2376 raise theError
2377 else
2378 begin
2379 theError.Free;
2380 FSRB := FLastStartSRB;
2381 end;
2382 end
2383 else
2384 raise theError;
2385 end;
2386 until done;
2387 finally
2388 FSRB := nil;
2389 end;
2390 if tfService in ServicesConnection.TraceFlags then
2391 MonitorHook.ServiceStart(Self);
2392 end;
2393
2394 procedure TIBXControlService.DoServiceQuery;
2395 var done: boolean;
2396 LastSRB: ISRB;
2397 LastSQPB: ISQPB;
2398 theError: EIBInterBaseError;
2399 begin
2400 done := false;
2401 theError := nil;
2402 repeat
2403 LastSRB := SRB;
2404 LastSQPB := SQPB;
2405 inherited DoServiceQuery;
2406 done := FServiceQueryResults <> nil;
2407 if not done then
2408 begin
2409 if ServicesConnection.GetFirebirdAPI.GetStatus.GetIBErrorCode = isc_sec_context then
2410 begin
2411 theError := EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus); {save exception}
2412 HandleSecContextErr;
2413 if FAction = scReconnect then
2414 begin
2415 {Restart service}
2416 theError.Free;
2417 FSRB := FLastStartSRB;
2418 InternalServiceStart;
2419 FSRB := LastSRB;
2420 FSQPB := LastSQPB;
2421 end
2422 else
2423 raise theError;
2424 end
2425 else
2426 break; {Let the caller handle the error}
2427 end;
2428 until done;
2429 end;
2430
2431 procedure TIBXControlService.SetServiceStartOptions;
2432 begin
2433 //Do nothing
2434 end;
2435
2436 procedure TIBXControlService.ServiceStart;
2437 begin
2438 CheckActive;
2439 CheckServiceNotRunning;
2440 SetServiceStartOptions;
2441 InternalServiceStart;
2442 end;
2443
2444 procedure TIBXControlService.Assign(Source: TPersistent);
2445 begin
2446 inherited Assign(Source);
2447 if Source is TIBXControlService then
2448 DatabaseName := TIBXControlService(Source).DatabaseName;
2449 end;
2450
2451 { TConfigParams }
2452
2453 constructor TConfigParams.Create;
2454 begin
2455 ConfigFileData := TConfigFileData.Create;
2456 ConfigFileParams := nil;
2457 end;
2458
2459 destructor TConfigParams.Destroy;
2460 begin
2461 ConfigFileData.Free;
2462 ConfigFileParams := nil;
2463 inherited Destroy;
2464 end;
2465
2466 { TConfigFileData }
2467
2468 constructor TConfigFileData.Create;
2469 begin
2470 ConfigFileValue := nil;
2471 ConfigFileKey := nil;
2472 end;
2473
2474 destructor TConfigFileData.Destroy;
2475 begin
2476 ConfigFileValue := nil;
2477 ConfigFileKey := nil;
2478 inherited Destroy;
2479 end;
2480
2481 { TDatabaseInfo }
2482
2483 constructor TDatabaseInfo.Create;
2484 begin
2485 DbName := nil;
2486 end;
2487
2488 destructor TDatabaseInfo.Destroy;
2489 begin
2490 DbName := nil;
2491 inherited Destroy;
2492 end;
2493
2494 { TIBXServerProperties }
2495
2496 function TIBXServerProperties.GetConfigParams: TConfigParams;
2497 var i, j: Integer;
2498 begin
2499 CheckActive;
2500 if FConfigParams = nil then
2501 begin
2502 SRB.Add(isc_info_svc_get_config);
2503 SRB.Add(isc_info_svc_get_env);
2504 SRB.Add(isc_info_svc_get_env_lock);
2505 SRB.Add(isc_info_svc_get_env_msg);
2506 SRB.Add(isc_info_svc_user_dbpath);
2507
2508 InternalServiceQuery;
2509
2510 FConfigParams := TConfigParams.Create;
2511 for i := 0 to FServiceQueryResults.Count - 1 do
2512 with FServiceQueryResults[i] do
2513 begin
2514 case getItemType of
2515 isc_info_svc_get_config:
2516 begin
2517 SetLength (FConfigParams.ConfigFileData.ConfigFileValue, Count);
2518 SetLength (FConfigParams.ConfigFileData.ConfigFileKey, Count);
2519
2520 for j := 0 to Count - 1 do
2521 begin
2522 FConfigParams.ConfigFileData.ConfigFileKey[j] := Items[j].getItemType;
2523 FConfigParams.ConfigFileData.ConfigFileValue[j] := Items[j].AsInteger;
2524 end;
2525 end;
2526
2527 isc_info_svc_get_env:
2528 FConfigParams.BaseLocation := AsString;
2529
2530 isc_info_svc_get_env_lock:
2531 FConfigParams.LockFileLocation := AsString;
2532
2533 isc_info_svc_get_env_msg:
2534 FConfigParams.MessageFileLocation := AsString;
2535
2536 isc_info_svc_user_dbpath:
2537 FConfigParams.SecurityDatabaseLocation := AsString;
2538
2539 else
2540 IBError(ibxeOutputParsingError, [getItemType]);
2541 end;
2542 end;
2543 end;
2544 Result := FConfigParams;
2545 end;
2546
2547 function TIBXServerProperties.GetDatabaseInfo: TDatabaseInfo;
2548 var i,j: Integer;
2549 begin
2550 if FDatabaseInfo = nil then
2551 begin
2552 SRB.Add(isc_info_svc_svr_db_info);
2553 InternalServiceQuery;
2554
2555 FDatabaseInfo := TDatabaseInfo.Create;
2556 SetLength(FDatabaseInfo.DbName,0);
2557 for i := 0 to FServiceQueryResults.Count - 1 do
2558 with FServiceQueryResults[i] do
2559 begin
2560 case getItemType of
2561 isc_info_svc_svr_db_info:
2562 for j := 0 to FServiceQueryResults[i].Count - 1 do
2563 with FServiceQueryResults[i][j] do
2564 case getItemType of
2565 isc_spb_num_att:
2566 FDatabaseInfo.NoOfAttachments := AsInteger;
2567
2568 isc_spb_num_db:
2569 FDatabaseInfo.NoOfDatabases := AsInteger;
2570
2571 isc_spb_dbname:
2572 begin
2573 SetLength(FDatabaseInfo.DbName,length(FDatabaseInfo.DbName)+1);
2574 FDatabaseInfo.DbName[length(FDatabaseInfo.DbName)-1] := AsString;
2575 end;
2576 else
2577 IBError(ibxeOutputParsingError, [getItemType]);
2578 end;
2579 else
2580 IBError(ibxeOutputParsingError, [getItemType]);
2581 end;
2582 end;
2583 end;
2584 Result := FDatabaseInfo;
2585 end;
2586
2587 function TIBXServerProperties.GetVersionInfo: TVersionInfo;
2588 var i : Integer;
2589 begin
2590 if FVersionInfo = nil then
2591 begin
2592 SRB.Add(isc_info_svc_version);
2593 SRB.Add(isc_info_svc_server_version);
2594 SRB.Add(isc_info_svc_implementation);
2595 InternalServiceQuery;
2596
2597 FVersionInfo := TVersionInfo.Create;
2598 for i := 0 to FServiceQueryResults.Count - 1 do
2599 with FServiceQueryResults[i] do
2600 begin
2601 case getItemType of
2602 isc_info_svc_version:
2603 FVersionInfo.ServiceVersion := AsInteger;
2604 isc_info_svc_server_version:
2605 FVersionInfo.ServerVersion := AsString;
2606 isc_info_svc_implementation:
2607 FVersionInfo.ServerImplementation := AsString;
2608 else
2609 IBError(ibxeOutputParsingError, [getItemType]);
2610 end;
2611 end;
2612 end;
2613 Result := FVersionInfo;
2614 end;
2615
2616 procedure TIBXServerProperties.Clear;
2617 begin
2618 inherited;
2619 if assigned(FDatabaseInfo) then FreeAndNil(FDatabaseInfo);
2620 if assigned(FVersionInfo) then FreeAndNil(FVersionInfo);
2621 if assigned(FConfigParams) then FreeAndNil(FConfigParams);
2622 end;
2623
2624 { TIBXCustomService }
2625
2626 procedure TIBXCustomService.CheckActive;
2627 begin
2628 if ServicesConnection = nil then
2629 IBError(ibxeServiceActive,[nil]);
2630 ServicesConnection.CheckActive;
2631 end;
2632
2633 function TIBXCustomService.GetSQPB: ISQPB;
2634 begin
2635 CheckActive;
2636 if FSQPB = nil then
2637 FSQPB := ServicesConnection.ServiceIntf.AllocateSQPB;
2638 Result := FSQPB;
2639 end;
2640
2641 function TIBXCustomService.GetSRB: ISRB;
2642 begin
2643 CheckActive;
2644 if FSRB = nil then
2645 FSRB := ServicesConnection.ServiceIntf.AllocateSRB;
2646 Result := FSRB;
2647 end;
2648
2649 procedure TIBXCustomService.SetServicesConnection(AValue: TIBXServicesConnection
2650 );
2651 begin
2652 if FServicesConnection = AValue then Exit;
2653 if FServicesConnection <> nil then
2654 begin
2655 FServicesConnection.UnRegisterIntf(self);
2656 RemoveFreeNotification(FServicesConnection);
2657 end;
2658 Clear;
2659 FServicesConnection := AValue;
2660 if FServicesConnection <> nil then
2661 begin
2662 FServicesConnection.RegisterIntf(self);
2663 FreeNotification(FServicesConnection);
2664 end;
2665 end;
2666
2667 procedure TIBXCustomService.OnBeforeDisconnect(Sender: TIBXServicesConnection);
2668 begin
2669 Clear;
2670 end;
2671
2672 procedure TIBXCustomService.InternalServiceQuery(RaiseExceptionOnError: boolean
2673 );
2674 begin
2675 CheckActive;
2676 try
2677 FServiceQueryResults := nil;
2678 DoServiceQuery;
2679 if (FServiceQueryResults = nil) and RaiseExceptionOnError then
2680 raise EIBInterBaseError.Create(ServicesConnection.GetFirebirdAPI.GetStatus);
2681 finally
2682 FSQPB := nil;
2683 FSRB := nil;
2684 end;
2685 if tfService in ServicesConnection.TraceFlags then
2686 MonitorHook.ServiceQuery(Self);
2687 end;
2688
2689 procedure TIBXCustomService.DoServiceQuery;
2690 begin
2691 FServiceQueryResults := ServicesConnection.ServiceIntf.Query(FSQPB,FSRB,false);
2692 end;
2693
2694 procedure TIBXCustomService.Notification(AComponent: TComponent;
2695 Operation: TOperation);
2696 begin
2697 inherited Notification(AComponent, Operation);
2698 if (Operation = opRemove) and (AComponent = ServicesConnection) then
2699 ServicesConnection := nil;
2700 end;
2701
2702 constructor TIBXCustomService.Create(AOwner: TComponent);
2703 begin
2704 inherited Create(AOwner);
2705 FSRB := nil;
2706 FServiceQueryResults := nil;
2707 FSQPB := nil;
2708 end;
2709
2710 destructor TIBXCustomService.Destroy;
2711 begin
2712 if ServicesConnection <> nil then
2713 begin
2714 OnBeforeDisconnect(ServicesConnection);
2715 ServicesConnection := nil;
2716 end;
2717 inherited Destroy;
2718 end;
2719
2720 procedure TIBXCustomService.Assign(Source: TPersistent);
2721 begin
2722 if Source is TIBXCustomService then
2723 ServicesConnection := TIBXCustomService(Source).ServicesConnection;
2724 end;
2725
2726 procedure TIBXCustomService.Clear;
2727 begin
2728 FSRB := nil;
2729 FServiceQueryResults := nil;
2730 FSQPB := nil;
2731 end;
2732
2733 procedure TIBXCustomService.OnAfterConnect(Sender: TIBXServicesConnection;
2734 aDatabaseName: string);
2735 begin
2736 //Do nothing
2737 end;
2738
2739 { TIBXServicesConnection }
2740
2741 procedure TIBXServicesConnection.SetParams(AValue: TStrings);
2742 begin
2743 FParams.Assign(AValue);
2744 end;
2745
2746 procedure TIBXServicesConnection.SetPortNo(AValue: string);
2747 begin
2748 if FPortNo = AValue then Exit;
2749 Connected := false;
2750 FPortNo := AValue;
2751 FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
2752 end;
2753
2754 procedure TIBXServicesConnection.CheckActive;
2755 begin
2756 if StreamedConnected and (not Connected) then
2757 Loaded;
2758 if FService = nil then
2759 IBError(ibxeServiceActive, [nil]);
2760 end;
2761
2762 procedure TIBXServicesConnection.CheckInactive;
2763 begin
2764 if FService <> nil then
2765 IBError(ibxeServiceInActive, [nil]);
2766 end;
2767
2768 procedure TIBXServicesConnection.CheckServerName;
2769 begin
2770 if (FServerName = '') and (FProtocol <> Local) then
2771 IBError(ibxeServerNameMissing, [nil]);
2772 end;
2773
2774 {
2775 * GenerateSPB -
2776 * Given a string containing a textual representation
2777 * of the Service parameters, generate a service
2778 * parameter buffer, and return it .
2779 }
2780 function TIBXServicesConnection.GenerateSPB(sl: TStrings): ISPB;
2781 var
2782 i, j, SPBServerVal: UShort;
2783 param_name, param_value: String;
2784 begin
2785 { The SPB is initially empty, with the exception that
2786 the SPB version must be the first byte of the string.
2787 }
2788 Result := FirebirdAPI.AllocateSPB;
2789
2790 { Iterate through the textual service parameters, constructing
2791 a SPB on-the-fly }
2792 if sl.Count > 0 then
2793 for i := 0 to sl.Count - 1 do
2794 begin
2795 { Get the parameter's name and value from the list,
2796 and make sure that the name is all lowercase with
2797 no leading 'isc_spb_' prefix }
2798 if (Trim(sl.Names[i]) = '') then continue;
2799 param_name := LowerCase(sl.Names[i]); {mbcs ok}
2800 param_value := sl.ValueFromIndex[i];
2801 if (Pos(SPBPrefix, param_name) = 1) then {mbcs ok}
2802 Delete(param_name, 1, Length(SPBPrefix));
2803 { We want to translate the parameter name to some integer
2804 value. We do this by scanning through a list of known
2805 service parameter names (SPBConstantNames, defined above). }
2806 SPBServerVal := 0;
2807 { Find the parameter }
2808 for j := 1 to isc_spb_last_spb_constant do
2809 if (param_name = SPBConstantNames[j]) then
2810 begin
2811 SPBServerVal := SPBConstantValues[j];
2812 break;
2813 end;
2814 case SPBServerVal of
2815 isc_spb_user_name,
2816 isc_spb_password,
2817 isc_spb_sql_role_name,
2818 isc_spb_expected_db:
2819 Result.Add(SPBServerVal).AsString := param_value;
2820 else
2821 begin
2822 if GetSPBConstName(SPBServerVal) <> '' then
2823 IBError(ibxeSPBConstantNotSupported,
2824 [GetSPBConstName(SPBServerVal)])
2825 else
2826 IBError(ibxeSPBConstantUnknown, [SPBServerVal]);
2827 end;
2828 end;
2829 end;
2830 if WireCompression then
2831 Result.Add(isc_spb_config).AsString := 'WireCompression=true';
2832 end;
2833
2834 function TIBXServicesConnection.GetFirebirdAPI: IFirebirdAPI;
2835 var fblib: IFirebirdLibrary;
2836 begin
2837 if FFirebirdAPI = nil then
2838 begin
2839 if (csDesigning in ComponentState) or (Trim(FFirebirdLibraryPathName) = '') then
2840 FFirebirdAPI := IB.FirebirdAPI
2841 else
2842 begin
2843 fblib := IB.LoadFBLibrary(FFirebirdLibraryPathName);
2844 if assigned(fblib) then
2845 FFirebirdAPI := fblib.GetFirebirdAPI;
2846 end;
2847 end;
2848 Result := FFirebirdAPI;
2849 end;
2850
2851 function TIBXServicesConnection.GetServerVersionNo(index: integer): integer;
2852 begin
2853 CheckActive;
2854 if (index >= Low(FServerVersionNo)) and (index <= High(FServerVersionNo)) then
2855 Result := FServerVersionNo[index]
2856 else
2857 IBError(ibxeInfoBufferIndexError,[index]);
2858 end;
2859
2860 function TIBXServicesConnection.GetSPBConstName(action: byte): string;
2861 var i: integer;
2862 begin
2863 Result := '';
2864 for i := Low(SPBConstantValues) to High(SPBConstantValues) do
2865 if SPBConstantValues[i] = action then
2866 begin
2867 Result := SPBConstantNames[i];
2868 break;
2869 end;
2870 end;
2871
2872 procedure TIBXServicesConnection.HandleException(Sender: TObject);
2873 var aParent: TComponent;
2874 begin
2875 aParent := Owner;
2876 while aParent <> nil do
2877 begin
2878 if aParent is TCustomApplication then
2879 begin
2880 TCustomApplication(aParent).HandleException(Sender);
2881 Exit;
2882 end;
2883 aParent := aParent.Owner;
2884 end;
2885 SysUtils.ShowException(ExceptObject,ExceptAddr);
2886 end;
2887
2888 procedure TIBXServicesConnection.HandleSecContextException(
2889 Sender: TIBXControlService; var action: TSecContextAction);
2890 var OldServiceIntf: IServiceManager;
2891 begin
2892 action := scRaiseError;
2893 if assigned(FOnSecurityContextException) then
2894 OnSecurityContextException(self,action);
2895
2896 if action = scReconnect then
2897 begin
2898 FExpectedDB := Sender.DatabaseName;
2899 try
2900 OldServiceIntf := FService;
2901 Connected := false;
2902 while not Connected do
2903 begin
2904 try
2905 Connected := true;
2906 except
2907 on E:EIBClientError do
2908 begin
2909 action := scRaiseError;
2910 FService := OldServiceIntf;
2911 break;
2912 end;
2913 else
2914 HandleException(self);
2915 end;
2916 end;
2917 finally
2918 FExpectedDB := '';
2919 end;
2920 end;
2921 end;
2922
2923 function TIBXServicesConnection.Login(var aServerName: string;
2924 LoginParams: TStrings): Boolean;
2925 var
2926 IndexOfUser, IndexOfPassword: Integer;
2927 Username, Password: String;
2928 ExtLoginParams: TStrings;
2929 begin
2930 if Assigned(FOnLogin) then
2931 begin
2932 Result := True;
2933 ExtLoginParams := TStringList.Create;
2934 try
2935 ExtLoginParams.Assign(Params);
2936 FOnLogin(Self, aServerName, ExtLoginParams);
2937 LoginParams.Assign (ExtLoginParams);
2938 finally
2939 ExtLoginParams.Free;
2940 end;
2941 end
2942 else
2943 if assigned(IBGUIInterface) then
2944 begin
2945 IndexOfUser := LoginParams.IndexOfName(GetSPBConstName(isc_spb_user_name));
2946 if IndexOfUser <> -1 then
2947 Username := LoginParams.ValueFromIndex[IndexOfUser]
2948 else
2949 UserName := '';
2950 IndexOfPassword :=LoginParams.IndexOfName(GetSPBConstName(isc_spb_password));
2951 if IndexOfPassword <> -1 then
2952 Password := LoginParams.ValueFromIndex[IndexOfPassword]
2953 else
2954 Password := '';
2955
2956 result := IBGUIInterface.ServerLoginDialog(aServerName, Username, Password);
2957 if result then
2958 begin
2959 LoginParams.Values[GetSPBConstName(isc_spb_user_name)] := UserName;
2960 LoginParams.Values[GetSPBConstName(isc_spb_password)] := Password;
2961 end
2962 end
2963 else
2964 IBError(ibxeNoLoginDialog,[]);
2965 end;
2966
2967 procedure TIBXServicesConnection.ParamsChanging(Sender: TObject);
2968 begin
2969 CheckInactive;
2970 end;
2971
2972 procedure TIBXServicesConnection.SetConnectString(AValue: string);
2973 var aServiceName: AnsiString;
2974 aProtocol: TProtocolAll;
2975 begin
2976 if FConnectString = AValue then Exit;
2977 Connected := false;
2978 if not ParseConnectString(AValue,FServerName,aServiceName,aProtocol,FPortNo)
2979 or (aServiceName <> 'service_mgr') or (aProtocol = unknownProtocol) then
2980 IBError(ibxeBadConnectString, [nil]);
2981 FConnectString := AValue;
2982 FProtocol := TProtocol(aProtocol);
2983 end;
2984
2985 procedure TIBXServicesConnection.SetFirebirdLibraryPathName(AValue: TIBFileName
2986 );
2987 begin
2988 if FFirebirdLibraryPathName = AValue then Exit;
2989 FFirebirdLibraryPathName := AValue;
2990 Connected := false;
2991 FFirebirdAPI := nil;
2992 end;
2993
2994 procedure TIBXServicesConnection.SetProtocol(AValue: TProtocol);
2995 begin
2996 if FProtocol = AValue then Exit;
2997 Connected := false;
2998 FProtocol := AValue;
2999 FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
3000 end;
3001
3002 procedure TIBXServicesConnection.SetServerName(AValue: string);
3003 begin
3004 if FServerName = AValue then Exit;
3005 Connected := false;
3006 FServerName := AValue;
3007 FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
3008 end;
3009
3010 procedure TIBXServicesConnection.DoConnect;
3011
3012 procedure ParseServerVersionNo;
3013 var Req: ISRB;
3014 Results: IServiceQueryResults;
3015 RegexObj: TRegExpr;
3016 s: string;
3017 begin
3018 Req := FService.AllocateSRB;
3019 Req.Add(isc_info_svc_server_version);
3020 Results := FService.Query(nil,Req);
3021 if (Results.Count = 1) and (Results[0].getItemType = isc_info_svc_server_version) then
3022 RegexObj := TRegExpr.Create;
3023 try
3024 {extact database file spec}
3025 RegexObj.ModifierG := false; {turn off greedy matches}
3026 RegexObj.Expression := '[A-Z][A-Z]-V([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+) .*';
3027 s := Results[0].AsString;
3028 if RegexObj.Exec(s) then
3029 begin
3030 FServerVersionNo[1] := StrToInt(RegexObj.Match[1]);
3031 FServerVersionNo[2] := StrToInt(RegexObj.Match[2]);
3032 FServerVersionNo[3] := StrToInt(RegexObj.Match[3]);
3033 FServerVersionNo[4] := StrToInt(RegexObj.Match[4]);
3034 end;
3035 finally
3036 RegexObj.Free;
3037 end;
3038 end;
3039
3040 var aServerName: string;
3041 aProtocol: TProtocolAll;
3042 aPortNo: string;
3043 aDBName: string;
3044 TempSvcParams: TStrings;
3045 SPB: ISPB;
3046 PW: ISPBItem;
3047 i: integer;
3048 begin
3049 CheckInactive;
3050 CheckServerName;
3051
3052 aServerName := FServerName;
3053 aProtocol := FProtocol;
3054 aPortNo := PortNo;
3055 aDBName := '';
3056
3057 if FDatabase <> nil then
3058 {Get Connect String from Database Connect String}
3059 begin
3060 FFirebirdAPI := FDatabase.FirebirdAPI;
3061 if ParseConnectString(FDatabase.Attachment.GetConnectString,aServerName,aDBName,aProtocol,aPortNo) and
3062 (aProtocol = Local) and
3063 (FDatabase.Attachment.GetRemoteProtocol <> '') then
3064 begin
3065 {Use loopback if database does not use embedded server}
3066 aServerName := 'Localhost';
3067 aProtocol := TCP;
3068 end;
3069 end;
3070
3071 TempSvcParams := TStringList.Create;
3072 try
3073 TempSvcParams.Assign(FParams);
3074 if LoginPrompt and not Login(aServerName,TempSvcParams) then
3075 IBError(ibxeOperationCancelled, [nil]);
3076
3077 {Use of non-default security database}
3078 if FExpectedDB <> '' then {set when handling an isc_sec_context exception}
3079 TempSvcParams.Values['expected_db'] := FExpectedDB
3080 else
3081 if (FDatabase <> nil) and (FDatabase.Attachment.GetSecurityDatabase <> 'Default')
3082 and (aDBName <> '') then
3083 {Connect using database using non-default security database}
3084 TempSvcParams.Values['expected_db'] := aDBName;
3085 SPB := GenerateSPB(TempSvcParams);
3086 finally
3087 TempSvcParams.Free;
3088 end;
3089
3090 FService := FirebirdAPI.GetServiceManager(aServerName,aPortNo,aProtocol,SPB);
3091 FServername := aServerName;
3092 FProtocol := aProtocol;
3093 FPortNo := aPortNo;
3094 FConnectString := MakeConnectString(FServerName,'service_mgr',FProtocol,FPortNo);
3095 PW := FService.getSPB.Find(isc_spb_password);
3096 if PW <> nil then PW.AsString := 'xxxxxxxx'; {Hide password}
3097
3098 ParseServerVersionNo;
3099
3100 for i := low(FIBXServices) to high(FIBXServices) do
3101 FIBXServices[i].OnAfterConnect(self,aDBName);
3102
3103 if tfService in TraceFlags then
3104 MonitorHook.ServiceAttach(Self);
3105 end;
3106
3107 procedure TIBXServicesConnection.DoDisconnect;
3108 var i: integer;
3109 begin
3110 CheckActive;
3111 for i := 0 to Length(FIBXServices) - 1 do
3112 FIBXServices[i].OnBeforeDisconnect(self);
3113 FService := nil;
3114 if tfService in TraceFlags then
3115 MonitorHook.ServiceDetach(Self);
3116 end;
3117
3118 function TIBXServicesConnection.GetConnected: Boolean;
3119 begin
3120 Result := FService <> nil;
3121 end;
3122
3123 function TIBXServicesConnection.GetDataset(Index: longint): TDataset;
3124 begin
3125 Result := inherited GetDataset(Index);
3126 end;
3127
3128 function TIBXServicesConnection.GetDataSetCount: Longint;
3129 begin
3130 Result := inherited GetDataSetCount;
3131 end;
3132
3133 procedure TIBXServicesConnection.ReadState(Reader: TReader);
3134 begin
3135 FParams.Clear;
3136 inherited ReadState(Reader);
3137 end;
3138
3139 procedure TIBXServicesConnection.RegisterIntf(intf: IIBXServicesClient);
3140 begin
3141 Setlength(FIBXServices,Length(FIBXServices) + 1);
3142 FIBXServices[Length(FIBXServices)-1] := intf;
3143 end;
3144
3145 procedure TIBXServicesConnection.UnRegisterIntf(intf: IIBXServicesClient);
3146 var i, j: integer;
3147 begin
3148 for i := length(FIBXServices) - 1 downto 0 do
3149 if FIBXServices[i] = intf then
3150 begin
3151 for j := i + 1 to length(FIBXServices) - 1 do
3152 FIBXServices[j-1] := FIBXServices[j];
3153 SetLength(FIBXServices,Length(FIBXServices)-1);
3154 break;
3155 end;
3156 end;
3157
3158 constructor TIBXServicesConnection.Create(AOwner: TComponent);
3159 begin
3160 inherited Create(AOwner);
3161 FServerName := '';
3162 FParams := TStringList.Create;
3163 Setlength(FIBXServices,0);
3164 TStringList(FParams).OnChanging := @ParamsChanging;
3165 FService := nil;
3166 FProtocol := Local;
3167 LoginPrompt := true;
3168 if (AOwner <> nil) and
3169 (AOwner is TCustomApplication) and
3170 TCustomApplication(AOwner).ConsoleApplication then
3171 LoginPrompt := false;
3172 end;
3173
3174 destructor TIBXServicesConnection.Destroy;
3175 begin
3176 inherited Destroy;
3177 Setlength(FIBXServices,0);
3178 if assigned(FParams) then FParams.Free;
3179 FFirebirdAPI := nil;
3180 end;
3181
3182 procedure TIBXServicesConnection.ConnectUsing(aDatabase: TIBDatabase);
3183 begin
3184 if not aDatabase.Connected then
3185 IBError(ibxeDatabaseNotConnected,[nil]);
3186 Connected := false;
3187 FDatabase := aDatabase;
3188 try
3189 Connected := true;
3190 finally
3191 FDatabase := nil;
3192 end;
3193 end;
3194
3195 procedure TIBXServicesConnection.SetDBParams(DBParams: TStrings);
3196 var i: integer;
3197 j: integer;
3198 k: integer;
3199 ParamName: string;
3200 begin
3201 Params.Clear;
3202 for i := 0 to DBParams.Count - 1 do
3203 begin
3204 ParamName := DBParams[i];
3205 k := Pos('=',ParamName);
3206 if k > 0 then system.Delete(ParamName,k,Length(ParamName)-k+1);
3207 for j := 1 to isc_spb_last_spb_constant do
3208 if CompareText(ParamName,SPBConstantNames[j]) = 0 then
3209 begin
3210 Params.Add(DBParams[i]);
3211 break;
3212 end;
3213 end;
3214 end;
3215
3216 end.
3217