Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/net/ServerStream.hpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2018, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#ifndef SERVER_STREAM_H
24
#define SERVER_STREAM_H
25
26
#include "net/RawTypeConvert.hpp"
27
#include "net/CommunicationStream.hpp"
28
#include "env/VerboseLog.hpp"
29
#include "control/CompilationThread.hpp" // for TR::compInfoPT->getCompThreadId()
30
#include "control/Options.hpp"
31
#include "runtime/JITClientSession.hpp"
32
33
class SSLOutputStream;
34
class SSLInputStream;
35
36
namespace JITServer
37
{
38
39
/**
40
@class ServerStream
41
@brief Implementation of the communication API for a server receiving JIT compilations requests
42
43
Typical usage:
44
1) Define a compilation handler by extending JITServer::BaseCompileDispatcher and providing
45
an implementation for abstract method "compile(JITServer::ServerStream *stream)"
46
This method will be called when a new connection request has been received at the server.
47
2) Create a dedicated thread that will listen for incoming connection requests
48
3) In this thread, instantiate a CompileDispatcher from a class defined in step (1)
49
E.g.: J9CompileDispatcher handler(jitConfig);
50
4) Call "TR_Listener::serveRemoteCompilationRequests(&handler);"
51
which will wait for a connection, accept the connection, create a ServerStream and call
52
handler->compile(stream) for further processing, e.g. add the stream
53
to a compilation queue
54
5) On a different thread, extract the compilation entry from the queue (which contains
55
the stream) and wait for a compilation request:
56
auto req = stream->readCompileRequest<....>();
57
6) At this point the server could query the client with:
58
stream->write(MessageType type, T... args);
59
auto recv = stream->read<....>();
60
7) When compilation is completed successfully, the server responds with finishCompilation(T... args).
61
When compilation is aborted, the sever responds with writeError(uint32_t statusCode).
62
*/
63
class ServerStream : public CommunicationStream
64
{
65
public:
66
/**
67
@brief Constructor of ServerStream class
68
69
@param connfd socket descriptor for the communication channel
70
@param ssl BIO for the SSL enabled stream
71
@param timeout timeout value (ms) to be set for connfd
72
*/
73
explicit ServerStream(int connfd, BIO *ssl);
74
virtual ~ServerStream()
75
{
76
_numConnectionsClosed++;
77
_pClientSessionData = NULL;
78
}
79
80
/**
81
@brief Send a message to the client
82
83
@param [in] type Message type to be sent
84
@param [in] args Variable number of additional parameters to be sent
85
*/
86
template <typename ...Args>
87
void write(MessageType type, Args... args)
88
{
89
if (isReadingClassUnload() &&
90
isClassUnloadingAttempted() &&
91
TR::compInfoPT->compilationCanBeInterrupted() &&
92
(MessageType::compilationFailure != type) &&
93
(MessageType::compilationCode != type))
94
{
95
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
96
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d MessageType[%u] %s: throw TR::CompilationInterrupted",
97
TR::compInfoPT->getCompThreadId(), type, messageNames[type]);
98
99
throw TR::CompilationInterrupted();
100
}
101
102
_sMsg.setType(type);
103
setArgsRaw<Args...>(_sMsg, args...);
104
writeMessage(_sMsg);
105
}
106
107
/**
108
@brief Read a message from the client
109
110
The read operation is blocking, subject to a timeout.
111
If the message received is `compilationInterrupted` then an exception of type StreamInterrupted is thrown.
112
If the message received is `connectionTerminate` then an exception of type StreamConnectionTerminate is thrown.
113
If the server detects an incompatibility with the client then a StreamMessageTypeMissmatch
114
exception is thrown.
115
Otherwise, the arguments sent by the client are returned as a tuple
116
117
@return Returns a tuple of arguments sent by the client
118
*/
119
template <typename ...T>
120
std::tuple<T...> read()
121
{
122
readMessage(_cMsg);
123
switch (_cMsg.type())
124
{
125
case MessageType::compilationInterrupted:
126
{
127
// If we are inside an uninterruptible operation on the server,
128
// but the corresponding operation hasn't yet started on the client,
129
// ignore the request to interrupt a compilation
130
if (TR::compInfoPT->compilationCanBeInterrupted())
131
throw StreamInterrupted();
132
}
133
case MessageType::connectionTerminate:
134
{
135
throw StreamConnectionTerminate();
136
}
137
default:
138
{
139
// We are expecting the response type (_cMsg.type()) to be the same as the request type (_sMsg.type())
140
if (_cMsg.type() != _sMsg.type())
141
throw StreamMessageTypeMismatch(_sMsg.type(), _cMsg.type());
142
}
143
}
144
return getArgsRaw<T...>(_cMsg);
145
}
146
147
/**
148
@brief Function to read the compilation request from a client
149
150
This is the first type of message received after a connection is established.
151
The number and position of parameters in the template must match the
152
the one sent by the client. In order to ensure this, the client will embed
153
version information in the first message it sends after a connection is established.
154
The server will check whether its version matches the client's version and throw
155
`StreamVersionIncompatible` if it doesn't.
156
157
Exceptions thrown: StreamConnectionTerminate, StreamClientSessionTerminate, StreamVersionIncompatible, StreamMessageTypeMismatch
158
159
@return Returns a tuple with information sent by the client
160
*/
161
template <typename... T>
162
std::tuple<T...> readCompileRequest()
163
{
164
readMessage(_cMsg);
165
if (_cMsg.fullVersion() != 0 && _cMsg.fullVersion() != getJITServerFullVersion())
166
{
167
throw StreamVersionIncompatible(getJITServerFullVersion(), _cMsg.fullVersion());
168
}
169
170
switch (_cMsg.type())
171
{
172
case MessageType::connectionTerminate:
173
{
174
throw StreamConnectionTerminate();
175
}
176
case MessageType::clientSessionTerminate:
177
{
178
uint64_t clientId = std::get<0>(getRecvData<uint64_t>());
179
throw StreamClientSessionTerminate(clientId);
180
}
181
case MessageType::compilationRequest:
182
{
183
return getArgsRaw<T...>(_cMsg);
184
}
185
default:
186
{
187
throw StreamMessageTypeMismatch(MessageType::compilationRequest, _cMsg.type());
188
}
189
}
190
}
191
192
/**
193
@brief Extract the data from the received message and return it
194
*/
195
template <typename... T>
196
std::tuple<T...> getRecvData()
197
{
198
return getArgsRaw<T...>(_cMsg);
199
}
200
201
/**
202
@brief Function invoked by server when compilation is completed successfully
203
204
This should be the last message sent by a server as a response to a compilation request.
205
It includes a variable number of parameters with compilation artifacts (including the compiled body).
206
*/
207
template <typename... T>
208
void finishCompilation(T... args)
209
{
210
try
211
{
212
write(MessageType::compilationCode, args...);
213
}
214
catch (std::exception &e)
215
{
216
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
217
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Could not finish compilation: %s", e.what());
218
}
219
}
220
221
/**
222
@brief Function invoked by server when compilation is aborted
223
*/
224
void writeError(uint32_t statusCode, uint64_t otherData = -1)
225
{
226
try
227
{
228
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
229
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d MessageType::compilationFailure: statusCode %u",
230
TR::compInfoPT->getCompThreadId(), statusCode);
231
write(MessageType::compilationFailure, statusCode, otherData);
232
}
233
catch (std::exception &e)
234
{
235
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
236
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Could not write error code: %s", e.what());
237
}
238
}
239
240
void setClientId(uint64_t clientId)
241
{
242
_clientId = clientId;
243
}
244
uint64_t getClientId() const
245
{
246
return _clientId;
247
}
248
249
void setClientData(ClientSessionData *pClientData)
250
{
251
_pClientSessionData = pClientData;
252
}
253
254
volatile bool isReadingClassUnload()
255
{
256
return (_pClientSessionData) ? _pClientSessionData->isReadingClassUnload() : false;
257
}
258
259
volatile bool isClassUnloadingAttempted()
260
{
261
return (_pClientSessionData) ? _pClientSessionData->isClassUnloadingAttempted() : false;
262
}
263
264
// Statistics
265
static int getNumConnectionsOpened() { return _numConnectionsOpened; }
266
static int getNumConnectionsClosed() { return _numConnectionsClosed; }
267
268
private:
269
static int _numConnectionsOpened;
270
static int _numConnectionsClosed;
271
uint64_t _clientId; // UID of client connected to this communication stream
272
ClientSessionData *_pClientSessionData;
273
};
274
275
}
276
277
#endif // SERVER_STREAM_H
278
279