Skip to content

Commit 95eb44c

Browse files
authored
[k2] support runtime-config argument (#1401)
1 parent 46f6777 commit 95eb44c

File tree

4 files changed

+61
-7
lines changed

4 files changed

+61
-7
lines changed

runtime-light/state/component-state.cpp

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,41 @@
44

55
#include "runtime-light/state/component-state.h"
66

7+
#include <cstddef>
78
#include <cstring>
89
#include <iterator>
10+
#include <memory>
11+
#include <span>
912
#include <string_view>
13+
#include <sys/stat.h>
1014
#include <utility>
1115

1216
#include "common/php-functions.h"
17+
#include "runtime-common/core/allocator/script-malloc-interface.h"
1318
#include "runtime-common/core/runtime-core.h"
1419
#include "runtime-common/stdlib/serialization/json-functions.h"
1520
#include "runtime-light/k2-platform/k2-api.h"
1621
#include "runtime-light/stdlib/diagnostics/logs.h"
22+
#include "runtime-light/stdlib/file/resource.h"
23+
24+
namespace {
25+
26+
void set_reference_counter_recursive(mixed obj, ExtraRefCnt rc) noexcept {
27+
switch (obj.get_type()) {
28+
case mixed::type::ARRAY:
29+
obj.set_reference_counter_to(rc);
30+
for (const auto& it : obj.as_array()) {
31+
set_reference_counter_recursive(it.get_key(), rc);
32+
set_reference_counter_recursive(it.get_value(), rc);
33+
}
34+
break;
35+
default:
36+
obj.set_reference_counter_to(rc);
37+
break;
38+
}
39+
}
40+
41+
} // namespace
1742

1843
void ComponentState::parse_env() noexcept {
1944
for (auto i = 0; i < envc; ++i) {
@@ -45,11 +70,37 @@ void ComponentState::parse_ini_arg(std::string_view key_view, std::string_view v
4570
}
4671

4772
void ComponentState::parse_runtime_config_arg(std::string_view value_view) noexcept {
48-
if (auto opt_config{json_decode(value_view)}; opt_config) [[likely]] {
49-
runtime_config = *std::move(opt_config);
50-
} else {
51-
kphp::log::warning("runtime config isn't a valid JSON");
73+
auto expected_canonicalized_path{k2::canonicalize(value_view)};
74+
if (!expected_canonicalized_path) [[unlikely]] {
75+
return kphp::log::warning("error canonicalizing runtime-config path: error_code -> {}, path -> '{}'", expected_canonicalized_path.error(), value_view);
76+
}
77+
78+
const auto [runtime_config_path, runtime_config_path_size]{*std::move(expected_canonicalized_path)};
79+
auto expected_runtime_config_file{kphp::fs::file::open({runtime_config_path.get(), runtime_config_path_size}, "r")};
80+
if (!expected_runtime_config_file) [[unlikely]] {
81+
return kphp::log::warning("error opening runtime-config: error code -> {}", expected_runtime_config_file.error());
82+
}
83+
84+
struct stat stat {};
85+
if (auto error_code{k2::stat({runtime_config_path.get(), runtime_config_path_size}, std::addressof(stat))}; error_code != k2::errno_ok) [[unlikely]] {
86+
return kphp::log::warning("error getting runtime-config stat: error code -> {}", error_code);
87+
}
88+
89+
const auto runtime_config_mem{std::unique_ptr<char, decltype(std::addressof(kphp::memory::script::free))>{
90+
reinterpret_cast<char*>(kphp::memory::script::alloc(static_cast<size_t>(stat.st_size))), kphp::memory::script::free}};
91+
kphp::log::assertion(runtime_config_mem != nullptr);
92+
auto runtime_config_buf{std::span<char>{runtime_config_mem.get(), static_cast<size_t>(stat.st_size)}};
93+
if (auto expected_read{(*expected_runtime_config_file).read(std::as_writable_bytes(runtime_config_buf))}; !expected_read || *expected_read != stat.st_size)
94+
[[unlikely]] {
95+
return kphp::log::warning("error reading runtime-config: error code -> {}, read bytes -> {}", expected_read.error_or(k2::errno_ok),
96+
expected_read.value_or(0));
97+
}
98+
99+
auto opt_config{json_decode({runtime_config_buf.data(), runtime_config_buf.size()})};
100+
if (!opt_config) [[unlikely]] {
101+
return kphp::log::warning("error decoding runtime-config");
52102
}
103+
runtime_config = *std::move(opt_config);
53104
}
54105

55106
void ComponentState::parse_args() noexcept {
@@ -66,6 +117,6 @@ void ComponentState::parse_args() noexcept {
66117
kphp::log::warning("unexpected argument format: {}", key_view);
67118
}
68119
}
69-
runtime_config.set_reference_counter_to(ExtraRefCnt::for_global_const);
70120
ini_opts.set_reference_counter_to(ExtraRefCnt::for_global_const);
121+
set_reference_counter_recursive(runtime_config, ExtraRefCnt::for_global_const);
71122
}

runtime-light/state/component-state.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ struct ComponentState final : private vk::not_copyable {
3838
private:
3939
static constexpr std::string_view INI_ARG_PREFIX = "ini ";
4040
static constexpr std::string_view RUNTIME_CONFIG_ARG = "runtime-config";
41-
static constexpr auto INIT_COMPONENT_ALLOCATOR_SIZE = static_cast<size_t>(512U * 1024U); // 512KB
41+
// FIXME: Temporary workaround (increased INIT_COMPONENT_ALLOCATOR_SIZE) to prevent segmentation fault during defragmentation
42+
static constexpr auto INIT_COMPONENT_ALLOCATOR_SIZE = static_cast<size_t>(128U * 1024U * 1024U); // 128MB
4243

4344
void parse_env() noexcept;
4445

tests/python/lib/k2_server.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ def __init__(self, k2_server_bin, working_dir, kphp_build_dir, options=None, aut
2929
"--restart-socket": "/tmp/k2_restart_node_{}".format(hash(self._working_dir)),
3030
"--linking": self._linking_file}
3131

32+
os.environ["RUNTIME_CONFIG_PATH"] = os.path.join(working_dir, "data/runtime_configuration.json")
33+
3234
if options:
3335
self.update_options(options)
3436
if auto_start:

tests/python/tests/http_server/php/data/component-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ components:
55
scope: Request
66
args:
77
ini hello: "world"
8-
runtime-config: "{\"name\": \"simple configuration\", \"version\": \"1.0.0\"}"
8+
runtime-config: ${RUNTIME_CONFIG_PATH}
99
links: {}

0 commit comments

Comments
 (0)