sThread
[ class tree: sThread ] [ index: sThread ] [ all elements ]

Source for file sThread.php

Documentation is available at sThread.php

  1. <?php
  2. /**
  3.  * Project: sThread :: Single Thread Monitoring Agent API<br>
  4.  * File: sThread.php
  5.  *
  6.  * sThread package는 async 방식의 L7 layer 모니터링 에이전트
  7.  * 이다.
  8.  *
  9.  * sThread package는 libevent를 이용하여 Multi session과
  10.  * 동시에 여러가지 protocol을 처리할 수 있도록 설계가 있다.
  11.  *
  12.  * 모듈 구조를 지원하므로, 필요한 모듈을 직접 만들어 추가할 수
  13.  * 있다.
  14.  *
  15.  * @category    Network
  16.  * @package     sThread
  17.  * @author      JoungKyun.Kim <http://oops.org>
  18.  * @copyright   (c) 2018, OOPS.ORG
  19.  * @license     BSD License
  20.  * @link        http://pear.oops.org/package/sThread
  21.  * @since       File available since relase 1.0.0
  22.  * @filesource
  23.  */
  24.  
  25. // {{{ 기본 include package
  26. /**
  27.  * include ePrint package
  28.  */
  29. require_once 'ePrint.php';
  30. /**
  31.  * sThread에서 사용하는 공통 변수 관리 Class
  32.  */
  33. require_once 'sThread/Vari.php';
  34. /**
  35.  * sThread에서 사용하는 모듈 관리 Class
  36.  */
  37. require_once 'sThread/Module.php';
  38. /**
  39.  * sThread에서 사용하는 주소 관리 Class
  40.  */
  41. require_once 'sThread/Addr.php';
  42. /**
  43.  * sThread의 logging Class
  44.  */
  45. require_once 'sThread/Log.php';
  46. // }}}
  47.  
  48. /**
  49.  * sThread 패키지의 메인 Class
  50.  *
  51.  * sThread package는 async 방식의 L7 layer 모니터링 에이전트
  52.  * 이다.
  53.  *
  54.  * sThread package는 libevent를 이용하여 Multi session과
  55.  * 동시에 여러가지 protocol을 처리할 수 있도록 설계가 있다.
  56.  *
  57.  * 모듈 구조를 지원하므로, 필요한 모듈을 직접 만들어 추가할 수
  58.  * 있다.
  59.  *
  60.  * @category    Network
  61.  * @package     sThread
  62.  * @author      JoungKyun.Kim <http://oops.org>
  63.  * @copyright   (c) 2018, OOPS.ORG
  64.  * @license     BSD License
  65.  * @link        http://pear.oops.org/package/sThread
  66.  */
  67. Class sThread {
  68.     // {{{ properties
  69.     // {{{ sThread constants
  70.     /**#@+
  71.      * @access public
  72.      */
  73.     /**
  74.      * sThread Major version 번호
  75.      */
  76.     const MAJOR_VERSION 1;
  77.     /**
  78.      * sThread Minor version 번호
  79.      */
  80.     const MINOR_VERSION 0;
  81.     /**
  82.      * sThread Patch 레벨 번호
  83.      */
  84.     const PATCH_VERSION 1;
  85.     /**
  86.      * sThread 버전
  87.      */
  88.     const VERSION '1.0.1';
  89.     /**#@-*/
  90.     // }}}
  91.  
  92.     /**#@+
  93.      * @access public
  94.      */
  95.     /**
  96.      * sThread_Module 패키지에서 등록한 모듈 object
  97.      * @var object 
  98.      */
  99.     static public $mod;
  100.     /**
  101.      * libevent 동작을 sync로 할지 async로 할지 여부.
  102.      * 기본값 'false'
  103.      * @var boolean 
  104.      */
  105.     static public $async;
  106.     /**
  107.      * 저장할 로그 파일 이름
  108.      * @var string 
  109.      */
  110.     static public $logfile;
  111.     /**
  112.      * 저장할 로그 파일이름 postfix.
  113.      * data function의 format으로 지정해야 한다.
  114.      * @var string 
  115.      */
  116.     static public $logformat;
  117.     /**
  118.      * 로그 저장 여부
  119.      * <ul>
  120.      *     <li>0  -> 실패한 로그만 저장</li>
  121.      *     <li>1  -> 모든 로그 저장</li>
  122.      *     <li>-1 -> 로그 저장 안함</li>
  123.      * </ul>
  124.      *
  125.      * @var int 
  126.      */
  127.     static public $logtype;
  128.     /**
  129.      * 실행 결과 데이터 보존 여부
  130.      * @var boolean 
  131.      */
  132.     static public $result = false;
  133.     /**#@-*/
  134.  
  135.     /**#@+
  136.      * @access private
  137.      */
  138.     /**
  139.      * 소켓 연결/읽기/쓰기 타임아웃
  140.      * @var    int 
  141.      */
  142.     static private $tmout;
  143.  
  144.     /**
  145.      * socket create interval
  146.      * @var    int 
  147.      */
  148.     static private $timer 200;
  149.     /**#@-*/
  150.     // }}}
  151.  
  152.     // {{{ (sThread) sThread::__construct (void)
  153.     /**
  154.      * OOP 스타일의 sThread Class 초기화
  155.      *
  156.      * @access public
  157.      * @return sThread 
  158.      */
  159.     function __construct ({
  160.         self::init ();
  161.         $this->mod     = &self::$mod;
  162.         $this->tmout   &self::$tmout;
  163.         $this->async   = &self::$async;
  164.         $this->result  = &self::$result;
  165.  
  166.         # sThread_LOG varibles
  167.         $this->logfile   = &sThread_Log::$fname;
  168.         $this->logformat = &sThread_Log::$format;
  169.         $this->logtype   = &sThread_Log::$type;
  170.     }
  171.     // }}}
  172.  
  173.     // {{{ (void) sThread::init ($mod_no_init = false)
  174.     /**
  175.      * sThread Class를 초기화 한다.
  176.      *
  177.      * @access public
  178.      * @return void 
  179.      * @param  bool (optional) true로 설정을 하면 sThread_Module
  180.      *               class를 호출 하지 않는다. 기본값 false.
  181.      */
  182.     function init ($mod_no_init false{
  183.         if $mod_no_init === false {
  184.             sThread_Module::init ();
  185.             self::$mod &sThread_Module::$obj;
  186.             self::$async  false;
  187.         }
  188.  
  189.         self::$result false;
  190.         Vari::$result &self::$result;
  191.  
  192.         # sThread_LOG varibles
  193.         self::$logfile   &sThread_Log::$fname;
  194.         self::$logformat &sThread_Log::$format;
  195.         self::$logtype   &sThread_Log::$type;
  196.     }
  197.     // }}}
  198.  
  199.     // {{{ (void) sThread::execute ($host, $tmout = 1, $protocol = 'tcp')
  200.     /**
  201.      * sThread를 실행한다.
  202.      *
  203.      * 실행 후 결과값은 Vari::$res 와 Vari::$sess 의 값을 확인하면
  204.      * 된다.
  205.      *
  206.      * @access public
  207.      * @return void 
  208.      * @param  mixed  연결 정보.<br>
  209.      *          host의 형식은 기본적으로 문자열 또는 배열을 사용할 수 있다.
  210.      *
  211.      *          주소 형식은 기본적으로 도메인이름 또는 IP주소와 PORT 번호로
  212.      *          구성이 된다.
  213.      *
  214.      *          <code>
  215.      *          $host = 'test.domaint.com:80';
  216.      *          </code>
  217.      *
  218.      *          sThread package의 장점은 여러개의 실행을 동시에 할 수 있다는
  219.      *          것이므로, 여러개의 주소를 한번에 넘길 경우에는 배열을 이용한다.
  220.      *
  221.      *          <code>
  222.      *          $host = array (
  223.      *              'test.domain.com:80',
  224.      *              'test1.domain.com:53',
  225.      *              'test16.domain.com:80'
  226.      *          );
  227.      *          </code>
  228.      * @param  int    소켓 연결/읽기/쓰기 타임아웃
  229.      * @param  string tcp 또는 udp. 기본값 tcp.
  230.      */
  231.     function execute ($hosts$tmout 1$protocol null{
  232.         Vari::clear ();
  233.         if is_array ($hosts) )
  234.             $hosts array ($hosts);
  235.  
  236.         self::$tmout $tmout;
  237.  
  238.         $sess &Vari::$sess;
  239.         $res  &Vari::$res;
  240.         $time &Vari::$time;
  241.  
  242.         $key 0;
  243.         foreach $hosts as $line {
  244.             $res->total++;
  245.             $line rtrim ($line);
  246.             if ( ($newline sThread_Address::parse ($line$key)) === false {
  247.                 list ($host$portexplode (':'$line);
  248.                 $res->failure++;
  249.                 $sess->status[$keyVari::EVENT_ERROR_CLOSE;
  250.                 $res->status[$keyarray ("{$host}:{$port}"false"Address parsing error");
  251.                 $key++;
  252.                 continue;
  253.             }
  254.  
  255.             $sess->opt[$keysThread_Address::extraOption ($newline);
  256.             $sess->addr[$keyexplode (':'$newline);
  257.  
  258.             self::explodeAddr ($host$port$type$newline);
  259.  
  260.             if $protocol == null {
  261.                 $protocol sThread_Module::proto ($type);
  262.                 if $protocol )
  263.                     $protocol 'tcp';
  264.             }
  265.  
  266.             $sess->proto[$key$protocol;
  267.             $addr "{$protocol}://{$host}:{$port}";
  268.  
  269.             $time->cstart[$keymicrotime ();
  270.             $async (self::$async === true?
  271.                     STREAM_CLIENT_CONNECT|STREAM_CLIENT_ASYNC_CONNECT STREAM_CLIENT_CONNECT;
  272.             $sess->sock[$key@stream_socket_client (
  273.                 $addr$errno$errstrself::$tmout$async
  274.             );
  275.             usleep (self::$timer);
  276.  
  277.             if self::$async !== true && is_resource ($sess->sock[$key]) ) {
  278.                 if ePrint::$debugLevel >= Vari::DEBUG1 {
  279.                     ePrint::ePrintf (
  280.                         "%s:%d (%02d) Failed socket create: %s on %s:%d[%s::%s]",
  281.                         array (
  282.                             $host$port$key$errstr,
  283.                             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  284.                         )
  285.                     );
  286.                 }
  287.                 $res->failure++;
  288.                 self::$mod->$type->set_last_status ($sess$key);
  289.                 $res->status[$keyarray ("{$host}:{$port}"false"Failed socket create: {$errstr}");
  290.                 $key++;
  291.                 self::timeResult ($key);
  292.                 continue;
  293.             }
  294.             $time->cend[$keymicrotime ();
  295.  
  296.             ePrint::dPrintf (
  297.                 Vari::DEBUG1"[%-12s #%d] %s:%d (%d) Socket create success on %s:%d[%s::%s]\n",
  298.                 get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port$key,
  299.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  300.             );
  301.  
  302.             $sess->status[$key1;
  303.             $sess->send[$keyVari::EVENT_READY_SEND;
  304.             stream_set_timeout ($sess->sock[$key]self::$tmout0);
  305.             stream_set_blocking ($sess->sock[$key]0);
  306.  
  307.             $host_all[$key$host;
  308.             $port_all[$key$port;
  309.             $key++;
  310.         }
  311.  
  312.         $base event_base_new ();
  313.         ePrint::dPrintf (
  314.             Vari::DEBUG1"[%-12s #%02d] Make event construct on %s:%d[%s::%s]\n",
  315.             get_resource_type ($base)$base,
  316.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  317.         );
  318.  
  319.         foreach $sess->sock as $key => $val {
  320.             if is_resource ($val) )
  321.                 continue;
  322.  
  323.             $time->pstart[$keymicrotime ();
  324.             $sess->event[$keyevent_buffer_new (
  325.                     $sess->sock[$key],
  326.                     'self::readCallback',
  327.                     'self::writeCallback',
  328.                     'self::exceptionCallback'array ($key)
  329.             );
  330.  
  331.             ePrint::dPrintf (
  332.                 Vari::DEBUG1"[%-12s #%02d] %s:%d (%d) make event buffer on %s:%d[%s::%s]\n",
  333.                 get_resource_type ($sess->event[$key])$sess->event[$key]$host_all[$key]$port_all[$key]$key,
  334.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  335.             );
  336.  
  337.             event_buffer_timeout_set ($sess->event[$key]self::$tmoutself::$tmout);
  338.  
  339.             ePrint::dPrintf (
  340.                 Vari::DEBUG1"[%-12s #%02d] set event buffer .. ",
  341.                 get_resource_type ($base)$base$sess->event[$key]);
  342.             event_buffer_base_set ($sess->event[$key]$base);
  343.             ePrint::dPrintf (
  344.                 Vari::DEBUG1"%s #%02d on %s:%d[%s::%s]\n",
  345.                 get_resource_type ($sess->event[$key])$sess->event[$key],
  346.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  347.             );
  348.  
  349.             if self::currentStatus ($key=== Vari::EVENT_READY_RECV )
  350.                 event_buffer_enable ($sess->event[$key]EV_READ);
  351.             else
  352.                 event_buffer_enable ($sess->event[$key]EV_WRITE);
  353.         }
  354.         unset ($host_all);
  355.         unset ($port_all);
  356.  
  357.         ePrint::dPrintf (
  358.             Vari::DEBUG1"[%-12s #%02d] regist event loop on %s:%d[%s::%s]\n",
  359.             get_resource_type ($base)$base,
  360.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  361.         );
  362.         event_base_loop ($base);
  363.         self::clearEvent ();
  364.         ePrint::dPrintf (
  365.             Vari::DEBUG1"[%-15s] destruct event construct on %s:%d[%s::%s]\n",
  366.             get_resource_type ($base)$base,
  367.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  368.         );
  369.         event_base_free ($base);
  370.         unset ($base);
  371.         // 필요 없는 정보 정리
  372.         Vari::clear (true);
  373.     }
  374.     // }}}
  375.  
  376.     /**
  377.      * libevent에서 exception callback
  378.      *
  379.      * 이 함수는 아무런 작동을 하지 않는다.
  380.      *
  381.      * @return void 
  382.      * @param  resource libevent resource
  383.      * @param  int      error code
  384.      *                   EVBUFFER_READ (1)
  385.      *                   EVBUFFER_WRITE (2)
  386.      *                   EVBUFFER_EOF (16)
  387.      *                   EVBUFFER_ERROR (32)
  388.      *                   EVBUFFER_TIMEOUT (64)
  389.      */
  390.     function exceptionCallback ($buf$err{
  391.         $sess &Vari::$sess;
  392.         $res  &Vari::$res;
  393.         if ( ($key array_search ($bufVari::$sess->eventtrue)) !== false {
  394.             if $err == (EVBUFFER_READ|EVBUFFER_EOF) ) {
  395.                 ePrint::dPrintf (
  396.                     Vari::DEBUG1"[%-12s #%02d] free %s on execption callback on %s:%d[%s::%s] {$err}\n",
  397.                     get_resource_type($buf)$bufget_resource_type ($buf),
  398.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  399.                 );
  400.                 event_buffer_free ($buf);
  401.                 return;
  402.             }
  403.  
  404.             switch ($err{
  405.                 case (EVBUFFER_READ|EVBUFFER_TIMEOUT:
  406.                     $errstr 'Event buffer read timeout';
  407.                     break;
  408.                 case (EVBUFFER_WRITE|EVBUFFER_TIMEOUT:
  409.                     $errstr 'Event buffer write timeout';
  410.                     break;
  411.                 case (EVBUFFER_READ|EVBUFFER_ERROR:
  412.                     $errstr 'Event buffer read error';
  413.                     break;
  414.                 case (EVBUFFER_WRITE|EVBUFFER_ERROR:
  415.                     $errstr 'Event buffer write error';
  416.                     break;
  417.                 case (EVBUFFER_CONNECTED:
  418.                     $errstr 'Event buffer connected error';
  419.                     break;
  420.                 default:
  421.                     $errstr 'Event buffer unknown error';
  422.             }
  423.  
  424.             $res->status[$keyarray (
  425.                 sprintf ('%s:%d'$sess->addr[$key][0]$sess->addr[$key][1]),
  426.                 false,
  427.                 $errstr
  428.             );
  429.         }
  430.  
  431.         ePrint::dPrintf (
  432.             Vari::DEBUG1"[%-12s #%02d] free %s on execption callback on %s:%d[%s::%s]\n",
  433.             get_resource_type($buf)$bufget_resource_type ($buf),
  434.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  435.         );
  436.         event_buffer_free ($buf);
  437.     }
  438.     // }}}
  439.  
  440.     // {{{ (bool) sThread::readCallback ($buf, $arg)
  441.     /**
  442.      * libevent read callback
  443.      *
  444.      * 이 메소드는 외부에서 사용할 필요가 없다. private로
  445.      * 지정이 되어야 하나, event_buffer_new api가 class method를
  446.      * callback 함수로 사용을 하지 못하게 되어 있어, 외부 wrapper
  447.      * 를 통하여 호출을 하기 때문에 public으로 선언이 되었다.
  448.      *
  449.      * @access public
  450.      * @return boolean 
  451.      * @param  resource libevent resource
  452.      * @param  array    callback argument
  453.      */
  454.     function readCallback ($buf$arg{
  455.         list ($key$arg;
  456.         $sess &Vari::$sess;
  457.         $res  &Vari::$res;
  458.         self::explodeAddr ($host$port$type$sess->addr[$key]);
  459.  
  460.         ePrint::dPrintf (
  461.             Vari::DEBUG3"[%-12s #%02d] Calling %s::%s %s:%d on %s:%d\n",
  462.             get_resource_type ($sess->sock[$key])$sess->sock[$key],
  463.             __CLASS____FUNCTION__,
  464.             $host$portself::__f(__FILE__)__LINE__
  465.         );
  466.  
  467.         if self::currentStatus ($key!== Vari::EVENT_READY_RECV )
  468.             return true;
  469.  
  470.         if ( ($handler self::getCallname ($key)) === false {
  471.             self::socketClose ($key);
  472.             ePrint::dPrintf (
  473.                 Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  474.                 get_resource_type ($sess->event[$key])$sess->event[$key],
  475.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  476.             );
  477.             event_buffer_disable ($sess->event[$key]EV_READ);
  478.             event_buffer_free ($sess->event[$key]);
  479.             return true;
  480.         }
  481.  
  482.         ePrint::dPrintf (
  483.             Vari::DEBUG2"[%-12s #%02d] %s:%d Recieve %s call on %s:%d[%s::%s]\n",
  484.             get_resource_type ($sess->sock[$key])$sess->sock[$key],
  485.             $host$port$handler,
  486.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  487.         );
  488.  
  489.         $buffer null;
  490.         while strlen ($_buf event_buffer_read ($buf8192)) )
  491.             $buffer .= $_buf;
  492.  
  493.         ePrint::dPrintf (
  494.             Vari::DEBUG3"[%-12s #%02d] %s:%d Recieved data on %s:%d[%s::%s]\n",
  495.             get_resource_type ($sess->sock[$key])$sess->sock[$key],
  496.             $host$portself::__f(__FILE__)__LINE____CLASS____FUNCTION__
  497.         );
  498.         if ePrint::$debugLevel >= Vari::DEBUG3 {
  499.             $msg rtrim ($buffer);
  500.             ePrint::echoi ($msg $msg "\n" "NONE\n"8);
  501.         }
  502.  
  503.         $recvR self::$mod->$type->$handler ($sess$key$buffer);
  504.  
  505.         // {{{ 전송이 완료되지 않은 경우
  506.         if $recvR !== true {
  507.             // protocol level error
  508.             if $recvR === null {
  509.                 $res->failure++;
  510.                 self::$mod->$type->set_last_status ($sess$key);
  511.                 self::socketClose ($key);
  512.                 ePrint::dPrintf (
  513.                     Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  514.                     get_resource_type ($sess->event[$key])$sess->event[$key],
  515.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  516.                 );
  517.                 event_buffer_disable ($sess->event[$key]EV_READ);
  518.                 event_buffer_free ($sess->event[$key]);
  519.                 return true;
  520.             }
  521.             return;
  522.         }
  523.         // }}}
  524.  
  525.         ePrint::dPrintf (
  526.             Vari::DEBUG2"[%-12s #%02d] %s:%d Complete %s call on %s:%d[%s::%s]\n",
  527.             get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port$handler,
  528.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  529.         );
  530.     
  531.         /*
  532.          * Unknown status or Regular connection end
  533.          */
  534.         if ( ($is_rw self::nextStatus ($key)) === false {
  535.             self::socketClose ($key);
  536.             ePrint::dPrintf (
  537.                 Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  538.                 get_resource_type($sess->event[$key])$sess->event[$key],
  539.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  540.             );
  541.             event_buffer_disable ($sess->event[$key]EV_READ);
  542.             event_buffer_free ($sess->event[$key]);
  543.             return true;
  544.         }
  545.  
  546.         return true;
  547.     }
  548.     // }}}
  549.  
  550.     // {{{ (bool) sThread::writeCallback ($buf, $arg)
  551.     /**
  552.      * libevent write callback
  553.      *
  554.      * 이 메소드는 외부에서 사용할 필요가 없다. private로
  555.      * 지정이 되어야 하나, event_buffer_new api가 class method를
  556.      * callback 함수로 사용을 하지 못하게 되어 있어, 외부 wrapper
  557.      * 를 통하여 호출을 하기 때문에 public으로 선언이 되었다.
  558.      *
  559.      * @access public
  560.      * @return boolean 
  561.      * @param  resource libevent resource
  562.      * @param  array    callback argument
  563.      */
  564.     function writeCallback ($buf$arg{
  565.         list ($key$arg;
  566.         $sess &Vari::$sess;
  567.         $res  &Vari::$res;
  568.         list ($host$port$type$sess->addr[$key];
  569.         self::explodeAddr ($host$port$type$sess->addr[$key]);
  570.  
  571.         if $sess->send[$key=== Vari::EVENT_SEND_DONE {
  572.             $sess->send[$keyVari::EVENT_READY_SEND;
  573.             /*
  574.              * Unknown status or Regular connection end
  575.              */
  576.             if ( ($is_rw self::nextStatus ($key)) === false {
  577.                 self::socketClose ($key);
  578.                 ePrint::dPrintf (
  579.                     Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  580.                     get_resource_type ($sess->event[$key])$sess->event[$key],
  581.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  582.                 );
  583.                 event_buffer_disable ($sess->event[$key]EV_WRITE);
  584.                 event_buffer_free ($sess->event[$key]);
  585.             }
  586.             return true;
  587.         }
  588.  
  589.         ePrint::dPrintf (
  590.             Vari::DEBUG3"[%-12s #%02d] Calling %s::%s %s:%d on %s:%d\n",
  591.             get_resource_type ($sess->sock[$key])$sess->sock[$key],
  592.             __CLASS____FUNCTION__,
  593.             $host$portself::__f(__FILE__)__LINE__
  594.         );
  595.  
  596.         if self::currentStatus ($key!== Vari::EVENT_READY_SEND )
  597.             return true;
  598.  
  599.  
  600.         if ( ($handler self::getCallname ($key)) === false {
  601.             self::socketClose ($key);
  602.             ePrint::dPrintf (
  603.                 Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  604.                 get_resource_type ($sess->event[$key])$sess->event[$key],
  605.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  606.             );
  607.             event_buffer_disable ($sess->event[$key]EV_WRITE);
  608.             event_buffer_free ($sess->event[$key]);
  609.             return true;
  610.         }
  611.  
  612.         ePrint::dPrintf (
  613.             Vari::DEBUG2"[%-12s #%02d] %s:%d Send %s call on %s:%d[%s::%s]\n",
  614.             get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port$handler,
  615.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  616.         );
  617.  
  618.         $send self::$mod->$type->$handler ($sess$key);
  619.  
  620.         // make error for send packet
  621.         if $send === false {
  622.             $res->failure++;
  623.             self::$mod->$type->set_last_status ($sess$key);
  624.             self::socketClose ($key);
  625.             ePrint::dPrintf (
  626.                 Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  627.                 get_resource_type ($sess->event[$key])$sess->event[$key],
  628.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  629.             );
  630.             event_buffer_disable ($sess->event[$key]EV_WRITE);
  631.             event_buffer_free ($sess->event[$key]);
  632.             return true;
  633.         }
  634.  
  635.         if event_buffer_write ($buf$sendstrlen ($send)) === false {
  636.             if ePrint::$debugLevel >= Vari::DEBUG1 {
  637.                 ePrint::ePrintf (
  638.                     "[%-12s #%02d] Error: %s:%d Send error on %s:%d[%s::%s]",
  639.                     array (
  640.                         get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  641.                         self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  642.                     )
  643.                 );
  644.             }
  645.             $res->failure++;
  646.             self::$mod->$type->set_last_status ($sess$key);
  647.             $res->status[$keyarray ("{$host}:{$port}"false"{$handler} Send error");
  648.             self::socketClose ($key);
  649.             ePrint::dPrintf (
  650.                 Vari::DEBUG1"[%-12s #%02d] free event buffer on %s:%d[%s::%s]\n",
  651.                 get_resource_type ($sess->event[$key])$sess->event[$key],
  652.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  653.             );
  654.             event_buffer_disable ($sess->event[$key]EV_WRITE);
  655.             event_buffer_free ($sess->event[$key]);
  656.             return true;
  657.         }
  658.         ePrint::dPrintf (
  659.             Vari::DEBUG3"[%-12s #%02d] %s:%d Send data on %s:%d[%s::%s]\n",
  660.             get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  661.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  662.         );
  663.         if ePrint::$debugLevel >= Vari::DEBUG3 {
  664.             $msg rtrim ($send);
  665.             ePrint::echoi ($send "\n"8);
  666.         }
  667.  
  668.         ePrint::dPrintf (
  669.             Vari::DEBUG2"[%-12s #%02d] %s:%d Complete %s call on %s:%d[%s::%s]\n",
  670.             get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port$handler,
  671.             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  672.         );
  673.  
  674.         $sess->send[$keyVari::EVENT_SEND_DONE;
  675.     }
  676.     // }}}
  677.  
  678.     /*
  679.      * Private functions
  680.      *
  681.     // {{{ private (string) sThread::getCallname ($key)
  682.     /**
  683.      * 현재 상태의 세션 handler 이름을 반환
  684.      *
  685.      * @access private
  686.      * @return string|false
  687.      * @param  int  세션 키
  688.      */
  689.     private function getCallname ($key{
  690.         $sess &Vari::$sess;
  691.         self::explodeAddr ($host$port$type$sess->addr[$key]);
  692.         $event self::$mod->$type->call_status ($sess->status[$key]true);
  693.         if $event === false {
  694.             if ePrint::$debugLevel >= Vari::DEBUG1 {
  695.                 ePrint::ePrintf (
  696.                     "[%-12s #%02d] Error: %s:%d 'Unknown status => %d (%s)",
  697.                     array (
  698.                         get_resource_type ($sess->sock[$key])$sess->sock[$key],
  699.                         $host$port$sess->status[$key]$type
  700.                     )
  701.                 );
  702.             }
  703.             $res->failure++;
  704.             self::$mod->$type->set_last_status ($sess$key);
  705.             $res->status[$keyarray (
  706.                 "{$host}:{$port}",
  707.                 false,
  708.                 "Unknown Status: {$sess->status[$key]} ({$type})"
  709.             );
  710.             return false;
  711.         }
  712.  
  713.         return $event;
  714.     }
  715.     // }}}
  716.  
  717.     // {{{ private (int) sThread::currentStatus ($key, $next = false)
  718.     /**
  719.      * 현재의 처리 단계를 반환
  720.      *
  721.      * @access private
  722.      * @return int 
  723.      * @param  int    세션 키
  724.      * @param  boolean true로 설정이 되면 처리 단계를 다음으로 전환한다.
  725.      */
  726.     private function currentStatus ($key$next false{
  727.         $sess &Vari::$sess;
  728.         $res  &Vari::$res;
  729.         self::explodeAddr ($host$port$type$sess->addr[$key]);
  730.  
  731.         if $next !== false {
  732.             self::$mod->$type->change_status ($sess$key);
  733.             $sess->recv[$key'';
  734.         }
  735.         $is_rw self::$mod->$type->check_buf_status ($sess->status[$key]);
  736.  
  737.         /*
  738.          * $is_wr가 sThread::EVENT_READY_CLOSE 상태가 되면, 모든 작업이
  739.          * 완료된 case 이므로 socket을 닫는다. $is_rw 가 false일 경우,
  740.          * 알 수 없는 상태이므로 종료 한다.
  741.          */
  742.         if $is_rw === Vari::EVENT_READY_CLOSE || $is_rw === false {
  743.             if $is_rw === false {
  744.                 if ePrint::$debugLevel >= Vari::DEBUG1 {
  745.                     ePrint::ePrintf (
  746.                         "[%-12s #%02d] Error: %s:%d 'Unknown status => %d (%s)' on %s:%d[%s::%s]",
  747.                         array (
  748.                             get_resource_type ($sess->sock[$key])$sess->sock[$key],
  749.                             $host$port$sess->status[$key]$type,
  750.                             self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  751.                         )
  752.                     );
  753.                 }
  754.                 $res->failure++;
  755.                 self::$mod->$type->set_last_status ($sess$key);
  756.                 $res->status[$keyarray (
  757.                     "{$host}:{$port}",
  758.                     false,
  759.                     "Unknown Status: {$sess->status[$key]} ({$type})"
  760.                 );
  761.             else {
  762.                 ePrint::dPrintf (
  763.                     Vari::DEBUG1"[%-12s #%02d] %s:%d Socket close on %s:%d[%s::%s]\n",
  764.                     get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  765.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  766.                 );
  767.                 $res->success++;
  768.                 $res->status[$keyarray ("{$host}:{$port}"true'Success');
  769.             }
  770.  
  771.             return false;
  772.         }
  773.  
  774.         if $next !== false {
  775.             switch ($is_rw{
  776.                 case Vari::EVENT_READY_SEND :
  777.                     ePrint::dPrintf (
  778.                         Vari::DEBUG3"[%-12s #%02d] %s:%d Enable write event on %s:%d[%s::%s]\n",
  779.                         get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  780.                         self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  781.                     );
  782.                     event_buffer_enable ($sess->event[$key]EV_WRITE);
  783.                     event_buffer_disable ($sess->event[$key]EV_READ);
  784.                     break;
  785.                 default :
  786.                     ePrint::dPrintf (
  787.                         Vari::DEBUG3"[%-12s #%02d] %s:%d Enable read event on %s:%d[%s::%s]\n",
  788.                         get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  789.                         self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  790.                     );
  791.                     event_buffer_enable ($sess->event[$key]EV_READ);
  792.                     event_buffer_disable ($sess->event[$key]EV_WRITE);
  793.             }
  794.         }
  795.  
  796.         return $is_rw;
  797.     }
  798.     // }}}
  799.  
  800.     // {{{ private (void) sThread::explodeAddr (&$host, &$port, &$type, $v)
  801.     /**
  802.      * 주소 형식 값에서 주소, 분리, 모듈 형식을 분리해 낸다.
  803.      *
  804.      * @access private
  805.      * @return void 
  806.      * @param  reference     주소 값을 저장할 변수 reference
  807.      * @param  reference     포트 값을 저장할 변수 reference
  808.      * @param  reference     모듈 이름을 저장할 변수 reference
  809.      * @param  array|string 분리되지 않은 문자열 or 배열
  810.      */
  811.     private function explodeAddr (&$host&$port&$type$v{
  812.         list ($host$port$typeis_array ($v$v explode (':'$v);
  813.         //$type = preg_replace ('/\|.*/', '', $type);
  814.     }
  815.     // }}}
  816.  
  817.     // {{{ private (int) sThread::nextStatus ($key)
  818.     /**
  819.      * 다음 처리단계로 전환
  820.      *
  821.      * @access private
  822.      * @return int 
  823.      * @param  int    세션 키
  824.      */
  825.     private function nextStatus ($key{
  826.         return self::currentStatus ($keytrue);
  827.     }
  828.     // }}}
  829.  
  830.     // {{{ private (void) sThread::clearEvent (void)
  831.     /**
  832.      * 각 세션에서 사용한 변수들 정리 및 소켓 close
  833.      *
  834.      * @access private
  835.      * @return void 
  836.      */
  837.     private function clearEvent ({
  838.         $sess &Vari::$sess;
  839.  
  840.         foreach $sess->status as $key => $val {
  841.             self::explodeAddr ($host$port$type$sess->addr[$key]);
  842.  
  843.             if $val !== Vari::EVENT_ERROR_CLOSE &&
  844.                  self::$mod->$type->check_buf_status ($val!== Vari::EVENT_READY_CLOSE {
  845.                 list ($host$port$typeVari::$sess->addr[$key];
  846.                 Vari::$res->failure++;
  847.                 if Vari::$res->status[$key{
  848.                     if $val == )
  849.                         Vari::$res->status[$keyarray ("{$host}:{$port}"false'Connection timeout');
  850.                     else
  851.                         Vari::$res->status[$keyarray ("{$host}:{$port}"false'Protocol timeout');
  852.                 }
  853.  
  854.                 if self::$mod->$type->clearsession === true )
  855.                     self::$mod->$type->clear_session ($key);
  856.  
  857.                 self::socketClose ($key);
  858.                 if is_resource ($sess->event[$key]) )
  859.                     event_buffer_free ($sess->event[$key]);
  860.             }
  861.         }
  862.  
  863.         if empty (self::$mod->$type) )
  864.             self::$mod->$type->init();
  865.     }
  866.     // }}}
  867.  
  868.     // {{{ private (void) sThread::socketClose ($key)
  869.     /**
  870.      * @access private
  871.      * @return void 
  872.      * @param  int  세션 키
  873.      */
  874.     private function socketClose ($key{
  875.         $sess &Vari::$sess;
  876.  
  877.         list ($host$port$type$sess->addr[$key];
  878.  
  879.         if Vari::$res->status[$key][1=== false {
  880.             $handler $type '_quit';
  881.             if method_exists (self::$mod->$type$handler) ) {
  882.                 ePrint::dPrintf (
  883.                     Vari::DEBUG2"[%-12s #%02d] %s:%d Quit call on %s:%d[%s::%s]\n",
  884.                     get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  885.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  886.                 );
  887.  
  888.                 $send self::$mod->$type->$handler ($sess$key);
  889.                 @fwrite ($sess->sock[$key]$sendstrlen ($send));
  890.  
  891.                 ePrint::dPrintf (
  892.                     Vari::DEBUG3,
  893.                     "[%-12s #%02d] %s:%d Send data on %s:%d[%s::%s]\n",
  894.                     get_resource_type ($sess->sock[$key])$sess->sock[$key]$host$port,
  895.                     self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  896.                 );
  897.  
  898.                 if ePrint::$debugLevel >= Vari::DEBUG3 {
  899.                     $msg rtrim ($send);
  900.                     ePrint::echoi ($send "\n"8);
  901.                 }
  902.             }
  903.         }
  904.  
  905.         sThread_Log::save ($key$sess->recv[$key]);
  906.  
  907.         if is_resource ($sess->sock[$key]) ) {
  908.             ePrint::dPrintf (
  909.                 Vari::DEBUG2"[%-12s #%02d] close socket call on %s:%d[%s::%s]\n",
  910.                 get_resource_type ($sess->sock[$key])$sess->sock[$key],
  911.                 self::__f(__FILE__)__LINE____CLASS____FUNCTION__
  912.             );
  913.             fclose ($sess->sock[$key]);
  914.         }
  915.  
  916.         self::timeResult ($key);
  917.     }
  918.     // }}}
  919.  
  920.     // {{{ private sThread::timeResult ($key)
  921.     /**
  922.      * 수행 시간을 정리
  923.      *
  924.      * @access private
  925.      * @return void 
  926.      * @param  int  세션 키
  927.      */
  928.     private function timeResult ($key{
  929.         $time &Vari::$time;
  930.         $sess &Vari::$sess;
  931.  
  932.         if isset ($time->pstart[$key]) )
  933.             $time->pend[$keymicrotime ();
  934.  
  935.         $sess->ctime[$keyVari::chkTime ($time->cstart[$key]$time->cend[$key]);
  936.         $sess->ptime[$keyVari::chkTime ($time->pstart[$key]$time->pend[$key]);
  937.         $sess->time[$key]  Vari::timeCalc (array ($sess->ctime[$key]$sess->ptime[$key]));
  938.  
  939.         unset (Vari::$time->cstart[$key]);
  940.         unset (Vari::$time->cend[$key]);
  941.         unset (Vari::$time->pstart[$key]);
  942.         unset (Vari::$time->pend[$key]);
  943.     }
  944.     // }}}
  945.  
  946.     // {{{ +-- private (string) sThread::__f($f)
  947.     /**
  948.      * 파일 경로중 파일 이름만 리턴
  949.      *
  950.      * @access private
  951.      * @return string 
  952.      * @param string 파일 경로
  953.      */
  954.     private function __f($f{
  955.         return preg_replace ('!.*/!'''$f);
  956.     }
  957.     // }}}
  958. }
  959. ?>

Documentation generated on Fri, 30 Aug 2024 06:11:09 +0900 by phpDocumentor 1.4.4