ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/nongui/IBXServices.pas
Revision: 263
Committed: Thu Dec 6 15:55:01 2018 UTC (5 years, 4 months ago) by tony
Content type: text/x-pascal
File size: 91169 byte(s)
Log Message:
Release 2.3.2 committed

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