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