Scanning…
Instructions designed for IBM i developer learning PHP and XMLSERVICE …
$ctl .= " *debug";
Job1 (threaded) Job 2 Job 3 (DB2 userid/password) Job 4 (optional XTOOLKIT job) (ctl=*debugcgi) (ctl=*debugproc) (ctl=*debug) browser -> Apache ->XMLCGI (Apache CGI child) -> QSQSRVR (XMLSERVICE *here) -> QSQSRVR (XMLSERVICE client) -> XTOOLKIT (XMLSERVICE ipc=/tmp/flinstone) $ctl .= " *debugcgi"; // Job 2 - debug XMLCGI to see REST/HTTP data passed by client (when using REST only) $ctl .= " *debugproc"; // Job 3 - debug XMLSERVICE "client" to see DB2 passed data (DB2 interface) $ctl .= " *debug"; // Job 4 - debug XMLSERVICE "server" to see XMLSERVICE calls (DB2 interface) // Note: when ctl='*here', both XMLSERVICE "client"/"server" // are in QSQSRVSR job (NO XTOOLKIT job) // remote: Attaching with LUW drivers changes QSQSRVR ... // CLIENT (Client Access drivers) <==> QZDAxxxx // CLIENT (DB2 Connect drivers) <==> QRWxxxx
This is a collection of debug tips and where you may find your problem data.
5=work -> 10. Display job log -> F10=Display detailed messages
can be very revealing
5=work -> 11. Display call stack -> F5=Refresh
watch stack during stress runs
(http://myibmi/hello.php)
.
(http://myibmi:10088/hello.php)
Here are a few common things that can provide useful information if working with outside support people.
call qp2term > tail /usr/local/zendsvr/var/log/php.log > tail /myasp2/www/zend2/logs/error_log.Q112061800 > tail /myasp2/www/zend2/logs/access_log.Q112061800
My Example: SYSASP -- ZENDSVR library ... everything as installed SYSASP -- /usr/local/zendsvr ... everything as installed SYSASP -- /tmp ... many Zend "enterprise" components use /tmp MYASP2 -- /myasp2/www/zend2 ... ALL "user data" moved from /www/zendsvr (/conf, /logs, /htdocs) More ... /myasp2/www/zend2 -- NO symbolic links between SYSAPS and MYASP2 for true "independent"ASP. -- config files /myasp2/www/zend2/conf attach: fastcgi.conf attach: httpd.conf
wrkoutq
If jobs are still active (php-cgi, etc.) ... wrkactjob 5 ZEND2 QTMHHTTP BCI .0 PGM-QZSRHTTP SIGW ZEND2 QTMHHTTP BCI .0 PGM-php-cgi.bi THDW 5 ZEND2 QTMHHTTP BCI .0 PGM-php-cgi.bi TIMW 10. Display job log, if active, on job queue, or pending F10 -- full job log
STRSST 1. Start a service tool 5. Licensed Internal Code log 1. Select entries from the Licensed Internal Code (LIC) log Specify Licensed Internal Code Log Selection Values -- leave as is enter --- 0100A890 i5/OS PASE 4700 0013 06/15/12 09:03:43 7 <--- PASE 0100A891 LIC log interface 0401 0100 06/15/12 09:04:08 1 0100A892 Signals management 4600 0001 06/15/12 09:04:51 255 0100A893 Process management 1300 0001 06/18/12 21:02:06 1 maybe look for PASE, storage management, ASP, so on around "failure time" Note: you can also dump logs to spool ...
Some times you just have no idea what is going on, here is a handy macro to dump a lot of stacks.
STRSST/STRDST 1. Start a service tool 4. Display/Alter/Dump 1. Display/Alter storage ... or option for dump to printer ... 2. Licensed Internal Code (LIC) data 14. Advanced analysis Option Command 1 processinfo In this case dumping all process dealing with keyword "ZEND" appearing in job ... Specify Advanced Analysis Options Output device . . . . . . : Display Type options, press Enter. Command . . . . : PROCESSINFO Options . . . . . -NAMES ZEND Note: Information dumped printer/display is same as paseps macro.
If you are using private connections (InternalKey or $ipc=‘/tmp/packers’), the XMLSERVICE job is probably available for examination with wrkactjob.
Work with Active Jobs LP0264D 05/17/12 11:35:12 CPU %: .0 Elapsed time: 00:00:00 Active jobs: 313 Type options, press Enter. 2=Change 3=Hold 4=End 5=Work with 6=Release 7=Display message 8=Work with spooled files 13=Disconnect ... Current Opt Subsystem/Job User Type CPU % Function Status 5 XTOOLKIT DB2 BCH .0 PGM-XMLSERVICE SEMW
1) Use option 5=work -> 10. Display job log -> F10=Display detailed messages
to examine joblog on errors …
Display All Messages System: LP0264D Job . . : XTOOLKIT User . . : DB2 Number . . . : 435915 >> CALL PGM(XMLSERVICE/XMLSERVICE) PARM('/tmp/packers') Pointer not set for location referenced. Application error. MCH3601 unmonitored by ZZSRV at statement 0000000448, instruction X'0000'.
2) Use option 5=work -> 11. Display call stack -> F5=Refresh
to examine stack during stress tests …
Display Call Stack System: LP0264D Job: XTOOLKIT User: DB2 Number: 437582 Thread: 0000000C Type Program Statement Procedure 1 QCMD QSYS /01C8 XMLSERVICE XMLSERVICE _QRNP_PEP_XMLSERVICE XMLSERVICE XMLSERVICE 1133 XMLSERVICE XMLSERVICE XMLSERVICE 4607 RUNSERVER XMLSERVICE XMLSERVICE 2983 SIGSETTIMEOUT XMLSERVICE XMLSERVICE 2876 SIGTIMEROFF QP0SSRV1 QSYS 19 setitimer QP0SSRV2 QSYS 159 qp0sitimer__F12qp0sitimer_t >
On my IBM i machine ... EDTF STMF('/usr/local/zendsvr/var/log/php.log') -- or -- call qp2term (or ssh myibmi) > tail /usr/local/zendsvr/var/log/php.log ... stuff ... in /MYASP2/www/zend2/htdocs/hello.php on line 1
On my Linux machine ... $ tail /usr/local/zend/var/log/php.log [16-May-2012 16:30:12] PHP Warning: db2_close() expects parameter 1 to be resource ...
error logs for date in question ... EDTF STMF('/myasp2/www/zend2/logs/error_log.Q112051500') -- or -- call qp2term (or ssh myibmi) > tail /myasp2/www/zend2/logs/error_log.Q112051500 [Tue May 15 17:10:11 2012] [error] [client 9.5.158.38] CGI PROGRAM /QSYS.LIB/XMLSERVICE.LIB/XMLCGI.PGM RETURNED EXCEPTION ID CEE9901 [Tue May 15 17:10:11 2012] [error] [client 9.5.158.38] SEE JOBLOG FOR JOB 428979/QTMHHTTP /ZEND2
access logs for date in question ... EDTF STMF('/myasp2/www/zend2/logs/access_log.Q112051500') -- or -- call qp2term (or ssh myibmi) > tail /myasp2/www/zend2/logs/access_log.Q112051500 9.5.158.38 - - [15/May/2012:17:47:41 -0500] "GET /cgi-bin/xmlcgi.pgm?db2=LP0264D
toolkit.ini logfile EDTF STMF('/usr/local/zendsvr/share/ToolkitApi/toolkit.log') -- or -- call qp2term (or ssh myibmi) > tail /usr/local/zendsvr/share/ToolkitAPI/toolkit.log 15 May 2012 22:53:35.752099 Running stateless; no IPC needed. Service library: ZENDSVR 15 May 2012 22:53:36.588466 i5Error: num=14 cat=9 msg="No more entries." desc="No more entries." location set in toolkit.ini ... EDTF STMF('/usr/local/zendsvr/share/ToolkitApi/toolkit.ini') [log] ; warnings and errors will be written to the logfile. logfile = "/usr/local/zendsvr/share/ToolkitApi/toolkit.log"
toolkit.ini debugLogFile EDTF STMF('/usr/local/zendsvr/share/ToolkitApi/debug.log') -- or -- call qp2term (or ssh myibmi) > tail /usr/local/zendsvr/share/ToolkitAPI/debug.log <data type='1A' var='ds1' comment='DSCHARA'><![CDATA[E]]></data> <data type='1A' var='ds2' comment='DSCHARB'><![CDATA[F]]></data> location set in toolkit.ini ... EDTF STMF('/usr/local/zendsvr/share/ToolkitApi/toolkit.ini') ; debug turns PHP toolkit's debug mode on or off (true/false). Default log file: /usr/local/zendsvr/share/ToolkitApi/debug.log ; This log will grow large, so leave this false when you do not need to log everything. debug = true debugLogFile = "/usr/local/zendsvr/share/ToolkitApi/debug.log"
PHP and XMLSERVICE bad XML ... EDTF STMF('/tmp/bad.xml') -- or -- > tail /tmp/bad.xml start <?xml version="1.0" encoding="ISO-8859-1" ?><script><cmd><success><ܬCDATA�+++ success QSYS/DLTDTAARA DTAARA(XMLSERVICE/BETTYBOOP)||></success></cmd>
Troubles on your PHP site or installation???
Often times if you take a deep breath, slow down and look at each level of web site components you can find your issue without reaching for the bat phone and calling Zend or IBM. The following set of tests walks up the PHP levels of components to give you confidence you are looking at the correct layer of your issue. Of course after you complete smaller PHP scripts (hello.php, etc.), you can likely use the same step up next level techniques on your sophisticated applications (WorldPeace.php).
If you are running on the IBM i machine it is always best to make sure your Apache/PHP setup can do anything.
Note: Your machine may have document root at /www/zendsvr vs. /MYASP2/www/zend2 (out-of-box installed Zend Server).
Test number #0
Install the following simple test in your Document root and see if “Hello World” appears.
/MYASP2/www/zend2/htdocs/hello.php <?php echo "Hello world"; ?>
Run the test …
call qp2term (or ssh myibmi) > export PATH=/usr/local/zendsvr/bin:$PATH > export LIBPATH=/usr/local/zendsvr/lib > cd /MYASP2/www/zend2/htdocs > php hello.php Hello world>
No, not working???
If you are running on the IBM i machine it is always best to make sure your Apache/PHP setup can do anything.
Note: Your machine may have document root at /www/zendsvr vs. /MYASP2/www/zend2 (out-of-box installed Zend Server).
Test number #1
Install the following simple test in your Document root and see if “Hello World” appears in your browser.
/MYASP2/www/zend2/htdocs/hello.php <?php echo "Hello world"; ?>
No, not working???
Ok, next run stress test …
call qp2term > cd /usr/local/Zend/apache2/bin > ab -t 25 -c 10 http://myibmi/hello.php -t 25 -- 25 seconds -c 10 -- 10 concurrent browsers (simulates ten browsers)
wrkactjob refresh (F10) - if you do not see multiple php-cgi jobs getting CPU re-run tests with more load
call qp2term > cd /usr/local/Zend/apache2/bin > ab -t 25 -c 10 http://myibmi/hello.php &; ab -t 25 -c 10 http://myibmi/hello.php &; ab -t 25 -c 10 http://myibmi/hello.php &; -t 25 -- 25 seconds -c 10 -- 10 concurrent browsers (simulates ten browsers) Multiply by 3 Apache ab jobs running background -- 30 concurrent browsers (simulates thirty browsers)
At this level we want to check our DB2 connections.
Note:
Test number #2
Install the following simple test in your Document root and see if “success” appears in your browser.
/MYASP2/www/zend2/htdocs/connection2.inc <?php $database = "*LOCAL"; // *LOCAL on IBM i ... LP0264D on Linux $cwdatabase = "localhost"; $user = "DB2"; $password = "XXXXXXXX"; $libxmlservice = "ZENDSVR"; // ZZCALL (Zend Server) $i5persistentconnect = false; ?> /MYASP2/www/zend2/htdocs/xxtoolkit_connect.php <?php require_once('connection2.inc'); // flip between persistent and non-persistent connections for ($i=0;$i<500;$i++) { for ($i5persistentconnect=1;$i5persistentconnect>-1;$i5persistentconnect--) { if ($i5persistentconnect) $conn = db2_pconnect($database,$user,$password); else $conn = db2_connect($database,$user,$password); if (!$conn) echo "<br>Bad connect: $conn,$database,$user,perm=$i5persistentconnect"; else echo "<br>Good connect: $conn,$database,$user,perm=$i5persistentconnect"; if ($i5persistentconnect) $ok = true; else $ok = db2_close($conn); echo ",ok=$ok\n"; } }
run the test Apache …
Point your browser to php program ... http://myibmi/xxtoolkit_connect.php Good connect: Resource id #2,*LOCAL,DB2,perm=1,ok=1 Good connect: Resource id #3,*LOCAL,DB2,perm=0,ok=1 Good connect: Resource id #4,*LOCAL,DB2,perm=1,ok=1 :
run the test 2-tier … I choose to run from command line on my Linux machine, but Linux Apache would also work.
$ which php /usr/local/zend/bin/php $ php xxtoolkit_connect.php <br>Good connect: Resource id #5,LP0264D,DB2,perm=1,ok=1 <br>Good connect: Resource id #6,LP0264D,DB2,perm=0,ok=1 <br>Good connect: Resource id #7,LP0264D,DB2,perm=1,ok=1 :
No, not working???
At this level we want to check our PHP raw XML Toolkit built on top of ibm_db2 connections (Level 2).
Note:
Test number #3
Install the following simple test in your Document root and see if “success” appears in your browser.
/MYASP2/www/zend2/htdocs/connection2.inc <?php $database = "*LOCAL"; // *LOCAL on IBM i ... LP0264D on Linux $cwdatabase = "localhost"; $user = "DB2"; $password = "XXXXXXXX"; $libxmlservice = "ZENDSVR"; // ZZCALL (Zend Server) $i5persistentconnect = false; ?> /MYASP2/www/zend2/htdocs/xxtoolkit_raw.php <?php require_once('connection2.inc'); if ($i5persistentconnect) $conn = db2_pconnect($database,$user,$password); else $conn = db2_connect($database,$user,$password); if (!$conn) echo "Bad connect: $conn,$database,$user,perm=$i5persistentconnect"; $stmt = db2_prepare($conn, "call XMLSERVICE.iPLUG4K(?,?,?,?)"); $ctl = "*sbmjob"; // *here for no additional private job $ipc='/tmp/packers'; // $ipc = ""; // *here no need ipc $clobIn = "<?xml version='1.0'?> <pgm name='ZZCALL' lib='$libxmlservice'> <parm io='both'> <data type='1A'>a</data> </parm> <parm io='both'> <data type='1A'>b</data> </parm> <parm io='both'> <data type='7p4'>11.1111</data> </parm> <parm io='both'> <data type='12p2'>222.22</data> </parm> <parm io='both'> <ds> <data type='1A'>x</data> <data type='1A'>y</data> <data type='7p4'>66.6666</data> <data type='12p2'>77777.77</data> </ds> </parm> <return> <data type='10i0'>0</data> </return> </pgm>"; $clobOut = ""; $ret=db2_bind_param($stmt, 1, "ipc", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 2, "ctl", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 3, "clobIn", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 4, "clobOut", DB2_PARAM_OUT); $ret=db2_execute($stmt); // var_dump($clobOut); if (strpos($clobOut,"4444444444.44")>0) echo "success"; else echo "fail"; ?>
run the test Apache …
Point your browser to php program ... http://myibmi/xxtoolkit_raw.php success
run the test 2-tier … I choose to run from command line on my Linux machine, but Linux Apache would also work.
$ which php /usr/local/zend/bin/php $ php xxtoolkit_raw.php success
No, not working???
Ok, next run stress test …
call qp2term > cd /usr/local/Zend/apache2/bin > ab -t 25 -c 10 http://lp0264d/xxtoolkit_raw.php -t 25 -- 25 seconds -c 10 -- 10 concurrent browsers (simulates ten browsers)
At this level we want to check our PHP CW Toolkit built on top of raw XML Toolkit (Level 3).
Note:
Test number #4
Install the following simple test in your Document root and see if “success” appears in your browser.
/MYASP2/www/zend2/htdocs/connection2.inc <?php $database = "*LOCAL"; // *LOCAL on IBM i ... LP0264D on Linux $cwdatabase = "localhost"; $user = "DB2"; $password = "XXXXXXXX"; $libxmlservice = "ZENDSVR"; // ZZCALL (Zend Server) $i5persistentconnect = false; ?> /MYASP2/www/zend2/htdocs/xxtoolkit_new.php <?php require_once('connection2.inc'); require_once("ToolkitService.php"); if ($i5persistentconnect) $conn = db2_pconnect($database,$user,$password); else $conn = db2_connect($database,$user,$password); if (!$conn) echo "Bad connect: $conn,$database,$user,perm=$i5persistentconnect"; try { $ToolkitServiceObj = ToolkitService::getInstance($conn); } catch (Exception $e) { die($e->getMessage()); } $param[] = $ToolkitServiceObj->AddParameterChar ('both', 1, 'INCHARA', 'var1', 'Y'); $param[] = $ToolkitServiceObj->AddParameterChar ('both', 1, 'INCHARB', 'var2', 'Z'); $param[] = $ToolkitServiceObj->AddParameterPackDec('both', 7,4,'INDEC1', 'var3', '001.0001'); $param[] = $ToolkitServiceObj->AddParameterPackDec('both', 12,2,'INDEC2', 'var4', '0000000003.04'); $ds[] = $ToolkitServiceObj->AddParameterChar ('both', 1, 'DSCHARA', 'ds1', 'A'); $ds[] = $ToolkitServiceObj->AddParameterChar ('both', 1, 'DSCHARB', 'ds2', 'B'); $ds[] = $ToolkitServiceObj->AddParameterPackDec('both', 7,4,'DSDEC1', 'ds3', '005.0007'); $ds[] = $ToolkitServiceObj->AddParameterPackDec('both', 12,2,'DSDEC1', 'ds4', '0000000006.08'); $param[] = $ToolkitServiceObj->AddDataStruct($ds); $clobOut = $ToolkitServiceObj->PgmCall('ZZCALL', $libxmlservice, $param, null, null); // var_dump($clobOut); $value = "what is ...".$clobOut["io_param"]["ds4"]; if (strpos($value,"4444444444.44")>-1) echo "success"; else echo "fail";
run the test Apache …
Point your browser to php program ... http://myibmi/xxtoolkit_new.php success
run the test 2-tier … I choose to run from command line on my Linux machine, but Linux Apache would also work.
$ which php /usr/local/zend/bin/php $ php xxtoolkit_new.php success
No, not working???
Ok, next run stress test …
call qp2term > cd /usr/local/Zend/apache2/bin > ab -t 25 -c 10 http://lp0264d/xxtoolkit_new.php -t 25 -- 25 seconds -c 10 -- 10 concurrent browsers (simulates ten browsers)
At this level we want to check our PHP CW Toolkit built on top of new Toolkit (Level 4).
Note:
Test number #5
Install the following simple test in your Document root and see if “success” appears in your browser.
/MYASP2/www/zend2/htdocs/connection2.inc <?php $database = "*LOCAL"; // *LOCAL on IBM i ... LP0264D on Linux $cwdatabase = "localhost"; $user = "DB2"; $password = "XXXXXXXX"; $libxmlservice = "ZENDSVR"; // ZZCALL (Zend Server) $i5persistentconnect = false; ?> /MYASP2/www/zend2/htdocs/xxtoolkit_cw.php <?php require_once('connection2.inc'); require_once('CW/cw.php'); // new toolkit compatibility (Alan) /* connect */ if ($i5persistentconnect) $conn = i5_pconnect($cwdatabase,$user,$password); else $conn = i5_connect($cwdatabase,$user,$password); if (!$conn) echo "Bad connect: $conn,$cwdatabase,$user,perm=$i5persistentconnect"; if (!$conn) { $tab = i5_error(); die("fail Connect: ".$tab[2]." "."$tab[3], $tab[0]"); } /* prepare */ $description = array ( // single parms array ( "Name"=>"INCHARA","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_CHAR,"Length"=>"1"), array ( "Name"=>"INCHARB","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_CHAR,"Length"=>"1"), array ( "Name"=>"INDEC1","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_PACKED,"Length"=>"7.4"), array ( "Name"=>"INDEC2","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_PACKED,"Length"=>"12.2"), // structure parm array ( "DSName"=>"INDS1", "Count"=>1, "DSParm"=> array ( array ( "Name"=>"DSCHARA","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_CHAR,"Length"=>"1"), array ( "Name"=>"DSCHARB","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_CHAR,"Length"=>"1"), array ( "Name"=>"DSDEC1","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_PACKED,"Length"=>"7.4"), array ( "Name"=>"DSDEC2","IO"=>I5_IN|I5_OUT,"Type"=>I5_TYPE_PACKED,"Length"=>"12.2"), ) ) ); $pgm = i5_program_prepare("$libxmlservice/ZZCALL", $description); if (!$pgm) { $tab = i5_error(); die("fail Prepare: ".$tab[2]." "."$tab[3], $tab[0]"); } // *** parameter list allocation $list= array ( "DSCHARA"=>"x", "DSCHARB"=>"y", "DSDEC1"=>66.6666, "DSDEC2"=>77777.77, ); // *** parameter values passed to procedure $in = array ( "INCHARA"=>"a", "INCHARB"=>"b", "INDEC1"=>11.1111, "INDEC2"=>222.22, "INDS1"=>$list, ); // *** name of variables created for out parameters $out = array ( "INCHARA"=>"INCHARA", "INCHARB"=>"INCHARB", "INDEC1"=>"INDEC1", "INDEC2"=>"INDEC2", "INDS1"=>"INDS1", ); $rc=i5_program_call($pgm, $in, $out); if ($rc != false) { if ($INCHARA != 'C') die("fail C == $INCHARA\n"); if ($INCHARB != 'D') die("fail D == $INCHARB\n"); if ($INDEC1 != 321.1234) die("fail 321.1234 == $INDEC1\n"); if ($INDEC2 != 1234567890.12) die("fail 1234567890.12 = $INDEC2\n"); if ($INDS1["DSCHARA"] != 'E' || $INDS1["DSCHARB"] != 'F' || $INDS1["DSDEC1"] != 333.333 || $INDS1["DSDEC2"] != 4444444444.44) { var_dump($INDS1); die("fail DS not correct\n"); } } else { $tab = i5_error(); die("fail Call: ".$tab[2]." "."$tab[3], $tab[0]"); } // good echo "success"; ?>
run the test Apache …
Point your browser to php program ... http://myibmi/xxtoolkit_cw.php success
run the test 2-tier … I choose to run from command line on my Linux machine, but Linux Apache would also work.
$ which php /usr/local/zend/bin/php $ php xxtoolkit_cw.php success
No, not working???
Ok, next run stress test …
call qp2term > cd /usr/local/Zend/apache2/bin > ab -t 25 -c 10 http://lp0264d/xxtoolkit_cw.php -t 25 -- 25 seconds -c 10 -- 10 concurrent browsers (simulates ten browsers)
Apache ab tool — Apache ab web site stress tests are performed from the 5250 command line (call qp2term) or ssh myibmi using PASE (see Apache ab link install instructions)
Example run my machine …
> ab -t 25 -c 10 http://lp0264d/hello.php This is ApacheBench, Version 2.0.40-dev <$Revision: 1.146 $> apache-2.0 Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright 2006 The Apache Software Foundation, http://www.apache.org/ Benchmarking lp0264d (be patient) Completed 5000 requests Completed 10000 requests Completed 15000 requests Completed 20000 requests Finished 20325 requests Server Software: Apache Server Hostname: lp0264d Server Port: 80 Document Path: /hello.php Document Length: 11 bytes Concurrency Level: 10 Time taken for tests: 25.5119 seconds Complete requests: 20325 Failed requests: 0 Write errors: 0 Total transferred: 3394275 bytes HTML transferred: 223575 bytes Requests per second: 812.83 [#/sec] (mean) <--- 800 hits/second Time per request: 12.303 [ms] (mean) Time per request: 1.230 [ms] (mean, across all concurrent requests) Transfer rate: 132.53 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 1.1 0 30 Processing: 2 11 7.2 10 322 Waiting: 2 10 7.2 10 322 Total: 2 11 7.3 11 322 Percentage of the requests served within a certain time (ms) 50% 11 66% 12 75% 14 80% 15 90% 17 95% 19 98% 21 99% 23 100% 322 (longest request) >
wrkactjob — during Apache ab test you can use refresh on wrkactjob scree to see the php-cgi jobs working
Work with Active Jobs LP0264D 05/16/12 13:37:25 CPU %: 100.0 Elapsed time: 00:00:00 Active jobs: 295 Type options, press Enter. 2=Change 3=Hold 4=End 5=Work with 6=Release 7=Display message 8=Work with spooled files 13=Disconnect ... Current Opt Subsystem/Job User Type CPU % Function Status ZEND2 QTMHHTTP BCI .0 PGM-zfcgi SELW ZEND2 QTMHHTTP BCI .0 PGM-php-cgi.bi THDW ZEND2 QTMHHTTP BCI .0 PGM-php-cgi.bi THDW ZEND2 QTMHHTTP BCI 2.8 PGM-php-cgi.bi TIMA ZEND2 QTMHHTTP BCI 1.8 PGM-php-cgi.bi TIMA ZEND2 QTMHHTTP BCI 2.3 PGM-php-cgi.bi TIMA ZEND2 QTMHHTTP BCI 2.8 PGM-php-cgi.bi TIMA ZEND2 QTMHHTTP BCI 1.8 PGM-php-cgi.bi RUN ZEND2 QTMHHTTP BCI 1.4 PGM-php-cgi.bi TIMA
IF you are running a private connection (ipc=‘/tmp/packers’), you can simply use WRKACTJOB and locate the XMLSERVICE job and attach debugger. However the next qsysopr message option is also available.
At times it is useful to stop the XMLSERVICE job to connect a debugger to examine an issue, especially if you are running stateless in the QSQSRVR job.
I often find the simple trick below to be very useful.
The trick …
At this time the PHP wrappers have not implemented a stop for debugger interface (cough … Alan), but XMLSERVICE has control *debug ability already available. In the following example adding $ctl .= " *debug";
will stop XMLSERVICE job with a inquire message on qsysopr, simply attach your debugger to job # in msg, set a breakpoint in your module (or in XMLSERVICE module), and answer qsysopr message with any character to let XMLSERVICE continue to your breakpoint. That is it …
Hint: PHP wrappers are sending XML just like below, so if you have toolkit.ini debug turned on you can often simply cut/paste your XML in debug log into the variable $clobIn below.
Test #3 as example …
/MYASP2/www/zend2/htdocs/connection2.inc <?php $database = "*LOCAL"; // *LOCAL on IBM i ... LP0264D on Linux $cwdatabase = "localhost"; $user = "DB2"; $password = "XXXXXXXX"; $libxmlservice = "ZENDSVR"; // ZZCALL (Zend Server) $i5persistentconnect = false; ?> /MYASP2/www/zend2/htdocs/xxtoolkit_raw.php <?php require_once('connection2.inc'); if ($i5persistentconnect) $conn = db2_pconnect($database,$user,$password); else $conn = db2_connect($database,$user,$password); if (!$conn) echo "Bad connect: $conn,$database,$user,perm=$i5persistentconnect"; $stmt = db2_prepare($conn, "call XMLSERVICE.iPLUG4K(?,?,?,?)"); $ctl = "*sbmjob"; // *here for no additional private job $ctl .= " *debug"; // THIS WILL STOP XMLSERVICE JOB MSG TO QSYSOPR (server side) // $ctl .= " *debugproc"; // THIS WILL STOP XMLSERVICE/QSQSRVR JOB MSG TO QSYSOPR (client side) // if running *here either *debug/*debugproc will work $ipc='/tmp/packers'; // $ipc = ""; // *here no need ipc $clobIn = "<?xml version='1.0'?> <pgm name='ZZCALL' lib='$libxmlservice'> <parm io='both'> <data type='1A'>a</data> </parm> <parm io='both'> <data type='1A'>b</data> </parm> <parm io='both'> <data type='7p4'>11.1111</data> </parm> <parm io='both'> <data type='12p2'>222.22</data> </parm> <parm io='both'> <ds> <data type='1A'>x</data> <data type='1A'>y</data> <data type='7p4'>66.6666</data> <data type='12p2'>77777.77</data> </ds> </parm> <return> <data type='10i0'>0</data> </return> </pgm>"; $clobOut = ""; $ret=db2_bind_param($stmt, 1, "ipc", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 2, "ctl", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 3, "clobIn", DB2_PARAM_IN); $ret=db2_bind_param($stmt, 4, "clobOut", DB2_PARAM_OUT); $ret=db2_execute($stmt); // var_dump($clobOut); if (strpos($clobOut,"4444444444.44")>0) echo "success"; else echo "fail"; ?>
Hint: If $clobIn PHP XML single quote / double quote issues are driving you nuts try the following technique.
BTW — For the enterprising do-it-yourself PHP builder you can see how very easy it would be to make a custom call *PGM API with parameter substitution using str_replace() function similar to test_lib_replace() … something like function ZZCALL($INCHARA,$INCHARB,$INDEC1,$INDEC2,$INDS1)
$xml = <<<ENDPROC <?xml version='1.0'?> <script> <pgm name='ZZCALL' lib='xyzlibxmlservicexyz'> <parm io='both'> <data type='1A' var='INCHARA'>a</data> </parm> <parm io='both'> <data type='1A' var='INCHARB'>b</data> </parm> <parm io='both'> <data type='7p4' var='INDEC1'>11.1111</data> </parm> <parm io='both'> <data type='12p2' var='INDEC2'>222.22</data> </parm> <parm io='both'> <ds> <data type='1A' var='INDS1.DSCHARA'>x</data> <data type='1A' var='INDS1.DSCHARB'>y</data> <data type='7p4' var='INDS1.DSDEC1'>66.6666</data> <data type='12p2' var='INDS1.DSDEC2'>77777.77</data> </ds> </parm> <return> <data type='10i0'>0</data> </return> </pgm> </script> ENDPROC; $clobIn = test_lib_replace($xml); // xml common text replacement function test_lib_replace($xml) { global $libxmlservice, $iOPM; if (!$iOPM) { $was = array("xyzlibxmlservicexyz"); $now = array("$libxmlservice"); } else { $was = array("xyzlibxmlservicexyz","<pgm"); $now = array("$libxmlservice","<pgm mode='opm'"); } $out = str_replace($was,$now,$xml); return $out; }
Debug technique: -------------- It's as easy as 1-2-3-4-5-6-7-8-9-10 :) 1. Add the following line to your PHP script before the program call to be debugged. $toolkitConn should be your toolkit connection object. $toolkitConn->setOptions(array('customControl'=>'*debug')). Run your script. The script will "hang" while it waits on #2 below... (move to green screen 5250 for steps 2-10) 2. A MSGW inquiry message in DSPMSG QSYSOPR will be generated by the toolkit. 3. Note the job information (number, name, user) provided in the MSGW. 4. STRSRVJOB using that job information as parameters. 5. STRDBG with the program and library you wish to debug. 6. Answer the MSGW. Any answer will do--"G" is fine. 7. The RPG program source will appear in debug mode in your terminal, ready to step through, allowing you to inspect variables, etc. 8. When done inspecting and stepping, let the RPG program complete (using function keys indicated on screen). 9. ENDDBG 10. ENDSRVJOB
Tony “Ranger” Cairns - IBM i PHP / PASE