opengris-scaler 1.12.7__cp312-cp312-musllinux_1_2_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of opengris-scaler might be problematic. Click here for more details.
- opengris_scaler-1.12.7.dist-info/METADATA +729 -0
- opengris_scaler-1.12.7.dist-info/RECORD +234 -0
- opengris_scaler-1.12.7.dist-info/WHEEL +5 -0
- opengris_scaler-1.12.7.dist-info/entry_points.txt +9 -0
- opengris_scaler-1.12.7.dist-info/licenses/LICENSE +201 -0
- opengris_scaler-1.12.7.dist-info/licenses/LICENSE.spdx +7 -0
- opengris_scaler-1.12.7.dist-info/licenses/NOTICE +8 -0
- opengris_scaler.libs/libcapnp-1-61c06778.1.0.so +0 -0
- opengris_scaler.libs/libgcc_s-2298274a.so.1 +0 -0
- opengris_scaler.libs/libkj-1-21b63b70.1.0.so +0 -0
- opengris_scaler.libs/libstdc++-08d5c7eb.so.6.0.33 +0 -0
- scaler/CMakeLists.txt +11 -0
- scaler/__init__.py +14 -0
- scaler/about.py +5 -0
- scaler/client/__init__.py +0 -0
- scaler/client/agent/__init__.py +0 -0
- scaler/client/agent/client_agent.py +210 -0
- scaler/client/agent/disconnect_manager.py +27 -0
- scaler/client/agent/future_manager.py +112 -0
- scaler/client/agent/heartbeat_manager.py +74 -0
- scaler/client/agent/mixins.py +89 -0
- scaler/client/agent/object_manager.py +98 -0
- scaler/client/agent/task_manager.py +64 -0
- scaler/client/client.py +635 -0
- scaler/client/future.py +252 -0
- scaler/client/object_buffer.py +129 -0
- scaler/client/object_reference.py +25 -0
- scaler/client/serializer/__init__.py +0 -0
- scaler/client/serializer/default.py +16 -0
- scaler/client/serializer/mixins.py +38 -0
- scaler/cluster/__init__.py +0 -0
- scaler/cluster/cluster.py +115 -0
- scaler/cluster/combo.py +148 -0
- scaler/cluster/object_storage_server.py +45 -0
- scaler/cluster/scheduler.py +83 -0
- scaler/config/__init__.py +0 -0
- scaler/config/defaults.py +87 -0
- scaler/config/loader.py +95 -0
- scaler/config/mixins.py +15 -0
- scaler/config/section/__init__.py +0 -0
- scaler/config/section/cluster.py +56 -0
- scaler/config/section/native_worker_adapter.py +44 -0
- scaler/config/section/object_storage_server.py +7 -0
- scaler/config/section/scheduler.py +53 -0
- scaler/config/section/symphony_worker_adapter.py +47 -0
- scaler/config/section/top.py +13 -0
- scaler/config/section/webui.py +16 -0
- scaler/config/types/__init__.py +0 -0
- scaler/config/types/object_storage_server.py +45 -0
- scaler/config/types/worker.py +57 -0
- scaler/config/types/zmq.py +79 -0
- scaler/entry_points/__init__.py +0 -0
- scaler/entry_points/cluster.py +133 -0
- scaler/entry_points/object_storage_server.py +41 -0
- scaler/entry_points/scheduler.py +135 -0
- scaler/entry_points/top.py +286 -0
- scaler/entry_points/webui.py +26 -0
- scaler/entry_points/worker_adapter_native.py +137 -0
- scaler/entry_points/worker_adapter_symphony.py +102 -0
- scaler/io/__init__.py +0 -0
- scaler/io/async_binder.py +85 -0
- scaler/io/async_connector.py +95 -0
- scaler/io/async_object_storage_connector.py +185 -0
- scaler/io/mixins.py +154 -0
- scaler/io/sync_connector.py +68 -0
- scaler/io/sync_object_storage_connector.py +185 -0
- scaler/io/sync_subscriber.py +83 -0
- scaler/io/utility.py +31 -0
- scaler/io/ymq/CMakeLists.txt +98 -0
- scaler/io/ymq/__init__.py +0 -0
- scaler/io/ymq/_ymq.pyi +96 -0
- scaler/io/ymq/_ymq.so +0 -0
- scaler/io/ymq/bytes.h +114 -0
- scaler/io/ymq/common.h +29 -0
- scaler/io/ymq/configuration.h +60 -0
- scaler/io/ymq/epoll_context.cpp +185 -0
- scaler/io/ymq/epoll_context.h +85 -0
- scaler/io/ymq/error.h +132 -0
- scaler/io/ymq/event_loop.h +55 -0
- scaler/io/ymq/event_loop_thread.cpp +64 -0
- scaler/io/ymq/event_loop_thread.h +46 -0
- scaler/io/ymq/event_manager.h +81 -0
- scaler/io/ymq/file_descriptor.h +203 -0
- scaler/io/ymq/interruptive_concurrent_queue.h +169 -0
- scaler/io/ymq/io_context.cpp +98 -0
- scaler/io/ymq/io_context.h +44 -0
- scaler/io/ymq/io_socket.cpp +299 -0
- scaler/io/ymq/io_socket.h +121 -0
- scaler/io/ymq/iocp_context.cpp +102 -0
- scaler/io/ymq/iocp_context.h +83 -0
- scaler/io/ymq/logging.h +163 -0
- scaler/io/ymq/message.h +15 -0
- scaler/io/ymq/message_connection.h +16 -0
- scaler/io/ymq/message_connection_tcp.cpp +672 -0
- scaler/io/ymq/message_connection_tcp.h +96 -0
- scaler/io/ymq/network_utils.h +179 -0
- scaler/io/ymq/pymod_ymq/bytes.h +113 -0
- scaler/io/ymq/pymod_ymq/exception.h +124 -0
- scaler/io/ymq/pymod_ymq/gil.h +15 -0
- scaler/io/ymq/pymod_ymq/io_context.h +166 -0
- scaler/io/ymq/pymod_ymq/io_socket.h +285 -0
- scaler/io/ymq/pymod_ymq/message.h +99 -0
- scaler/io/ymq/pymod_ymq/python.h +153 -0
- scaler/io/ymq/pymod_ymq/ymq.cpp +23 -0
- scaler/io/ymq/pymod_ymq/ymq.h +357 -0
- scaler/io/ymq/readme.md +114 -0
- scaler/io/ymq/simple_interface.cpp +80 -0
- scaler/io/ymq/simple_interface.h +24 -0
- scaler/io/ymq/tcp_client.cpp +367 -0
- scaler/io/ymq/tcp_client.h +75 -0
- scaler/io/ymq/tcp_operations.h +41 -0
- scaler/io/ymq/tcp_server.cpp +410 -0
- scaler/io/ymq/tcp_server.h +79 -0
- scaler/io/ymq/third_party/concurrentqueue.h +3747 -0
- scaler/io/ymq/timed_queue.h +272 -0
- scaler/io/ymq/timestamp.h +102 -0
- scaler/io/ymq/typedefs.h +20 -0
- scaler/io/ymq/utils.h +34 -0
- scaler/io/ymq/ymq.py +130 -0
- scaler/object_storage/CMakeLists.txt +50 -0
- scaler/object_storage/__init__.py +0 -0
- scaler/object_storage/constants.h +11 -0
- scaler/object_storage/defs.h +14 -0
- scaler/object_storage/io_helper.cpp +44 -0
- scaler/object_storage/io_helper.h +9 -0
- scaler/object_storage/message.cpp +56 -0
- scaler/object_storage/message.h +130 -0
- scaler/object_storage/object_manager.cpp +126 -0
- scaler/object_storage/object_manager.h +52 -0
- scaler/object_storage/object_storage_server.cpp +359 -0
- scaler/object_storage/object_storage_server.h +126 -0
- scaler/object_storage/object_storage_server.so +0 -0
- scaler/object_storage/pymod_object_storage_server.cpp +104 -0
- scaler/protocol/__init__.py +0 -0
- scaler/protocol/capnp/__init__.py +0 -0
- scaler/protocol/capnp/_python.py +6 -0
- scaler/protocol/capnp/common.capnp +63 -0
- scaler/protocol/capnp/message.capnp +216 -0
- scaler/protocol/capnp/object_storage.capnp +52 -0
- scaler/protocol/capnp/status.capnp +73 -0
- scaler/protocol/introduction.md +105 -0
- scaler/protocol/python/__init__.py +0 -0
- scaler/protocol/python/common.py +135 -0
- scaler/protocol/python/message.py +726 -0
- scaler/protocol/python/mixins.py +13 -0
- scaler/protocol/python/object_storage.py +118 -0
- scaler/protocol/python/status.py +279 -0
- scaler/protocol/worker.md +228 -0
- scaler/scheduler/__init__.py +0 -0
- scaler/scheduler/allocate_policy/__init__.py +0 -0
- scaler/scheduler/allocate_policy/allocate_policy.py +9 -0
- scaler/scheduler/allocate_policy/capability_allocate_policy.py +280 -0
- scaler/scheduler/allocate_policy/even_load_allocate_policy.py +159 -0
- scaler/scheduler/allocate_policy/mixins.py +55 -0
- scaler/scheduler/controllers/__init__.py +0 -0
- scaler/scheduler/controllers/balance_controller.py +65 -0
- scaler/scheduler/controllers/client_controller.py +131 -0
- scaler/scheduler/controllers/config_controller.py +31 -0
- scaler/scheduler/controllers/graph_controller.py +424 -0
- scaler/scheduler/controllers/information_controller.py +81 -0
- scaler/scheduler/controllers/mixins.py +201 -0
- scaler/scheduler/controllers/object_controller.py +147 -0
- scaler/scheduler/controllers/scaling_controller.py +86 -0
- scaler/scheduler/controllers/task_controller.py +373 -0
- scaler/scheduler/controllers/worker_controller.py +168 -0
- scaler/scheduler/object_usage/__init__.py +0 -0
- scaler/scheduler/object_usage/object_tracker.py +131 -0
- scaler/scheduler/scheduler.py +253 -0
- scaler/scheduler/task/__init__.py +0 -0
- scaler/scheduler/task/task_state_machine.py +92 -0
- scaler/scheduler/task/task_state_manager.py +61 -0
- scaler/ui/__init__.py +0 -0
- scaler/ui/constants.py +9 -0
- scaler/ui/live_display.py +118 -0
- scaler/ui/memory_window.py +146 -0
- scaler/ui/setting_page.py +47 -0
- scaler/ui/task_graph.py +370 -0
- scaler/ui/task_log.py +83 -0
- scaler/ui/utility.py +35 -0
- scaler/ui/webui.py +125 -0
- scaler/ui/worker_processors.py +85 -0
- scaler/utility/__init__.py +0 -0
- scaler/utility/debug.py +19 -0
- scaler/utility/event_list.py +63 -0
- scaler/utility/event_loop.py +58 -0
- scaler/utility/exceptions.py +42 -0
- scaler/utility/formatter.py +44 -0
- scaler/utility/graph/__init__.py +0 -0
- scaler/utility/graph/optimization.py +27 -0
- scaler/utility/graph/topological_sorter.py +11 -0
- scaler/utility/graph/topological_sorter_graphblas.py +174 -0
- scaler/utility/identifiers.py +105 -0
- scaler/utility/logging/__init__.py +0 -0
- scaler/utility/logging/decorators.py +25 -0
- scaler/utility/logging/scoped_logger.py +33 -0
- scaler/utility/logging/utility.py +183 -0
- scaler/utility/many_to_many_dict.py +123 -0
- scaler/utility/metadata/__init__.py +0 -0
- scaler/utility/metadata/profile_result.py +31 -0
- scaler/utility/metadata/task_flags.py +30 -0
- scaler/utility/mixins.py +13 -0
- scaler/utility/network_util.py +7 -0
- scaler/utility/one_to_many_dict.py +72 -0
- scaler/utility/queues/__init__.py +0 -0
- scaler/utility/queues/async_indexed_queue.py +37 -0
- scaler/utility/queues/async_priority_queue.py +70 -0
- scaler/utility/queues/async_sorted_priority_queue.py +45 -0
- scaler/utility/queues/indexed_queue.py +114 -0
- scaler/utility/serialization.py +9 -0
- scaler/version.txt +1 -0
- scaler/worker/__init__.py +0 -0
- scaler/worker/agent/__init__.py +0 -0
- scaler/worker/agent/heartbeat_manager.py +107 -0
- scaler/worker/agent/mixins.py +137 -0
- scaler/worker/agent/processor/__init__.py +0 -0
- scaler/worker/agent/processor/object_cache.py +107 -0
- scaler/worker/agent/processor/processor.py +279 -0
- scaler/worker/agent/processor/streaming_buffer.py +28 -0
- scaler/worker/agent/processor_holder.py +145 -0
- scaler/worker/agent/processor_manager.py +365 -0
- scaler/worker/agent/profiling_manager.py +109 -0
- scaler/worker/agent/task_manager.py +150 -0
- scaler/worker/agent/timeout_manager.py +19 -0
- scaler/worker/preload.py +84 -0
- scaler/worker/worker.py +264 -0
- scaler/worker_adapter/__init__.py +0 -0
- scaler/worker_adapter/native.py +154 -0
- scaler/worker_adapter/symphony/__init__.py +0 -0
- scaler/worker_adapter/symphony/callback.py +45 -0
- scaler/worker_adapter/symphony/heartbeat_manager.py +79 -0
- scaler/worker_adapter/symphony/message.py +24 -0
- scaler/worker_adapter/symphony/task_manager.py +288 -0
- scaler/worker_adapter/symphony/worker.py +205 -0
- scaler/worker_adapter/symphony/worker_adapter.py +142 -0
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
// Python
|
|
4
|
+
#include "scaler/io/ymq/pymod_ymq/python.h"
|
|
5
|
+
|
|
6
|
+
// C
|
|
7
|
+
#include <fcntl.h>
|
|
8
|
+
#include <unistd.h>
|
|
9
|
+
|
|
10
|
+
// C++
|
|
11
|
+
#include <expected>
|
|
12
|
+
#include <string>
|
|
13
|
+
#include <string_view>
|
|
14
|
+
#include <utility>
|
|
15
|
+
|
|
16
|
+
// First-party
|
|
17
|
+
#include "scaler/io/ymq/error.h"
|
|
18
|
+
|
|
19
|
+
struct YMQState {
|
|
20
|
+
OwnedPyObject<> enumModule; // Reference to the enum module
|
|
21
|
+
OwnedPyObject<> asyncioModule; // Reference to the asyncio module
|
|
22
|
+
|
|
23
|
+
OwnedPyObject<> PyIOSocketEnumType; // Reference to the IOSocketType enum
|
|
24
|
+
OwnedPyObject<> PyErrorCodeType; // Reference to the Error enum
|
|
25
|
+
OwnedPyObject<> PyBytesYMQType; // Reference to the PyBytesYMQ type
|
|
26
|
+
OwnedPyObject<> PyMessageType; // Reference to the Message type
|
|
27
|
+
OwnedPyObject<> PyIOSocketType; // Reference to the IOSocket type
|
|
28
|
+
OwnedPyObject<> PyIOContextType; // Reference to the IOContext type
|
|
29
|
+
OwnedPyObject<> PyExceptionType; // Reference to the Exception type
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static YMQState* YMQStateFromSelf(PyObject* self)
|
|
33
|
+
{
|
|
34
|
+
// replace with PyType_GetModuleByDef(Py_TYPE(self), &YMQ_module) in a newer Python version
|
|
35
|
+
// https://docs.python.org/3/c-api/type.html#c.PyType_GetModuleByDef
|
|
36
|
+
PyObject* pyModule = PyType_GetModule(Py_TYPE(self));
|
|
37
|
+
if (!pyModule)
|
|
38
|
+
return nullptr;
|
|
39
|
+
|
|
40
|
+
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8
|
|
41
|
+
Py_DECREF(pyModule); // As we get a real ref in 3.8 backport
|
|
42
|
+
#endif
|
|
43
|
+
|
|
44
|
+
return (YMQState*)PyModule_GetState(pyModule);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
PyObject* PyErr_CreateFromString(PyObject* type, const char* message)
|
|
48
|
+
{
|
|
49
|
+
OwnedPyObject args = Py_BuildValue("(s)", message);
|
|
50
|
+
if (!args)
|
|
51
|
+
return nullptr;
|
|
52
|
+
|
|
53
|
+
return PyObject_CallObject(type, *args);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// this is a polyfill for PyErr_GetRaisedException() added in Python 3.12+
|
|
57
|
+
std::expected<PyObject*, PyObject*> YMQ_GetRaisedException()
|
|
58
|
+
{
|
|
59
|
+
#if (PY_MAJOR_VERSION <= 3) && (PY_MINOR_VERSION <= 12)
|
|
60
|
+
PyObject *excType, *excValue, *excTraceback;
|
|
61
|
+
PyErr_Fetch(&excType, &excValue, &excTraceback);
|
|
62
|
+
Py_XDECREF(excType);
|
|
63
|
+
Py_XDECREF(excTraceback);
|
|
64
|
+
if (!excValue)
|
|
65
|
+
Py_RETURN_NONE;
|
|
66
|
+
|
|
67
|
+
return std::unexpected {excValue};
|
|
68
|
+
#else
|
|
69
|
+
PyObject* excValue = PyErr_GetRaisedException();
|
|
70
|
+
if (!excValue)
|
|
71
|
+
Py_RETURN_NONE;
|
|
72
|
+
|
|
73
|
+
return std::unexpected {excValue};
|
|
74
|
+
#endif
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void completeCallbackWithRaisedException(PyObject* callback)
|
|
78
|
+
{
|
|
79
|
+
auto result = YMQ_GetRaisedException();
|
|
80
|
+
OwnedPyObject _ =PyObject_CallFunctionObjArgs(callback, result.value_or(result.error()));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// First-Party
|
|
84
|
+
#include "scaler/io/ymq/pymod_ymq/bytes.h"
|
|
85
|
+
#include "scaler/io/ymq/pymod_ymq/exception.h"
|
|
86
|
+
#include "scaler/io/ymq/pymod_ymq/io_context.h"
|
|
87
|
+
#include "scaler/io/ymq/pymod_ymq/io_socket.h"
|
|
88
|
+
#include "scaler/io/ymq/pymod_ymq/message.h"
|
|
89
|
+
|
|
90
|
+
extern "C" {
|
|
91
|
+
|
|
92
|
+
static void YMQ_free(YMQState* state)
|
|
93
|
+
{
|
|
94
|
+
try {
|
|
95
|
+
state->enumModule.~OwnedPyObject();
|
|
96
|
+
state->asyncioModule.~OwnedPyObject();
|
|
97
|
+
state->PyIOSocketEnumType.~OwnedPyObject();
|
|
98
|
+
state->PyErrorCodeType.~OwnedPyObject();
|
|
99
|
+
state->PyBytesYMQType.~OwnedPyObject();
|
|
100
|
+
state->PyMessageType.~OwnedPyObject();
|
|
101
|
+
state->PyIOSocketType.~OwnedPyObject();
|
|
102
|
+
state->PyIOContextType.~OwnedPyObject();
|
|
103
|
+
state->PyExceptionType.~OwnedPyObject();
|
|
104
|
+
} catch (...) {
|
|
105
|
+
PyErr_SetString(PyExc_RuntimeError, "Failed to free YMQState");
|
|
106
|
+
PyErr_WriteUnraisable(nullptr);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
static int YMQ_createIntEnum(
|
|
111
|
+
PyObject* pyModule,
|
|
112
|
+
OwnedPyObject<>* storage,
|
|
113
|
+
std::string enumName,
|
|
114
|
+
std::vector<std::pair<std::string, int>> entries)
|
|
115
|
+
{
|
|
116
|
+
// create a python dictionary to hold the entries
|
|
117
|
+
OwnedPyObject enumDict = PyDict_New();
|
|
118
|
+
if (!enumDict)
|
|
119
|
+
return -1;
|
|
120
|
+
|
|
121
|
+
// add each entry to the dictionary
|
|
122
|
+
for (const auto& entry: entries) {
|
|
123
|
+
OwnedPyObject value = PyLong_FromLong(entry.second);
|
|
124
|
+
if (!value)
|
|
125
|
+
return -1;
|
|
126
|
+
|
|
127
|
+
auto status = PyDict_SetItemString(*enumDict, entry.first.c_str(), *value);
|
|
128
|
+
if (status < 0)
|
|
129
|
+
return -1;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
auto state = (YMQState*)PyModule_GetState(pyModule);
|
|
133
|
+
|
|
134
|
+
if (!state)
|
|
135
|
+
return -1;
|
|
136
|
+
|
|
137
|
+
// create our class by calling enum.IntEnum(enumName, enumDict)
|
|
138
|
+
OwnedPyObject enumClass = PyObject_CallMethod(*state->enumModule, "IntEnum", "sO", enumName.c_str(), *enumDict);
|
|
139
|
+
if (!enumClass)
|
|
140
|
+
return -1;
|
|
141
|
+
|
|
142
|
+
*storage = enumClass;
|
|
143
|
+
|
|
144
|
+
// add the class to the module
|
|
145
|
+
// this increments the reference count of enumClass
|
|
146
|
+
return PyModule_AddObjectRef(pyModule, enumName.c_str(), *enumClass);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
static int YMQ_createIOSocketTypeEnum(PyObject* pyModule, YMQState* state)
|
|
150
|
+
{
|
|
151
|
+
std::vector<std::pair<std::string, int>> ioSocketTypes = {
|
|
152
|
+
{"Uninit", (int)IOSocketType::Uninit},
|
|
153
|
+
{"Binder", (int)IOSocketType::Binder},
|
|
154
|
+
{"Connector", (int)IOSocketType::Connector},
|
|
155
|
+
{"Unicast", (int)IOSocketType::Unicast},
|
|
156
|
+
{"Multicast", (int)IOSocketType::Multicast},
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return YMQ_createIntEnum(pyModule, &state->PyIOSocketEnumType, "IOSocketType", ioSocketTypes);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
static PyObject* YMQErrorCode_explanation(PyObject* self, PyObject* Py_UNUSED(args))
|
|
163
|
+
{
|
|
164
|
+
OwnedPyObject pyValue = PyObject_GetAttrString(self, "value");
|
|
165
|
+
if (!pyValue)
|
|
166
|
+
return nullptr;
|
|
167
|
+
|
|
168
|
+
if (!PyLong_Check(*pyValue)) {
|
|
169
|
+
PyErr_SetString(PyExc_TypeError, "Expected an integer value");
|
|
170
|
+
return nullptr;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
long value = PyLong_AsLong(*pyValue);
|
|
174
|
+
|
|
175
|
+
if (value == -1 && PyErr_Occurred())
|
|
176
|
+
return nullptr;
|
|
177
|
+
|
|
178
|
+
std::string_view explanation = Error::convertErrorToExplanation(static_cast<Error::ErrorCode>(value));
|
|
179
|
+
return PyUnicode_FromString(std::string(explanation).c_str());
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// IDEA: CREATE AN INT ENUM AND ATTACH METHOD AFTERWARDS
|
|
183
|
+
// OR: CREATE A NON-INT ENUM AND USE A TUPLE FOR THE VALUES
|
|
184
|
+
static int YMQ_createErrorCodeEnum(PyObject* pyModule, YMQState* state)
|
|
185
|
+
{
|
|
186
|
+
std::vector<std::pair<std::string, int>> errorCodeValues = {
|
|
187
|
+
{"Uninit", (int)Error::ErrorCode::Uninit},
|
|
188
|
+
{"InvalidPortFormat", (int)Error::ErrorCode::InvalidPortFormat},
|
|
189
|
+
{"InvalidAddressFormat", (int)Error::ErrorCode::InvalidAddressFormat},
|
|
190
|
+
{"ConfigurationError", (int)Error::ErrorCode::ConfigurationError},
|
|
191
|
+
{"SignalNotSupported", (int)Error::ErrorCode::SignalNotSupported},
|
|
192
|
+
{"CoreBug", (int)Error::ErrorCode::CoreBug},
|
|
193
|
+
{"RepetetiveIOSocketIdentity", (int)Error::ErrorCode::RepetetiveIOSocketIdentity},
|
|
194
|
+
{"RedundantIOSocketRefCount", (int)Error::ErrorCode::RedundantIOSocketRefCount},
|
|
195
|
+
{"MultipleConnectToNotSupported", (int)Error::ErrorCode::MultipleConnectToNotSupported},
|
|
196
|
+
{"MultipleBindToNotSupported", (int)Error::ErrorCode::MultipleBindToNotSupported},
|
|
197
|
+
{"InitialConnectFailedWithInProgress", (int)Error::ErrorCode::InitialConnectFailedWithInProgress},
|
|
198
|
+
{"SendMessageRequestCouldNotComplete", (int)Error::ErrorCode::SendMessageRequestCouldNotComplete},
|
|
199
|
+
{"SetSockOptNonFatalFailure", (int)Error::ErrorCode::SetSockOptNonFatalFailure},
|
|
200
|
+
{"IPv6NotSupported", (int)Error::ErrorCode::IPv6NotSupported},
|
|
201
|
+
{"RemoteEndDisconnectedOnSocketWithoutGuaranteedDelivery",
|
|
202
|
+
(int)Error::ErrorCode::RemoteEndDisconnectedOnSocketWithoutGuaranteedDelivery},
|
|
203
|
+
{"ConnectorSocketClosedByRemoteEnd", (int)Error::ErrorCode::ConnectorSocketClosedByRemoteEnd},
|
|
204
|
+
{"IOSocketStopRequested", (int)Error::ErrorCode::IOSocketStopRequested},
|
|
205
|
+
{"BinderSendMessageWithNoAddress", (int)Error::ErrorCode::BinderSendMessageWithNoAddress},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
if (YMQ_createIntEnum(pyModule, &state->PyErrorCodeType, "ErrorCode", errorCodeValues) < 0)
|
|
209
|
+
return -1;
|
|
210
|
+
|
|
211
|
+
static PyMethodDef YMQErrorCode_explanation_def = {
|
|
212
|
+
"explanation",
|
|
213
|
+
(PyCFunction)YMQErrorCode_explanation,
|
|
214
|
+
METH_NOARGS,
|
|
215
|
+
PyDoc_STR("Returns an explanation of a YMQ error code")};
|
|
216
|
+
|
|
217
|
+
OwnedPyObject iter = PyObject_GetIter(*state->PyErrorCodeType);
|
|
218
|
+
if (!iter)
|
|
219
|
+
return -1;
|
|
220
|
+
|
|
221
|
+
// is this the best way to add a method to each enum item?
|
|
222
|
+
// in python you can just write: MyEnum.new_method = ...
|
|
223
|
+
// for some reason this does not seem to work with the c api
|
|
224
|
+
// docs and examples are unfortunately scarce for this
|
|
225
|
+
// for now this will work just fine
|
|
226
|
+
OwnedPyObject item {};
|
|
227
|
+
while ((item = PyIter_Next(*iter))) {
|
|
228
|
+
OwnedPyObject fn = PyCFunction_NewEx(&YMQErrorCode_explanation_def, *item, pyModule);
|
|
229
|
+
if (!fn)
|
|
230
|
+
return -1;
|
|
231
|
+
|
|
232
|
+
auto status = PyObject_SetAttrString(*item, "explanation", *fn);
|
|
233
|
+
if (status < 0)
|
|
234
|
+
return -1;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return 0;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// internal convenience function to create a type and add it to the module
|
|
242
|
+
static int YMQ_createType(
|
|
243
|
+
// the module object
|
|
244
|
+
PyObject* pyModule,
|
|
245
|
+
// storage for the generated type object
|
|
246
|
+
OwnedPyObject<>* storage,
|
|
247
|
+
// the type's spec
|
|
248
|
+
PyType_Spec* spec,
|
|
249
|
+
// the name of the type, can be omitted if `add` is false
|
|
250
|
+
const char* name,
|
|
251
|
+
// whether or not to add this type to the module
|
|
252
|
+
bool add = true,
|
|
253
|
+
// the types base classes
|
|
254
|
+
PyObject* bases = nullptr,
|
|
255
|
+
getbufferproc getbuffer = nullptr,
|
|
256
|
+
releasebufferproc releasebuffer = nullptr)
|
|
257
|
+
{
|
|
258
|
+
assert(storage != nullptr);
|
|
259
|
+
|
|
260
|
+
*storage = PyType_FromModuleAndSpec(pyModule, spec, bases);
|
|
261
|
+
if (!*storage)
|
|
262
|
+
return -1;
|
|
263
|
+
|
|
264
|
+
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8
|
|
265
|
+
if (PyObject_SetAttrString(**storage, "__module_object__", pyModule) < 0)
|
|
266
|
+
return -1;
|
|
267
|
+
|
|
268
|
+
if (getbuffer && releasebuffer) {
|
|
269
|
+
PyTypeObject* type_obj = (PyTypeObject*)**storage;
|
|
270
|
+
|
|
271
|
+
type_obj->tp_as_buffer->bf_getbuffer = getbuffer;
|
|
272
|
+
type_obj->tp_as_buffer->bf_releasebuffer = releasebuffer;
|
|
273
|
+
type_obj->tp_flags |= 0; // Do I need to add tp_flags? Seems not
|
|
274
|
+
}
|
|
275
|
+
#endif
|
|
276
|
+
|
|
277
|
+
if (add)
|
|
278
|
+
if (PyModule_AddObjectRef(pyModule, name, **storage) < 0)
|
|
279
|
+
return -1;
|
|
280
|
+
|
|
281
|
+
return 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
static int YMQ_exec(PyObject* pyModule)
|
|
285
|
+
{
|
|
286
|
+
auto state = (YMQState*)PyModule_GetState(pyModule);
|
|
287
|
+
if (!state)
|
|
288
|
+
return -1;
|
|
289
|
+
|
|
290
|
+
state->enumModule = PyImport_ImportModule("enum");
|
|
291
|
+
if (!state->enumModule)
|
|
292
|
+
return -1;
|
|
293
|
+
|
|
294
|
+
state->asyncioModule = PyImport_ImportModule("asyncio");
|
|
295
|
+
if (!state->asyncioModule)
|
|
296
|
+
return -1;
|
|
297
|
+
|
|
298
|
+
if (YMQ_createIOSocketTypeEnum(pyModule, state) < 0)
|
|
299
|
+
return -1;
|
|
300
|
+
|
|
301
|
+
if (YMQ_createErrorCodeEnum(pyModule, state) < 0)
|
|
302
|
+
return -1;
|
|
303
|
+
|
|
304
|
+
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION == 8
|
|
305
|
+
if (YMQ_createType(
|
|
306
|
+
pyModule,
|
|
307
|
+
&state->PyBytesYMQType,
|
|
308
|
+
&PyBytesYMQ_spec,
|
|
309
|
+
"Bytes",
|
|
310
|
+
true,
|
|
311
|
+
nullptr,
|
|
312
|
+
(getbufferproc)PyBytesYMQ_getbuffer,
|
|
313
|
+
(releasebufferproc)PyBytesYMQ_releasebuffer) < 0)
|
|
314
|
+
return -1;
|
|
315
|
+
#else
|
|
316
|
+
if (YMQ_createType(pyModule, &state->PyBytesYMQType, &PyBytesYMQ_spec, "Bytes") < 0)
|
|
317
|
+
return -1;
|
|
318
|
+
#endif
|
|
319
|
+
|
|
320
|
+
if (YMQ_createType(pyModule, &state->PyMessageType, &PyMessage_spec, "Message") < 0)
|
|
321
|
+
return -1;
|
|
322
|
+
|
|
323
|
+
if (YMQ_createType(pyModule, &state->PyIOSocketType, &PyIOSocket_spec, "BaseIOSocket") < 0)
|
|
324
|
+
return -1;
|
|
325
|
+
|
|
326
|
+
if (YMQ_createType(pyModule, &state->PyIOContextType, &PyIOContext_spec, "BaseIOContext") < 0)
|
|
327
|
+
return -1;
|
|
328
|
+
|
|
329
|
+
PyObject* exceptionBases = PyTuple_Pack(1, PyExc_Exception);
|
|
330
|
+
if (!exceptionBases)
|
|
331
|
+
return -1;
|
|
332
|
+
|
|
333
|
+
if (YMQ_createType(pyModule, &state->PyExceptionType, &YMQException_spec, "YMQException", true, exceptionBases) <
|
|
334
|
+
0) {
|
|
335
|
+
Py_DECREF(exceptionBases);
|
|
336
|
+
return -1;
|
|
337
|
+
}
|
|
338
|
+
Py_DECREF(exceptionBases);
|
|
339
|
+
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
static PyModuleDef_Slot YMQ_slots[] = {
|
|
344
|
+
{Py_mod_exec, (void*)YMQ_exec},
|
|
345
|
+
{0, nullptr},
|
|
346
|
+
};
|
|
347
|
+
|
|
348
|
+
static PyModuleDef YMQ_module = {
|
|
349
|
+
.m_base = PyModuleDef_HEAD_INIT,
|
|
350
|
+
.m_name = "_ymq",
|
|
351
|
+
.m_doc = PyDoc_STR("YMQ Python bindings"),
|
|
352
|
+
.m_size = sizeof(YMQState),
|
|
353
|
+
.m_slots = YMQ_slots,
|
|
354
|
+
.m_free = (freefunc)YMQ_free,
|
|
355
|
+
};
|
|
356
|
+
|
|
357
|
+
PyMODINIT_FUNC PyInit_ymq(void);
|
scaler/io/ymq/readme.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
|
|
2
|
+
# YMQ
|
|
3
|
+
|
|
4
|
+
Welcome. This file contains schedule for each day, for each person.
|
|
5
|
+
|
|
6
|
+
Each person maintains a todo and done list.
|
|
7
|
+
|
|
8
|
+
## gxu
|
|
9
|
+
|
|
10
|
+
### DONE
|
|
11
|
+
|
|
12
|
+
- CMake integration, generate C++ stuff in build dir
|
|
13
|
+
- Basic coroutine API
|
|
14
|
+
- develop the so-called coro_context and their utility DEAD
|
|
15
|
+
- write up interfaces(not impl) that uses coroutine DEAD
|
|
16
|
+
|
|
17
|
+
## DONE:
|
|
18
|
+
- Remember (or remove) the IOSocketIdentity of closed connection
|
|
19
|
+
- Basic coroutine API (DEAD)
|
|
20
|
+
- develop the so-called coro_context and their utility (DEAD)
|
|
21
|
+
- write up interfaces(not impl) that uses coroutine (DEAD)
|
|
22
|
+
- Use unified file path (only include dir is project dir)
|
|
23
|
+
- Start organize files that they can be compiled in one go
|
|
24
|
+
- Write delayed execution utility
|
|
25
|
+
- Write timed execution utility
|
|
26
|
+
- IOSocket exchange identity on connected
|
|
27
|
+
- General message passing assuming user passed in Message with header
|
|
28
|
+
- Guaranteed message delivery
|
|
29
|
+
- Retry on disconnect
|
|
30
|
+
- Delete fd from eventloop on disconnect
|
|
31
|
+
- Put Recv on iosocket level because user don't know which connection it should recv from
|
|
32
|
+
- cleanup: IOSocket destructor should release resources bound to it
|
|
33
|
+
- cleanup: Clarify Bytes ownership of send/recv messages
|
|
34
|
+
- Provide connect(str) function that parse the string to a sockaddr.
|
|
35
|
+
- make connectTo takes a callback
|
|
36
|
+
- Implement bind function with interface address (str) and callback
|
|
37
|
+
- cleanup: report error when no connection with desired identity presents
|
|
38
|
+
- cleanup: Give user more control about port/addr
|
|
39
|
+
- test the project (now working when user kills the program)
|
|
40
|
+
- cleanup: Provide actual remote sockaddr in the connection class
|
|
41
|
+
- test the user provided callback logic and think about sync issue
|
|
42
|
+
- connect do not happen twice, monitor for read/write instead
|
|
43
|
+
- remove the end of each loop hook, this is stupid
|
|
44
|
+
- test the abnormal breakup (break up due to network issue instead of killing)
|
|
45
|
+
- Per action cancellation
|
|
46
|
+
- refactor: Ownership, Public/Private, destructor
|
|
47
|
+
- cleanup: Do not constraint thee size of identity (current maximum being 128-8 bytes)
|
|
48
|
+
- make IO with send/recv msg
|
|
49
|
+
- automatically destroy threads when no ioSocket is running on it
|
|
50
|
+
- update numbers -> constants
|
|
51
|
+
- cleanup: Change InterruptiveConcurrentQueue behavior
|
|
52
|
+
- Fix issue lambda captures being copied instead of move
|
|
53
|
+
- allow user to change how many times they want to retry
|
|
54
|
+
- cleanup: make sure when eventloop is destructed all resources is freed
|
|
55
|
+
- remove bytes ownership code
|
|
56
|
+
- add constexpr, noexcept, overloads, explicit to the code
|
|
57
|
+
- make sure every call is moved instead of being copied
|
|
58
|
+
- iosocket behaves differently when provided with different IOSocketType
|
|
59
|
+
- Refactor: MessageConnectionTCP is easier to construct correctly
|
|
60
|
+
- provide reference implementation of the error type (Error)
|
|
61
|
+
- reference usage of the error type
|
|
62
|
+
-
|
|
63
|
+
-
|
|
64
|
+
-
|
|
65
|
+
-
|
|
66
|
+
-
|
|
67
|
+
- LEAVE A FEW BLANKS HERE TO AVOID CONFLICT
|
|
68
|
+
|
|
69
|
+
## TODO:
|
|
70
|
+
- resolve github comment (there are still some)
|
|
71
|
+
- cleanup: Do not use std::string as identity type
|
|
72
|
+
- cleanup: Error handling
|
|
73
|
+
- Use one consistent print logic
|
|
74
|
+
- add proper logging message
|
|
75
|
+
- configuration won't work because we are compiliing it on github box, figure out a new way
|
|
76
|
+
- write tests
|
|
77
|
+
- examples
|
|
78
|
+
- performance measurement
|
|
79
|
+
- Determine what happens when user close socket but there are pending send/recv
|
|
80
|
+
- multiple connectTo issue consecutively support
|
|
81
|
+
-
|
|
82
|
+
-
|
|
83
|
+
-
|
|
84
|
+
-
|
|
85
|
+
-
|
|
86
|
+
-
|
|
87
|
+
-
|
|
88
|
+
-
|
|
89
|
+
-
|
|
90
|
+
-
|
|
91
|
+
-
|
|
92
|
+
- allow staticlly linking the project
|
|
93
|
+
- Namespace support, and move third_party code to top directory.
|
|
94
|
+
- Optimize performance in `updateWriteOperations`
|
|
95
|
+
- LEAVE A FEW BLANKS HERE TO AVOID CONFLICT
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
## magniloquency
|
|
99
|
+
=======
|
|
100
|
+
- support for cancel of execution
|
|
101
|
+
-
|
|
102
|
+
-
|
|
103
|
+
-
|
|
104
|
+
-
|
|
105
|
+
- LEAVE A FEW BLANKS HERE TO AVOID CONFLICT
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
### DONE
|
|
109
|
+
|
|
110
|
+
- CPython module stub
|
|
111
|
+
|
|
112
|
+
### TODO
|
|
113
|
+
|
|
114
|
+
- ?
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
|
|
2
|
+
#include "scaler/io/ymq/simple_interface.h"
|
|
3
|
+
|
|
4
|
+
#include <optional>
|
|
5
|
+
|
|
6
|
+
namespace scaler {
|
|
7
|
+
namespace ymq {
|
|
8
|
+
|
|
9
|
+
std::shared_ptr<IOSocket> syncCreateSocket(IOContext& context, IOSocketType type, std::string name)
|
|
10
|
+
{
|
|
11
|
+
auto createSocketPromise = std::promise<std::shared_ptr<IOSocket>>();
|
|
12
|
+
auto createSocketFuture = createSocketPromise.get_future();
|
|
13
|
+
context.createIOSocket(
|
|
14
|
+
std::move(name), type, [&createSocketPromise](auto sock) { createSocketPromise.set_value(sock); });
|
|
15
|
+
|
|
16
|
+
auto clientSocket = createSocketFuture.get();
|
|
17
|
+
return clientSocket;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
void syncBindSocket(std::shared_ptr<IOSocket> socket, std::string address)
|
|
21
|
+
{
|
|
22
|
+
auto bind_promise = std::promise<std::expected<void, Error>>();
|
|
23
|
+
auto bind_future = bind_promise.get_future();
|
|
24
|
+
// Optionally handle result in the callback
|
|
25
|
+
socket->bindTo(address, [&bind_promise](std::expected<void, Error> result) { bind_promise.set_value(result); });
|
|
26
|
+
bind_future.wait();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
void syncConnectSocket(std::shared_ptr<IOSocket> socket, std::string address)
|
|
30
|
+
{
|
|
31
|
+
auto connect_promise = std::promise<std::expected<void, Error>>();
|
|
32
|
+
auto connect_future = connect_promise.get_future();
|
|
33
|
+
|
|
34
|
+
socket->connectTo(
|
|
35
|
+
address, [&connect_promise](std::expected<void, Error> result) { connect_promise.set_value(result); });
|
|
36
|
+
|
|
37
|
+
connect_future.wait();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
std::expected<Message, Error> syncRecvMessage(std::shared_ptr<IOSocket> socket)
|
|
41
|
+
{
|
|
42
|
+
auto fut = futureRecvMessage(std::move(socket));
|
|
43
|
+
return fut.get();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
std::optional<Error> syncSendMessage(std::shared_ptr<IOSocket> socket, Message message)
|
|
47
|
+
{
|
|
48
|
+
auto fut = futureSendMessage(std::move(socket), std::move(message));
|
|
49
|
+
return fut.get();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
std::future<std::expected<Message, Error>> futureRecvMessage(std::shared_ptr<IOSocket> socket)
|
|
53
|
+
{
|
|
54
|
+
auto recv_promise_ptr = std::make_unique<std::promise<std::expected<Message, Error>>>();
|
|
55
|
+
auto recv_future = recv_promise_ptr->get_future();
|
|
56
|
+
socket->recvMessage([recv_promise = std::move(recv_promise_ptr)](std::pair<Message, Error> result) {
|
|
57
|
+
if (result.second._errorCode == Error::ErrorCode::Uninit)
|
|
58
|
+
recv_promise->set_value(std::move(result.first));
|
|
59
|
+
else
|
|
60
|
+
recv_promise->set_value(std::unexpected {std::move(result.second)});
|
|
61
|
+
});
|
|
62
|
+
return recv_future;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
std::future<std::optional<Error>> futureSendMessage(std::shared_ptr<IOSocket> socket, Message message)
|
|
66
|
+
{
|
|
67
|
+
auto send_promise_ptr = std::make_unique<std::promise<std::optional<Error>>>();
|
|
68
|
+
auto send_future = send_promise_ptr->get_future();
|
|
69
|
+
socket->sendMessage(
|
|
70
|
+
std::move(message), [send_promise = std::move(send_promise_ptr)](std::expected<void, Error> result) {
|
|
71
|
+
if (result)
|
|
72
|
+
send_promise->set_value(std::nullopt);
|
|
73
|
+
else
|
|
74
|
+
send_promise->set_value(std::move(result.error()));
|
|
75
|
+
});
|
|
76
|
+
return send_future;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
} // namespace ymq
|
|
80
|
+
} // namespace scaler
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <future>
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
#include "scaler/io/ymq/error.h"
|
|
7
|
+
#include "scaler/io/ymq/io_context.h"
|
|
8
|
+
#include "scaler/io/ymq/io_socket.h"
|
|
9
|
+
|
|
10
|
+
namespace scaler {
|
|
11
|
+
namespace ymq {
|
|
12
|
+
|
|
13
|
+
std::shared_ptr<IOSocket> syncCreateSocket(IOContext& context, IOSocketType type, std::string name);
|
|
14
|
+
void syncBindSocket(std::shared_ptr<IOSocket> socket, std::string address);
|
|
15
|
+
void syncConnectSocket(std::shared_ptr<IOSocket> socket, std::string address);
|
|
16
|
+
|
|
17
|
+
std::expected<Message, Error> syncRecvMessage(std::shared_ptr<IOSocket> socket);
|
|
18
|
+
std::optional<Error> syncSendMessage(std::shared_ptr<IOSocket> socket, Message message);
|
|
19
|
+
|
|
20
|
+
std::future<std::expected<Message, Error>> futureRecvMessage(std::shared_ptr<IOSocket> socket);
|
|
21
|
+
std::future<std::optional<Error>> futureSendMessage(std::shared_ptr<IOSocket> socket, Message message);
|
|
22
|
+
|
|
23
|
+
} // namespace ymq
|
|
24
|
+
} // namespace scaler
|