home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 October / PCWorld_2000-10_cd2.bin / Borland / interbase / IBConsole_src.ZIP / ibconsole / frmuDBTransactions.pas < prev    next >
Pascal/Delphi Source File  |  2000-07-24  |  15KB  |  461 lines

  1. {
  2.  * The contents of this file are subject to the InterBase Public License
  3.  * Version 1.0 (the "License"); you may not use this file except in
  4.  * compliance with the License.
  5.  * 
  6.  * You may obtain a copy of the License at http://www.Inprise.com/IPL.html.
  7.  * 
  8.  * Software distributed under the License is distributed on an "AS IS"
  9.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  10.  * the License for the specific language governing rights and limitations
  11.  * under the License.  The Original Code was created by Inprise
  12.  * Corporation and its predecessors.
  13.  * 
  14.  * Portions created by Inprise Corporation are Copyright (C) Inprise
  15.  * Corporation. All Rights Reserved.
  16.  * 
  17.  * Contributor(s): ______________________________________.
  18. }
  19.  
  20. {****************************************************************
  21. *
  22. *  f r m u D B T r a n s a c t i o n s
  23. *
  24. ****************************************************************
  25. *  Author: The Client Server Factory Inc.
  26. *  Date:   March 1, 1999
  27. *
  28. *  Description:  This unit provides an interface to view and
  29. *                recover (if possible) limbo transasctions.
  30. *
  31. *****************************************************************
  32. * Revisions:
  33. *
  34. *****************************************************************}
  35. unit frmuDBTransactions;
  36.  
  37. interface
  38.  
  39. uses
  40.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  41.   Dialogs, zluibcClasses, StdCtrls, ComCtrls, ExtCtrls, IBServices,
  42.   IB, ImgList, frmuDlgClass;
  43.  
  44. type
  45.   TfrmDBTransactions = class(TDialog)
  46.     edtPath: TEdit;
  47.     lblConnectPath: TLabel;
  48.     lblStatus: TLabel;
  49.     lvTransactions: TListView;
  50.     memAdvice: TMemo;
  51.     pgcMain: TPageControl;
  52.     tabAdvice: TTabSheet;
  53.     tabTransactions: TTabSheet;
  54.     stxDatabase: TStaticText;
  55.     lblDatabase: TLabel;
  56.     btnOK: TButton;
  57.     btnCancel: TButton;
  58.     rgOptions: TRadioGroup;
  59.     lblRepairStatus: TLabel;
  60.     procedure btnCancelClick(Sender: TObject);
  61.     procedure btnOKClick(Sender: TObject);
  62.     procedure lvTransactionsSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
  63.     procedure pgcMainChange(Sender: TObject);
  64.     procedure pgcMainChanging(Sender: TObject; var AllowChange: Boolean);
  65.     procedure rgOptionsClick(Sender: TObject);
  66.     procedure FormCreate(Sender: TObject);
  67.   private
  68.     { Private declarations }
  69.     FValidation : TIBValidationService;
  70.     FGlobalAction: TTransactionGlobalAction;
  71.     FCurrentRecord : Integer;
  72.     procedure GetLimboTransactions(const SourceServerNode : TibcServerNode; const CurrSelDatabase : TibcDatabaseNode);
  73.     procedure WMNCLButtonDown( var Message: TWMNCLBUTTONDOWN ); message WM_NCLBUTTONDOWN ;
  74.   public
  75.     { Public declarations }
  76.   end;
  77.  
  78. function DoDBTransactions(const SourceServerNode: TibcServerNode; const CurrSelDatabase: TibcDatabaseNode): integer;
  79.  
  80. implementation
  81.  
  82. uses
  83.   zluGlobal, zluUtility, zluContextHelp, frmuMessage, frmuMain, IBErrorCodes;
  84.  
  85. {$R *.DFM}
  86.  
  87. {****************************************************************
  88. *
  89. *  D o D B T r a n s a c t i o n s ( )
  90. *
  91. ****************************************************************
  92. *  Author: The Client Server Factory Inc.
  93. *  Date:   March 1, 1999
  94. *
  95. *  Input:  SourceServerNode - The currently selected server
  96. *          CurrSelDatabase  - The currently selected database
  97. *
  98. *  Return: Integer - Determines whether the operation was a
  99. *                    success or a failure
  100. *
  101. *  Description: This function checks for limbo transactions,
  102. *               if any exist the form is shown, otherwise
  103. *               a message is displayed and control is returned
  104. *               to the main
  105. *
  106. *****************************************************************
  107. * Revisions:
  108. *
  109. *****************************************************************}
  110. function DoDBTransactions(const SourceServerNode: TibcServerNode; const CurrSelDatabase: TibcDatabaseNode): integer;
  111. var
  112.   frmDBTransactions : TfrmDBTransactions;
  113. begin
  114.   frmDBTransactions := Nil;
  115.   try
  116.     frmDBTransactions := TfrmDBTransactions.Create(Application);
  117.  
  118.     Screen.Cursor := crHourGlass;
  119.     frmDBTransactions.stxDatabase.Caption:=CurrSelDatabase.NodeName;
  120.     // get a list of limbo transactions
  121.     frmDBTransactions.GetLimboTransactions(SourceServerNode, CurrSelDatabase);
  122.  
  123.     // if the record count is not 0 then there are limbo transactions
  124.     if frmDBTransactions.FCurrentRecord <> 0 then
  125.       frmDBTransactions.ShowModal     // show the form as a modal dialog box
  126.     else                               // if there were no limbo transactions
  127.     begin                              // then display message
  128.       DisplayMsg(INF_NO_PENDING_TRANSACTIONS, '');
  129.       Result := FAILURE;
  130.       Exit;
  131.     end;
  132.  
  133.     if (frmDBTransactions.ModalResult = mrOK) and
  134.        (not frmDBTransactions.GetErrorState) then
  135.       result:=SUCCESS
  136.     else
  137.       result:=FAILURE;
  138.   finally
  139.     // deallocate memory
  140.     frmDBTransactions.Free;
  141.     Screen.Cursor := crDefault;
  142.   end;
  143. end;
  144.  
  145. procedure TfrmDBTransactions.btnCancelClick(Sender: TObject);
  146. begin
  147.   ModalResult := mrCancel;
  148. end;
  149.  
  150. {****************************************************************
  151. *
  152. *  G e t L i m b o T r a n s a c t i o n s
  153. *
  154. ****************************************************************
  155. *  Author: The Client Server Factory Inc.
  156. *  Date:   March 1, 1999
  157. *
  158. *  Input:  SourceServerNode - The currently selected server
  159. *          CurrSelDatabase  - The currently selected database
  160. *
  161. *  Return: None
  162. *
  163. *  Description: This procedure populates the listview with
  164. *               a list of limbo transactions and they're IDs.
  165. *
  166. *****************************************************************
  167. * Revisions:
  168. *
  169. *****************************************************************}
  170. procedure TfrmDBTransactions.GetLimboTransactions(const SourceServerNode : TibcServerNode; const CurrSelDatabase : TibcDatabaseNode);
  171. var
  172.   lListItem : TListItem;
  173. begin
  174.   FValidation := nil;
  175.   try
  176.     // create validation service object
  177.     FValidation := TIBValidationService.Create(nil);
  178.     try
  179.       // assign server details
  180.       FValidation.LoginPrompt := false;
  181.       FValidation.ServerName := SourceServerNode.Server.ServerName;
  182.       FValidation.Protocol := SourceServerNode.Server.Protocol;
  183.       FValidation.Params.Clear;
  184.       FValidation.Params.Assign(SourceServerNode.Server.Params);
  185.       // assign database details
  186.       case SourceServerNode.Server.Protocol of
  187.         TCP : FValidation.DatabaseName := Format('%s:%s',[SourceServerNode.ServerName,CurrSelDatabase.DatabaseFiles.Strings[0]]);
  188.         NamedPipe : FValidation.DatabaseName := Format('\\%s\%s',[SourceServerNode.ServerName,CurrSelDatabase.DatabaseFiles.Strings[0]]);
  189.         SPX : FValidation.DatabaseName := Format('%s@%s',[SourceServerNode.ServerName,CurrSelDatabase.DatabaseFiles.Strings[0]]);
  190.         Local : FValidation.DatabaseName := CurrSelDatabase.DatabaseFiles.Strings[0];
  191.       end;
  192.       // attach to server and start service
  193.       FValidation.Options := [LimboTransactions];
  194.       FValidation.Attach();
  195.       FValidation.ServiceStart;
  196.     except
  197.       on E: EIBError do
  198.       begin
  199.         DisplayMsg(E.IBErrorCode, E.Message);
  200.         if (E.IBErrorCode = isc_lost_db_connection) or
  201.            (E.IBErrorCode = isc_unavailable) or
  202.            (E.IBErrorCode = isc_network_error) then
  203.           frmMain.SetErrorState;
  204.         SetErrorState;
  205.         Exit;
  206.       end;
  207.     end;
  208.  
  209.     // get limbo transactions and populate LimboTransactionsInfo array
  210.     FValidation.FetchLimboTransactionInfo;
  211.  
  212.     while (FValidation.IsServiceRunning) and (not gApplShutdown) do
  213.     begin
  214.       Application.ProcessMessages;
  215.     end;
  216.  
  217.     if FValidation.Active then
  218.       FValidation.Detach();
  219.  
  220.     // get number of records and populate listview
  221.     FCurrentRecord := 0;
  222.     while FValidation.LimboTransactionInfo[FCurrentRecord].ID > 0 do
  223.     begin
  224.       lListItem := lvTransactions.Items.Add;
  225.  
  226.       if FValidation.LimboTransactionInfo[FCurrentRecord].MultiDatabase then
  227.         lListItem.Caption := 'Multi-Database Transaction'
  228.       else
  229.         lListItem.Caption := 'Transaction';
  230.  
  231.       lListItem.SubItems.Add(IntToStr(FValidation.LimboTransactionInfo[FCurrentRecord].ID));
  232.       case FValidation.LimboTransactionInfo[FCurrentRecord].Advise of
  233.         CommitAdvise   : lListItem.SubItems.Add('Commit');
  234.         RollBackAdvise : lListItem.SubItems.Add('Rollback');
  235.         UnknownAdvise  : lListItem.SubItems.Add('Unknown');
  236.       end;
  237.       lListItem.SubItems.Add('In Limbo');
  238.  
  239.       Inc(FCurrentRecord);
  240.     end;
  241.   finally
  242.     // FValidation.Free;
  243.   end;
  244. end;
  245.  
  246. {****************************************************************
  247. *
  248. *  p g c M a i n C h a n g e
  249. *
  250. ****************************************************************
  251. *  Author: The Client Server Factory Inc.
  252. *  Date:   March 1, 1999
  253. *
  254. *  Input:  Sender - The object that initiated the event
  255. *
  256. *  Return: None
  257. *
  258. *  Description: This procedure shows details about the
  259. *               currently selected transaction if the Advice
  260. *               tab is selected
  261. *
  262. *****************************************************************
  263. * Revisions:
  264. *
  265. *****************************************************************}
  266. procedure TfrmDBTransactions.pgcMainChange(Sender: TObject);
  267. var
  268.   i         : Integer;
  269.   lListItem : TListItem;
  270.   lStr      : String;
  271. begin
  272.   // determine which page is active
  273.   lListItem := lvTransactions.Selected;
  274.   if pgcMain.ActivePage = tabAdvice then
  275.   begin
  276.     // find transaction record
  277.     i := 0;
  278.     while (FValidation.LimboTransactionInfo[i].ID <> 0) and (FValidation.LimboTransactionInfo[i].ID <> StrToInt(lListItem.SubItems[0]))  do
  279.       Inc(i);
  280.  
  281.     // make it the current record
  282.     FCurrentRecord := i;
  283.  
  284.     // if there an item is currently selected in the list
  285.     if (lListItem <> Nil) and (lListItem.Caption <> '') then
  286.     begin
  287.       // populate memo
  288.       with memAdvice.Lines do
  289.       begin
  290.         Clear;
  291.         Add(lListItem.Caption);
  292.         Add(Format('  Host Site: %s', [FValidation.LimboTransactionInfo[i].HostSite]));
  293.  
  294.         case FValidation.LimboTransactionInfo[i].State of
  295.           LimboState    : lStr := 'is in limbo';
  296.           CommitState   : lStr := 'has been committed';
  297.           RollBackState : lStr := 'has been rolled back';
  298.           UnknownState  : lStr := 'is in an unknown state';
  299.         end;
  300.         Add(Format('  Transaction %d %s.', [FValidation.LimboTransactionInfo[i].ID, lStr]));
  301.  
  302.         Add(Format('  Remote Site: %s', [FValidation.LimboTransactionInfo[i].RemoteSite]));
  303.         Add(Format('  Database Path: %s', [FValidation.LimboTransactionInfo[i].RemoteDatabasePath]));
  304.  
  305.         Add('');
  306.  
  307.         case FValidation.LimboTransactionInfo[i].Advise of
  308.           CommitAdvise   : lStr := 'Commit';
  309.           RollBackAdvise : lStr := 'Rollback';
  310.           UnknownAdvise  : lStr := 'Unknown';
  311.         end;
  312.  
  313.         Add(Format('Recommended Action: %s', [lStr]));
  314.  
  315.       end;
  316.     end
  317.     else
  318.     begin
  319.       // show message in memo if no item is selected
  320.       memAdvice.Lines.Clear;
  321.       memAdvice.Lines.Add('Please select an item from the Transactions tab.');
  322.     end;
  323.   end
  324.   else
  325.   begin
  326.     // give the listview control focus
  327.     lvTransactions.SetFocus;
  328.   end;
  329. end;
  330.  
  331. procedure TfrmDBTransactions.lvTransactionsSelectItem(Sender: TObject; Item: TListItem; Selected: Boolean);
  332. var
  333.   i : Integer;
  334. begin
  335.   // find currently selected record
  336.   i := 0;
  337.   while (FValidation.LimboTransactionInfo[i].ID <> StrToInt(Item.SubItems[0])) and (FValidation.LimboTransactionInfo[i].ID <> 0) do
  338.     Inc(i);
  339.  
  340.   FCurrentRecord := i;
  341.  
  342.   // show its database path
  343.   edtPath.Text := FValidation.LimboTransactionInfo[i].RemoteDatabasePath;
  344. end;
  345.  
  346. {****************************************************************
  347. *
  348. *  b t n O K C l i c k
  349. *
  350. ****************************************************************
  351. *  Author: The Client Server Factory Inc.
  352. *  Date:   March 1, 1999
  353. *
  354. *  Input:  Sender - The object that initiated the event
  355. *
  356. *  Return: None
  357. *
  358. *  Description: This procedure will try to fix any limbo
  359. *               transactions.
  360. *
  361. *****************************************************************
  362. * Revisions:
  363. *
  364. *****************************************************************}
  365. procedure TfrmDBTransactions.btnOKClick(Sender: TObject);
  366. var
  367.   lCnt: integer;
  368. begin
  369.   try
  370.     FValidation.GlobalAction := FGlobalAction;
  371.     Screen.Cursor := crHourGlass;
  372.     { Fix:  Service only allows 1 transaction to be fixed at a time }
  373.     for lCnt := 0 to lvTransactions.Items.Count-1 do
  374.     begin
  375.       Application.ProcessMessages;    
  376.       lblRepairStatus.Caption := Format('Repairing transaction %s',[lvTransactions.Items[lCnt].Subitems[0]]);
  377.       lblRepairStatus.Visible := true;
  378.       FValidation.Attach;
  379.       FValidation.FixLimboTransactionErrors;
  380.       while FValidation.IsServiceRunning do
  381.         Application.ProcessMessages;
  382.       lvTransactions.Items[lCnt].SubItems[2] := 'Fixed';        
  383.       FValidation.Detach;
  384.       FValidation.Attach;
  385.       FValidation.ServiceStart;
  386.       Application.ProcessMessages;      
  387.       FValidation.FetchLimboTransactionInfo;
  388.       while FValidation.IsServiceRunning do
  389.         Application.ProcessMessages;
  390.       FValidation.Detach;      
  391.     end;
  392.   except
  393.     on E:EIBError do
  394.     begin
  395.       DisplayMsg(E.IBErrorCode, E.Message);
  396.       if (E.IBErrorCode = isc_lost_db_connection) or
  397.          (E.IBErrorCode = isc_unavailable) or
  398.          (E.IBErrorCode = isc_network_error) then
  399.       begin
  400.         frmMain.SetErrorState;
  401.         SetErrorState;
  402.       end
  403.       else
  404.       if Fvalidation.Active then
  405.         FValidation.Detach;
  406.     end;
  407.   end;
  408.   ModalResult := mrOK;
  409.   Screen.Cursor := crDefault;
  410.   if Fvalidation.Active then
  411.     FValidation.Detach;
  412.   MessageDlg ('Limbo transaction recovery completed.', mtInformation, [mbOK], 0);
  413. end;
  414.  
  415. procedure TfrmDBTransactions.WMNCLButtonDown( var Message: TWMNCLButtonDown );
  416. var
  417.   ScreenPt: TPoint;
  418.   ClientPt: TPoint;
  419. begin
  420.   ScreenPt.X := Message.XCursor;
  421.   ScreenPt.Y := Message.YCursor;
  422.   ClientPt := ScreenToClient( ScreenPt );
  423.   if( ClientPt.X > Width-45 )and (ClientPt.X < Width-29) then
  424.    begin
  425.     WinHelp(WindowHandle,CONTEXT_HELP_FILE,HELP_CONTEXT,TRANSACTIONS_RECOVERY);
  426.     Message.Result := 0;
  427.   end else
  428.    inherited;
  429. end;
  430.  
  431. procedure TfrmDBTransactions.pgcMainChanging(Sender: TObject;
  432.   var AllowChange: Boolean);
  433. begin
  434.   inherited;
  435.   if not Assigned(lvTransactions.Selected) then
  436.   begin
  437.     ShowMessage('Select a transaction for information about that transaction.');
  438.     AllowChange := false;
  439.   end;
  440.  
  441. end;
  442.  
  443. procedure TfrmDBTransactions.rgOptionsClick(Sender: TObject);
  444. begin
  445.   inherited;
  446.   case rgOptions.ItemIndex of
  447.     0: FGlobalAction := NoGlobalAction;
  448.     1: FGlobalAction := CommitGlobal;
  449.     2: FGlobalAction := RollbackGlobal;
  450.     3: FGlobalAction := RecoverTwoPhaseGlobal;
  451.   end;
  452. end;
  453.  
  454. procedure TfrmDBTransactions.FormCreate(Sender: TObject);
  455. begin
  456.   inherited;
  457.   FGlobalAction := NoGlobalAction;
  458. end;
  459.  
  460. end.
  461.