Branch data Line data Source code
1 : : // Copyright 2026 HPActor Contributors
2 : : //
3 : : // Licensed under the Apache License, Version 2.0 (the "License");
4 : : // you may not use this file except in compliance with the License.
5 : : // You may obtain a copy of the License at
6 : : //
7 : : // http://www.apache.org/licenses/LICENSE-2.0
8 : : //
9 : : // Unless required by applicable law or agreed to in writing, software
10 : : // distributed under the License is distributed on an "AS IS" BASIS,
11 : : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : : // See the License for the specific language governing permissions and
13 : : // limitations under the License.
14 : :
15 : : #include <hpactor/config/toml_config_parser.hpp>
16 : : #include <hpactor/config/toml_parser_registry.hpp>
17 : : #include <hpactor/mailbox/dead_letter_queue.hpp>
18 : : #include <hpactor/mailbox/mailbox_policy.hpp>
19 : :
20 : : namespace hpactor::config {
21 : : namespace {
22 : :
23 : : // ---------------------------------------------------------------------------
24 : : // DispatchPolicy string parsing
25 : : // ---------------------------------------------------------------------------
26 : 56 : static DispatchPolicy parse_dispatch_policy(const std::string& s) {
27 : 56 : if (s == "DedicatedThread")
28 : 0 : return DispatchPolicy::DedicatedThread;
29 : 56 : if (s == "DedicatedPool")
30 : 0 : return DispatchPolicy::DedicatedPool;
31 : 56 : return DispatchPolicy::Cooperative;
32 : : }
33 : :
34 : : // ---------------------------------------------------------------------------
35 : : // OverflowPolicy string parsing
36 : : // ---------------------------------------------------------------------------
37 : : static hpactor::mailbox::OverflowPolicy
38 : 4 : parse_overflow_policy(const std::string& s) {
39 : 4 : if (s == "drop_newest")
40 : 4 : return hpactor::mailbox::OverflowPolicy::DropNewest;
41 : 0 : if (s == "drop_oldest")
42 : 0 : return hpactor::mailbox::OverflowPolicy::DropOldest;
43 : 0 : if (s == "drop_lowest_priority")
44 : 0 : return hpactor::mailbox::OverflowPolicy::DropLowestPriority;
45 : 0 : if (s == "dead_letter")
46 : 0 : return hpactor::mailbox::OverflowPolicy::DeadLetter;
47 : 0 : if (s == "spill_to_overflow_queue")
48 : 0 : return hpactor::mailbox::OverflowPolicy::SpillToOverflowQueue;
49 : 0 : if (s == "signal_only")
50 : 0 : return hpactor::mailbox::OverflowPolicy::SignalOnly;
51 : 0 : if (s == "block_when_allowed")
52 : 0 : return hpactor::mailbox::OverflowPolicy::BlockWhenAllowed;
53 : 0 : return hpactor::mailbox::OverflowPolicy::RejectNewest;
54 : : }
55 : :
56 : : // ---------------------------------------------------------------------------
57 : : // Parse [[dispatcher]] from a toml table
58 : : // ---------------------------------------------------------------------------
59 : 2 : static DispatcherDef parse_dispatcher(const TomlTableView& tbl) {
60 : 2 : DispatcherDef def;
61 : 2 : def.name = tbl.read_string("name");
62 : 2 : def.threads = static_cast<uint16_t>(tbl.read_uint32("threads", 1));
63 : :
64 : 2 : tbl.for_each_integer_array("cpu_affinity", [&](int64_t val) {
65 : 2 : if (val >= 0 && val <= 255)
66 : 2 : def.cpu_affinity.push_back(static_cast<uint8_t>(val));
67 : 2 : });
68 : 2 : return def;
69 : : }
70 : :
71 : : // ---------------------------------------------------------------------------
72 : : // Parse [[actor]] from a toml table
73 : : // ---------------------------------------------------------------------------
74 : 56 : static ActorDef parse_actor(const TomlTableView& tbl) {
75 : 56 : ActorDef def;
76 : 56 : def.id = tbl.read_string("id");
77 : 56 : def.behavior = tbl.read_string("behavior");
78 : 56 : def.supervisor = tbl.read_string("supervisor");
79 : 56 : def.dispatcher = tbl.read_string("dispatcher");
80 : 56 : def.mailbox_capacity = tbl.read_uint32("mailbox_capacity");
81 : 56 : def.dispatch_policy =
82 : 56 : parse_dispatch_policy(tbl.read_string("dispatch_policy", "Cooperativ"
83 : : "e"));
84 : :
85 : 56 : auto resources = tbl.table("resources");
86 : 56 : if (resources.valid()) {
87 : 0 : def.resources.slab_class_bytes = resources.read_uint32("slab_class_"
88 : : "bytes");
89 : 0 : def.resources.max_memory_kb = resources.read_uint32("max_memory_kb");
90 : : }
91 : :
92 : 56 : auto mailbox = tbl.table("mailbox");
93 : 56 : if (mailbox.valid()) {
94 : 4 : def.mailbox.policy =
95 : 4 : parse_overflow_policy(mailbox.read_string("policy", "reject_"
96 : : "newest"));
97 : 4 : def.mailbox.priority_aware = mailbox.read_bool("priority_aware", false);
98 : 4 : def.mailbox.max_overflow_depth =
99 : 4 : mailbox.read_uint32("max_overflow_depth", 0);
100 : : }
101 : :
102 : 56 : auto args = tbl.table("args");
103 : 56 : if (args.valid()) {
104 : 15 : args.for_each_entry([&](std::string_view key, TomlValueView val) {
105 : 9 : std::string key_str{key};
106 : 9 : if (val.is_string())
107 : 9 : def.args[key_str] = val.as_string("");
108 : 0 : else if (val.is_integer())
109 : 0 : def.args[key_str] = std::to_string(val.as_int64(0));
110 : 0 : else if (val.is_floating_point())
111 : 0 : def.args[key_str] = std::to_string(val.as_double(0.0));
112 : 0 : else if (val.is_boolean())
113 : 0 : def.args[key_str] = val.as_bool(false) ? "true" : "false";
114 : 9 : });
115 : : }
116 : :
117 : 56 : return def;
118 : : }
119 : :
120 : : // ---------------------------------------------------------------------------
121 : : // Topology document parser
122 : : // ---------------------------------------------------------------------------
123 : : class TopologyConfigParser final : public ITomlDocumentConfigParser {
124 : : public:
125 : : static constexpr std::string_view kName = "topology.document";
126 : : static constexpr int kOrder = 0;
127 : :
128 : 0 : std::string_view name() const noexcept override {
129 : 0 : return kName;
130 : : }
131 : 0 : int order() const noexcept override {
132 : 0 : return kOrder;
133 : : }
134 : :
135 : 37 : result<void> parse(const TomlTableView& root, TomlFileData& out,
136 : : TomlParseContext& /*ctx*/) const override {
137 : : // Parse [[dispatcher]]
138 : 37 : root.for_each_table_array("dispatcher", [&](TomlTableView disp_tbl) {
139 : 2 : out.dispatchers.emplace_back(parse_dispatcher(disp_tbl));
140 : 2 : });
141 : :
142 : : // Parse [template.*]
143 : 37 : root.for_each_subtable("template", [&](std::string_view tmpl_name,
144 : : TomlTableView tmpl_tbl) {
145 : 12 : out.templates[std::string{tmpl_name}] = parse_actor(tmpl_tbl);
146 : 4 : });
147 : :
148 : : // Parse [[actor]]
149 : 37 : root.for_each_table_array("actor", [&](TomlTableView actor_tbl) {
150 : 52 : TomlRawActor raw;
151 : 52 : raw.def = parse_actor(actor_tbl);
152 : 52 : raw.inherits = actor_tbl.read_string("inherits");
153 : 52 : out.actors.emplace_back(std::move(raw));
154 : 52 : });
155 : :
156 : 37 : return result<void>::make();
157 : : }
158 : : };
159 : :
160 : : const TomlDocumentParserRegistration<TopologyConfigParser> kRegisterTopologyConfigParser;
161 : :
162 : : } // anonymous namespace
163 : : } // namespace hpactor::config
|