diff --git a/ext-src/php_swoole_library.h b/ext-src/php_swoole_library.h index 7f5f085e09f..dd3aa6b375e 100644 --- a/ext-src/php_swoole_library.h +++ b/ext-src/php_swoole_library.h @@ -2,7 +2,7 @@ * Generated by build-library.php, Please DO NOT modify! */ -/* $Id: 1b421d51331d70d14a1b971c1a20c31c14b523d7 */ +/* $Id: 3efc2e949a7125178561fb5c3f3ae5a4dd176dfa */ static const char* swoole_library_source_constants = "\n" @@ -170,6 +170,8 @@ static const char* swoole_library_source_core_constant = "\n" " public const OPTION_SOCKET_TIMEOUT = 'socket_timeout';\n" "\n" + " public const OPTION_MAX_CONCURRENCY = 'max_concurrency';\n" + "\n" " public const OPTION_AIO_CORE_WORKER_NUM = 'aio_core_worker_num';\n" "\n" " public const OPTION_AIO_WORKER_NUM = 'aio_worker_num';\n" @@ -595,15 +597,15 @@ static const char* swoole_library_source_core_string_object = " }\n" "\n" " /**\n" + " * @param mixed $characters\n" " * @return static\n" " */\n" " public function trim($characters = ''): self\n" " {\n" " if ($characters) {\n" " return new static(trim($this->string, $characters));\n" - " } else {\n" - " return new static(trim($this->string));\n" " }\n" + " return new static(trim($this->string));\n" " }\n" "\n" " /**\n" @@ -6790,7 +6792,7 @@ static const char* swoole_library_source_core_process_manager = " }\n" "}\n"; -static const char* swoole_library_source_core_server_helper = +static const char* swoole_library_source_core_server_admin = "\n" "/**\n" " * This file is part of Swoole.\n" @@ -6804,12 +6806,1028 @@ static const char* swoole_library_source_core_server_helper = "\n" "namespace Swoole\\Server;\n" "\n" + "use Reflection;\n" + "use ReflectionClass;\n" + "use ReflectionExtension;\n" "use Swoole\\Coroutine;\n" + "use Swoole\\Coroutine\\System;\n" + "use Swoole\\Http\\Request;\n" + "use Swoole\\Http\\Response;\n" "use Swoole\\Server;\n" "use Swoole\\Timer;\n" - "use Swoole\\Http\\Response;\n" - "use Swoole\\Http\\Request;\n" "\n" + "class Admin\n" + "{\n" + " /**\n" + " * gdb php\n" + " * (gdb) p sizeof(zval)\n" + " * $2 = 16\n" + " * (gdb) p sizeof(zend_array)\n" + " * $1 = 56\n" + " * (gdb) p sizeof(zend_string)\n" + " * $3 = 32\n" + " * (gdb) p sizeof(zend_object)\n" + " * $4 = 56\n" + " */\n" + " const SIZE_OF_ZVAL = 16;\n" + "\n" + " const SIZE_OF_ZEND_STRING = 32;\n" + "\n" + " const SIZE_OF_ZEND_OBJECT = 56;\n" + "\n" + " const SIZE_OF_ZEND_ARRAY = 56;\n" + "\n" + " const DASHBOARD_DIR = '/opt/swoole/dashboard';\n" + "\n" + " public static function init(Server $server)\n" + " {\n" + " $accepted_process_types = SWOOLE_SERVER_COMMAND_MASTER |\n" + " SWOOLE_SERVER_COMMAND_MANAGER |\n" + " SWOOLE_SERVER_COMMAND_EVENT_WORKER |\n" + " SWOOLE_SERVER_COMMAND_TASK_WORKER;\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_stats',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(Coroutine::stats());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_list',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(iterator_to_array(Coroutine::list()));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'coroutine_bt',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $json = json_decode($msg);\n" + " $cid = empty($json->cid) ? 0 : intval($json->cid);\n" + " $bt = Coroutine::getBackTrace($cid);\n" + " if ($bt === false) {\n" + " return self::json(\"Coroutine#{$cid} not exists\", 4004);\n" + " }\n" + " return self::json($bt);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'server_stats',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json($server->stats());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'server_setting',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " /**\n" + " * @var Server $server\n" + " */\n" + " $setting = $server->setting;\n" + " $setting['mode'] = $server->mode;\n" + " $setting['host'] = $server->host;\n" + " $setting['port'] = $server->port;\n" + " $setting['master_pid'] = $server->master_pid;\n" + " $setting['manager_pid'] = $server->manager_pid;\n" + " return self::json($setting);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_client_info',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['session_id'])) {\n" + " return self::json('require session_id', 4003);\n" + " }\n" + " return self::json($server->getClientInfo(intval($json['session_id'])));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'close_session',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['session_id'])) {\n" + " return self::json('require session_id', 4003);\n" + " }\n" + " if ($server->close(intval($json['session_id']), !empty($json['force']))) {\n" + " return self::json([]);\n" + " }\n" + " return self::json(['error' => swoole_last_error()], 4004);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand('get_version_info', $accepted_process_types, [__CLASS__, 'handlerGetVersionInfo']);\n" + " $server->addCommand('get_worker_info', $accepted_process_types, [__CLASS__, 'handlerGetWorkerInfo']);\n" + " $server->addCommand('get_timer_list', $accepted_process_types, [__CLASS__, 'handlerGetTimerList']);\n" + " $server->addCommand('get_coroutine_list', $accepted_process_types, [__CLASS__, 'handlerGetCoroutineList']);\n" + " $server->addCommand('get_objects', $accepted_process_types, [__CLASS__, 'handlerGetObjects']);\n" + " $server->addCommand('get_class_info', $accepted_process_types, [__CLASS__, 'handlerGetClassInfo']);\n" + " $server->addCommand('get_function_info', $accepted_process_types, [__CLASS__, 'handlerGetFunctionInfo']);\n" + " $server->addCommand('get_object_by_handle', $accepted_process_types, [__CLASS__, 'handlerGetObjectByHandle']);\n" + " $server->addCommand('get_server_cpu_usage', $accepted_process_types, [__CLASS__, 'handlerGetServerCpuUsage']);\n" + " $server->addCommand(\n" + " 'get_server_memory_usage',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetServerMemoryUsage']\n" + " );\n" + " $server->addCommand(\n" + " 'get_static_property_value',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetStaticPropertyValue']\n" + " );\n" + " $server->addCommand(\n" + " 'get_defined_functions',\n" + " $accepted_process_types,\n" + " [__CLASS__, 'handlerGetDefinedFunctions']\n" + " );\n" + " $server->addCommand('get_declared_classes', $accepted_process_types, [__CLASS__, 'handlerGetDeclaredClasses']);\n" + "\n" + " if (PHP_VERSION_ID > 70300) {\n" + " $server->addCommand(\n" + " 'gc_status',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(gc_status());\n" + " }\n" + " );\n" + " }\n" + "\n" + " if (extension_loaded('opcache')) {\n" + " $server->addCommand(\n" + " 'opcache_status',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(opcache_get_status(true));\n" + " }\n" + " );\n" + " }\n" + "\n" + " $server->addCommand(\n" + " 'getpid',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(['pid' => posix_getpid()]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'memory_usage',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json([\n" + " 'usage' => memory_get_usage(),\n" + " 'real_usage' => memory_get_usage(true),\n" + " ]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_included_files',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(['files' => get_included_files()]);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand('get_resources', $accepted_process_types, [__CLASS__, 'handlerGetResources']);\n" + "\n" + " $server->addCommand(\n" + " 'get_defined_constants',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $constants = get_defined_constants();\n" + " foreach ($constants as $k => $c) {\n" + " if (is_resource($c)) {\n" + " unset($constants[$k]);\n" + " }\n" + " }\n" + " unset($constants['NULL'], $constants['NAN'], $constants['INF']);\n" + " return self::json($constants);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_loaded_extensions',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $extensions = get_loaded_extensions();\n" + " $list = [];\n" + " foreach ($extensions as $key => $extension) {\n" + " $ext = new \\ReflectionExtension($extension);\n" + " $list[$key] = [\n" + " 'id' => ++$key,\n" + " 'name' => $extension,\n" + " 'version' => $ext->getVersion() ?? '',\n" + " ];\n" + " }\n" + " return self::json($list);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_declared_interfaces',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(get_declared_interfaces());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_declared_traits',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " return self::json(get_declared_traits());\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_included_file_contents',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['filename'])) {\n" + " return self::json('require filename', 4003);\n" + " }\n" + "\n" + " if (!file_exists($json['filename'])) {\n" + " return self::json(\"{$json['filename']} not exist\", 4004);\n" + " }\n" + "\n" + " if (!in_array($json['filename'], get_included_files())) {\n" + " return self::json('no permission', 4003);\n" + " }\n" + "\n" + " return self::json(file_get_contents($json['filename']));\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_globals',\n" + " $accepted_process_types,\n" + " function ($server, $msg) {\n" + " $globals = [];\n" + " foreach ($GLOBALS as $key => $item) {\n" + " if ($key === 'GLOBALS') {\n" + " continue;\n" + " }\n" + " $type = gettype($item);\n" + " $other = [];\n" + " if ($type === 'object') {\n" + " $other = [\n" + " 'class_name' => get_class($item),\n" + " 'object_id' => spl_object_id($item),\n" + " 'object_hash' => spl_object_hash($item),\n" + " ];\n" + " }\n" + " if ($type == 'resource' || $type == 'resource (closed)') {\n" + " $item = '';\n" + " }\n" + " $globals[] = [\n" + " 'key' => $key,\n" + " 'value' => $item,\n" + " 'type' => $type,\n" + " 'other' => $other,\n" + " ];\n" + " }\n" + " return self::json($globals);\n" + " }\n" + " );\n" + "\n" + " $server->addCommand(\n" + " 'get_extension_info',\n" + " $accepted_process_types,\n" + " function (Server $server, $msg) {\n" + " $json = json_decode($msg, true);\n" + "\n" + " if (empty($json['extension_name']) || !extension_loaded($json['extension_name'])) {\n" + " return self::json('require extension_name', 4004);\n" + " }\n" + "\n" + " $ext = new ReflectionExtension($json['extension_name']);\n" + "\n" + " ob_start();\n" + " $ext->info();\n" + " $info = ob_get_clean();\n" + "\n" + " $constants = $ext->getConstants();\n" + " foreach ($constants as $k => $c) {\n" + " if (is_resource($c)) {\n" + " unset($constants[$k]);\n" + " }\n" + " }\n" + "\n" + " unset($constants['NULL'], $constants['NAN'], $constants['INF']);\n" + "\n" + " return self::json([\n" + " 'classes' => $ext->getClassNames(),\n" + " 'version' => $ext->getVersion(),\n" + " 'constants' => $constants,\n" + " 'ini_entries' => $ext->getINIEntries(),\n" + " 'dependencies' => $ext->getDependencies(),\n" + " 'functions' => array_keys($ext->getFunctions()),\n" + " 'info' => trim($info),\n" + " ]);\n" + " }\n" + " );\n" + " }\n" + "\n" + " public static function start(Server $server)\n" + " {\n" + " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" + " if ($admin_server_uri->startsWith('unix:/')) {\n" + " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" + " } else {\n" + " [$host, $port] = $admin_server_uri->split(':', 2)->toArray();\n" + " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" + " }\n" + " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" + " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" + " if ($path_array->count() < 2 or $path_array->count() > 3) {\n" + " $resp->status(403);\n" + " $resp->end(self::json('Bad API path', 4003));\n" + " return;\n" + " }\n" + "\n" + " $cmd = $path_array->get(1)->toString();\n" + " if ($path_array->count() == 2) {\n" + " $process = swoole_string('master');\n" + " } else {\n" + " $process = $path_array->get(2);\n" + " }\n" + "\n" + " if ($process->startsWith('master')) {\n" + " $process_type = SWOOLE_SERVER_COMMAND_MASTER;\n" + " $process_id = 0;\n" + " } elseif ($process->startsWith('manager')) {\n" + " $process_type = SWOOLE_SERVER_COMMAND_MANAGER;\n" + " $process_id = 0;\n" + " } else {\n" + " $array = $process->split('-');\n" + " if ($array->count() != 2) {\n" + " _bad_process:\n" + " $resp->status(403);\n" + " $resp->end(self::json('Bad process', 4003));\n" + " return;\n" + " }\n" + "\n" + " static $map = [\n" + " 'reactor' => SWOOLE_SERVER_COMMAND_REACTOR_THREAD,\n" + " 'reactor_thread' => SWOOLE_SERVER_COMMAND_REACTOR_THREAD,\n" + " 'worker' => SWOOLE_SERVER_COMMAND_EVENT_WORKER,\n" + " 'event_worker' => SWOOLE_SERVER_COMMAND_EVENT_WORKER,\n" + " 'task' => SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" + " 'task_worker' => SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" + " ];\n" + "\n" + " if (!isset($map[$array->get(0)->toString()])) {\n" + " goto _bad_process;\n" + " }\n" + "\n" + " $process_type = $map[$array->get(0)->toString()];\n" + " $process_id = intval($array->get(1)->toString());\n" + " }\n" + "\n" + " if ($req->getMethod() == 'GET') {\n" + " $data = $req->get;\n" + " } else {\n" + " $data = $req->post;\n" + " }\n" + "\n" + " $resp->header('Access-Control-Allow-Origin', '*');\n" + " $resp->header('Access-Control-Allow-Methods', 'GET, OPTIONS');\n" + " $resp->header('Access-Control-Allow-Headers', 'X-ACCESS-TOKEN');\n" + "\n" + " $result = $server->command($cmd, intval($process_id), intval($process_type), $data, false);\n" + " if (!$result) {\n" + " $resp->end(json_encode([\n" + " 'code' => swoole_last_error(),\n" + " 'data' => swoole_strerror(swoole_last_error()),\n" + " ]));\n" + " } else {\n" + " $resp->end($result);\n" + " }\n" + " });\n" + " $admin_server->handle('/', function (Request $req, Response $resp) use ($server) {\n" + " if ($req->server['request_uri'] == '/' or $req->server['request_uri'] == '/index.html') {\n" + " $dir = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION;\n" + " $index_file = $dir . '/dist/index.html';\n" + " if (!is_file($index_file)) {\n" + " $url = 'https://business.swoole.com/static/swoole_dashboard/' . SWOOLE_VERSION . '.tar.gz';\n" + " $download_request = Coroutine\\Http\\get($url);\n" + " if (!$download_request or $download_request->getStatusCode() != '200') {\n" + " $resp->end(\"download [{$url}] failed\");\n" + " return;\n" + " }\n" + " $tmp_file = '/tmp/swoole_dashborad.' . SWOOLE_VERSION . '.tar.gz';\n" + " file_put_contents($tmp_file, $download_request->getBody());\n" + " if (is_file($tmp_file) or filesize($tmp_file) == 0) {\n" + " $resp->end(\"write [{$tmp_file}] failed\");\n" + " return;\n" + " }\n" + " if (!is_dir($dir)) {\n" + " mkdir($dir, 0777, true);\n" + " }\n" + " $sh = 'tar zxvf ' . $tmp_file . ' -C ' . $dir;\n" + " System::exec($sh);\n" + " }\n" + " }\n" + "\n" + " $file = self::DASHBOARD_DIR . '/' . SWOOLE_VERSION . '/dist/' . ($req->server['request_uri'] == '/' ? 'index.html' : $req->server['request_uri']);\n" + " if (!is_file($file)) {\n" + " $resp->status(404);\n" + " $resp->end('file ' . $file . ' not found');\n" + " } else {\n" + " $resp->sendfile($file);\n" + " }\n" + " });\n" + " $server->admin_server = $admin_server;\n" + " $admin_server->start();\n" + " }\n" + "\n" + " /**\n" + " * @param $server Server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetResources($server, $msg)\n" + " {\n" + " $resources = get_resources();\n" + " $list = [];\n" + " foreach ($resources as $r) {\n" + " $info = [\n" + " 'id' => function_exists('get_resource_id') ? get_resource_id($r) : intval($r),\n" + " 'type' => get_resource_type($r),\n" + " ];\n" + " if ($info['type'] == 'stream') {\n" + " $info['info'] = stream_get_meta_data($r);\n" + " }\n" + " $list[] = $info;\n" + " }\n" + " return self::json($list);\n" + " }\n" + "\n" + " /**\n" + " * @param $server Server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetWorkerInfo($server, $msg)\n" + " {\n" + " $info = [\n" + " 'id' => $server->getWorkerId(),\n" + " 'pid' => $server->getWorkerPid(),\n" + " 'gc_status' => gc_status(),\n" + " 'memory_usage' => memory_get_usage(),\n" + " 'memory_real_usage' => memory_get_usage(true),\n" + " 'process_status' => self::getProcessStatus(),\n" + " 'coroutine_stats' => Coroutine::stats(),\n" + " 'timer_stats' => Timer::stats(),\n" + " ];\n" + " if (function_exists('swoole_get_vm_status')) {\n" + " $info['vm_status'] = swoole_get_vm_status();\n" + " }\n" + " return self::json($info);\n" + " }\n" + "\n" + " /**\n" + " * @param $server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetTimerList($server, $msg)\n" + " {\n" + " $list = [];\n" + " foreach (Timer::list() as $timer_id) {\n" + " $list[] = [\n" + " 'id' => $timer_id,\n" + " 'info' => Timer::info($timer_id),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " /**\n" + " * @param $server\n" + " * @param $msg\n" + " * @return false|string\n" + " */\n" + " public static function handlerGetCoroutineList($server, $msg)\n" + " {\n" + " $list = [];\n" + " foreach (Coroutine::list() as $cid) {\n" + " $list[] = [\n" + " 'id' => $cid,\n" + " 'elapsed' => Coroutine::getElapsed($cid),\n" + " 'stack_usage' => Coroutine::getStackUsage($cid),\n" + " 'backTrace' => Coroutine::getBackTrace($cid, DEBUG_BACKTRACE_IGNORE_ARGS, 1),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " public static function handlerGetObjects($server, $msg)\n" + " {\n" + " if (!function_exists('swoole_get_objects')) {\n" + " return self::json(['require ext-swoole_plus'], 5000);\n" + " }\n" + " $list = [];\n" + " $objects = swoole_get_objects();\n" + " foreach ($objects as $o) {\n" + " $class_name = get_class($o);\n" + " $class = new ReflectionClass($class_name);\n" + " $filename = $class->getFileName();\n" + " $line = $class->getStartLine();\n" + " $list[] = [\n" + " 'id' => spl_object_id($o),\n" + " 'hash' => spl_object_hash($o),\n" + " 'class' => $class_name,\n" + " 'filename' => $filename ?: '',\n" + " 'line' => $line ?: '',\n" + " 'memory_size' => self::getObjectMemorySize($o),\n" + " ];\n" + " }\n" + "\n" + " return self::json($list);\n" + " }\n" + "\n" + " public static function handlerGetClassInfo($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['class_name'])) {\n" + " return self::json(['error' => 'require class_name'], 4004);\n" + " }\n" + "\n" + " if (!class_exists($json['class_name'], false)) {\n" + " return self::json(\"{$json['class_name']} not exists\", 4003);\n" + " }\n" + "\n" + " $class = new ReflectionClass($json['class_name']);\n" + "\n" + " $filename = $class->getFileName();\n" + "\n" + " $getTmpConstants = function ($data) {\n" + " $tmp = [];\n" + " foreach ($data as $k => $v) {\n" + " $tmp[] = [\n" + " 'name' => $k,\n" + " 'value' => is_array($v) ? var_export($v, true) : $v,\n" + " 'type' => is_array($v) ? 'detail' : 'default',\n" + " ];\n" + " }\n" + " return $tmp;\n" + " };\n" + "\n" + " $tmpConstants = $class->getConstants();\n" + " $constants = $tmpConstants ? $getTmpConstants($tmpConstants) : [];\n" + "\n" + " $staticProperties = [];\n" + " $properties = [];\n" + " $tmpProperties = $class->getProperties();\n" + "\n" + " $getTmpProperties = function ($class, $data) {\n" + " $static = [];\n" + " $no_static = [];\n" + " $reflProp = $class->getDefaultProperties();\n" + " foreach ($data as $k => $v) {\n" + " $name = $v->getName();\n" + " $modifiers = Reflection::getModifierNames($v->getModifiers());\n" + " if ($v->isStatic()) {\n" + " $static[] = [\n" + " 'name' => $name,\n" + " 'value' => $reflProp[$name],\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " } else {\n" + " $no_static[] = [\n" + " 'name' => $name,\n" + " 'value' => $reflProp[$name],\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " }\n" + " }\n" + " return ['static' => $static, 'no_static' => $no_static];\n" + " };\n" + "\n" + " if ($tmpProperties) {\n" + " $tmpProperties = $getTmpProperties($class, $tmpProperties);\n" + " $staticProperties = $tmpProperties['static'];\n" + " $properties = $tmpProperties['no_static'];\n" + " }\n" + "\n" + " $staticMethods = [];\n" + " $methods = [];\n" + " $tmpStaticMethods = $class->getMethods();\n" + "\n" + " $getTmpMethods = function ($data) {\n" + " $static = [];\n" + " $no_static = [];\n" + " foreach ($data as $k => $v) {\n" + " $name = $v->getName();\n" + " $line = $v->getStartLine();\n" + " $modifiers = \\Reflection::getModifierNames($v->getModifiers());\n" + " if ($v->isStatic()) {\n" + " $static[] = [\n" + " 'name' => $name,\n" + " 'line' => $line ?: '',\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " } else {\n" + " $no_static[] = [\n" + " 'name' => $name,\n" + " 'line' => $line ?: '',\n" + " 'modifiers' => implode(' ', $modifiers),\n" + " ];\n" + " }\n" + " }\n" + " return ['static' => $static, 'no_static' => $no_static];\n" + " };\n" + "\n" + " if ($tmpStaticMethods) {\n" + " $tmpStaticMethods = $getTmpMethods($tmpStaticMethods);\n" + " $staticMethods = $tmpStaticMethods['static'];\n" + " $methods = $tmpStaticMethods['no_static'];\n" + " }\n" + "\n" + " $tmpParentClass = $class->getParentClass();\n" + " $parentClass = $tmpParentClass ? $tmpParentClass->getName() : '';\n" + "\n" + " $tmpInterface = $class->getInterfaceNames();\n" + " $interface = $tmpInterface ? $tmpInterface : [];\n" + "\n" + " $data = [\n" + " 'filename' => $filename,\n" + " 'constants' => $constants,\n" + " 'staticProperties' => $staticProperties,\n" + " 'properties' => $properties,\n" + " 'staticMethods' => $staticMethods,\n" + " 'methods' => $methods,\n" + " 'parentClass' => $parentClass,\n" + " 'interface' => $interface,\n" + " ];\n" + " return self::json($data);\n" + " }\n" + "\n" + " public static function handlerGetFunctionInfo($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (!$json || empty($json['function_name'])) {\n" + " return self::json('require function_name', 4004);\n" + " }\n" + " if (!function_exists($json['function_name'])) {\n" + " return self::json(\"{$json['function_name']} not exists\", 4004);\n" + " }\n" + " $function = new \\ReflectionFunction($json['function_name']);\n" + "\n" + " $result = [\n" + " 'filename' => $function->getFileName(),\n" + " 'line' => $function->getStartLine() ?? '',\n" + " 'num' => $function->getNumberOfParameters(),\n" + " 'user_defined' => $function->isUserDefined(),\n" + " 'extension' => $function->getExtensionName(),\n" + " ];\n" + "\n" + " $params = $function->getParameters();\n" + "\n" + " $list = [];\n" + " foreach ($params as $param) {\n" + " $type = $param->hasType() ? $param->getType()->getName() : '';\n" + "\n" + " $optional = $default = '';\n" + " if ($param->isOptional() && !$param->isVariadic() && PHP_VERSION_ID >= 80000) {\n" + " $optional = '?';\n" + " $value = $param->getDefaultValue();\n" + " if (in_array($value, [true, false, null])) {\n" + " if ($value === null) {\n" + " $value = 'null';\n" + " }\n" + " if ($value === true) {\n" + " $value = 'true';\n" + " }\n" + " if ($value === false) {\n" + " $value = 'false';\n" + " }\n" + " }\n" + " $default = \" = {$value}\";\n" + " }\n" + "\n" + " $isPassedByReference = $param->isPassedByReference() ? '&' : '';\n" + " $isVariadic = $param->isVariadic() ? '...' : '';\n" + "\n" + " $param_value = \"{$optional}{$type} {$isPassedByReference}{$isVariadic}{$param->getName()}{$default}\";\n" + "\n" + " $list[] = $param_value;\n" + " }\n" + " $result['params'] = $list;\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetObjectByHandle($server, $msg)\n" + " {\n" + " if (!function_exists('swoole_get_object_by_handle')) {\n" + " return self::json(['require ext-swoole_plus'], 5000);\n" + " }\n" + "\n" + " $json = json_decode($msg, true);\n" + " if (!$json || !isset($json['object_id']) || empty($json['object_id']) || !isset($json['object_hash']) || empty($json['object_hash'])) {\n" + " return self::json(['error' => 'Params Error!'], 4004);\n" + " }\n" + "\n" + " $object = swoole_get_object_by_handle((int) $json['object_id']);\n" + " if (!$object) {\n" + " return self::json(['error' => 'Object destroyed!'], 4004);\n" + " }\n" + "\n" + " $object_hash = spl_object_hash($object);\n" + " if ($object_hash != $json['object_hash']) {\n" + " return self::json(['error' => 'Object destroyed!'], 4004);\n" + " }\n" + "\n" + " return self::json(var_export($object, true));\n" + " }\n" + "\n" + " public static function handlerGetVersionInfo($server, $msg)\n" + " {\n" + " $ip_arr = swoole_get_local_ip();\n" + " $host = [];\n" + " $local = [];\n" + " foreach ($ip_arr as $k => $ip) {\n" + " if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {\n" + " $host[] = $ip;\n" + " } else {\n" + " $local[] = $ip;\n" + " }\n" + " }\n" + " $data = [\n" + " 'os' => php_uname('s') . '-' . php_uname('r'),\n" + " 'swoole' => swoole_version(),\n" + " 'php' => phpversion(),\n" + " 'ip' => $host ? $host[0] : $local[0],\n" + " ];\n" + " return self::json($data);\n" + " }\n" + "\n" + " public static function handlerGetDefinedFunctions($server, $msg)\n" + " {\n" + " $functions = get_defined_functions();\n" + " $arr = [];\n" + " if ($functions) {\n" + " $arr['internal'] = $functions['internal'];\n" + "\n" + " foreach ($functions['user'] as $function_name) {\n" + " $function = new \\ReflectionFunction($function_name);\n" + " $filename = $function->getFileName();\n" + " $line = $function->getStartLine();\n" + " $arr['user'][] = [\n" + " 'function' => $function_name,\n" + " 'filename' => $filename,\n" + " 'line' => $line,\n" + " ];\n" + " }\n" + " }\n" + " return self::json($arr);\n" + " }\n" + "\n" + " public static function handlerGetDeclaredClasses($server, $msg)\n" + " {\n" + " $classes = get_declared_classes();\n" + " $arr = [];\n" + " if ($classes) {\n" + " foreach ($classes as $classes_name) {\n" + " $function = new \\ReflectionClass($classes_name);\n" + " $filename = $function->getFileName();\n" + " $line = $function->getStartLine();\n" + " $arr[] = [\n" + " 'class' => $classes_name,\n" + " 'filename' => $filename ?: '',\n" + " 'line' => $line ?: '',\n" + " ];\n" + " }\n" + " }\n" + " return self::json($arr);\n" + " }\n" + "\n" + " public static function handlerGetServerMemoryUsage($server, $msg)\n" + " {\n" + " $total = 0;\n" + "\n" + " $result['master'] = self::getProcessMemoryRealUsage($server->master_pid);\n" + " $total += $result['master'];\n" + "\n" + " $result['manager'] = self::getProcessMemoryRealUsage($server->manager_pid);\n" + " $total += $result['manager'];\n" + "\n" + " $n = $server->setting['worker_num'] + $server->setting['task_worker_num'];\n" + " for ($i = 0; $i < $n; $i++) {\n" + " $key = 'worker-' . $i;\n" + " $result[$key] = self::getProcessMemoryRealUsage($server->getWorkerPid($i));\n" + " $total += $result[$key];\n" + " }\n" + "\n" + " $result['total'] = $total;\n" + "\n" + " $result['memory_size'] = 0;\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY === 'Linux') {\n" + " preg_match('#MemTotal:\\s+(\\d+) kB#i', file_get_contents('/proc/meminfo'), $match);\n" + " $result['memory_size'] = $match[1] * 1024;\n" + " }\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetServerCpuUsage($server, $msg)\n" + " {\n" + " $total = 0;\n" + "\n" + " $result['master'] = self::getProcessCpuUsage($server->master_pid);\n" + " $total += $result['master'][1] ?? 0;\n" + "\n" + " $result['manager'] = self::getProcessCpuUsage($server->manager_pid);\n" + " $total += $result['manager'][1] ?? 0;\n" + "\n" + " $n = $server->setting['worker_num'] + $server->setting['task_worker_num'];\n" + " for ($i = 0; $i < $n; $i++) {\n" + " $key = 'worker-' . $i;\n" + " $result[$key] = self::getProcessCpuUsage($server->getWorkerPid($i))[1] ?? 0;\n" + " $total += $result[$key];\n" + " }\n" + "\n" + " $result['total'] = $total;\n" + " $result['cpu_num'] = swoole_cpu_num();\n" + "\n" + " return self::json($result);\n" + " }\n" + "\n" + " public static function handlerGetStaticPropertyValue($server, $msg)\n" + " {\n" + " $json = json_decode($msg, true);\n" + " if (empty($json['class_name'])) {\n" + " return self::json(['error' => 'require class_name!'], 4004);\n" + " }\n" + " if (empty($json['property_name'])) {\n" + " return self::json(['error' => 'require property_name!'], 4004);\n" + " }\n" + "\n" + " $class_name = $json['class_name'];\n" + " $property_name = $json['property_name'];\n" + "\n" + " $refClass = new ReflectionClass($class_name);\n" + " if (!$refClass) {\n" + " return self::json(\"class[{$class_name}] not exists\", 4004);\n" + " }\n" + "\n" + " $property = $refClass->getProperty($property_name);\n" + " if (!$property) {\n" + " return self::json(\"property[{$property_name}] not exists\", 4004);\n" + " }\n" + "\n" + " $property->setAccessible(true);\n" + " $value = $property->getValue($property_name);\n" + "\n" + " $result = [\n" + " 'value' => var_export($value, true),\n" + " ];\n" + " return self::json($result);\n" + " }\n" + "\n" + " private static function getProcessCpuUsage($pid)\n" + " {\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY !== 'Linux') {\n" + " return [0];\n" + " }\n" + "\n" + " $statAll = file_get_contents('/proc/stat');\n" + " $statProc = file_get_contents(\"/proc/{$pid}/stat\");\n" + "\n" + " $dataAll = preg_split(\"/[ \\t]+/\", $statAll, 6);\n" + " assert($dataAll[0] === 'cpu', '/proc/stat malformed');\n" + " $dataProc = preg_split(\"/[ \\t]+/\", $statProc, 15);\n" + "\n" + " if (isset($dataProc[13]) and isset($dataProc[14])) {\n" + " return [\n" + " (int) $dataAll[1] + (int) $dataAll[2] + (int) $dataAll[3] + (int) $dataAll[4],\n" + " (int) $dataProc[13] + (int) $dataProc[14],\n" + " ];\n" + " }\n" + " return [(int) $dataAll[1] + (int) $dataAll[2] + (int) $dataAll[3] + (int) $dataAll[4]];\n" + " }\n" + "\n" + " private static function getProcessMemoryRealUsage($pid = 'self')\n" + " {\n" + " $status = self::getProcessStatus($pid);\n" + " if (!is_array($status) || !isset($status['VmRSS'])) {\n" + " return 0;\n" + " }\n" + " return intval($status['VmRSS']) * 1024;\n" + " }\n" + "\n" + " private static function getProcessStatus($pid = 'self')\n" + " {\n" + " $array = [];\n" + " // TODO: Support other OS\n" + " if (PHP_OS_FAMILY !== 'Linux') {\n" + " return $array;\n" + " }\n" + " $status = swoole_string(trim(file_get_contents('/proc/' . $pid . '/status')));\n" + " $lines = $status->split(\"\\n\");\n" + " foreach ($lines as $l) {\n" + " if (empty($l)) {\n" + " continue;\n" + " }\n" + " [$k, $v] = swoole_string($l)->split(':');\n" + " $array[$k] = trim($v);\n" + " }\n" + " return $array;\n" + " }\n" + "\n" + " private static function getArrayMemorySize(array $a): int\n" + " {\n" + " $size = self::SIZE_OF_ZVAL + self::SIZE_OF_ZEND_ARRAY;\n" + " foreach ($a as $k => $v) {\n" + " if (is_string($k)) {\n" + " $size += self::getStringMemorySize($k);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " if (is_string($v)) {\n" + " $size += self::getStringMemorySize($v);\n" + " } elseif (is_array($v)) {\n" + " $size += self::getArrayMemorySize($v);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " }\n" + " return $size;\n" + " }\n" + "\n" + " private static function getStringMemorySize(string $s): int\n" + " {\n" + " return self::SIZE_OF_ZVAL + self::SIZE_OF_ZEND_STRING + strlen($s);\n" + " }\n" + "\n" + " private static function getObjectMemorySize(object $o): int\n" + " {\n" + " $vars = get_object_vars($o);\n" + " $size = self::SIZE_OF_ZEND_OBJECT;\n" + "\n" + " foreach ($vars as $v) {\n" + " if (is_array($v)) {\n" + " $size += self::getArrayMemorySize($v);\n" + " } elseif (is_string($v)) {\n" + " $size += self::getStringMemorySize($v);\n" + " } else {\n" + " $size += self::SIZE_OF_ZVAL;\n" + " }\n" + " }\n" + "\n" + " return $size;\n" + " }\n" + "\n" + " private static function json($data, $code = 0)\n" + " {\n" + " $result = json_encode(['code' => $code, 'data' => $data], JSON_INVALID_UTF8_IGNORE);\n" + " if (empty($result)) {\n" + " return json_encode([\n" + " 'code' => 5010,\n" + " 'data' => ['message' => json_last_error_msg(), 'code' => json_last_error()],\n" + " ]);\n" + " }\n" + " return $result;\n" + " }\n" + "}\n"; + +static const char* swoole_library_source_core_server_helper = + "\n" + "/**\n" + " * This file is part of Swoole.\n" + " *\n" + " * @link https://www.swoole.com\n" + " * @contact team@swoole.com\n" + " * @license https://github.com/swoole/library/blob/master/LICENSE\n" + " */\n" + "\n" + "declare(strict_types=1);\n" + "\n" + "namespace Swoole\\Server;\n" + "\n" + "use Swoole\\Server;\n" + "use Swoole\\Timer;\n" "use function Swoole\\Coroutine\\go;\n" "\n" "class Helper\n" @@ -6951,6 +7969,7 @@ static const char* swoole_library_source_core_server_helper = "\n" " const HELPER_OPTIONS = [\n" " 'stats_file' => true,\n" + " 'stats_timer_interval' => true,\n" " 'admin_server' => true,\n" " ];\n" "\n" @@ -6970,26 +7989,37 @@ static const char* swoole_library_source_core_server_helper = " public static function onBeforeStart(Server $server)\n" " {\n" " if (!empty($server->setting['admin_server'])) {\n" - " $server->addCommand('coroutine_stats',\n" - " 'Get the statistical data of the coroutine scheduler, PATH: /api/coroutine_stats/{$workerId}, GET: [], POST: []',\n" - " SWOOLE_SERVER_COMMAND_EVENT_WORKER | SWOOLE_SERVER_COMMAND_TASK_WORKER,\n" - " function ($server, $msg) {\n" - " return json_encode(Coroutine::stats());\n" - " }\n" - " );\n" + " Admin::init($server);\n" + " }\n" + " }\n" + "\n" + " public static function onBeforeShutdown(Server $server)\n" + " {\n" + " if ($server->admin_server) {\n" + " $server->admin_server->shutdown();\n" + " $server->admin_server = null;\n" " }\n" " }\n" "\n" " public static function onWorkerStart(Server $server, int $workerId)\n" " {\n" " if (!empty($server->setting['stats_file']) and $workerId == 0) {\n" - " $server->stats_timer = Timer::tick(self::STATS_TIMER_INTERVAL_TIME, function () use ($server) {\n" + " $interval_ms = empty($server->setting['stats_timer_interval']) ? self::STATS_TIMER_INTERVAL_TIME : intval($server->setting['stats_timer_interval']);\n" + "\n" + " $server->stats_timer = Timer::tick($interval_ms, function () use ($server) {\n" " $stats = $server->stats();\n" - " $lines = [];\n" - " foreach ($stats as $k => $v) {\n" - " $lines[] = \"{$k}: {$v}\";\n" + " $stats_file = swoole_string($server->setting['stats_file']);\n" + " if ($stats_file->endsWith('.json')) {\n" + " $out = json_encode($stats);\n" + " } elseif ($stats_file->endsWith('.php')) {\n" + " $out = \" $v) {\n" + " $lines[] = \"{$k}: {$v}\";\n" + " }\n" + " $out = implode(\"\\n\", $lines);\n" " }\n" - " $out = implode(\"\\n\", $lines);\n" " file_put_contents($server->setting['stats_file'], $out);\n" " });\n" " }\n" @@ -7011,32 +8041,7 @@ static const char* swoole_library_source_core_server_helper = " {\n" " if (!empty($server->setting['admin_server'])) {\n" " go(function () use ($server) {\n" - " $admin_server_uri = swoole_string($server->setting['admin_server']);\n" - " if ($admin_server_uri->startsWith('unix:/')) {\n" - " $admin_server = new Coroutine\\Http\\Server($admin_server_uri->toString());\n" - " } else {\n" - " list($host, $port) = $admin_server_uri->split(':', 2)->toArray();\n" - " $admin_server = new Coroutine\\Http\\Server($host, intval($port));\n" - " }\n" - " $admin_server->handle('/api', function (Request $req, Response $resp) use ($server) {\n" - " $path_array = swoole_string($req->server['request_uri'])->trim('/')->split('/');\n" - " $cmd = $path_array->get(1)->toString();\n" - " $worker_id = $path_array->get(2)->toString();\n" - " if ($req->getMethod() == 'GET') {\n" - " var_dump($cmd, intval($worker_id), $req->get);\n" - " $result = $server->command($cmd, intval($worker_id), $req->get);\n" - " } else {\n" - " $result = $server->command($cmd, intval($worker_id), $req->post);\n" - " }\n" - " if (!$result) {\n" - " $resp->end(json_encode(['code' => swoole_last_error(),]));\n" - " } else {\n" - " $resp->end(json_encode(['code' => 0, $result]));\n" - " }\n" - " });\n" - " $admin_server->handle('/app', function (Request $req, Response $resp) use ($server) {\n" - " });\n" - " $admin_server->start();\n" + " Admin::start($server);\n" " });\n" " }\n" " }\n" @@ -7730,6 +8735,7 @@ void php_swoole_load_library() zend::eval(swoole_library_source_core_coroutine_fast_cgi_client_exception, "@swoole-src/library/core/Coroutine/FastCGI/Client/Exception.php"); zend::eval(swoole_library_source_core_coroutine_fast_cgi_proxy, "@swoole-src/library/core/Coroutine/FastCGI/Proxy.php"); zend::eval(swoole_library_source_core_process_manager, "@swoole-src/library/core/Process/Manager.php"); + zend::eval(swoole_library_source_core_server_admin, "@swoole-src/library/core/Server/Admin.php"); zend::eval(swoole_library_source_core_server_helper, "@swoole-src/library/core/Server/Helper.php"); zend::eval(swoole_library_source_core_coroutine_functions, "@swoole-src/library/core/Coroutine/functions.php"); zend::eval(swoole_library_source_ext_curl, "@swoole-src/library/ext/curl.php"); diff --git a/src/memory/fixed_pool.cc b/src/memory/fixed_pool.cc index 2a598e280ec..fdb89aef055 100644 --- a/src/memory/fixed_pool.cc +++ b/src/memory/fixed_pool.cc @@ -82,13 +82,13 @@ FixedPool::FixedPool(uint32_t slice_size, void *memory, size_t size, bool shared impl = (FixedPoolImpl*) memory; memory = (char*) memory + sizeof(*impl); sw_memset_zero(impl, sizeof(*impl)); + impl->shared = shared; + impl->slice_size = slice_size; + impl->size = size - sizeof(*impl); uint32_t slice_num = impl->size / (slice_size + sizeof(FixedPoolSlice)); if (slice_num < 2) { throw Exception(SW_ERROR_INVALID_PARAMS); } - impl->shared = shared; - impl->slice_size = slice_size; - impl->size = size - sizeof(*impl); impl->slice_num = slice_num; impl->memory = memory; impl->allocated = false; diff --git a/tests/include/functions.php b/tests/include/functions.php index 98c954b799e..a57b77d59d5 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -798,4 +798,9 @@ function swoole_get_variance($avg, $array, $is_swatch = false) function swoole_get_average($array) { return array_sum($array) / count($array); -} \ No newline at end of file +} + +function assert_server_stats($stats) { + Assert::keyExists($stats, 'connection_num'); + Assert::keyExists($stats, 'request_count'); +} diff --git a/tests/swoole_server/stats_file.phpt b/tests/swoole_server/stats_file.phpt index 22741a68687..62a438c7ae4 100644 --- a/tests/swoole_server/stats_file.phpt +++ b/tests/swoole_server/stats_file.phpt @@ -9,9 +9,12 @@ require __DIR__ . '/../include/bootstrap.php'; use function Swoole\Coroutine\run; const STATS_FILE = __DIR__ . '/stats.log'; -if (is_file(STATS_FILE)) { - unlink(STATS_FILE); -} +$rm_fn = function () { + if (is_file(STATS_FILE)) { + unlink(STATS_FILE); + } +}; +$rm_fn(); $pm = new ProcessManager; $pm->initFreePorts(1); @@ -59,5 +62,6 @@ $pm->childFunc = function () use ($pm) { $pm->childFirst(); $pm->run(); +$rm_fn(); ?> --EXPECT-- diff --git a/tests/swoole_server/stats_file_json.phpt b/tests/swoole_server/stats_file_json.phpt new file mode 100644 index 00000000000..47dc6717f5c --- /dev/null +++ b/tests/swoole_server/stats_file_json.phpt @@ -0,0 +1,62 @@ +--TEST-- +swoole_server: stats_file [json] +--SKIPIF-- + +--FILE-- +initFreePorts(1); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm, $pid) { + httpRequest('http://127.0.0.1:' . $pm->getFreePort(0)); + for ($i = 0; $i < 4; ++$i) { + Co::sleep(0.5); + $content = @file_get_contents(STATS_FILE); + if ('' != $content) { + $stats = json_decode($content, true); + assert_server_stats($stats); + break; + } + } + }); + echo "\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $mode = SERVER_MODE_RANDOM; + $worker_num = rand(1, 4); + phpt_var_dump("mode: $mode\nworker_num: $worker_num\n"); + $server = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(0), $mode); + $server->set([ + 'stats_file' => STATS_FILE, + 'log_file' => DEV_NULL, + 'worker_num' => $worker_num, + ]); + $server->on('ManagerStart', function ($serv) use ($pm) { + $pm->wakeup(); + }); + $server->on('request', function ($request, $response) { + $response->end("

Hello Swoole. #" . rand(1000, 9999) . "

"); + }); + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); +$rm_fn(); +?> +--EXPECT-- diff --git a/tests/swoole_server/stats_file_php.phpt b/tests/swoole_server/stats_file_php.phpt new file mode 100644 index 00000000000..6f95430bd0e --- /dev/null +++ b/tests/swoole_server/stats_file_php.phpt @@ -0,0 +1,65 @@ +--TEST-- +swoole_server: stats_file [php] +--SKIPIF-- + +--FILE-- +initFreePorts(1); + +$pm->parentFunc = function ($pid) use ($pm) { + run(function () use ($pm, $pid) { + httpRequest('http://127.0.0.1:' . $pm->getFreePort(0)); + for ($i = 0; $i < 4; ++$i) { + Co::sleep(0.5); + if (!is_file(STATS_FILE)) { + continue; + } + $stats = include STATS_FILE; + if (empty($stats)) { + assert_server_stats($stats); + break; + } + } + }); + echo "\n"; + $pm->kill(); +}; + +$pm->childFunc = function () use ($pm) { + $mode = SERVER_MODE_RANDOM; + $worker_num = rand(1, 4); + phpt_var_dump("mode: $mode\nworker_num: $worker_num\n"); + $server = new Swoole\Http\Server('127.0.0.1', $pm->getFreePort(0), $mode); + $server->set([ + 'stats_file' => STATS_FILE, + 'log_file' => DEV_NULL, + 'worker_num' => $worker_num, + ]); + $server->on('ManagerStart', function ($serv) use ($pm) { + $pm->wakeup(); + }); + $server->on('request', function ($request, $response) { + $response->end("

Hello Swoole. #" . rand(1000, 9999) . "

"); + }); + $server->start(); +}; + +$pm->childFirst(); +$pm->run(); + +$rm_fn(); +?> +--EXPECT-- diff --git a/tools/build-library.php b/tools/build-library.php index 9a77ac5b979..4055ed71f53 100755 --- a/tools/build-library.php +++ b/tools/build-library.php @@ -85,6 +85,7 @@ # # 'core/Process/Manager.php', # # + 'core/Server/Admin.php', 'core/Server/Helper.php', # # 'core/Coroutine/functions.php',