Path: blob/master/runtime/compiler/net/ClientStream.hpp
6000 views
/*******************************************************************************1* Copyright (c) 2018, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#ifndef CLIENT_STREAM_H23#define CLIENT_STREAM_H2425#include "compile/CompilationTypes.hpp"26#include "ilgen/J9IlGeneratorMethodDetails.hpp"27#include "net/RawTypeConvert.hpp"28#include "net/CommunicationStream.hpp"2930class SSLOutputStream;31class SSLInputStream;3233namespace JITServer34{35enum VersionCheckStatus36{37NOT_DONE = 0,38PASSED = 1,39};4041/**42@class ClientStream43@brief Implementation of the communication API for a client asking for remote JIT compilations4445Typical sequence executed by a client is:46(1) Establish a connection to the JITServer by creating a ClientStream object47client = new (PERSISTENT_NEW) JITServer::ClientStream(compInfo->getPersistentInfo());48(2) Determine compilation parameters and send the compilation request over the network49client->buildCompileRequest(method, clazz, .................);50(3) Handle any queries from the server51Typical seq: (3.1) client->read(); (3.2) client->getRecvData(...); (3.3) client->write(...);52while(!handleServerMessage(client, frontend));53(4) Read compilation result54auto recv = client->getRecvData<uint32_t, std::string, std::string, .......>();55(5) install compiled code into code cache56*/57class ClientStream : public CommunicationStream58{59public:60/**61@brief Function called to perform static initialization of ClientStream6263This is called during startup from rossa.cpp.64Creates SSL context, loads certificates and keys.65Only needs to be done once during JVM initialization.6667Returns 0 if successful;; Otherwise, returns -1.68*/69static int static_init(TR::PersistentInfo *info);7071explicit ClientStream(TR::PersistentInfo *info);72virtual ~ClientStream()73{74_numConnectionsClosed++;75}7677/**78@brief Send a compilation request to the JITServer7980As a side-effect, this function may also embed version information in the message81if this is the first message sent after a connection request.82*/83template <typename... T>84void buildCompileRequest(T... args)85{86if (getVersionCheckStatus() == NOT_DONE)87{88_cMsg.setFullVersion(getJITServerVersion(), CONFIGURATION_FLAGS);89write(MessageType::compilationRequest, args...);90_cMsg.clearFullVersion();91}92else // getVersionCheckStatus() == PASSED93{94_cMsg.clearFullVersion(); // the compatibility check is done. We clear the version to save message size.95write(MessageType::compilationRequest, args...);96}97}9899/**100@brief Send a message to the JITServer101102@param [in] type Message type103@param [in] args Additional arguments sent to the JITServer104*/105template <typename ...T>106void write(MessageType type, T... args)107{108_cMsg.setType(type);109setArgsRaw<T...>(_cMsg, args...);110111writeMessage(_cMsg);112}113114/**115@brief Read a message from the server116117The read operation is blocking (subject to a timeout)118119@return Returns the type of the message being received120*/121MessageType read()122{123readMessage(_sMsg);124return _sMsg.type();125}126127/**128@brief Extract the data from the received message and return it129*/130template <typename ...T>131std::tuple<T...> getRecvData()132{133return getArgsRaw<T...>(_sMsg);134}135136/**137@brief Send an error message to the JITServer138139Examples of error messages include 'compilationInterrupted' (e.g. when class unloading happens),140'clientSessionTerminate' (e.g. when the client is about to exit),141and 'connectionTerminate' (e.g. when the client is closing the connection)142*/143template <typename ...T>144void writeError(MessageType type, T... args)145{146_cMsg.setType(type);147if (type == MessageType::compilationInterrupted || type == MessageType::connectionTerminate)148{149// _cMsg.clear();150}151else152setArgsRaw<T...>(_cMsg, args...);153writeMessage(_cMsg);154}155156VersionCheckStatus getVersionCheckStatus()157{158return _versionCheckStatus;159}160161void setVersionCheckStatus()162{163_versionCheckStatus = PASSED;164}165166/**167@brief Function called when JITServer was discovered to be incompatible with the client168*/169static void incrementIncompatibilityCount(OMRPortLibrary *portLibrary)170{171OMRPORT_ACCESS_FROM_OMRPORT(portLibrary);172_incompatibilityCount += 1;173_incompatibleStartTime = omrtime_current_time_millis();174}175176/**177@brief Function that answers whether JITServer is compatible with the client178179Note that the discovery of the incompatibility is done in the first message180that the client sends to the server. This function is actually called to181determine if we need to try the compatibilty check again. The idea is that182the incompatible server could be killed and another one (compatible) could be183instantiated. If enough time has passed since the server was found to be184incompatible, then the client should try again. "Enough time" is defined as a185constant 10 second interval.186*/187static bool isServerCompatible(OMRPortLibrary *portLibrary)188{189OMRPORT_ACCESS_FROM_OMRPORT(portLibrary);190uint64_t current_time = omrtime_current_time_millis();191// the client periodically checks whether the server is compatible or not192// the retry interval is defined by RETRY_COMPATIBILITY_INTERVAL_MS193// we set _incompatibilityCount to 0 when it's time to retry for compatibility check194// otherwise, check if we exceed the number of incompatible connections195if ((current_time - _incompatibleStartTime) > RETRY_COMPATIBILITY_INTERVAL_MS)196_incompatibilityCount = 0;197198return _incompatibilityCount < INCOMPATIBILITY_COUNT_LIMIT;199}200201// Statistics202static int getNumConnectionsOpened() { return _numConnectionsOpened; }203static int getNumConnectionsClosed() { return _numConnectionsClosed; }204205private:206static int _numConnectionsOpened;207static int _numConnectionsClosed;208VersionCheckStatus _versionCheckStatus; // indicates whether a version checking has been performed209static int _incompatibilityCount;210static uint64_t _incompatibleStartTime; // Time when version incomptibility has been detected211static const uint64_t RETRY_COMPATIBILITY_INTERVAL_MS; // (ms) When we should perform again a version compatibilty check212static const int INCOMPATIBILITY_COUNT_LIMIT;213214static SSL_CTX *_sslCtx;215};216217}218219#endif // CLIENT_STREAM_H220221222