opengris-scaler 1.12.7__cp38-cp38-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,672 @@
|
|
|
1
|
+
|
|
2
|
+
#include "scaler/io/ymq/message_connection_tcp.h"
|
|
3
|
+
|
|
4
|
+
#include "scaler/io/ymq/configuration.h"
|
|
5
|
+
|
|
6
|
+
#ifdef __linux__
|
|
7
|
+
#include <unistd.h>
|
|
8
|
+
#endif // __linux__
|
|
9
|
+
#ifdef _WIN32
|
|
10
|
+
// clang-format off
|
|
11
|
+
#include <windows.h>
|
|
12
|
+
#include <winsock2.h>
|
|
13
|
+
#include <mswsock.h>
|
|
14
|
+
// clang-format on
|
|
15
|
+
#endif // _WIN32
|
|
16
|
+
|
|
17
|
+
#include <algorithm>
|
|
18
|
+
#include <cerrno>
|
|
19
|
+
#include <cstddef>
|
|
20
|
+
#include <cstdint>
|
|
21
|
+
#include <cstdio>
|
|
22
|
+
#include <expected>
|
|
23
|
+
#include <functional>
|
|
24
|
+
#include <memory>
|
|
25
|
+
#include <optional>
|
|
26
|
+
|
|
27
|
+
#include "scaler/io/ymq/error.h"
|
|
28
|
+
#include "scaler/io/ymq/event_loop_thread.h"
|
|
29
|
+
#include "scaler/io/ymq/event_manager.h"
|
|
30
|
+
#include "scaler/io/ymq/io_socket.h"
|
|
31
|
+
#include "scaler/io/ymq/network_utils.h"
|
|
32
|
+
|
|
33
|
+
namespace scaler {
|
|
34
|
+
namespace ymq {
|
|
35
|
+
|
|
36
|
+
static constexpr const size_t HEADER_SIZE = sizeof(uint64_t);
|
|
37
|
+
|
|
38
|
+
constexpr bool MessageConnectionTCP::isCompleteMessage(const TcpReadOperation& x)
|
|
39
|
+
{
|
|
40
|
+
if (x._cursor < HEADER_SIZE) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (x._cursor == x._header + HEADER_SIZE && x._payload.data() != nullptr) {
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
MessageConnectionTCP::MessageConnectionTCP(
|
|
50
|
+
std::shared_ptr<EventLoopThread> eventLoopThread,
|
|
51
|
+
int connFd,
|
|
52
|
+
sockaddr localAddr,
|
|
53
|
+
sockaddr remoteAddr,
|
|
54
|
+
std::string localIOSocketIdentity,
|
|
55
|
+
bool responsibleForRetry,
|
|
56
|
+
std::shared_ptr<std::queue<RecvMessageCallback>> pendingRecvMessageCallbacks) noexcept
|
|
57
|
+
: _eventLoopThread(eventLoopThread)
|
|
58
|
+
, _remoteAddr(std::move(remoteAddr))
|
|
59
|
+
, _responsibleForRetry(responsibleForRetry)
|
|
60
|
+
, _remoteIOSocketIdentity(std::nullopt)
|
|
61
|
+
, _eventManager(std::make_unique<EventManager>())
|
|
62
|
+
, _connFd(std::move(connFd))
|
|
63
|
+
, _localAddr(std::move(localAddr))
|
|
64
|
+
, _localIOSocketIdentity(std::move(localIOSocketIdentity))
|
|
65
|
+
, _sendCursor {}
|
|
66
|
+
, _pendingRecvMessageCallbacks(pendingRecvMessageCallbacks)
|
|
67
|
+
, _disconnect {false}
|
|
68
|
+
{
|
|
69
|
+
_eventManager->onRead = [this] { this->onRead(); };
|
|
70
|
+
_eventManager->onWrite = [this] { this->onWrite(); };
|
|
71
|
+
_eventManager->onClose = [this] { this->onClose(); };
|
|
72
|
+
_eventManager->onError = [this] { this->onError(); };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
MessageConnectionTCP::MessageConnectionTCP(
|
|
76
|
+
std::shared_ptr<EventLoopThread> eventLoopThread,
|
|
77
|
+
std::string localIOSocketIdentity,
|
|
78
|
+
std::string remoteIOSocketIdentity,
|
|
79
|
+
std::shared_ptr<std::queue<RecvMessageCallback>> pendingRecvMessageCallbacks) noexcept
|
|
80
|
+
: _eventLoopThread(eventLoopThread)
|
|
81
|
+
, _remoteAddr {}
|
|
82
|
+
, _responsibleForRetry(false)
|
|
83
|
+
, _remoteIOSocketIdentity(std::move(remoteIOSocketIdentity))
|
|
84
|
+
, _eventManager(std::make_unique<EventManager>())
|
|
85
|
+
, _connFd {}
|
|
86
|
+
, _localAddr {}
|
|
87
|
+
, _localIOSocketIdentity(std::move(localIOSocketIdentity))
|
|
88
|
+
, _sendCursor {}
|
|
89
|
+
, _pendingRecvMessageCallbacks(pendingRecvMessageCallbacks)
|
|
90
|
+
, _disconnect {false}
|
|
91
|
+
{
|
|
92
|
+
_eventManager->onRead = [this] { this->onRead(); };
|
|
93
|
+
_eventManager->onWrite = [this] { this->onWrite(); };
|
|
94
|
+
_eventManager->onClose = [this] { this->onClose(); };
|
|
95
|
+
_eventManager->onError = [this] { this->onError(); };
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void MessageConnectionTCP::onCreated()
|
|
99
|
+
{
|
|
100
|
+
if (_connFd != 0) {
|
|
101
|
+
#ifdef __linux__
|
|
102
|
+
this->_eventLoopThread->_eventLoop.addFdToLoop(
|
|
103
|
+
_connFd, EPOLLIN | EPOLLOUT | EPOLLET, this->_eventManager.get());
|
|
104
|
+
_writeOperations.emplace_back(
|
|
105
|
+
Bytes {_localIOSocketIdentity.data(), _localIOSocketIdentity.size()}, [](auto) {});
|
|
106
|
+
#endif // __linux__
|
|
107
|
+
#ifdef _WIN32
|
|
108
|
+
// This probably need handle the addtwice problem
|
|
109
|
+
this->_eventLoopThread->_eventLoop.addFdToLoop(_connFd, 0, nullptr);
|
|
110
|
+
_writeOperations.emplace_back(
|
|
111
|
+
Bytes {_localIOSocketIdentity.data(), _localIOSocketIdentity.size()}, [](auto) {});
|
|
112
|
+
onWrite();
|
|
113
|
+
const bool ok = ReadFile((HANDLE)(SOCKET)_connFd, nullptr, 0, nullptr, this->_eventManager.get());
|
|
114
|
+
if (ok) {
|
|
115
|
+
onRead();
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const int lastError = GetLastError();
|
|
119
|
+
if (lastError == ERROR_IO_PENDING) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
unrecoverableError({
|
|
123
|
+
Error::ErrorCode::CoreBug,
|
|
124
|
+
"Originated from",
|
|
125
|
+
"ReadFile",
|
|
126
|
+
"Errno is",
|
|
127
|
+
lastError,
|
|
128
|
+
"_connfd",
|
|
129
|
+
_connFd,
|
|
130
|
+
});
|
|
131
|
+
#endif // _WIN32
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
std::expected<void, MessageConnectionTCP::IOError> MessageConnectionTCP::tryReadOneMessage()
|
|
136
|
+
{
|
|
137
|
+
if (_receivedReadOperations.empty() || isCompleteMessage(_receivedReadOperations.back())) {
|
|
138
|
+
_receivedReadOperations.emplace();
|
|
139
|
+
}
|
|
140
|
+
while (!isCompleteMessage(_receivedReadOperations.back())) {
|
|
141
|
+
char* readTo = nullptr;
|
|
142
|
+
size_t remainingSize = 0;
|
|
143
|
+
|
|
144
|
+
auto& message = _receivedReadOperations.back();
|
|
145
|
+
if (message._cursor < HEADER_SIZE) {
|
|
146
|
+
readTo = (char*)&message._header + message._cursor;
|
|
147
|
+
remainingSize = HEADER_SIZE - message._cursor;
|
|
148
|
+
} else if (message._cursor == HEADER_SIZE) {
|
|
149
|
+
if (message._header >= LARGEST_PAYLOAD_SIZE) {
|
|
150
|
+
return std::unexpected {IOError::MessageTooLarge};
|
|
151
|
+
}
|
|
152
|
+
message._payload = Bytes::alloc(message._header);
|
|
153
|
+
readTo = (char*)message._payload.data();
|
|
154
|
+
remainingSize = message._payload.len();
|
|
155
|
+
} else {
|
|
156
|
+
readTo = (char*)message._payload.data() + (message._cursor - HEADER_SIZE);
|
|
157
|
+
remainingSize = message._payload.len() - (message._cursor - HEADER_SIZE);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// We have received an empty message, which is allowed
|
|
161
|
+
if (remainingSize == 0) {
|
|
162
|
+
return {};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
int n = ::recv(_connFd, readTo, remainingSize, 0);
|
|
166
|
+
if (n == 0) {
|
|
167
|
+
return std::unexpected {IOError::Disconnected};
|
|
168
|
+
} else if (n == -1) {
|
|
169
|
+
const int myErrno = GetErrorCode();
|
|
170
|
+
#ifdef _WIN32
|
|
171
|
+
if (myErrno == WSAEWOULDBLOCK) {
|
|
172
|
+
return std::unexpected {IOError::Drained};
|
|
173
|
+
}
|
|
174
|
+
if (myErrno == WSAECONNRESET || myErrno == WSAENOTSOCK) {
|
|
175
|
+
return std::unexpected {IOError::Aborted};
|
|
176
|
+
} else {
|
|
177
|
+
// NOTE: On Windows we don't have signals and weird IO Errors
|
|
178
|
+
unrecoverableError({
|
|
179
|
+
Error::ErrorCode::CoreBug,
|
|
180
|
+
"Originated from",
|
|
181
|
+
"recv",
|
|
182
|
+
"Errno is",
|
|
183
|
+
myErrno,
|
|
184
|
+
"_connfd",
|
|
185
|
+
_connFd,
|
|
186
|
+
"readTo",
|
|
187
|
+
(void*)readTo,
|
|
188
|
+
"remainingSize",
|
|
189
|
+
remainingSize,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
#endif // _WIN32
|
|
193
|
+
#ifdef __linux__
|
|
194
|
+
if (myErrno == ECONNRESET) {
|
|
195
|
+
return std::unexpected {IOError::Aborted};
|
|
196
|
+
}
|
|
197
|
+
if (myErrno == EAGAIN || myErrno == EWOULDBLOCK) {
|
|
198
|
+
return std::unexpected {IOError::Drained};
|
|
199
|
+
} else {
|
|
200
|
+
const int myErrno = errno;
|
|
201
|
+
switch (myErrno) {
|
|
202
|
+
case EBADF:
|
|
203
|
+
case EISDIR:
|
|
204
|
+
case EINVAL:
|
|
205
|
+
unrecoverableError({
|
|
206
|
+
Error::ErrorCode::CoreBug,
|
|
207
|
+
"Originated from",
|
|
208
|
+
"read(2)",
|
|
209
|
+
"Errno is",
|
|
210
|
+
strerror(myErrno),
|
|
211
|
+
"_connfd",
|
|
212
|
+
_connFd,
|
|
213
|
+
"readTo",
|
|
214
|
+
(void*)readTo,
|
|
215
|
+
"remainingSize",
|
|
216
|
+
remainingSize,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
case EINTR:
|
|
220
|
+
unrecoverableError({
|
|
221
|
+
Error::ErrorCode::SignalNotSupported,
|
|
222
|
+
"Originated from",
|
|
223
|
+
"read(2)",
|
|
224
|
+
"Errno is",
|
|
225
|
+
strerror(myErrno),
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
case EFAULT:
|
|
229
|
+
case EIO:
|
|
230
|
+
default:
|
|
231
|
+
unrecoverableError({
|
|
232
|
+
Error::ErrorCode::ConfigurationError,
|
|
233
|
+
"Originated from",
|
|
234
|
+
"read(2)",
|
|
235
|
+
"Errno is",
|
|
236
|
+
strerror(myErrno),
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
#endif // __linux__
|
|
241
|
+
} else {
|
|
242
|
+
message._cursor += n;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return {};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// on Return, unexpected value shall be interpreted as this - 0 = close, other -> errno
|
|
249
|
+
std::expected<void, MessageConnectionTCP::IOError> MessageConnectionTCP::tryReadMessages()
|
|
250
|
+
{
|
|
251
|
+
while (true) {
|
|
252
|
+
auto res = tryReadOneMessage();
|
|
253
|
+
if (!res) {
|
|
254
|
+
return res;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
void MessageConnectionTCP::updateReadOperation()
|
|
260
|
+
{
|
|
261
|
+
while (_pendingRecvMessageCallbacks->size() && _receivedReadOperations.size()) {
|
|
262
|
+
if (isCompleteMessage(_receivedReadOperations.front())) {
|
|
263
|
+
Bytes address(_remoteIOSocketIdentity->data(), _remoteIOSocketIdentity->size());
|
|
264
|
+
Bytes payload(std::move(_receivedReadOperations.front()._payload));
|
|
265
|
+
_receivedReadOperations.pop();
|
|
266
|
+
auto recvMessageCallback = std::move(_pendingRecvMessageCallbacks->front());
|
|
267
|
+
_pendingRecvMessageCallbacks->pop();
|
|
268
|
+
|
|
269
|
+
recvMessageCallback({Message(std::move(address), std::move(payload)), {}});
|
|
270
|
+
} else {
|
|
271
|
+
assert(_pendingRecvMessageCallbacks->size());
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
void MessageConnectionTCP::setRemoteIdentity() noexcept
|
|
278
|
+
{
|
|
279
|
+
if (!_remoteIOSocketIdentity &&
|
|
280
|
+
(_receivedReadOperations.size() && isCompleteMessage(_receivedReadOperations.front()))) {
|
|
281
|
+
auto id = std::move(_receivedReadOperations.front());
|
|
282
|
+
_remoteIOSocketIdentity.emplace((char*)id._payload.data(), id._payload.len());
|
|
283
|
+
_receivedReadOperations.pop();
|
|
284
|
+
auto sock = this->_eventLoopThread->_identityToIOSocket[_localIOSocketIdentity];
|
|
285
|
+
sock->onConnectionIdentityReceived(this);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
void MessageConnectionTCP::onRead()
|
|
290
|
+
{
|
|
291
|
+
if (_connFd == 0) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
auto maybeCloseConn = [this](IOError err) -> std::expected<void, IOError> {
|
|
296
|
+
setRemoteIdentity();
|
|
297
|
+
|
|
298
|
+
if (_remoteIOSocketIdentity) {
|
|
299
|
+
updateReadOperation();
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
switch (err) {
|
|
303
|
+
case IOError::Drained: return {};
|
|
304
|
+
case IOError::Aborted: _disconnect = false; break;
|
|
305
|
+
case IOError::Disconnected: _disconnect = true; break;
|
|
306
|
+
case IOError::MessageTooLarge: _disconnect = true; break;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
onClose();
|
|
310
|
+
return std::unexpected {err};
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
auto res = _remoteIOSocketIdentity
|
|
314
|
+
.or_else([this, maybeCloseConn] {
|
|
315
|
+
auto _ = tryReadOneMessage()
|
|
316
|
+
.or_else(maybeCloseConn) //
|
|
317
|
+
.and_then([this]() -> std::expected<void, IOError> {
|
|
318
|
+
setRemoteIdentity();
|
|
319
|
+
return {};
|
|
320
|
+
});
|
|
321
|
+
return _remoteIOSocketIdentity;
|
|
322
|
+
})
|
|
323
|
+
.and_then([this, maybeCloseConn](const std::string&) -> std::optional<std::string> {
|
|
324
|
+
auto _ = tryReadMessages()
|
|
325
|
+
.or_else(maybeCloseConn) //
|
|
326
|
+
.and_then([this]() -> std::expected<void, IOError> {
|
|
327
|
+
updateReadOperation();
|
|
328
|
+
return {};
|
|
329
|
+
});
|
|
330
|
+
return _remoteIOSocketIdentity;
|
|
331
|
+
});
|
|
332
|
+
if (!res) {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
#ifdef _WIN32
|
|
337
|
+
const bool ok = ReadFile((HANDLE)(SOCKET)_connFd, nullptr, 0, nullptr, this->_eventManager.get());
|
|
338
|
+
if (ok) {
|
|
339
|
+
onRead();
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
const auto lastError = GetLastError();
|
|
343
|
+
if (lastError == ERROR_IO_PENDING) {
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
unrecoverableError({
|
|
347
|
+
Error::ErrorCode::CoreBug,
|
|
348
|
+
"Originated from",
|
|
349
|
+
"ReadFile",
|
|
350
|
+
"Errno is",
|
|
351
|
+
lastError,
|
|
352
|
+
"_connfd",
|
|
353
|
+
_connFd,
|
|
354
|
+
});
|
|
355
|
+
#endif // _WIN32
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
void MessageConnectionTCP::onWrite()
|
|
359
|
+
{
|
|
360
|
+
// This is because after disconnected, onRead will be called first, and that will set
|
|
361
|
+
// _connFd to 0. There's no way to not call onWrite in this case. So we return early.
|
|
362
|
+
if (_connFd == 0) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
auto res = trySendQueuedMessages();
|
|
367
|
+
if (res) {
|
|
368
|
+
updateWriteOperations(res.value());
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (res.error() == IOError::Aborted) {
|
|
373
|
+
onClose();
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
#ifdef _WIN32
|
|
378
|
+
// NOTE: Precondition is the queue still has messages (perhaps a partial one).
|
|
379
|
+
// We don't need to update the queue because trySendQueuedMessages is okay with a complete message in front.
|
|
380
|
+
if (res.error() == IOError::Drained) {
|
|
381
|
+
void* addr = nullptr;
|
|
382
|
+
if (_sendCursor < HEADER_SIZE) {
|
|
383
|
+
addr = (char*)(&_writeOperations.front()._header) + _sendCursor;
|
|
384
|
+
} else {
|
|
385
|
+
addr = (char*)_writeOperations.front()._payload.data() + _sendCursor - HEADER_SIZE;
|
|
386
|
+
}
|
|
387
|
+
++_sendCursor; // Next onWrite() will not be called until the asyncop complete
|
|
388
|
+
|
|
389
|
+
const bool writeFileRes = WriteFile((HANDLE)(SOCKET)_connFd, addr, 1, nullptr, _eventManager.get());
|
|
390
|
+
if (writeFileRes) {
|
|
391
|
+
onWrite();
|
|
392
|
+
return;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
const auto lastError = GetLastError();
|
|
396
|
+
if (lastError == ERROR_IO_PENDING) {
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
unrecoverableError({
|
|
400
|
+
Error::ErrorCode::CoreBug,
|
|
401
|
+
"Originated from",
|
|
402
|
+
"WriteFile",
|
|
403
|
+
"Errno is",
|
|
404
|
+
lastError,
|
|
405
|
+
"_connfd",
|
|
406
|
+
_connFd,
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
#endif // _WIN32
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
void MessageConnectionTCP::onClose()
|
|
413
|
+
{
|
|
414
|
+
if (_connFd) {
|
|
415
|
+
_eventLoopThread->_eventLoop.removeFdFromLoop(_connFd);
|
|
416
|
+
CloseAndZeroSocket(_connFd);
|
|
417
|
+
auto& sock = _eventLoopThread->_identityToIOSocket.at(_localIOSocketIdentity);
|
|
418
|
+
sock->onConnectionDisconnected(this, !_disconnect);
|
|
419
|
+
}
|
|
420
|
+
};
|
|
421
|
+
|
|
422
|
+
std::expected<size_t, MessageConnectionTCP::IOError> MessageConnectionTCP::trySendQueuedMessages()
|
|
423
|
+
{
|
|
424
|
+
// typedef struct _WSABUF {
|
|
425
|
+
// ULONG(same to sizet on x64 machine) len; /* the length of the buffer */
|
|
426
|
+
// _Field_size_bytes_(len) CHAR FAR *buf; /* the pointer to the buffer */
|
|
427
|
+
// } WSABUF, FAR * LPWSABUF;
|
|
428
|
+
#ifdef _WIN32
|
|
429
|
+
#define iovec ::WSABUF
|
|
430
|
+
#define IOV_MAX (1024)
|
|
431
|
+
#define iov_base buf
|
|
432
|
+
#define iov_len len
|
|
433
|
+
#endif // _WIN32
|
|
434
|
+
|
|
435
|
+
std::vector<iovec> iovecs;
|
|
436
|
+
iovecs.reserve(IOV_MAX);
|
|
437
|
+
for (auto it = _writeOperations.begin(); it != _writeOperations.end(); ++it) {
|
|
438
|
+
if (iovecs.size() > IOV_MAX - 2) {
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
iovec iovHeader {};
|
|
443
|
+
iovec iovPayload {};
|
|
444
|
+
if (it == _writeOperations.begin()) {
|
|
445
|
+
if (_sendCursor < HEADER_SIZE) {
|
|
446
|
+
iovHeader.iov_base = (char*)(&it->_header) + _sendCursor;
|
|
447
|
+
iovHeader.iov_len = HEADER_SIZE - _sendCursor;
|
|
448
|
+
iovPayload.iov_base = (char*)(it->_payload.data());
|
|
449
|
+
iovPayload.iov_len = it->_payload.len();
|
|
450
|
+
} else {
|
|
451
|
+
iovHeader.iov_base = nullptr;
|
|
452
|
+
iovHeader.iov_len = 0;
|
|
453
|
+
iovPayload.iov_base = (char*)(it->_payload.data()) + (_sendCursor - HEADER_SIZE);
|
|
454
|
+
iovPayload.iov_len = it->_payload.len() - (_sendCursor - HEADER_SIZE);
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
iovHeader.iov_base = (char*)(&it->_header);
|
|
458
|
+
iovHeader.iov_len = HEADER_SIZE;
|
|
459
|
+
iovPayload.iov_base = (char*)(it->_payload.data());
|
|
460
|
+
iovPayload.iov_len = it->_payload.len();
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
iovecs.push_back(iovHeader);
|
|
464
|
+
iovecs.push_back(iovPayload);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (iovecs.empty()) {
|
|
468
|
+
return 0;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
#ifdef _WIN32
|
|
472
|
+
DWORD bytesSent {};
|
|
473
|
+
const int sendToResult =
|
|
474
|
+
WSASendTo(_connFd, iovecs.data(), iovecs.size(), &bytesSent, 0, nullptr, 0, nullptr, nullptr);
|
|
475
|
+
if (sendToResult == 0) {
|
|
476
|
+
return bytesSent;
|
|
477
|
+
}
|
|
478
|
+
const int myErrno = GetErrorCode();
|
|
479
|
+
if (myErrno == WSAEWOULDBLOCK) {
|
|
480
|
+
return std::unexpected {IOError::Drained};
|
|
481
|
+
}
|
|
482
|
+
if (myErrno == WSAESHUTDOWN || myErrno == WSAENOTCONN) {
|
|
483
|
+
return std::unexpected {IOError::Aborted};
|
|
484
|
+
}
|
|
485
|
+
unrecoverableError({
|
|
486
|
+
Error::ErrorCode::CoreBug,
|
|
487
|
+
"Originated from",
|
|
488
|
+
"WSASendTo",
|
|
489
|
+
"Errno is",
|
|
490
|
+
myErrno,
|
|
491
|
+
"_connfd",
|
|
492
|
+
_connFd,
|
|
493
|
+
"iovecs.size()",
|
|
494
|
+
iovecs.size(),
|
|
495
|
+
});
|
|
496
|
+
#endif // _WIN32
|
|
497
|
+
|
|
498
|
+
#ifdef __linux__
|
|
499
|
+
struct msghdr msg {};
|
|
500
|
+
msg.msg_iov = iovecs.data();
|
|
501
|
+
msg.msg_iovlen = iovecs.size();
|
|
502
|
+
|
|
503
|
+
ssize_t bytesSent = ::sendmsg(_connFd, &msg, MSG_NOSIGNAL);
|
|
504
|
+
if (bytesSent == -1) {
|
|
505
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
506
|
+
return std::unexpected {IOError::Drained};
|
|
507
|
+
} else {
|
|
508
|
+
const int myErrno = errno;
|
|
509
|
+
switch (myErrno) {
|
|
510
|
+
case EAFNOSUPPORT:
|
|
511
|
+
case EBADF:
|
|
512
|
+
case EINVAL:
|
|
513
|
+
case EMSGSIZE:
|
|
514
|
+
case ENOTCONN:
|
|
515
|
+
case ENOTSOCK:
|
|
516
|
+
case EOPNOTSUPP:
|
|
517
|
+
case ENAMETOOLONG:
|
|
518
|
+
case ENOENT:
|
|
519
|
+
case ENOTDIR:
|
|
520
|
+
case ELOOP:
|
|
521
|
+
case EDESTADDRREQ:
|
|
522
|
+
case EHOSTUNREACH:
|
|
523
|
+
case EISCONN:
|
|
524
|
+
unrecoverableError({
|
|
525
|
+
Error::ErrorCode::CoreBug,
|
|
526
|
+
"Originated from",
|
|
527
|
+
"sendmsg(2)",
|
|
528
|
+
"Errno is",
|
|
529
|
+
strerror(myErrno),
|
|
530
|
+
"_connfd",
|
|
531
|
+
_connFd,
|
|
532
|
+
"msg.msg_iovlen",
|
|
533
|
+
msg.msg_iovlen,
|
|
534
|
+
});
|
|
535
|
+
break;
|
|
536
|
+
|
|
537
|
+
case ECONNRESET:
|
|
538
|
+
case EPIPE: return std::unexpected {IOError::Aborted}; break;
|
|
539
|
+
|
|
540
|
+
case EINTR:
|
|
541
|
+
unrecoverableError({
|
|
542
|
+
Error::ErrorCode::SignalNotSupported,
|
|
543
|
+
"Originated from",
|
|
544
|
+
"sendmsg(2)",
|
|
545
|
+
"Errno is",
|
|
546
|
+
strerror(myErrno),
|
|
547
|
+
});
|
|
548
|
+
break;
|
|
549
|
+
|
|
550
|
+
case EIO:
|
|
551
|
+
case EACCES:
|
|
552
|
+
case ENETDOWN:
|
|
553
|
+
case ENETUNREACH:
|
|
554
|
+
case ENOBUFS:
|
|
555
|
+
case ENOMEM:
|
|
556
|
+
default:
|
|
557
|
+
unrecoverableError({
|
|
558
|
+
Error::ErrorCode::ConfigurationError,
|
|
559
|
+
"Originated from",
|
|
560
|
+
"sendmsg(2)",
|
|
561
|
+
"Errno is",
|
|
562
|
+
strerror(myErrno),
|
|
563
|
+
});
|
|
564
|
+
break;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return bytesSent;
|
|
570
|
+
#endif // __linux__
|
|
571
|
+
|
|
572
|
+
#ifdef _WIN32
|
|
573
|
+
#undef iovec
|
|
574
|
+
#undef IOV_MAX
|
|
575
|
+
#undef iov_base
|
|
576
|
+
#undef iov_len
|
|
577
|
+
#endif // _WIN32
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// TODO: There is a classic optimization that can (and should) be done. That is, we store
|
|
581
|
+
// prefix sum in each write operation, and perform binary search instead of linear search
|
|
582
|
+
// to find the first write operation we haven't complete. - gxu
|
|
583
|
+
void MessageConnectionTCP::updateWriteOperations(size_t n)
|
|
584
|
+
{
|
|
585
|
+
auto firstIncomplete = _writeOperations.begin();
|
|
586
|
+
_sendCursor += n;
|
|
587
|
+
// Post condition of the loop: firstIncomplete contains the first write op we haven't complete.
|
|
588
|
+
for (auto it = _writeOperations.begin(); it != _writeOperations.end(); ++it) {
|
|
589
|
+
size_t msgSize = it->_payload.len() + HEADER_SIZE;
|
|
590
|
+
if (_sendCursor < msgSize) {
|
|
591
|
+
firstIncomplete = it;
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (_sendCursor == msgSize) {
|
|
596
|
+
firstIncomplete = it + 1;
|
|
597
|
+
_sendCursor = 0;
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
_sendCursor -= msgSize;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
for (auto it = _writeOperations.begin(); it != firstIncomplete; ++it) {
|
|
605
|
+
it->_callbackAfterCompleteWrite({});
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
const int numPopItems = std::distance(_writeOperations.begin(), firstIncomplete);
|
|
609
|
+
for (int i = 0; i < numPopItems; ++i) {
|
|
610
|
+
_writeOperations.pop_front();
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
// _writeOperations.shrink_to_fit();
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
void MessageConnectionTCP::sendMessage(Message msg, SendMessageCallback onMessageSent)
|
|
617
|
+
{
|
|
618
|
+
TcpWriteOperation writeOp(std::move(msg), std::move(onMessageSent));
|
|
619
|
+
_writeOperations.emplace_back(std::move(writeOp));
|
|
620
|
+
|
|
621
|
+
if (_connFd == 0) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
onWrite();
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
bool MessageConnectionTCP::recvMessage()
|
|
628
|
+
{
|
|
629
|
+
if (_receivedReadOperations.empty() || _pendingRecvMessageCallbacks->empty() ||
|
|
630
|
+
!isCompleteMessage(_receivedReadOperations.front())) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
updateReadOperation();
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
void MessageConnectionTCP::disconnect()
|
|
639
|
+
{
|
|
640
|
+
#ifdef __linux__
|
|
641
|
+
_disconnect = true;
|
|
642
|
+
shutdown(_connFd, SHUT_WR);
|
|
643
|
+
onClose();
|
|
644
|
+
#endif
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
MessageConnectionTCP::~MessageConnectionTCP() noexcept
|
|
648
|
+
{
|
|
649
|
+
if (_connFd != 0) {
|
|
650
|
+
_eventLoopThread->_eventLoop.removeFdFromLoop(_connFd);
|
|
651
|
+
|
|
652
|
+
#ifdef __linux__
|
|
653
|
+
shutdown(_connFd, SHUT_RD);
|
|
654
|
+
|
|
655
|
+
#endif // __linux__
|
|
656
|
+
#ifdef _WIN32
|
|
657
|
+
shutdown(_connFd, SD_BOTH);
|
|
658
|
+
#endif // _WIN32
|
|
659
|
+
|
|
660
|
+
CloseAndZeroSocket(_connFd);
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
std::ranges::for_each(_writeOperations, [](auto&& x) {
|
|
664
|
+
x._callbackAfterCompleteWrite(std::unexpected {Error::ErrorCode::SendMessageRequestCouldNotComplete});
|
|
665
|
+
});
|
|
666
|
+
|
|
667
|
+
// TODO: What to do with this?
|
|
668
|
+
// std::queue<std::vector<char>> _receivedMessages;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
} // namespace ymq
|
|
672
|
+
} // namespace scaler
|