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