ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/runtime/nongui/IBXServices.pas
Revision: 209
Committed: Wed Mar 14 12:48:51 2018 UTC (6 years, 1 month ago) by tony
Content type: text/x-pascal
File size: 89573 byte(s)
Log Message:
Fixes Merged

File Contents

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