|
|
@@ -33,7 +33,7 @@ class Worker
|
|
|
*
|
|
|
* @var string
|
|
|
*/
|
|
|
- const VERSION = '3.5.14';
|
|
|
+ const VERSION = '3.5.16';
|
|
|
|
|
|
/**
|
|
|
* Status starting.
|
|
|
@@ -85,6 +85,13 @@ class Worker
|
|
|
const MAX_UDP_PACKAGE_SIZE = 65535;
|
|
|
|
|
|
/**
|
|
|
+ * The safe distance for columns adjacent
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ const UI_SAFE_LENGTH = 4;
|
|
|
+
|
|
|
+ /**
|
|
|
* Worker id.
|
|
|
*
|
|
|
* @var int
|
|
|
@@ -329,7 +336,7 @@ class Worker
|
|
|
protected static $_workers = array();
|
|
|
|
|
|
/**
|
|
|
- * All worker porcesses pid.
|
|
|
+ * All worker processes pid.
|
|
|
* The format is like this [worker_id=>[pid=>pid, pid=>pid, ..], ..]
|
|
|
*
|
|
|
* @var array
|
|
|
@@ -381,6 +388,27 @@ class Worker
|
|
|
protected static $_maxUserNameLength = 12;
|
|
|
|
|
|
/**
|
|
|
+ * Maximum length of the Proto names.
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ protected static $_maxProtoNameLength = 4;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Maximum length of the Processes names.
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ protected static $_maxProcessesNameLength = 9;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Maximum length of the Status names.
|
|
|
+ *
|
|
|
+ * @var int
|
|
|
+ */
|
|
|
+ protected static $_maxStatusNameLength = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
* The file to store status info of current worker process.
|
|
|
*
|
|
|
* @var string
|
|
|
@@ -425,8 +453,9 @@ class Worker
|
|
|
*/
|
|
|
protected static $_availableEventLoops = array(
|
|
|
'libevent' => '\Workerman\Events\Libevent',
|
|
|
- 'event' => '\Workerman\Events\Event',
|
|
|
- 'swoole' => '\Workerman\Events\Swoole'
|
|
|
+ 'event' => '\Workerman\Events\Event'
|
|
|
+ // Temporarily removed swoole because it is not stable enough
|
|
|
+ //'swoole' => '\Workerman\Events\Swoole'
|
|
|
);
|
|
|
|
|
|
/**
|
|
|
@@ -562,18 +591,6 @@ class Worker
|
|
|
$worker->name = 'none';
|
|
|
}
|
|
|
|
|
|
- // Get maximum length of worker name.
|
|
|
- $worker_name_length = strlen($worker->name);
|
|
|
- if (static::$_maxWorkerNameLength < $worker_name_length) {
|
|
|
- static::$_maxWorkerNameLength = $worker_name_length;
|
|
|
- }
|
|
|
-
|
|
|
- // Get maximum length of socket name.
|
|
|
- $socket_name_length = strlen($worker->getSocketName());
|
|
|
- if (static::$_maxSocketNameLength < $socket_name_length) {
|
|
|
- static::$_maxSocketNameLength = $socket_name_length;
|
|
|
- }
|
|
|
-
|
|
|
// Get unix user of the worker process.
|
|
|
if (empty($worker->user)) {
|
|
|
$worker->user = static::getCurrentUser();
|
|
|
@@ -583,10 +600,18 @@ class Worker
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Get maximum length of unix user name.
|
|
|
- $user_name_length = strlen($worker->user);
|
|
|
- if (static::$_maxUserNameLength < $user_name_length) {
|
|
|
- static::$_maxUserNameLength = $user_name_length;
|
|
|
+ // Socket name.
|
|
|
+ $worker->socket = $worker->getSocketName();
|
|
|
+
|
|
|
+ // Status name.
|
|
|
+ $worker->status = '<g> [OK] </g>';
|
|
|
+
|
|
|
+ // Get column mapping for UI
|
|
|
+ foreach(static::getUiColumns() as $column_name => $prop){
|
|
|
+ !isset($worker->{$prop}) && $worker->{$prop}= 'NNNN';
|
|
|
+ $prop_length = strlen($worker->{$prop});
|
|
|
+ $key = '_max' . ucfirst(strtolower($column_name)) . 'NameLength';
|
|
|
+ static::$$key = max(static::$$key, $prop_length);
|
|
|
}
|
|
|
|
|
|
// Listen.
|
|
|
@@ -661,19 +686,41 @@ class Worker
|
|
|
static::safeEcho("worker listen processes status\r\n");
|
|
|
return;
|
|
|
}
|
|
|
- static::safeEcho("<n>-----------------------<w> WORKERMAN </w>-----------------------------</n>\r\n");
|
|
|
- static::safeEcho('Workerman version:'. static::VERSION. " PHP version:". PHP_VERSION. "\r\n");
|
|
|
- static::safeEcho("------------------------<w> WORKERS </w>-------------------------------\r\n");
|
|
|
- static::safeEcho("<w>proto</w> <w>user</w>". str_pad('',
|
|
|
- static::$_maxUserNameLength + 2 - strlen('user')). "<w>worker</w>". str_pad('',
|
|
|
- static::$_maxWorkerNameLength + 2 - strlen('worker')). "<w>listen</w>". str_pad('',
|
|
|
- static::$_maxSocketNameLength + 2 - strlen('listen')). "<w>processes</w> <w>status</w>\n");
|
|
|
+
|
|
|
+ //show version
|
|
|
+ $line_version = 'Workerman version:' . static::VERSION . str_pad('PHP version:', 22, ' ', STR_PAD_LEFT) . PHP_VERSION . PHP_EOL;
|
|
|
+ !defined('LINE_VERSIOIN_LENGTH') && define('LINE_VERSIOIN_LENGTH', strlen($line_version));
|
|
|
+ $total_length = static::getSingleLineTotalLength();
|
|
|
+ $line_one = '<n>' . str_pad('<w> WORKERMAN </w>', $total_length + strlen('<w></w>'), '-', STR_PAD_BOTH) . '</n>'. PHP_EOL;
|
|
|
+ $line_two = str_pad('<w> WORKERS </w>' , $total_length + strlen('<w></w>'), '-', STR_PAD_BOTH) . PHP_EOL;
|
|
|
+ static::safeEcho($line_one . $line_version . $line_two);
|
|
|
+
|
|
|
+ //Show title
|
|
|
+ $title = '';
|
|
|
+ foreach(static::getUiColumns() as $column_name => $prop){
|
|
|
+ $key = '_max' . ucfirst(strtolower($column_name)) . 'NameLength';
|
|
|
+ //just keep compatible with listen name
|
|
|
+ $column_name == 'socket' && $column_name = 'listen';
|
|
|
+ $title.= "<w>{$column_name}</w>" . str_pad('', static::$$key + static::UI_SAFE_LENGTH - strlen($column_name));
|
|
|
+ }
|
|
|
+ $title && static::safeEcho($title . PHP_EOL);
|
|
|
+
|
|
|
+ //Show content
|
|
|
foreach (static::$_workers as $worker) {
|
|
|
- static::safeEcho(str_pad($worker->transport,9). str_pad($worker->user, static::$_maxUserNameLength + 2). str_pad($worker->name,
|
|
|
- static::$_maxWorkerNameLength + 2). str_pad($worker->getSocketName(),
|
|
|
- static::$_maxSocketNameLength + 2). str_pad(' ' . $worker->count, 9). " <g> [OK] </g>\n");
|
|
|
+ $content = '';
|
|
|
+ foreach(static::getUiColumns() as $column_name => $prop){
|
|
|
+ $key = '_max' . ucfirst(strtolower($column_name)) . 'NameLength';
|
|
|
+ preg_match_all("/(<n>|<\/n>|<w>|<\/w>|<g>|<\/g>)/is", $worker->{$prop}, $matches);
|
|
|
+ $place_holder_length = !empty($matches) ? strlen(implode('', $matches[0])) : 0;
|
|
|
+ $content .= str_pad($worker->{$prop}, static::$$key + static::UI_SAFE_LENGTH + $place_holder_length);
|
|
|
+ }
|
|
|
+ $content && static::safeEcho($content . PHP_EOL);
|
|
|
}
|
|
|
- static::safeEcho("----------------------------------------------------------------\n");
|
|
|
+
|
|
|
+ //Show last line
|
|
|
+ $line_last = str_pad('', static::getSingleLineTotalLength(), '-') . PHP_EOL;
|
|
|
+ $content && static::safeEcho($line_last);
|
|
|
+
|
|
|
if (static::$daemonize) {
|
|
|
static::safeEcho("Input \"php $argv[0] stop\" to stop. Start success.\n\n");
|
|
|
} else {
|
|
|
@@ -682,6 +729,49 @@ class Worker
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
+ * Get UI columns to be shown in terminal
|
|
|
+ *
|
|
|
+ * 1. $column_map: array('ui_column_name' => 'clas_property_name')
|
|
|
+ * 2. Consider move into configuration in future
|
|
|
+ *
|
|
|
+ * @return array
|
|
|
+ */
|
|
|
+ public static function getUiColumns()
|
|
|
+ {
|
|
|
+ $column_map = array(
|
|
|
+ 'proto' => 'transport',
|
|
|
+ 'user' => 'user',
|
|
|
+ 'worker' => 'name',
|
|
|
+ 'socket' => 'socket',
|
|
|
+ 'processes' => 'count',
|
|
|
+ 'status' => 'status',
|
|
|
+ );
|
|
|
+
|
|
|
+ return $column_map;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Get single line total length for ui
|
|
|
+ *
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ public static function getSingleLineTotalLength()
|
|
|
+ {
|
|
|
+ $total_length = 0;
|
|
|
+
|
|
|
+ foreach(static::getUiColumns() as $column_name => $prop){
|
|
|
+ $key = '_max' . ucfirst(strtolower($column_name)) . 'NameLength';
|
|
|
+ $total_length += static::$$key + static::UI_SAFE_LENGTH;
|
|
|
+ }
|
|
|
+
|
|
|
+ //keep beauty when show less colums
|
|
|
+ !defined('LINE_VERSIOIN_LENGTH') && define('LINE_VERSIOIN_LENGTH', 0);
|
|
|
+ $total_length <= LINE_VERSIOIN_LENGTH && $total_length = LINE_VERSIOIN_LENGTH;
|
|
|
+
|
|
|
+ return $total_length;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
* Parse command.
|
|
|
*
|
|
|
* @return void
|
|
|
@@ -1105,7 +1195,7 @@ class Worker
|
|
|
return static::$eventLoopClass;
|
|
|
}
|
|
|
|
|
|
- if (!class_exists('\Swoole\Event')) {
|
|
|
+ if (!class_exists('\Swoole\Event', false)) {
|
|
|
unset(static::$_availableEventLoops['swoole']);
|
|
|
}
|
|
|
|
|
|
@@ -1339,6 +1429,8 @@ class Worker
|
|
|
static::$_idMap[$worker->workerId][$id] = $pid;
|
|
|
} // For child processes.
|
|
|
elseif (0 === $pid) {
|
|
|
+ srand();
|
|
|
+ mt_srand();
|
|
|
if ($worker->reusePort) {
|
|
|
$worker->listen();
|
|
|
}
|
|
|
@@ -1497,18 +1589,13 @@ class Worker
|
|
|
unset(static::$_pidsToRestart[$pid]);
|
|
|
static::reload();
|
|
|
}
|
|
|
- } else {
|
|
|
- // If shutdown state and all child processes exited then master process exit.
|
|
|
- if (!static::getAllWorkerPids()) {
|
|
|
- static::exitAndClearAll();
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- // If shutdown state and all child processes exited then master process exit.
|
|
|
- if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) {
|
|
|
- static::exitAndClearAll();
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // If shutdown state and all child processes exited then master process exit.
|
|
|
+ if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) {
|
|
|
+ static::exitAndClearAll();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -2161,8 +2248,7 @@ class Worker
|
|
|
if ($this->transport !== 'udp') {
|
|
|
static::$globalEvent->add($this->_mainSocket, EventInterface::EV_READ, array($this, 'acceptConnection'));
|
|
|
} else {
|
|
|
- static::$globalEvent->add($this->_mainSocket, EventInterface::EV_READ,
|
|
|
- array($this, 'acceptUdpConnection'));
|
|
|
+ static::$globalEvent->add($this->_mainSocket, EventInterface::EV_READ, array($this, 'acceptUdpConnection'));
|
|
|
}
|
|
|
$this->_pauseAccept = false;
|
|
|
}
|
|
|
@@ -2332,13 +2418,29 @@ class Worker
|
|
|
if ($this->protocol !== null) {
|
|
|
/** @var \Workerman\Protocols\ProtocolInterface $parser */
|
|
|
$parser = $this->protocol;
|
|
|
- $recv_buffer = $parser::decode($recv_buffer, $connection);
|
|
|
- // Discard bad packets.
|
|
|
- if ($recv_buffer === false)
|
|
|
- return true;
|
|
|
+ if(method_exists($parser,'input')){
|
|
|
+ while($recv_buffer !== ''){
|
|
|
+ $len = $parser::input($recv_buffer, $connection);
|
|
|
+ if($len == 0)
|
|
|
+ return true;
|
|
|
+ $package = substr($recv_buffer,0,$len);
|
|
|
+ $recv_buffer = substr($recv_buffer,$len);
|
|
|
+ $data = $parser::decode($package,$connection);
|
|
|
+ if ($data === false)
|
|
|
+ continue;
|
|
|
+ call_user_func($this->onMessage, $connection, $data);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ $data = $parser::decode($recv_buffer, $connection);
|
|
|
+ // Discard bad packets.
|
|
|
+ if ($data === false)
|
|
|
+ return true;
|
|
|
+ call_user_func($this->onMessage, $connection, $data);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ call_user_func($this->onMessage, $connection, $recv_buffer);
|
|
|
}
|
|
|
ConnectionInterface::$statistics['total_request']++;
|
|
|
- call_user_func($this->onMessage, $connection, $recv_buffer);
|
|
|
} catch (\Exception $e) {
|
|
|
static::log($e);
|
|
|
exit(250);
|