[DB2] – Cos’è un DBRM, un Plan, ed un Package ?

10 October 2008 4 comments

Quando si sviluppa un Programma COBOLII ( ambiente MainframeMVS ) che accede al Data Base DB2, si devono effettuare una serie di funzioni che non sono necessarie quando un Programma utilizza solo files di tipo VSAM.

Queste funzioni sono eseguite, in maniera semplificata, attraverso il DB2 Interface – ( DB2I ).

Il DB2I è una serie di pannelli ISPF che consentono la “preparazione” dei programmi COBOL – DB2.

Passi per lo sviluppo di un programma COBOLDB2

1. La Precompilazione DB2

Un programma contenente statements SQL deve essere preventivamente analizzato e modificato prima che possa essere compilato. Il Precompilatore DB2 esegue queste funzioni, ed in particolare :

  • – ricerca ed espande i membri realtivi alle INCLUDE
  • – ricerca gli statements EXEC SQL …. END-EXEC
  • – crea una versione del sorgente modificata, in cui ogni statement SQL è commentato e viene  sostituito da un’istruzione CALL ai moduli di interfaccia di runtime del DB2
  • – estrae tutte le istruzioni SQL dal programma e le inserisce in un modulo chiamato DBRM – (Data Base Request Module)
  • – pone un ‘timestamp’ nel sorgente modificato e nel DBRM affinchè ci sia una “corrispondenza esatta” tra i due
  • – riporta gli esiti della precompilazione (eventuali errori, etc…)

Dopo che la fase di precompilazione è terminata, inizia quella della compilazione. Il compilatore COBOL compila il programma sorgente modificato (dal precompilatore) e produce un modulo oggetto.

Il Linkage Editor “links” (collega) il modulo oggetto (object module) con altri moduli richiesti includendo tutti i moduli necessari per l’interfaccia al DB2; questo produrrà un modulo caricabile (load module) …

… ma prima che il programma possa essere eseguito,  il DB2 deve eseguire la fase di BIND !

 

2. La fase di BIND

Il comando BIND è un tipo di “compilazione” delle istruzioni SQL.

In generale, il comando BIND legge gli statements SQL dai DBRMs e produce un meccanismo per accedere ai dati come indicato dagli statements SQL.

Ci sono due tipi di comandi BIND :

     – BIND PLAN e

     – BIND PACKAGE

 

2.1  Il comando BIND PLAN

Il comando BIND PLAN accetta in INPUT :

  • Uno o più DBRMs prodotti dalla precompilazione
  • Uno o più PACKAGEs prodotti da una precedente BIND PACKAGE
  • … oppure una combinazione di liste di DBRMs e PACKAGEs

 

L’OUTPUT del comando BIND PLAN è un PIANO APPLICATIVO contenente la rappresentazione della logica eseguibile degli accessi ottimizzati ai dati del DB2.

Un PLAN (PIANO APPLICATIVO) è eseguibile solo con un modulo caricabile (load module) corrispondente !

Prima di eseguire un Programma COBOL-DB2, si deve specificare il PLAN corispondente.

 

 

2.2  Il comando BIND PACKAGE

Il comando BIND PACKAGE accetta in INPUT :

  • Un solo DBRM e produce (OUTPUT) un singolo PACKAGE contenente la logica ottimizzata di accesso ai dati.

Successivamente, i PACKAGEs prodotti devono essere collegati in un PLAN (PIANO APPLICATIVO) con il comando BIND PLAN.

Un PACKAGE non è eseguibile e non può essere specificato quando si esegue il programma DB2!

dobbiamo sempre ottenere prima un PLAN (PIANO APPLICATIVO) !

 

Il processo di BIND

La fase di BIND esegue una serie di funzioni per creare i PACKAGEs o i PLANs che accedono ai dati DB2 richiesti, tra cui :

  • – lettura e controllo della sintassi SQL dai DBRMs
  • – controllo delle TABELLE DB2 e delle COLONNE a cui si accede se conformi a quelle presenti nel CATALOGO DB2
  • – validazione delle AUTORIZZAZIONI
  • – ottimizzazione degli statements SQL in “paths” (cammini) più efficienti (DB2 optimizer)

 

 

Al termine di queste due fasi (precompilazione DB2 / compilazione COBOL e BIND) , sono stati prodotti due COMPONENTI (separati)

  • Il PLAN DB2
  • … ed il modulo caricabile linkato (load module); il nostro programma eseguibile 🙂

… ma nessuno dei due è eseguibile senza l’altro!

Quando si esegue un programma contenente istruzioni SQL si deve specificare il PLAN che verrà utilizzato.

 

 

Cos’è un DBRM ?

Spesso si fa confusione con la definizione di DBRM e le sue relazioni ai programmi, plans e packages.

Un DBRM è un modulo contenente gli statements SQL estratti dal programma sorgente ( dal precompilatore ).

Esso è memorizzato come membro di un data set partizionato; non è memorizzato nel Catalogo DB2.

 

Cos’è un PLAN ?

Un PLAN è un modulo eseguibile contenete la logica dei ‘paths’ di accesso (ai dati), prodotti dal DB2 Optimizer.

Esso può essere composto da uno o più DBRMs o PACKAGEs.

 

Cos’è un PACKAGE ?

Un PACKAGE è il prodotto del comando BIND su di un singlo DBRM contenete i ‘paths’ ottimizzati di accesso ai dati (dalla v2.3 del DB2).

Per eseguire un PACKAGE, bisogna prima inserirlo nella lista dei PACKAGEs di un PLAN.

Un PACKAGE non è mai eseguito direttamente, esso è eseguito indirettamente quando verrà eseguito il PLAN che lo contiene.

Un PLAN può consistere di uno o più DBRMs, uno o più PACKAGEs, o combinazioni di DBRMs e PACKAGEs.

 

Ma qual’è la differenza tra un PLAN ed un PACKAGE ?

Prima di andare al supermercato,  in genere,  prepariamo la LISTA dei PRODOTTI da acquistare.

Una volta li, come troviamo un prodotto presente nella nostra LISTA, lo mettiamo nel carrello; arrivati alla cassa, paghiamo 😦 ed inseriamo tutti PRODOTTI acquistati in una BUSTA.

  • I PRODOTTI acquistati, sono i DBRMs
  • … e la BUSTA, è il PLAN (PIANO APPLICATIVO)

Ci possono essere più DBRMs in un PLAN (ci sono più PRODOTTI acquistati nella BUSTA).

… abbiamo effettuato una fase di BIND PLAN indicando come INPUT uno o più DBRMs.

Se invece di prendere i PRODOTTI dallo scaffale e metterli nel carrello segniamo la loro ubicazione sulla nostra LISTA, una volta alla cassa, possiamo consegnare la LISTA al cassiere per il conteggio.

Dopo il conteggio ed il pagamento :(, inseriamo la LISTA dei PRODOTTI acquistati con le relative ubicazioni nella BUSTA, … e non i PRODOTTI !

Il PLAN (la BUSTA) ora contiene la LISTA che fa riferimento alla posizione fisica dei PRODOTTI sugli scaffali.

  • La LISTA dei PRODOTTI con le relative ubicazioni, è la lista dei PACKAGEs

… abbiamo prima effettuato le fasi di BIND PACKAGE indicando in INPUT i DBRMs (ubicazione dei prodotti), e poi la fase di BIND PLAN indicando in INPUT la LISTA dei PACKAGEs. 

 

… dedicato a tutti quei giovani che ancora oggi sono “reclutati” nel mondo dei mainframe.

“Una nuova vita vi attende nelle colonie Extra-Mondo. L’occasione per ricominciare in un Eldorado di buone  occasioni e di avventure, un nuovo clima, divertimenti ricreativi…”
                                              ( Annuncio pubblicitario dall’alto, dal film Blade Runner – Ridley Scott 1982 )

Advertisements
Categories: DB2 - SQL

[DELPHI] – Impostare e ripristinare la risoluzione del Video

8 October 2008 Comments off

L’esempio di seguito mostra come impostare e ripristinare la risoluzione video richiamando l’API di Windows : ChangeDisplaySettings().


unit USetVideo;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    B_SET: TBitBtn;
    B_RESET: TBitBtn;

    procedure B_SETClick(Sender: TObject);
    procedure B_RESETClick(Sender: TObject);

    function  ImpostaRisoluzioneVideo(pWidth:Integer; pHeight:Integer): Integer;

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1 : TForm1;

  // ... Variabili globali contenenti i valori della risoluzione
  //     del video prima della nuova impostazione
  OldWidth  : Integer;
  OldHeight : Integer;

implementation
{$R *.DFM}
// .........................................................................
//   PROCEDURE : B_SETClick()
//               CLICK SUL BOTTONE : B_SET
// .........................................................................
procedure TForm1.B_SETClick(Sender: TObject);
begin
    // ... salva la risoluzione del Video Corrente
    OldWidth    := GetSystemMetrics(SM_CXSCREEN);
    OldHeight   := GetSystemMetrics(SM_CYSCREEN);

    // ... imposta la risoluzione Video ( es.: 1024 x 768 )
    ImpostaRisoluzioneVideo(1024, 768);
end;
// .........................................................................

// .........................................................................
//   FUNCTION : ImpostaRisoluzioneVideo()
//              IMPOSTAZIONE DELLA RISOLUZIONE VIDEO
// .........................................................................
function TForm1.ImpostaRisoluzioneVideo(pWidth, pHeight:Integer):Integer;
var
    DeviceMode: TDeviceMode;
begin

    // ... imposta i parametri della struttura TDeviceMode
    DeviceMode.dmSize       := SizeOf(TDeviceMode);
    DeviceMode.dmPelsWidth  := pWidth;
    DeviceMode.dmPelsHeight := pHeight;
    DeviceMode.dmFields     := DM_PELSWIDTH or DM_PELSHEIGHT;

    // ... richiama l'API di Windows per il set della risoluzione.
    //     Il secondo parametro rappresenta il Flag per il set.
    //
    //     Valori :
    //
    //    0                   = La risoluzione e' cambiata dinamicamente
    //    CDS_UPDATEREGISTRY  = La risoluzione e' cambiata dinamicamente e
    //                          sara' aggiornata nel registro
    //                          La modalita' e' memorizzata nel profilo
    //                          utente
    //    CDS_TEST            = Il sistema verifica se e' possibile impostare
    //                          la risoluzione (effettua un TEST)

    // ... per maggiori dettagli vedere l'SDK di Windows.

    Result := ChangeDisplaySettings(DeviceMode, CDS_UPDATEREGISTRY);

    //  ... possibili valori di ritorno :
    //
    //  DISP_CHANGE_SUCCESSFUL	= Impostazione effettuata con successo.
    //  DISP_CHANGE_RESTART	    = Il Sistema deve essere riavviato affinche'
    //                            l'impostazione abbia effetto.
    //  DISP_CHANGE_BADFLAGS	= Valore dei Flags passati errati.
    //  DISP_CHANGE_FAILED	    = Errore durante l'impostazione della
    //                            risoluzione.
    //  DISP_CHANGE_BADMODE	    = Risoluzione Video non supportata.
    //  DISP_CHANGE_NOTUPDATED  = Windows NT solo : non in grado di scrivere
    //                            nel registro.
end;
// .........................................................................

// .........................................................................
//   PROCEDURE : B_RESETClick()
//               CLICK SUL BOTTONE : B_RESET
// .........................................................................
procedure TForm1.B_RESETClick(Sender: TObject);
begin
    // ... Ripristina la risoluzione video con i valori salvati
    ImpostaRisoluzioneVideo(OldWidth, OldHeight);
end;
// .........................................................................

// ... END OF JOB

end.

Categories: EMBARCADERO - DELPHI

[AS3] – Analizzatore di Spettro Audio (Parte I)

26 September 2008 2 comments

 
Questo esempio mostra come realizzare un semplice Analizzatore di Spettro Audio con effetti di sfocatura ( Classe : BlurFilter ), trasformazione del colore ( Classe : ColorMatrixFilter ), ed “avanzamento” della curva.

 

… click sull’immagine

… il codice

// .......................................................
// PROGRAM-ID.    SOUND010.fla
//
// AUTHOR.        silver peacock.
// DATE-WRITTEN.  10/06/2008
// DATE-COMPILED. 25/09/2009
//
// REMARKS.       Analizzatore di Spettro Audio.
//                Questo esempio mostra come acquisire i
//                valori della forma d'onda di un audio in
//                riproduzione con il metodo statico
//                computeSpectrum() della classe SoundMixer
//                e disegnare un grafico corrispondente in
//                un oggetto BitMapData con effetti di
//                sfocatura (BlurFilter) e trasformazione
//                del colore (ColorMatrixFilter).
// .......................................................

import flash.media.Sound;
import flash.utils.ByteArray;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.filters.BlurFilter;
import flash.filters.ColorMatrixFilter;

// ... dichiarazione variabili globali :
var audio       :Sound;
var byteArray   :ByteArray;

var bitMapData  :BitmapData;
var bitMap      :Bitmap;

var curva       :Sprite;
var filtro      :BlurFilter;
var mtxColori   :ColorMatrixFilter;

var box         :Sprite;

var x_0         :Number;
var y_0         :Number;
var xx          :Number;
var yy          :Number;
var coef_x      :uint;
var coef_y      :uint;

// ... crea gli oggetti :

// ... l'oggetto Sound
audio    = new Sound(new URLRequest("Heartbreaker.mp3"));

// ... l'oggetto ByteArray che sara' passato come
//     argomento al metodo statico computeSpectrum()
//     della Classe SounMixer che lo valorizzerà con 512
//     valori a virgola mobile, di cui i primi 256 valori
//     rappresentano il canale sinistro e gli altri 256
//     valori il canale destro.
//
// ... nota : i valori caricati nel ByteArray sono
//     "normalizzati" e compresi tra : -1.0 a +1.0
//     ( vedere la guida in linea )
byteArray   = new ByteArray();

// ... l'oggetto BitmapData (lo sfondo) su cui disegnare
// ... al metodo costruttore sono passati come argomenti :
//     larghezza, altezza, trasparenza e colore.
bitMapData = new BitmapData(400, 200, true, 0x00000000);

// ... la BitMap relativa
bitMap     = new Bitmap(bitMapData);

// ... l'oggetto Sprite
curva      = new Sprite();

// ... l'ggetto BlurFilter per creare l'effetto sfocatura.
// ... al costruttore sono passati come argomenti :
//     quantita' di sfocatura orizzontale, quantita' di
//     di sfocatura verticale e numero di operazioni di
//     sfocatura da ripetere (qualita' della sfocatura)
filtro     = new BlurFilter(2, 2, BitmapFilterQuality.LOW);

// ... l'oggetto ColorMatrixFilter per creare l'effetto di
//     trasformazione dei Colori.
// ... al costruttore viene passato un'Array di 20
//     elementi (una matrice 4x5) corrispondenti ai valori
//     per la trasformazione del colore ed alpha (RGBA)
mtxColori  = new ColorMatrixFilter([1,0,0,0,0,
					  				0,1,0,0,0,
									0,0,2,0,0,
									0,0,0,0.98,0]);

// ... crea un oggetto contenitore della BitMap
box        = new Sprite();
box.graphics.clear();
box.graphics.beginFill(0x666666, 1);
box.graphics.drawRect(0, 0, bitMap.width, bitMap.height);
box.graphics.endFill();

// ... imposta le posizioni iniziali del grafico
x_0    = 0;
y_0    = (bitMap.height/2);

// ... imposta i coefficienti moltiplicativi per ottenere
//     le coordinate x ed y a partire dai valori della
//     forma d'onda presenti nel ByteArray (-1.0 e + 1.0)
coef_x = 20;
coef_y = 80;

// ... aggiungi la BitMap al box (contenitore)
box.addChild(bitMap);

// ... aggiungta la cura al box
box.addChild(curva);

// ... posiziona ed aggiungi il box allo Stage
box.x   =  -1;
box.y   = 100;

addChild(box);

// ... aggiungi l'ascoltatore evento : ENTER_FRAME
// ... la funzione sara' richiamata ad ogni riproduzione
//     del frame (fps)
addEventListener(Event.ENTER_FRAME, disegnaAnalizzatore);

// ... ok, avvia il sound!
audio.play(0, 1);

// ...

// .......................................................
//  FUNCTION : disegnaAnalizzatore()
//             acquisizione dei dati realtivi alla forma
//             d'onda e disegno della curva
// .......................................................
function disegnaAnalizzatore(evento:Event):void
{
    // ... pulisci il graphics prima di ridisegnare
    curva.graphics.clear();

    // ... imposta lo stile (spessore e colore)
    curva.graphics.lineStyle(1, 0x99CCFF);

	// ... posiziona la penna
	curva.graphics.moveTo(x_0, y_0);

	// ... carica la forma d'onda del sound nel ByteArray
	SoundMixer.computeSpectrum(byteArray);

	// ... ciclo sugli elementi del ByteArray
	for(var i:uint = 0; i  (bitMap.width-2))
		{
			xx = (bitMap.width-1);
			yy = (bitMap.height/2);
		}

		if (xx == 0)
		{
			yy = (bitMap.height/2);
		}

		// ... calcola la coordinata y :
		//     leggi il valore dal byteArray e moltiplica
		//     per il coefficiente della y.
		// ... nota : i valori presenti nel byteArray sono
		//            compresi tra -1.0 e +1.0
		yy = y_0 + ( byteArray.readFloat() * coef_y );

		// ... traccia la linea fino a
		curva.graphics.lineTo(xx, yy);
	}

	// ... disegna la curva nella bitmap
	bitMapData.draw(curva);

	// ... applica il filtro di sfocatura
	bitMapData.applyFilter(bitMapData, bitMapData.rect,
						   new Point(), filtro);

	// ... applica la matrice di trasfomazione dei
	//     colori
	bitMapData.applyFilter(bitMapData, bitMapData.rect,
						   new Point(), mtxColori);

	// ... scroll della bitmapData, per dare l'effetto
	//     di avanzamento (e' lo sfondo che si sposta)
	//     (+ verso destra, - verso sinistra)
	bitMapData.scroll(3,0);
}
// .......................................................

// ... END OF PROGRAM

Categories: ACTIONSCRIPT 3.0

[DELPHI] – Start e Stop del MySQL Server da un’applicazione Delphi su Pendrive

15 September 2008 1 comment

Scenario…

Abbiamo un’applicazione Delphi (desktop) con Data Base MySQL. Vogliamo che l’applicazione possa essere avviata da una pendrive e che i dati (le Tabelle) siano anch’essi memorizzati su pendrive. Ma vogliamo anche che lo stesso MySQL Server sia sulla pendrive e che la nostra applicazione lo avvii alla partenza e lo arresti all’uscita.

… in poche parole vogliamo che tutto (La nostra applicazione, le Tabelle del DataBase  e l’engine del MySQL Server) sia presente sulla pendrive … e che l’utilizzatore della nostra applicazione non debba installare alcun software sul proprio computer! 

 

 Il MySQL Server sulla Pendrive.

Prepariamo l’ambiente sulla pendrive :

1. Creamo un directory nella pendrive (es. \contab) in cui copieremo la nostra applicazione Delphi, l’eseguibile (es. coge.exe)

2. Nella stessa direcotory ( \contab ), copiamo l’intera cartella ( \mysql ) con tutte le sue sottocarelle : \bin, \data, \share e \Docs (possiamo anche, se preferiamo, rinominarla)

3. Nel file di configurazione del MySQL (my.ini), modifichiamo i percorsi assegnati a basedir e datadir

File di Configurazione del MySQL :  my.ini (presente nella cartella \mysql)

...
# CLIENT SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by MySQL client applications.
# Note that only client applications shipped by MySQL are guaranteed
# to read this section. If you want your own MySQL client program to
# honor these values, you need to specify it as an option during the
# MySQL client library initialization.
#
[client]

port=3306

default-character-set=latin1

# SERVER SECTION
# ----------------------------------------------------------------------
#
# The following options will be read by the MySQL Server. Make sure that
# you have installed the server correctly (see above) so it reads this
# file.
#
[mysqld]

# The TCP/IP Port the MySQL Server will listen on
port=3306

#Path to installation directory. All paths are usually resolved relative to this.
basedir="\mysql\"

#Path to the database root
datadir="\mysql\data\"
...

Le Funzioni per lo Start e Stop del MySQL Sever.

Di seguito sono riportate le quattro funzioni per la gestione dell’avvio e l’arresto del MySQL Server.
Le funzioni SP_MySQLStart() e SP_MySQLStop() effettuano rispettivamente l’avvio e l’arresto del MySQL Server, la funzione SP_ExecProcess() avvia un processo richiamando a sua volta l’API di Windows CreateProcess(), ed infine la funzione SP_CheckProcess() controlla se un processo è in esecuzione o meno.

… le funzioni sono state raccolte in una unit : MySQLServer_Lib.pas, così da poter essere facilmente incluse ed utilizzate nei propri progetti…


unit MYSQLServer_Lib;

interface

Uses Forms,SysUtils, DBTables, Classes, DB, Dialogs, StdCtrls,
        WinTypes, WinProcs;

   // ... funzioni per lo Start e Stop del servizio MySQL Server
   function  SP_MySQLStart(var pHandle_Server:THandle):Integer;
   function  SP_MySQLStop(pHandle_Server:THandle) :Integer;

   function  SP_ExecProcess(pApplication, pCommandLine, pDirectory : string): THandle;
   function  SP_CheckProcess(pHandle: THandle): Boolean;

const

   // ... costanti relative ai valori di ritorno delle funzioni
   //     di Strat e Stop.
   ENGINE_STARTED             = 9001;
   ENGINE_RUNNING             = 9002;
   ENGINE_START_ERROR         = 9003;

   ENGINE_STOPPED             = 9004;
   ENGINE_NOT_RUNNING         = 9005;
   ENGINE_STOP_ERROR          = 9006;

implementation

//--------------------------------------------------------------------------
// FUNCTION  : SP_MySQLStart()
//             La Funzione effettua lo Start del MySQL Server (mysql-nt.exe)
//
// PARAMETRI : Nessuno
//
// RETURN    : La funzione ritorna uno dei valori interi dichiarati
//             come const :
//              ENGINE_STARTED      = 9001 - MySQL Server avviato.
//              ENGINE_RUNNING      = 9002 - MySQL Server gia' in esecuzione.
//              ENGINE_START_ERROR  = 9003 - Errore durante l'avvio.
//--------------------------------------------------------------------------
function SP_MySQLStart(var pHandle_Server:THandle):Integer;
var
  Start_Code        : Integer;

  PathEngine        : string;

  ApplicationName   : string;
  CommandLine       : string;
  CurrentDirectory  : string;
begin

  // ... directory corrente dell'Applicazione Delphi
  //     ( da dove l'applicazione è stata avviata)
  PathEngine        := GetCurrentDir;

  // ... assegna : Nome Applicazione, Linea di Comando e Directory di lavore
  ApplicationName   := PathEngine + '\DataBase\bin\mysqld-nt.exe';
  CommandLine       := '--defaults-file="\DataBase\my.ini"';
  CurrentDirectory  := PathEngine + '\DataBase';

  // ... controlla se il Processo ( il MySQL Engine è già in esecuzione )
  if SP_CheckProcess(pHandle_Server) = true then begin
     // ... il processo MySQL Server è gia' in esecuzione
     Start_Code := ENGINE_RUNNING;
     // ShowMessage('MYSQL Server gia'' in esecuzione');
  end
  else begin
     // ShowMessage('MYSQL Server non in esecuzione, START...');

     // ... Start dell'MSQL Engine!
     pHandle_Server := SP_ExecProcess(ApplicationName, CommandLine, CurrentDirectory);
     // ... Sleep ( attendi un po' )
     sleep(3000);
     if pHandle_Server <> 0 then begin
        // ... Ok, avviato !
        Start_Code := ENGINE_STARTED;
     end
     else begin
        // ... errore durante l'avvio del servizio MySQL Server
        Start_Code := ENGINE_START_ERROR;
        // ShowMessage('Errore durante lo START!');
     end;
  end;
  // ... ritorna lo Start Code relativo
  Result := Start_Code;
end;
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
//
// FUNCTION  : SP_MySQLStop()
//             La Funzione effettua lo Stop del servizion MySQL Server
//
// PARAMETRI : Nessuno
//
// RETURN    : La funzione ritorna uno dei valori interi dichiarati
//             come const :
//              ENGINE_STOPPED      = 9004 - MySQL Server arrestato.
//              ENGINE_NOT_RUNNING  = 9005 - MySQL Server non in esecuzione.
//              ENGINE_STOP_ERROR   = 9005 - Errore durante l'arresto.
//
//--------------------------------------------------------------------------
function SP_MySQLStop(pHandle_Server:THandle):Integer;
var
  Stop_Code         : Integer;

  Handle_Admin      : THandle;

  PathEngine        : string;

  ApplicationName   : string;
  CommandLine       : string;
  CurrentDirectory  : string;

  contatore         : Integer;
begin

  // ... directory dell'Applicazione Delphi ( da dove è stata avviata )
  PathEngine        := GetCurrentDir;

  // ... avviamo il msqladmin.exe che ci consentirà di arretsare il MySQL Engine
  //     (mysqld-nt.exe)

  // ... assegna : Nome Applicazione, Linea di Comando e Directory di lavoro
  ApplicationName   := PathEngine + '\DataBase\bin\mysqladmin.exe';

  // ... User e Password (sono impostate a root root ...impostare le proprie)
  CommandLine       := '-u root -proot shutdown';

  // ... direcoty di lavoro
  CurrentDirectory  := PathEngine + '\DataBase';

  // ... controlla se il Processo ( il MySQL Engine è in esecuzione )
  if SP_CheckProcess(pHandle_Server) = FALSE then begin
     // ... esci!
     Stop_Code := ENGINE_NOT_RUNNING;
     // ShowMessage('MySQL NON E'' IN ESECUZIONE');
  end
  else begin
     // ShowMessage('MySQL E'' IN ESECUZIONE, STOP...');

     // ... per fermare il servizio MySQL Server, dobbiamo avviare il servizio
     // mysqladmin.exe indicando, nella riga di comando ( CommandLine ),
     // ... lo shutdown del servizio con la relativa utenza e password
     Handle_Admin := SP_ExecProcess(ApplicationName, CommandLine, CurrentDirectory);

     if Handle_Admin <> 0 then begin
        // ... il servizio myqladmin.exe e' avviato,
        // ... ora attendi che il mysqladmin arresti il MySQL Engine (msqld-nt.exe)
        contatore := 10;
        repeat
            // ... decrementa il contatore
            dec(contatore);
            // ... controlla se il Processo è ancora attivo
            if SP_CheckProcess(pHandle_Server) = TRUE then begin
               // ... si, ancora attivo ... attendi un po'
               Sleep(3000);
            end;
        until (contatore < 1) or (Handle_Admin = 0);

        // ... chiudi l'Handle del msqladmin.exe
        CloseHandle(Handle_Admin);
        // ShowMessage('MySQl Server stopped');
        Stop_Code := ENGINE_STOPPED;
        // ShowMessage('STOPPED OK !');
     end
     else begin
        // ... errore durante l'avvio del servizio msqadmin.exe...
        //     (che avrebbe dovuto fermare il mysqld-nt.exe)
        Stop_Code := ENGINE_STOP_ERROR;
        // ShowMessage('ERRORE DURANTE LO STOP !');
     end;
  end;

  // ... ritorna lo Stop Code relativo
  Result := Stop_Code;
end;
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
//
// FUNCTION  :  SP_ExecProcess()
//              La Funzione avvia un'applicazione creandone il
//              processo relativo.
//              Richiama l'API di Windows CreateProcess().
//
// PARAMS    :  Sono previsti tre parametri in ingresso :
//
//              pApplication = Nome del l'applicazione che
//                             da avviare.
//
//              pCommandLine = Linea di comando.
//                             (eventuali parametri e flags
//                              da passare all'applicazione
//                              da avviare).
//
//              pDirectory   = Directory di lavoro
//                             dell'applicazione.
//
// RETURN    :  La funzione ritorna l'handle relativo al processo
//              avviato.
//
//--------------------------------------------------------------------------
function SP_ExecProcess(pApplication, pCommandLine,
                        pDirectory : string): THandle;
var
  // ... struttura contenete le Info di StartUp dell'applicazione
  //     da avviare.
  //     (vedere la documentazione Windows SDK Developer's Reference)
  sInfo          : TStartupInfo;

  // ... struttura contenete le Info del processo avviato.
  //     (vedere la documentazione Windows SDK Developer's Reference)
  pInfo          : TProcessInformation;

  // ... handle del processo
  Handle_Process : THandle;

  // ... flag che indica se il processo e' stato creato o meno
  CreatedOK      : Boolean;

begin

  // ... inizializza la Struttura sInfo
  FillChar(sInfo, SizeOf(sInfo), 0);

  // ... ora inizializza la Struttura pInfo
  FillChar(pInfo, SizeOf(pInfo), 0);

  // ... l'elemento .cb (della struttura TStartupInfo) indica
  //     la taglia, in bytes, della struttura...
  // ... assegnagli il valore!
  sInfo.cb := SizeOf(TStartupInfo);

  // ... l'elemento .wShowWindow indica SE e COME deve apparire
  //     la Window relativa al processo che stiamo avviando.
  // ... voglio che il MySQL Sever parta senza che appaia
  //     la finestra del prompt dei comandi.
  sInfo.wShowWindow := SW_HIDE;
  sInfo.dwFlags     := STARTF_USESHOWWINDOW;

  // ... inizializza a FALSE il Flag di creazione del processo
  CreatedOK := FALSE;

  // ... richiama l'API di Windows CreateProcess()
  CreatedOK := CreateProcess(nil, PChar(pApplication + ' ' +
                                        pCommandLine),
                                        nil,
                                        nil,
                                        False,
                                        CREATE_NEW_PROCESS_GROUP +
                                        HIGH_PRIORITY_CLASS,
                                        nil,
                                        PChar(pDirectory),
                                        sInfo,
                                        pInfo);

  // ... test del valore di ritorno della funzione CreateProcess()
  if (createdOK = TRUE) then begin
     // ... ok! il processo e' stato creato...
     // ... ritorna l'id del processo
     Handle_Process := pInfo.hProcess;
  end
  else begin
     // ... il processo non e' stato creato !
     // ... ritorna 0 !
     Handle_Process := 0;
  end;
  //
  Result := Handle_Process;
end;
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//
// FUNCTION  : SP_CheckProcess()
//             La Funzione controlla se un processo è attivo o meno
//
// PARAMETRI : E' previsto un unico parametro in ingresso :
//             pHandle  =  L'identificativo (Handle) del processo
//                         ...il valore dell'Handle è quello ritornato dalla
//                         funzione SP_ExecProcess()
//
// RETURN    : La funzione ritorna un valore Booleano :
//             True  = se il processo è attivo
//             False = se il processo non è attivo
//
//--------------------------------------------------------------------------
function SP_CheckProcess(pHandle: THandle): Boolean;
var
  Check_Flag : Boolean;
  ExitCode   : Cardinal;
begin

  // ... assegna FALSE al valore di ritorno
  Check_Flag := FALSE;

  // ... test sull'Handle del processo
  if (pHandle <> 0) then begin
     // ... è diverso da ZERO... allora :
     // ... richiamo dell'API di Windows GetExitCode() che valorizzerà
     //     ExitCode e ritornerà TRUE se la funzione ha successo.
     if (GetExitCodeProcess(pHandle, ExitCode) = TRUE) then begin
        // ... analisi dell'ExitCode
        if (ExitCode = STILL_ACTIVE) then begin
           // ... il processo è ancora attivo
           // showmessage('ancora attivo');
           Check_Flag := TRUE;
        end
        else begin
           // ... il processo non e' attivo
           // showmessage('non attivo');
           CloseHandle(pHandle);
           pHandle    := 0;
           // ... il processo non e' attivo
           Check_Flag := FALSE;
        end;
     end
     else begin
        // ShowMessage('Valore della ExitCodeProcess = FALSE (insuccesso) ');
     end;
  end
  else begin
     // ShowMessage('Halndle da controllare e'' ZERO');
  end;

  // ... ritorna il Check Flag
  Result := Check_Flag;
end;
//--------------------------------------------------------------------------

end.

La Form per il test delle Funzioni…

Una semplice Form per effettuare il test delle funzioni di Start e Stop del MySQL Server.
La Form prevede solo due bottoni, uno per l’avvio e l’altro per l’arresto del MySQL Server, ed una Label in cui sarà visualizzato il messaggio relativo…


unit UMySQLServer_Test;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons,

  MySQLServer_Lib;

type
  TFMySQLServer_Test = class(TForm)
    B_START : TBitBtn;
    B_STOP  : TBitBtn;

    MSG     : TLabel;

    procedure B_STARTClick(Sender: TObject);
    procedure B_STOPClick(Sender: TObject);

    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }

  end;

var
  FMySQLServer_Test    : TFMySQLServer_Test;

  //  ... identificativo del processo relativo al MySQL Server
  MySQL_Server_Handle : THandle;

implementation

{$R *.DFM}

//--------------------------------------------------------------------------
//   EVENTO : FormCreate
//--------------------------------------------------------------------------
procedure TFMySQLServer_Test.FormCreate(Sender: TObject);
begin
  // ... inizializza a 0
  MySQL_Server_Handle := 0;
end;
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
//   EVENTO : FormShow
//--------------------------------------------------------------------------
procedure TFMySQLServer_Test.FormShow(Sender: TObject);
begin
  // ... messaggio a video
  MSG.Caption := '';
end;
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//   EVENTO : Click sul BOTTONE START_ENGINE
//--------------------------------------------------------------------------
procedure TFMySQLServer_Test.B_STARTClick(Sender: TObject);
var
  Start_Code : Integer;
begin

  // Start MySQL Server

  // ... imposta il Cursore a clessidra
  Screen.Cursor := crHourglass;

  // ... eventuale messaggio di attesa
  MSG.Caption := 'Start MySQL Server ...please wait';

  // ... forza la visualizzazione del messaggio
  Application.ProcessMessages;

  // ... richiamo della Funzione di Start del MySQL Server
  Start_Code := SP_MySQLStart(MySQL_Server_Handle);

  // ... analisi del Codice di ritorno :
  case Start_Code of
           ENGINE_STARTED : begin
                               MSG.Caption := 'MySQL Server started!';
                            end;

           ENGINE_RUNNING : begin
                               MSG.Caption := 'MySQL Server running';
                            end;

       ENGINE_START_ERROR : begin
                               MSG.Caption := 'MySQL Server Start Error!';
                            end;
  end;

  // ... ripristina il Cursore
  Screen.Cursor := crDefault;
end;
//--------------------------------------------------------------------------
//--------------------------------------------------------------------------
//   EVENTO : Click sul BOTTONE STOP_ENGINE
//--------------------------------------------------------------------------
procedure TFMySQLServer_Test.B_STOPClick(Sender: TObject);
var
  Stop_Code : Integer;
begin

  // ... Stop MYSQL Server :

  // ... imposta il Cursore a clessidra
  Screen.Cursor := crHourglass;

  // ... eventuale messaggio di attesa
  MSG.Caption := 'Stop MySQL Server ...please wait';

  // ... forza la visualizzazione del messaggio
  Application.ProcessMessages;

  // ... richiamo della Funzione di Start del MySQL Server
  Stop_Code   := SP_MySQLStop(MySQL_Server_Handle);

  // ... analisi del Codice di ritorno :
  case Stop_Code of
          ENGINE_STOPPED : begin
                               MSG.Caption := 'MySQL Server stopped!';
                           end;

      ENGINE_NOT_RUNNING : begin
                               MSG.Caption := 'MySQL Server not running';
                           end;

       ENGINE_STOP_ERROR : begin
                               MSG.Caption := 'MySQL Server Stop Error!';
                           end;
  end;

  // ... ripristina il Cursore
  Screen.Cursor := crDefault;
end;
//--------------------------------------------------------------------------

end.

Categories: EMBARCADERO - DELPHI

31 August 2008 Comments off

 

 

Computer science is not about machines, in the same way that astronomy is not about telescopes.  

Edsger Dijkstra

 

 

 

 

Categories: IBM MAINFRAME