PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/code/classes/Daemon/NetBatch/Persist.class.php

https://github.com/blekkzor/pinetd2
PHP | 123 lines | 102 code | 16 blank | 5 comment | 12 complexity | 7f1563bec05b09502138b5cf584a2edc MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. namespace Daemon\NetBatch;
  3. use pinetd\Logger;
  4. use pinetd\IPC;
  5. use pinetd\SQL;
  6. use pinetd\Timer;
  7. class Persist extends \pinetd\Process {
  8. protected $runners = array();
  9. protected $run_login = array();
  10. public function __construct($id, $daemon, $IPC, $node) {
  11. parent::__construct($id, $daemon, $IPC, $node);
  12. }
  13. public function run(array $pkt, array $login) {
  14. $IPC = $this->getRunner($login);
  15. return $IPC->doCall('doRun', array($pkt));
  16. }
  17. public function poll($pid, array $login) {
  18. $IPC = $this->getRunner($login);
  19. return $IPC->doCall('pollPid', array($pid));
  20. }
  21. public function proxy($pid, array $login, $func, array $args) {
  22. $IPC = $this->getRunner($login);
  23. $IPC->doCall($func, $args);
  24. return $IPC->doCall('pollPid', array($pid));
  25. }
  26. protected function getRunner(array $login) {
  27. if (isset($this->run_login[$login['login']])) {
  28. $pid = $this->run_login[$login['login']];
  29. if (isset($this->runners[$pid])) {
  30. return $this->runners[$pid]['IPC'];
  31. }
  32. }
  33. $this->launchRunner($login);
  34. if (isset($this->run_login[$login['login']])) {
  35. $pid = $this->run_login[$login['login']];
  36. if (isset($this->runners[$pid])) {
  37. return $this->runners[$pid]['IPC'];
  38. }
  39. }
  40. throw new Exception('Failed to start runner!');
  41. }
  42. protected function launchRunner(array $login) {
  43. $pair = stream_socket_pair(STREAM_PF_UNIX, STREAM_SOCK_STREAM, 0);
  44. $pid = pcntl_fork();
  45. if ($pid > 0) {
  46. // parent's speaking
  47. SQL::parentForked(); // close all sql links to avoid bugs
  48. fclose($pair[1]);
  49. $this->runners[$pid] = array(
  50. 'pid' => $pid,
  51. 'launch' => time(),
  52. 'IPC' => new IPC($pair[0], false, $this, $this->IPC),
  53. );
  54. $this->run_login[$login['login']] = $pid;
  55. $this->IPC->registerSocketWait($pair[0], array($this->runners[$pid]['IPC'], 'run'), $foobar = array(&$this->runners[$pid]));
  56. usleep(50000); // give time for the child to init
  57. return true;
  58. }
  59. if ($pid == 0) {
  60. SQL::parentForked(); // close all sql links to avoid bugs
  61. Timer::reset();
  62. fclose($pair[0]);
  63. $IPC = new IPC($pair[1], true, $foo = null, $this->IPC);
  64. Logger::setIPC($IPC);
  65. Logger::log(Logger::LOG_DEBUG, 'Persistent runner started with pid '.getmypid());
  66. $class = relativeclass($this, 'Persist_Client');
  67. $child = new $class($IPC);
  68. $child->setLogin($login);
  69. $child->mainLoop($IPC);
  70. exit;
  71. }
  72. }
  73. public function IPCDied($fd) {
  74. $info = $this->IPC->getSocketInfo($fd);
  75. $this->IPC->removeSocket($fd);
  76. unset($this->runners[$info['pid']]);
  77. // $info = &$this->fclients[$info['pid']];
  78. // Logger::log(Logger::LOG_WARN, 'IPC for '.$info['pid'].' died');
  79. }
  80. public function shutdown() {
  81. // send stop signal to clients
  82. Logger::log(Logger::LOG_INFO, 'MTA stopping...');
  83. foreach($this->runners as $pid => $data) {
  84. $data['IPC']->stop();
  85. }
  86. return true;
  87. }
  88. public function mainLoop() {
  89. parent::initMainLoop();
  90. $this->IPC->createPort('NetBatch::Persist', $this);
  91. while(1) {
  92. $this->IPC->selectSockets(200000);
  93. }
  94. }
  95. public function childSignaled($res, $status, $signal = NULL) {
  96. if (count($this->runners) == 0) return; // nothing to do
  97. // search what ended
  98. $ended = $this->runners[$res];
  99. if (is_null($ended)) return; // we do not know what ended
  100. if (is_null($signal)) {
  101. Logger::log(Logger::LOG_DEBUG, 'Process runner with pid #'.$res.' exited');
  102. } else {
  103. Logger::log(Logger::LOG_INFO, 'Process runner with pid #'.$res.' died due to signal '.$signal);
  104. }
  105. unset($this->runners[$res]);
  106. }
  107. }