/app-clients/LockClient.php

https://github.com/Erika31/phpdaemon · PHP · 200 lines · 111 code · 26 blank · 63 comment · 14 complexity · cc6b120e71d08fda50a0f77747aafb9a MD5 · raw file

  1. <?php
  2. /**
  3. * @package Applications
  4. * @subpackage LockClient
  5. *
  6. * @author Zorin Vasily <kak.serpom.po.yaitsam@gmail.com>
  7. */
  8. class LockClient extends AsyncServer {
  9. public $sessions = array(); // Active sessions
  10. public $servers = array(); // Array of servers
  11. public $servConn = array(); // Active connections
  12. public $prefix = ''; // Prefix
  13. public $jobs = array(); // Active jobs
  14. public $dtags_enabled = FALSE; // Enables tags for distibution
  15. /**
  16. * Setting default config options
  17. * Overriden from AppInstance::getConfigDefaults
  18. * @return array|false
  19. */
  20. protected function getConfigDefaults() {
  21. return array(
  22. // default server
  23. 'servers' => '127.0.0.1',
  24. // default port
  25. 'port' => 833,
  26. // @todo add description
  27. 'prefix' => '',
  28. 'protologging' => 0
  29. );
  30. }
  31. /**
  32. * Constructor
  33. * @return void
  34. */
  35. public function init() {
  36. $this->prefix = $this->config->prefix->value;
  37. $servers = explode(',', $this->config->servers->value);
  38. foreach ($servers as $s) {
  39. $e = explode(':',$s);
  40. $this->addServer($e[0], isset($e[1]) ? $e[1] : NULL);
  41. }
  42. }
  43. /**
  44. * Adds memcached server
  45. * @param string Server's host
  46. * @param string Server's port
  47. * @param integer Weight
  48. * @return void
  49. */
  50. public function addServer($host, $port = NULL, $weight = NULL) {
  51. if ($port === NULL) {
  52. $port = $this->config->port->value;
  53. }
  54. $this->servers[$host . ':' . $port] = $weight;
  55. }
  56. /**
  57. * Runs a job
  58. * @param string Name of job
  59. * @param bool wait. If true - will wait in queue for lock.
  60. * @param callback onRun. Job's runtime.
  61. * @param callback onSuccess. Called when job successfully done.
  62. * @param callback onFailure. Called when job failed.
  63. * @return void
  64. */
  65. public function job($name, $wait, $onRun, $onSuccess = NULL, $onFailure = NULL) {
  66. $name = $this->prefix . $name;
  67. $connId = $this->getConnectionByName($name);
  68. if (!isset($this->sessions[$connId])) {
  69. return;
  70. }
  71. $sess = $this->sessions[$connId];
  72. $this->jobs[$name] = array($onRun, $onSuccess, $onFailure);
  73. $sess->writeln('acquire' . ($wait ? 'Wait' : '') . ' ' . $name);
  74. }
  75. /**
  76. * Sends done-event
  77. * @param string Name of job
  78. * @return void
  79. */
  80. public function done($name) {
  81. $connId = $this->getConnectionByName($name);
  82. $sess = $this->sessions[$connId];
  83. $sess->writeln('done ' . $name);
  84. }
  85. /**
  86. * Sends failed-event
  87. * @param string Name of job
  88. * @return void
  89. */
  90. public function failed($name) {
  91. $connId = $this->getConnectionByName($name);
  92. $sess = $this->sessions[$connId];
  93. $sess->writeln('failed ' . $name);
  94. }
  95. /**
  96. * Establishes connection
  97. * @param string Address
  98. * @return integer Connection's ID
  99. */
  100. public function getConnection($addr) {
  101. if (isset($this->servConn[$addr])) {
  102. foreach ($this->servConn[$addr] as &$c) {
  103. return $c;
  104. }
  105. } else {
  106. $this->servConn[$addr] = array();
  107. }
  108. $e = explode(':', $addr);
  109. $connId = $this->connectTo($e[0], $e[1]);
  110. $this->sessions[$connId] = new LockClientSession($connId, $this);
  111. $this->sessions[$connId]->addr = $addr;
  112. $this->servConn[$addr][$connId] = $connId;
  113. return $connId;
  114. }
  115. /**
  116. * Returns available connection from the pool by name
  117. * @param string Key
  118. * @return object MemcacheSession
  119. */
  120. public function getConnectionByName($name) {
  121. if (
  122. ($this->dtags_enabled)
  123. && (($sp = strpos($name, '[')) !== FALSE)
  124. && (($ep = strpos($name, ']')) !== FALSE)
  125. && ($ep > $sp)
  126. ) {
  127. $name = substr($name,$sp + 1, $ep - $sp - 1);
  128. }
  129. srand(crc32($name));
  130. $addr = array_rand($this->servers);
  131. srand();
  132. return $this->getConnection($addr);
  133. }
  134. }
  135. class LockClientSession extends SocketSession {
  136. /**
  137. * Called when new data received
  138. * @param string New data
  139. * @return void
  140. */
  141. public function stdin($buf) {
  142. $this->buf .= $buf;
  143. while (($l = $this->gets()) !== FALSE) {
  144. $e = explode(' ', rtrim($l, "\r\n"));
  145. if ($e[0] === 'RUN') {
  146. if (isset($this->appInstance->jobs[$e[1]])) {
  147. call_user_func($this->appInstance->jobs[$e[1]][0], $e[0], $e[1], $this->appInstance);
  148. }
  149. }
  150. elseif ($e[0] === 'DONE') {
  151. if (isset($this->appInstance->jobs[$e[1]][1])) {
  152. call_user_func($this->appInstance->jobs[$e[1]][1], $e[0], $e[1], $this->appInstance);
  153. }
  154. }
  155. elseif ($e[0] === 'FAILED') {
  156. if (isset($this->appInstance->jobs[$e[1]][2])) {
  157. call_user_func($this->appInstance->jobs[$e[1]][2], $e[0], $e[1], $this->appInstance);
  158. }
  159. }
  160. if($this->appInstance->config->protologging->value) {
  161. Daemon::log('Lock client <-- Lock server: ' . Debug::exportBytes(implode(' ', $e)) . "\n");
  162. }
  163. }
  164. }
  165. /**
  166. * Called when session finishes
  167. * @return void
  168. */
  169. public function onFinish() {
  170. $this->finished = TRUE;
  171. unset($this->appInstance->servConn[$this->addr][$this->connId]);
  172. unset($this->appInstance->sessions[$this->connId]);
  173. }
  174. }