ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/examples/services/MainFormUnit.pas
Revision: 143
Committed: Fri Feb 23 12:11:21 2018 UTC (6 years, 2 months ago) by tony
Content type: text/x-pascal
File size: 17242 byte(s)
Log Message:
Fixes Merged

File Contents

# User Rev Content
1 tony 143 (*
2     * IBX For Lazarus (Firebird Express)
3     *
4     * The contents of this file are subject to the Initial Developer's
5     * Public License Version 1.0 (the "License"); you may not use this
6     * file except in compliance with the License. You may obtain a copy
7     * of the License here:
8     *
9     * http://www.firebirdsql.org/index.php?op=doc&id=idpl
10     *
11     * Software distributed under the License is distributed on an "AS
12     * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13     * implied. See the License for the specific language governing rights
14     * and limitations under the License.
15     *
16     * The Initial Developer of the Original Code is Tony Whyman.
17     *
18     * The Original Code is (C) 2015 Tony Whyman, MWA Software
19     * (http://www.mwasoftware.co.uk).
20     *
21     * All Rights Reserved.
22     *
23     * Contributor(s): ______________________________________.
24     *
25     *)
26    
27     unit MainFormUnit;
28    
29     {$mode objfpc}{$H+}
30    
31     interface
32    
33     uses
34     Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
35     ActnList, Menus, IBServices, IB;
36    
37     type
38    
39     TRunServiceProc = procedure of object;
40    
41     { TMainForm }
42    
43     TMainForm = class(TForm)
44     IBConfigService1: TIBConfigService;
45     MenuItem6: TMenuItem;
46     Shutdown: TAction;
47     BringOnline: TAction;
48     MenuItem1: TMenuItem;
49     MenuItem5: TMenuItem;
50     Sweep: TAction;
51     LimboTransactions: TAction;
52     MenuItem2: TMenuItem;
53     MenuItem3: TMenuItem;
54     MenuItem4: TMenuItem;
55     PopupMenu1: TPopupMenu;
56     Validate: TAction;
57     Statistics: TAction;
58     ActionList1: TActionList;
59     CLoseBtn: TButton;
60     BackupBtn: TButton;
61     RestoreBtn: TButton;
62     ServerLOgBtn: TButton;
63     DatabaseBtn: TButton;
64     UsersBtn: TButton;
65     IBLogService1: TIBLogService;
66     IBOnlineValidationService1: TIBOnlineValidationService;
67     IBServerProperties1: TIBServerProperties;
68     IBStatisticalService1: TIBStatisticalService;
69     IBValidationService1: TIBValidationService;
70     Memo1: TMemo;
71     procedure BringOnlineExecute(Sender: TObject);
72     procedure BringOnlineUpdate(Sender: TObject);
73     procedure CLoseBtnClick(Sender: TObject);
74     procedure BackupBtnClick(Sender: TObject);
75     procedure RestoreBtnClick(Sender: TObject);
76     procedure ServerLOgBtnClick(Sender: TObject);
77     procedure DatabaseBtnClick(Sender: TObject);
78     procedure ShutdownExecute(Sender: TObject);
79     procedure SweepExecute(Sender: TObject);
80     procedure UsersBtnClick(Sender: TObject);
81     procedure FormShow(Sender: TObject);
82     procedure IBServerProperties1Login(Service: TIBCustomService;
83     LoginParams: TStrings);
84     procedure AltSecDBLogin(Service: TIBCustomService;
85     LoginParams: TStrings);
86     procedure LimboTransactionsExecute(Sender: TObject);
87     procedure StatisticsExecute(Sender: TObject);
88     procedure ValidateExecute(Sender: TObject);
89     private
90     { private declarations }
91     FValidationService: TIBControlAndQueryService;
92     FDBName: string;
93     FServerUserName: string;
94     FServerPassword: string;
95     FShutDownMode: TShutdownMode;
96     FDelay: integer;
97     procedure SetDBName(AValue: string);
98     procedure UseServerLogin;
99     function RunService(aService: TIBCustomService; RunProc: TRunServiceProc
100     ): boolean;
101     procedure RunShowStatistics;
102     procedure RunValidation;
103     procedure RunLimboTransactions;
104     procedure RunSweep;
105     procedure RunBringOnline;
106     procedure RunShutdown;
107     property DBName: string read FDBName write SetDBName;
108     public
109     { public declarations }
110     function IsDatabaseOnline: boolean;
111     end;
112    
113     var
114     MainForm: TMainForm;
115    
116     implementation
117    
118     {$R *.lfm}
119    
120     uses IBErrorCodes, FBMessages, ServicesLoginDlgUnit, SelectValidationDlgUnit, SelectDBDlgUnit,
121     BackupDlgUnit, RestoreDlgUnit, ListUsersUnit, LimboTransactionsUnit, AltDBSvcLoginDlgUnit,
122     ShutdownDatabaseDlgUnit, ShutdownRegDlgUnit;
123    
124     resourcestring
125     sDBSweep = 'Database sweep started';
126     sSweepOK = 'Sweep successfully completed';
127    
128    
129     { TMainForm }
130    
131     procedure TMainForm.FormShow(Sender: TObject);
132     var i: integer;
133     begin
134     {Set IB Exceptions to only show text message - omit SQLCode and Engine Code}
135     FirebirdAPI.GetStatus.SetIBDataBaseErrorMessages([ShowIBMessage]);
136     RestoreDlg.IBRestoreService1.DatabaseName.Clear;
137     RestoreDlg.IBRestoreService1.DatabaseName.Add(GetTempDir + 'mytest.fdb');
138     FDBName := IBStatisticalService1.DatabaseName;
139     with IBServerProperties1 do
140     begin
141     while not Active do
142     begin
143     try
144     Active := true;
145     except
146     on E:EIBClientError do
147     begin
148     Close;
149     Exit
150     end;
151     On E:Exception do
152     MessageDlg(E.Message,mtError,[mbOK],0);
153     end;
154     end; {Loop until logged in or user cancels}
155    
156     {Display the server properties}
157     FetchVersionInfo;
158     Memo1.Lines.Add('Server Version = ' + VersionInfo.ServerVersion);
159     Memo1.Lines.Add('Server Implementation = ' + VersionInfo.ServerImplementation);
160     Memo1.Lines.Add('Service Version = ' + IntToStr(VersionInfo.ServiceVersion));
161     Memo1.Lines.Add(Format('Firebird Release = %d.%d.%d (Build no. %d)',[ServerVersionNo[1],
162     ServerVersionNo[2],
163     ServerVersionNo[3],
164     ServerVersionNo[4]]));
165     FetchDatabaseInfo;
166     Memo1.Lines.Add('No. of attachments = ' + IntToStr(DatabaseInfo.NoOfAttachments));
167     Memo1.Lines.Add('No. of databases = ' + IntToStr(DatabaseInfo.NoOfDatabases));
168     for i := 0 to DatabaseInfo.NoOfDatabases - 1 do
169     Memo1.Lines.Add('DB Name = ' + DatabaseInfo.DbName[i]);
170     FetchConfigParams;
171     Memo1.Lines.Add('Base Location = ' + ConfigParams.BaseLocation);
172     Memo1.Lines.Add('Lock File Location = ' + ConfigParams.LockFileLocation);
173     Memo1.Lines.Add('Security Database Location = ' + ConfigParams.SecurityDatabaseLocation);
174     Memo1.Lines.Add('Message File Location = ' + ConfigParams.MessageFileLocation);
175     for i := Low(ConfigParams.ConfigFileParams) to High(ConfigParams.ConfigFileParams) do
176     writeln(ConfigParams.ConfigFileParams[i]);
177     for i := Low(ConfigParams.ConfigFileData.ConfigFileKey) to High(ConfigParams.ConfigFileData.ConfigFileKey) do
178     writeln(ConfigParams.ConfigFileData.ConfigFileKey[i],' = ',ConfigParams.ConfigFileData.ConfigFileValue[i]);
179     end;
180     IBServerProperties1.OnLogin := @AltSecDBLogin;
181     {Leave IBServerProperties1 as active and use this as the common service interface}
182     end;
183    
184     {This is the initial logon to the default security database on the server}
185    
186     procedure TMainForm.IBServerProperties1Login(Service: TIBCustomService;
187     LoginParams: TStrings);
188     var aServiceName: string;
189     aUserName: string;
190     aPassword: string;
191     begin
192     aServiceName := Service.ServerName;
193     aUserName := LoginParams.Values['user_name'];
194     aPassword := '';
195     if SvcLoginDlg.ShowModal(aServiceName, aUserName, aPassword) = mrOK then
196     begin
197     Service.ServerName := aServiceName;
198     LoginParams.Values['user_name'] := aUserName;
199     LoginParams.Values['password'] := aPassword;
200     FServerUserName := aUserName;
201     FServerPassword := aPassword;
202     end
203     else
204     IBError(ibxeOperationCancelled, [nil]);
205     end;
206    
207     {This is the login dialog for a alt. security database}
208    
209     procedure TMainForm.AltSecDBLogin(Service: TIBCustomService;
210     LoginParams: TStrings);
211     var aServiceName: string;
212     aUserName: string;
213     aPassword: string;
214     begin
215     aServiceName := Service.ServerName;
216     aUserName := LoginParams.Values['user_name'];
217     aPassword := '';
218     if AltDBSvcLoginDlg.ShowModal(aServiceName, aUserName, aPassword) = mrOK then
219     begin
220     Service.ServerName := aServiceName;
221     LoginParams.Values['user_name'] := aUserName;
222     LoginParams.Values['password'] := aPassword;
223     end
224     else
225     IBError(ibxeOperationCancelled, [nil]);
226     end;
227    
228     procedure TMainForm.LimboTransactionsExecute(Sender: TObject);
229     var aDBName: string;
230     begin
231     aDBName := DBName;
232     with LimboTransactionsForm do
233     begin
234     if SelectDBDlg.ShowModal(aDBName) = mrOK then
235     begin
236     DBName := aDBName;
237     RunService(LimboTransactionValidation,@RunLimboTransactions);
238     end;
239     end;
240     end;
241    
242     procedure TMainForm.StatisticsExecute(Sender: TObject);
243     var aDBName: string;
244     begin
245     aDBName := DBName;
246     if SelectDBDlg.ShowModal(aDBName) = mrOK then
247     begin
248     DBName := aDBName;
249     IBStatisticalService1.Options := [DataPages];
250     RunService(IBStatisticalService1,@RunShowStatistics);
251     end;
252     end;
253    
254     procedure TMainForm.ValidateExecute(Sender: TObject);
255     var UseOnlineValidation: boolean;
256     aDBName: string;
257     begin
258     UseOnlineValidation := false;
259     aDBName := DBName;
260     if SelectValidationDlg.ShowModal(IBServerProperties1.ServerName,aDBName,UseOnlineValidation) = mrOK then
261     begin
262     DBName := aDBName;
263     if UseOnlineValidation then
264     FValidationService := IBOnlineValidationService1
265     else
266     begin
267     FValidationService := IBValidationService1;
268     IBValidationService1.Options := [ValidateFull];
269     end;
270     RunService(FValidationService,@RunValidation);
271     end;
272     end;
273    
274     procedure TMainForm.SetDBName(AValue: string);
275     begin
276     if FDBName = AValue then Exit;
277     UseServerLogin;
278     FDBName := AValue;
279     end;
280    
281     procedure TMainForm.UseServerLogin;
282     var index: integer;
283     begin
284     index := IBServerProperties1.Params.IndexOfName('expected_db');
285     if index <> -1 then
286     begin
287     {Log back in at Server Level}
288     IBServerProperties1.Active := false;
289     IBServerProperties1.LoginPrompt := false;
290     IBServerProperties1.Params.Values['user_name'] := FServerUserName;
291     IBServerProperties1.Params.Values['password'] := FServerPassword;
292     IBServerProperties1.Params.Delete(index);
293     IBServerProperties1.Active := true;
294     end;
295     end;
296    
297     {Common code for launching a service that might need to use and alt. security database}
298    
299     function TMainForm.RunService(aService: TIBCustomService; RunProc: TRunServiceProc
300     ): boolean;
301    
302     procedure AltDBLogin;
303     var index: integer;
304     begin
305     with IBServerProperties1 do
306     begin
307     Active := false;
308     LoginPrompt := true;
309     Params.Add('expected_db='+DBName);
310     index := Params.IndexOfName('password');
311     if index <> -1 then
312     Params.Delete(index);
313    
314     {Now make sure we are logged in}
315    
316     while not Active do
317     begin
318     try
319     Active := true;
320     except
321     on E:EIBClientError do
322     raise;
323     On E:Exception do
324     begin
325     MessageDlg(E.Message,mtError,[mbOK],0);
326     Active := false;
327     end;
328     end;
329     end; {Loop until logged in or user cancels}
330    
331     end;
332     end;
333    
334     begin
335     Result := false;
336     if aService is TIBValidationService then
337     TIBValidationService(aService).DatabaseName := DBName
338     else
339     if aService is TIBOnlineValidationService then
340     TIBOnlineValidationService(aService).DatabaseName := DBName
341     else
342     if aService is TIBStatisticalService then
343     TIBStatisticalService(aService).DatabaseName := DBName
344     else
345     if aService is TIBConfigService then
346     TIBConfigService(aService).DatabaseName := DBName;
347     try
348     repeat
349     with aService do
350     begin
351     Active := false;
352     Assign(IBServerProperties1);
353     end;
354     try
355     RunProc;
356     Result := true;
357     except
358     on E:EIBClientError do {Typically Login cancelled}
359     begin
360     MessageDlg(E.Message,mtError,[mbOK],0);
361     Exit;
362     end;
363     on E: EIBInterBaseError do
364     if E.IBErrorCode = isc_sec_context then {Need expected_db}
365     AltDBLogin
366     else
367     raise;
368     end;
369     aService.Active := false;
370     until Result;
371     except on E:Exception do
372     MessageDlg(E.Message,mtError,[mbOK],0);
373     end;
374     end;
375    
376     procedure TMainForm.RunShowStatistics;
377     begin
378     with IBStatisticalService1 do
379     begin
380     ServiceStart;
381     Memo1.Lines.Add('Database Statistics for ' + IBStatisticalService1.DatabaseName);
382     while not Eof do
383     begin
384     Memo1.Lines.Add(GetNextLine);
385     Application.ProcessMessages;
386     end;
387     end;
388     end;
389    
390     procedure TMainForm.RunValidation;
391     begin
392     with FValidationService do
393     begin
394     ServiceStart;
395     Memo1.Lines.Add('Running...');
396     while not Eof do
397     begin
398     Memo1.Lines.Add(GetNextLine);
399     Application.ProcessMessages;
400     end;
401     Memo1.Lines.Add('Validation Completed');
402     MessageDlg('Validation Completed',mtInformation,[mbOK],0);
403     end;
404     end;
405    
406     procedure TMainForm.RunLimboTransactions;
407     begin
408     with LimboTransactionsForm do
409     begin
410     {test access credentials}
411     LimboTransactionValidation.ServiceStart;
412     LimboTransactionValidation.FetchLimboTransactionInfo;
413     ShowModal;
414     end;
415     end;
416    
417     procedure TMainForm.RunSweep;
418     var ReportCount: integer;
419     begin
420     ReportCount := 0;
421     with IBValidationService1 do
422     begin
423     Memo1.Lines.Add(Format(sDBSweep,[DatabaseName]));
424     try
425     ServiceStart;
426     While not Eof do
427     begin
428     Inc(ReportCount);
429     Memo1.Lines.Add(GetNextLine);
430     Application.ProcessMessages;
431     end
432     finally
433     while IsServiceRunning do;
434     end
435     end;
436     Memo1.Lines.Add(sSweepOK);
437     end;
438    
439     function TMainForm.IsDatabaseOnline: boolean;
440     var Line: string;
441     begin
442     {Scan header page to see if database is online - assumes that service is already set up}
443     Result := true;
444     with IBStatisticalService1 do
445     begin
446     Assign(IBServerProperties1);
447     Options := [HeaderPages];
448     Active := True;
449     try
450     ServiceStart;
451     while not Eof do
452     begin
453     Line := GetNextLine;
454     if (Pos('Attributes',Line) <> 0) and ((Pos('database shutdown',Line) <> 0)
455     or (Pos('multi-user maintenance',Line) <> 0)) then
456     Result := false;
457    
458     end;
459     while IsServiceRunning do;
460     finally
461     Active := False;
462     end
463     end;
464     end;
465    
466     procedure TMainForm.RunBringOnline;
467     begin
468     if IsDatabaseOnline then
469     MessageDlg('Database is already online!',mtInformation,[mbOK],0)
470     else
471     begin
472     IBConfigService1.Assign(IBServerProperties1);
473     IBConfigService1.DatabaseName := DBName;
474     IBConfigService1.BringDatabaseOnline;
475     while IBConfigService1.IsServiceRunning do;
476     if IsDatabaseOnline then
477     MessageDlg('Database is back online',mtInformation,[mbOK],0)
478     else
479     MessageDlg('Database is still shutdown!',mtError,[mbOK],0);
480     end;
481     end;
482    
483     procedure TMainForm.RunShutdown;
484     begin
485     if not IsDatabaseOnline then
486     MessageDlg('Database is already shutdown!',mtInformation,[mbOK],0)
487     else
488     begin
489     ShutdownDatabaseDlg.IBConfigService.DatabaseName := DBName;
490     ShutdownDatabaseDlg.Shutdown(FShutDownMode,FDelay);
491     end;
492     end;
493    
494     procedure TMainForm.CLoseBtnClick(Sender: TObject);
495     begin
496     Close
497     end;
498    
499     procedure TMainForm.BringOnlineExecute(Sender: TObject);
500     var aDBName: string;
501     begin
502     aDBName := DBName;
503     if SelectDBDlg.ShowModal(aDBName) = mrOK then
504     begin
505     DBName := aDBName;
506     RunService(IBStatisticalService1,@RunBringOnline);
507     end;
508     end;
509    
510     procedure TMainForm.BringOnlineUpdate(Sender: TObject);
511     begin
512     (Sender as TAction).Enabled := not ShutdownDatabaseDlg.Aborting;
513     end;
514    
515     procedure TMainForm.BackupBtnClick(Sender: TObject);
516     begin
517     BackupDlg.IBBackupService1.ServerName := IBServerProperties1.ServerName;
518     BackupDlg.IBBackupService1.DatabaseName := DBName;
519     if BackupDlg.ShowModal = mrOK then
520     begin
521     DBName := BackupDlg.IBBackupService1.DatabaseName;
522     Runservice(BackupDlg.IBBackupService1,@BackupDlg.RunBackup);
523     end;
524     end;
525    
526     procedure TMainForm.RestoreBtnClick(Sender: TObject);
527     begin
528     RestoreDlg.IBRestoreService1.ServerName := IBServerProperties1.ServerName;
529     RestoreDlg.IBRestoreService1.DatabaseName[0] := DBName;
530     if RestoreDlg.ShowModal = mrOK then
531     begin
532     DBName := RestoreDlg.IBRestoreService1.DatabaseName[0];
533     UseServerLogin; {Avoid server hanging if we use an alt. sec. database wrongly}
534     RunService(RestoreDlg.IBRestoreService1,@RestoreDlg.RunRestore);
535     end;
536     end;
537    
538     procedure TMainForm.ServerLOgBtnClick(Sender: TObject);
539     begin
540     Memo1.Lines.Add('Server Log');
541     {No chance that we will need an alt. security database - so just assign it the
542     server connection}
543     IBLogService1.Assign(IBServerProperties1);
544     with IBLogService1 do
545     begin
546     ServiceStart;
547     while not Eof do
548     begin
549     Memo1.Lines.Add(GetNextLine);
550     Application.ProcessMessages;
551     end;
552     end;
553     end;
554    
555     procedure TMainForm.DatabaseBtnClick(Sender: TObject);
556     begin
557     PopupMenu1.PopUp(Mouse.CursorPos.X,Mouse.CursorPos.Y);
558     end;
559    
560     procedure TMainForm.ShutdownExecute(Sender: TObject);
561     var aDBName: string;
562     begin
563     aDBName := DBName;
564     FShutDownMode := DenyTransaction;
565     if ShutdownReqDlg.ShowModal(aDBName,FShutDownMode,FDelay) = mrOK then
566     begin
567     DBName := aDBName;
568     RunService(ShutdownDatabaseDlg.IBConfigService,@RunShutdown);
569     end;
570     end;
571    
572     procedure TMainForm.SweepExecute(Sender: TObject);
573     var aDBName: string;
574     begin
575     aDBName := DBName;
576     if SelectDBDlg.ShowModal(aDBName) = mrOK then
577     begin
578     DBName := aDBName;
579     IBValidationService1.Options := [SweepDB];
580     RunService(IBValidationService1,@RunSweep);
581     end;
582     end;
583    
584     procedure TMainForm.UsersBtnClick(Sender: TObject);
585     begin
586     UseServerLogin;
587     with ListUsersForm do
588     begin
589     {No chance that we will need an alt. security database - so just assign it the
590     server connection}
591     IBSecurityService1.Assign(IBServerProperties1);
592     ShowModal;
593     end;
594     end;
595    
596     end.
597