OS/2 Code - Detail View


Date

Name

Plattform

Language

Kurzbeschreibung

Owner

Link

17.11.2001

THREADS.REXX

OS/2

REXX

DB2 Thread Terminate Tool

Gernot Ruban

 

DB2 ist ein Produkt der
IBM Corporation. Bitte
Copyright-  und Trademark-Hinweise beachten!

/****************************************************************REXX*/
/* THREADS..: DB2/2 Threads anzeigen und/oder terminieren            */
/*-------------------------------------------------------------------*/
/* ARGUMENTE: DATABASE - Database-Namen oder '' fr alle lokalen DB's*/
/*            OPTIONS  - DISPlay   Anzeigen der Verbindungen         */
/*                       TERMinate Beenden der Verbindungen          */
/*            AGENTID  - (opt.) Agent-ID, die zu beenden ist         */
/*-------------------------------------------------------------------*/
/* CALLS...:  WLOG     - DB2 Server Logging Queue beschreiben        */
/*-------------------------------------------------------------------*/
/* DB2.....:  Version  - V2                                          */
/*-------------------------------------------------------------------*/
/* RšCKGABE:  RC       - Return Code: immer RC=0                     */
/*-------------------------------------------------------------------*/
/* ŽNDERUNG : $RUB/26.06.97 - erste Version                          */
/*            $RUB/28.07.97 - 5 Sec warten nach TERM,                */
/*                            auáerdem remote Nodes anzeigen         */
/*            $RUB/19.08.97 - alles auf WLOG, weitere Verbesserungen */
/*     V1.3   $RUB/09.10.97 - DEACTIVATE DB eingebaut                */
/*            $RUB/10.10.97 - Hilfe erweitert                        */
/*     V1.4   $RUB/04.11.97 - kein Abbruch wenn SQL Warning (eg.1230)*/
/*     V1.5   $RUB/16.01.98 - DEACT-Verarbeitung korrigiert, liest   */
/*                            bei Bedarf DB-Directory                */
/*     V2.0   $RUB/10.03.98 - erkennt DB2/2 V2 und V5                */
/*********************************************************************/

/*********************************************************************/
/* Parameter Auswertungen                                            */
/*********************************************************************/
    parse upper arg database "," option "," agentid
    parse source . . src
    Version = "V2.0"
    src     = filespec("N",src)
    src     = translate(substr(src,1,pos(".",src)-1))

    database = translate(database)
    option   = translate(option)

    MsgOut  = "THREADS.LOG"

/*********************************************************************/
/* Korrektur der Parameter, wenn TERM 1. Parameter                   */
/*********************************************************************/
    If ABBREV("TERMINATE",database) & agentid = ""
    then do
         agentid  = option
         option   = database
         database = ""
    end

/*********************************************************************/
/* REXX Utilities aus DLL bei Bedarf hinzuladen                      */
/*********************************************************************/
    if RxFuncQuery("SysFileDelete") <> 0
    then call RxFuncAdd "SysFileDelete", "RexxUtil", "SysFileDelete"
    if RxFuncQuery("SysSleep")      <> 0
    then call RxFuncAdd "SysSleep",      "RexxUtil", "SysSleep"
    if RxFuncQuery("SQLDBS")        <> 0
    then call RXFuncAdd "SQLDBS",        "SQLAR",    "SQLDBS"

/*********************************************************************/
/* Log Informationen                                                 */
/*********************************************************************/
    Call SysFileDelete MsgOut
    Call SayMsg(copies("þ",79))
    Call SayMsg("þ "left(src version": Display/Term DB2/2 Threads                  " ||,
                         date("o")"-"time(),75)" þ");
    Call SayMsg(copies("þ",79))
    if database = "?" | database = "/?" | database = "-H"
    then do
         say "<Help> for "src": Possible parameters are ..."
         say "           [database][,option][,id]"
         say "           database  ¯  Name of Database or '' for all local Databases"
         say "           option    ¯  DISPlay (default)"
         say "                        TERMinate (cancel Connection(s))"
         say "           id        ¯  for TERMinate: id of agent to terminate/cancel/force"
         Call VerarbeitungsEnde(8)
    end
    if option = "" then option = "DISPLAY"
  
/*********************************************************************/
/* DB2 Release/Versions-Informationen ausgebene                      */
/*********************************************************************/
    call SQLDBS "GET INSTANCE INTO :DB2I"
    parse value sqlca.sqlerrp with "SQL"DB2Ver
    say src": DB2/2 Version "db2ver" (vvrrm) at instance "space(db2i)"."
  
/*********************************************************************/
/* Verbindungs-Informationen beschaffen und sortieren                */
/*********************************************************************/
    Call GetConn
    Call SortConn
    If c = 0
    then do
         Call saymsg src": No connects found matching your "option" request!"
         Call WLog src": No connects found matching your "option" request!"
    end

/*********************************************************************/
/* Informationen zur gewnschten Database anzeigen                   */
/*********************************************************************/
    do i=1 to c
       if database = database.i | database = ""
       then do
            parse value applid.i with  . "." . "." since
            parse value since with yy 3 mm 5 dd 7 hh 9 mi 11 ss
            since = yy"/"mm"/"dd"-"hh":"mi":"ss
            x = i-1
            if database.i <> database.x
            then say "Database.....: "left(database.i,8)||copies(" ",7)||"Path.............: "dbpath.i
            say "             þ Current User : "left(uid.i,8)"/"left(nodename.i,8)"  Agent-ID: "aid.i
            say "               Application .: "left(appl.i,18)" TimeStmp: "since
            say "               Appl.-ID.....: "applid.i
       end /* do */
    end /* do */

  
/*********************************************************************/
/* Connection abbrechen wenn erwnscht                               */
/*********************************************************************/
    if abbrev("TERMINATE",option) = 1
    then do
         /************************************************************/
         /* keine Applications abzubrechen                           */
         /************************************************************/
         if c = 0
         then do
              call saymsg src": No application to force/cancel!"
              Call WLog src": No application to force/cancel!"
              Call DBDeact
              Call Verarbeitungsende(0)
         end
         /************************************************************/
         /* Connections je Datenbank ermitteln                       */
         /************************************************************/
         x = 0
         do i=1 to c
            if ( database = database.i | database = "" ),
            &  ( agentid  = aid.i      | agentid  = "" )
            then do
                 x = x + 1
                 termid.x   = aid.i
                 termdb.x   = database.i
                 termuid.x  = uid.i
                 termnode.x = nodename.i
            end /* do */
         end /* do */
         /************************************************************/
         /* Ausgew„hlte Connects terminieren                         */
         /************************************************************/
         termid.0 = x
         do i=1 to x
            call sqldbs "FORCE APPLICATION :TERMID"
            /*if sqlca.sqlcode <> 0 */
            if sqlca.sqlcode < 0
            then do
                 Call saymsg "FORCE on DB="database" failed, SQLCODE="sqlca.sqlcode
                 Call saymsg sqlmsg
                 Call WLog src": FORCE on DB="database" failed, SQLCODE="sqlca.sqlcode
                 Call VerarbeitungsEnde(20)
            end
         end
         if termid.0 = 0
         then do
              Call saymsg "No connects found for/on Database-/Agent-ID!"
              Call WLog src": No connects found for/on Database-/Agent-ID!"
         end
         /************************************************************/
         /* Kontrollieren, ob Connect immer noch besteht             */
         /************************************************************/
         call SYSSleep 5
         Call GetConn
         Call SortConn
         do j=1 to termid.0
            if ScanID(termid.j) = 1
            then do
                 Call SayMsg "Connection...: DB="termdb.j", UID="termuid.j", Node="termnode.j", AID="termid.j" still exists!"
                 Call WLog src": Connect to DB="termdb.j", UID="termuid.j", Node="termnode.j", AID="termid.j" still exists!"
                 Call VerarbeitungsEnde(8)
            end
            else do
                 Call SayMsg "Connection...: DB="termdb.j", UID="termuid.j", Node="termnode.j", AID="termid.j" canceled!"
                 Call WLog src": Connect to DB="termdb.j", UID="termuid.j", Node="termnode.j", AID="termid.j" canceled!"
            end
         end
         /************************************************************/
         /* Deactivate active Databases                              */
         /************************************************************/
         Call DBDeact
    end /* do */
    Call VerarbeitungsEnde(0)

exit 0

  
/*############### Unterprogramme/Funktionen #######################***/

  
/*********************************************************************/
/* Agent-ID in Liste der aktuell verbundenen Agents suchen           */
/*********************************************************************/
ScanID:
    arg sid
    Do ii=1 to c
       if aid.ii = sid then return 1
    end
Return 0
  
/*********************************************************************/
/* Verbindungs-Informationen beschaffen                              */
/*********************************************************************/
GetConn:
    c = 0
    "@DB2 LIST APPLICATIONS SHOW DETAIL | RXQUEUE"
    do while queued() <> 0
       parse pull line
       if pos("SQL1032N",line) = 1
       then do
            Call SayMsg "DB2 has not been started."
            Call WLog src": DB2 has not been started."
            "@RXQUEUE /CLEAR"
            Call VerarbeitungsEnde(8)
       end        
       if pos("SQL1611W",line) = 1
       then nop
       else do
            if pos("-",line) = 1,
            | pos("Ber.-ID",line) = 1,
            | pos("Auth Id",line) = 1,
            | pos("           ",line) = 1,
            | line = "",
            | pos("0D"x,line) = 1
            then nop
            else do
                 c = c + 1
                 parse value line with uid.c appl.c aid.c applid.c database.c rest.c
                 uid.c = space(uid.c)
                 appl.c = space(appl.c)
                 aid.c  = space(aid.c)
                 applid.c = space(applid.c)
                 j = words(rest.c)
                 if j > 0
                 then do
                      dbpath.c = word(rest.c,j)
                      database.c = word(rest.c,j-1)
                      /* database.c = substr(rest.c,82,8) */  /*space(database.c)*/
                      j = wordindex(rest.c,j-1) - 10
                      nodename.c = substr(rest.c,j,8)
                 end
                 else do
                      dbpath.c = "n/a"
                      database.c = "n/a"
                      nodename.c = "n/a"
                 end
            end
       end
    end /* do */
    "@RXQUEUE /CLEAR"
return
  
/*********************************************************************/
/* Verbindungs-Informationen  sortieren                              */
/*********************************************************************/
SortConn:
    do i=1 to c
       do j=i+1 to c
          if database.i||uid.i||aid.i > database.j||uid.j||aid.j
          then do
               xuid = uid.j
               xappl = appl.j
               xaid  = aid.j
               xapplid = applid.j
               xdatabase = database.j
               xnodename = nodename.j
               uid.j = uid.i
               appl.j = appl.i
               aid.j  = aid.i
               applid.j = applid.i
               database.j = database.i
               nodename.j = nodename.i
               uid.i = xuid
               appl.i = xappl
               aid.i  = xaid
               applid.i = xapplid
               database.i = xdatabase
               nodename.i = xnodename
          end /* do */
       end
    end /* do */
return

/*********************************************************************/
/* Get Database Directory (only local databases)                     */
/*********************************************************************/
GetDBDir:

    dd = 0
    call SQLDBS 'OPEN DATABASE DIRECTORY ON 0 USING :scan_db'
    if SQLCA.SQLCODE <> 0
    then do
         Call saymsg "OPEN DB DIR failed, SQLCODE="sqlca.sqlcode
         Call saymsg sqlmsg
         Call VerarbeitungsEnde(20)
    end
    else do
         do d=1 to scan_db.2
            call SQLDBS 'GET DATABASE DIRECTORY ENTRY :scan_db.1 USING :entry'
            /* if drive is not empty it is a local database */
            if space(entry.3) <> ""
            then do
                 dd = dd + 1
                 dbd.dd = space(entry.2)
            end
         end
    end
    call SQLDBS 'CLOSE DATABASE DIRECTORY :scan_db.1'
    if SQLCA.SQLCODE <> 0
    then do
         Call saymsg "CLOSE DB DIR failed, SQLCODE="sqlca.sqlcode
         Call saymsg sqlmsg
    end
return

/*********************************************************************/
/* Deactivate activated Databases                                    */
/*********************************************************************/
DBDeact:
   /******************************************************************/
   /* Get list of local Databases if none specified                  */
   /******************************************************************/
   if database = ""
   then Call GetDBDir
   else do
        dd = 1
        dbd.1 = database
   end
   /******************************************************************/
   /* Get list of local Databases if none specified                  */
   /******************************************************************/
   do i=1 to dd
      address CMD "@DB2 CONNECT RESET | RXQUEUE"
      address CMD "@RXQUEUE /CLEAR"
      address CMD "@DB2 DEACTIVATE DATABASE "dbd.i" | RXQUEUE"
      pull line
      address CMD "@RXQUEUE /CLEAR"
      if word(line,1) = "SQL1492N"
      then do
           Call saymsg src": Database "dbd.i" is not active!"
           Call WLog src": Database"dbd.i" is not active!"
      end
      if word(line,1) = "SQL1491N"
      then do
           Call saymsg src": Deactivation failed for Database "dbd.i" - active connect(s)!"
           Call WLog src": DEACT failed for Database "dbd.i" - active connect(s)!"
      end
      if word(line,1) = "SQL1013N"
      then do
           Call saymsg src": Deactivation failed for Database "dbd.i" - not found!"
           Call WLog src": DEACT failed for Database "dbd.i" - not found!"
      end
      if word(line,1) = "DB20000I"
      then do
           Call saymsg src": Deactivation for Database "dbd.i" successful!"
           Call WLog src": DEACT for Database "dbd.i" successful!"
      end
   end
return
/***************************************************************************
 *
 * int WLog( [Message] )
 *
 * Schreiben einer Nachricht in die REXX Logqueue
 *
 * Diese Prozedur schreibt eine Nachricht in eine REXX Queue.     
 * Loqqueue. Die Nachrichten k”nnen dann von einer separaten     
 * Logtask gelesen und in ein zentrales Log geschrieben          
 * werden.                                                       
 *                                                                    
 * Der Name der Logqueue wird der Umgebungsvariable LOGQUEUE     
 * entnommen. Ist die Umgebungsvariable nicht gesetzt, wird      
 * der Default-Queuenamen SRVLOG verwendet.                      
 *
 * Ablauf der Prozedur:
 *      1. Auswerten der Umgebungsvariable LOGQUEUE zur
 *         Ermittlung des Namens der Logqueue.
 *      2. Schreiben der Nachricht in die Logqueue.
 *
 *
 * Message :   Beliebiger Text (auch leer), der in                
 *             die Logqueue geschrieben werden soll.              
 *                                                                    
 *
 * Rckgabewert:
 *      RetCode (Die Returncodes entsprechen den Returncodes der
 *               Built-in Function LINEOUT)
 *
 * ben”tigte Funktionen:
 *      keine
 *
 * ben”tigte Umgebungsvariablen:
 *      LOGQUEUE    Name der Logqueue
 *      TEST        Test-Flag                                        
 */

WLog: procedure
parse arg Message

   /*** "Variablendefinition" ********************************/
   /*-- "Konstanten" ----------------------------------------*/

   logqueue_default   = 'SRVLOG'          /* Default Logqueue Name       */

   /*-- Name von Env. Variablen fr Vorbelegung von Werten --*/

   logqueue_envar     = 'LOGQUEUE'        /* Environment Var. fr        */
                                          /*    REXX Queue-Name          */
   test_envar         = 'TEST'            /* Environment Var. fr        */
                                          /*    Test-Flag                */

   /*-- Wichtige benutzte Variablen --------------------------*/

   logqueue           = ''                /* Variable fr den Namen      */
                                          /*    der priv. REXX-Queue     */
   test               = 0                 /* Test-Flag                   */

   /*** Auswertung von Environmentvariablen *******************/

   envar_value = translate(value(test_envar,,'OS2ENVIRONMENT'))
   if (envar_value = 'JA'  ) | ,
      (envar_value = 'YES' ) then do      /* Falls TEST Environment-      */
      test = 1                            /* Variable auf JA oder YES ge- */
   end /* if */                           /* setzt, dann Test-Flag setzen */

   envar_value = translate(value(logqueue_envar,,'OS2ENVIRONMENT'))

   if (envar_value <> '') then do          /* Falls LOGQUEUE Environment  */
      logqueue = envar_value               /*    Variable gesetzt, dann   */
      if (test) then do                    /*    Inhalt als Loqueue-Name  */
         say 'Logqueue ist' logqueue       /*    benutzen, sonst Default  */
      end                                  /*    Queuename verwenden.     */
   end
   else do
      logqueue = logqueue_default
      if (test) then do
         say 'Keine' logqueue_envar 'Umgebungsvariable gesetzt'
         say 'Default Queuename' logqueue_default 'wird verwendet'
      end /* if */
   end /* if */

   /****** Prfen auf Existenz der Logqueue *******************/

   /* Es wird keine Prfung auf Existenz der Logqueue durchgefhrt.      */
   /*    Falls sie nicht existiert, gibt es einen Return Code  bei       */
   /*    Schreiben in die Queue.                                         */

   /****** Nachricht in Logqueue schreiben ********************/

   akt_queue = RxQueue("Set",logqueue)    /* Aktuellen Queuenamen sich.  */
   rcode     = lineout("QUEUE:",message)  /* In die Queue schreiben      */
   call RxQueue "SET", akt_queue          /* Vorherige Queue aktivieren  */

   if (rcode <> 0) then do
      if (test) then do
         say "Fehler beim Schreiben der Nachricht"
         say "Return Code" rcode "von write_queue()"
      end /* if */
   end
   else do
      if (test) then do
         say "Nachricht in Logqueue" logqueue "geschrieben"
      end /* if */
   end

return


/*********************************************************************/
/* Anzeige/Ausgabe von Verarbeitungsprotokoll                        */
/*********************************************************************/
SayMsg: procedure expose MSGOut

   parse arg MSG
   Say MSG
   Call LineOut MSGOut, Msg
   Call Stream  MSGOut,"C", "CLOSE"

return

/*********************************************************************/
/* Error Condition                                                   */
/*********************************************************************/
ERROR:
     call SayMSG(src" "Version": Internal Error")
     call VerarbeitungsEnde(20)
return

SyntaxErr:
Return

/*********************************************************************/
/* Ausgabe der Nachricht fr Verarbeitungsende                       */
/*********************************************************************/
VerarbeitungsEnde:

   arg cc
   if cc = 0
   then Call SayMSG(src": Processing ends with RC="cc".",
                    date("o")"-"time());
   else Call SayMSG(src": Processing ends with RC="cc".",
                    date("o")"-"time());

   exit cc

return

© Gernot Ruban