summaryrefslogtreecommitdiffstats
path: root/Source/cmServer.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2020-10-14 16:46:55 (GMT)
committerBrad King <brad.king@kitware.com>2020-10-14 20:41:50 (GMT)
commit9952ee063a1a2b31c784733b0cf676b4a6efc36e (patch)
treef019b22a20973bd61f944c002148b8312f64d0bc /Source/cmServer.cxx
parentc5559597177eabd5620766e9dbc6f02a3b827ddb (diff)
downloadCMake-9952ee063a1a2b31c784733b0cf676b4a6efc36e.zip
CMake-9952ee063a1a2b31c784733b0cf676b4a6efc36e.tar.gz
CMake-9952ee063a1a2b31c784733b0cf676b4a6efc36e.tar.bz2
server: remove deprecated 'cmake -E server' mode
The server mode has been deprecated since commit 996e1885c4 (server: deprecate in favor of the file-api, 2019-04-19, v3.15.0-rc1~198^2). Clients should now be using the file-api. Remove the server mode.
Diffstat (limited to 'Source/cmServer.cxx')
-rw-r--r--Source/cmServer.cxx570
1 files changed, 0 insertions, 570 deletions
diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx
deleted file mode 100644
index 7f97406..0000000
--- a/Source/cmServer.cxx
+++ /dev/null
@@ -1,570 +0,0 @@
-/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
- file Copyright.txt or https://cmake.org/licensing for details. */
-#include "cmServer.h"
-
-#include <algorithm>
-#include <cassert>
-#include <csignal>
-#include <cstdint>
-#include <iostream>
-#include <mutex>
-#include <utility>
-
-#include <cm/memory>
-#include <cm/shared_mutex>
-
-#include <cm3p/json/reader.h>
-#include <cm3p/json/writer.h>
-
-#include "cmsys/FStream.hxx"
-
-#include "cmConnection.h"
-#include "cmFileMonitor.h"
-#include "cmJsonObjectDictionary.h"
-#include "cmServerDictionary.h"
-#include "cmServerProtocol.h"
-#include "cmSystemTools.h"
-#include "cmake.h"
-
-void on_signal(uv_signal_t* signal, int signum)
-{
- auto conn = static_cast<cmServerBase*>(signal->data);
- conn->OnSignal(signum);
-}
-
-static void on_walk_to_shutdown(uv_handle_t* handle, void* arg)
-{
- (void)arg;
- assert(uv_is_closing(handle));
- if (!uv_is_closing(handle)) {
- uv_close(handle, &cmEventBasedConnection::on_close);
- }
-}
-
-class cmServer::DebugInfo
-{
-public:
- DebugInfo()
- : StartTime(uv_hrtime())
- {
- }
-
- bool PrintStatistics = false;
-
- std::string OutputFile;
- uint64_t StartTime;
-};
-
-cmServer::cmServer(cmConnection* conn, bool supportExperimental)
- : cmServerBase(conn)
- , SupportExperimental(supportExperimental)
-{
- // Register supported protocols:
- this->RegisterProtocol(cm::make_unique<cmServerProtocol1>());
-}
-
-cmServer::~cmServer()
-{
- Close();
-}
-
-void cmServer::ProcessRequest(cmConnection* connection,
- const std::string& input)
-{
- Json::Reader reader;
- Json::Value value;
- if (!reader.parse(input, value)) {
- this->WriteParseError(connection, "Failed to parse JSON input.");
- return;
- }
-
- std::unique_ptr<DebugInfo> debug;
- Json::Value debugValue = value["debug"];
- if (!debugValue.isNull()) {
- debug = cm::make_unique<DebugInfo>();
- debug->OutputFile = debugValue["dumpToFile"].asString();
- debug->PrintStatistics = debugValue["showStats"].asBool();
- }
-
- const cmServerRequest request(this, connection, value[kTYPE_KEY].asString(),
- value[kCOOKIE_KEY].asString(), value);
-
- if (request.Type.empty()) {
- cmServerResponse response(request);
- response.SetError("No type given in request.");
- this->WriteResponse(connection, response, nullptr);
- return;
- }
-
- cmSystemTools::SetMessageCallback(
- [&request](const std::string& msg, const char* title) {
- reportMessage(msg, title, request);
- });
-
- if (this->Protocol) {
- this->Protocol->CMakeInstance()->SetProgressCallback(
- [&request](const std::string& msg, float prog) {
- reportProgress(msg, prog, request);
- });
- this->WriteResponse(connection, this->Protocol->Process(request),
- debug.get());
- } else {
- this->WriteResponse(connection, this->SetProtocolVersion(request),
- debug.get());
- }
-}
-
-void cmServer::RegisterProtocol(std::unique_ptr<cmServerProtocol> protocol)
-{
- if (protocol->IsExperimental() && !this->SupportExperimental) {
- protocol.reset();
- return;
- }
- auto version = protocol->ProtocolVersion();
- assert(version.first >= 0);
- assert(version.second >= 0);
- auto it = std::find_if(
- this->SupportedProtocols.begin(), this->SupportedProtocols.end(),
- [version](const std::unique_ptr<cmServerProtocol>& p) {
- return p->ProtocolVersion() == version;
- });
- if (it == this->SupportedProtocols.end()) {
- this->SupportedProtocols.push_back(std::move(protocol));
- }
-}
-
-void cmServer::PrintHello(cmConnection* connection) const
-{
- Json::Value hello = Json::objectValue;
- hello[kTYPE_KEY] = "hello";
-
- Json::Value& protocolVersions = hello[kSUPPORTED_PROTOCOL_VERSIONS] =
- Json::arrayValue;
-
- for (auto const& proto : this->SupportedProtocols) {
- auto version = proto->ProtocolVersion();
- Json::Value tmp = Json::objectValue;
- tmp[kMAJOR_KEY] = version.first;
- tmp[kMINOR_KEY] = version.second;
- if (proto->IsExperimental()) {
- tmp[kIS_EXPERIMENTAL_KEY] = true;
- }
- protocolVersions.append(tmp);
- }
-
- this->WriteJsonObject(connection, hello, nullptr);
-}
-
-void cmServer::reportProgress(const std::string& msg, float progress,
- const cmServerRequest& request)
-{
- if (progress < 0.0f || progress > 1.0f) {
- request.ReportMessage(msg, "");
- } else {
- request.ReportProgress(0, static_cast<int>(progress * 1000), 1000, msg);
- }
-}
-
-void cmServer::reportMessage(const std::string& msg, const char* title,
- const cmServerRequest& request)
-{
- std::string titleString;
- if (title) {
- titleString = title;
- }
- request.ReportMessage(msg, titleString);
-}
-
-cmServerResponse cmServer::SetProtocolVersion(const cmServerRequest& request)
-{
- if (request.Type != kHANDSHAKE_TYPE) {
- return request.ReportError("Waiting for type \"" + kHANDSHAKE_TYPE +
- "\".");
- }
-
- Json::Value requestedProtocolVersion = request.Data[kPROTOCOL_VERSION_KEY];
- if (requestedProtocolVersion.isNull()) {
- return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
- "\" is required for \"" + kHANDSHAKE_TYPE +
- "\".");
- }
-
- if (!requestedProtocolVersion.isObject()) {
- return request.ReportError("\"" + kPROTOCOL_VERSION_KEY +
- "\" must be a JSON object.");
- }
-
- Json::Value majorValue = requestedProtocolVersion[kMAJOR_KEY];
- if (!majorValue.isInt()) {
- return request.ReportError("\"" + kMAJOR_KEY +
- "\" must be set and an integer.");
- }
-
- Json::Value minorValue = requestedProtocolVersion[kMINOR_KEY];
- if (!minorValue.isNull() && !minorValue.isInt()) {
- return request.ReportError("\"" + kMINOR_KEY +
- "\" must be unset or an integer.");
- }
-
- const int major = majorValue.asInt();
- const int minor = minorValue.isNull() ? -1 : minorValue.asInt();
- if (major < 0) {
- return request.ReportError("\"" + kMAJOR_KEY + "\" must be >= 0.");
- }
- if (!minorValue.isNull() && minor < 0) {
- return request.ReportError("\"" + kMINOR_KEY +
- "\" must be >= 0 when set.");
- }
-
- this->Protocol =
- cmServer::FindMatchingProtocol(this->SupportedProtocols, major, minor);
- if (!this->Protocol) {
- return request.ReportError("Protocol version not supported.");
- }
-
- std::string errorMessage;
- if (!this->Protocol->Activate(this, request, &errorMessage)) {
- this->Protocol = nullptr;
- return request.ReportError("Failed to activate protocol version: " +
- errorMessage);
- }
- return request.Reply(Json::objectValue);
-}
-
-bool cmServer::Serve(std::string* errorMessage)
-{
- if (this->SupportedProtocols.empty()) {
- *errorMessage =
- "No protocol versions defined. Maybe you need --experimental?";
- return false;
- }
- assert(!this->Protocol);
-
- return cmServerBase::Serve(errorMessage);
-}
-
-cmFileMonitor* cmServer::FileMonitor() const
-{
- return fileMonitor.get();
-}
-
-void cmServer::WriteJsonObject(const Json::Value& jsonValue,
- const DebugInfo* debug) const
-{
- cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : this->Connections) {
- WriteJsonObject(connection.get(), jsonValue, debug);
- }
-}
-
-void cmServer::WriteJsonObject(cmConnection* connection,
- const Json::Value& jsonValue,
- const DebugInfo* debug) const
-{
- Json::FastWriter writer;
-
- auto beforeJson = uv_hrtime();
- std::string result = writer.write(jsonValue);
-
- if (debug) {
- Json::Value copy = jsonValue;
- if (debug->PrintStatistics) {
- Json::Value stats = Json::objectValue;
- auto endTime = uv_hrtime();
-
- stats["jsonSerialization"] = double(endTime - beforeJson) / 1000000.0;
- stats["totalTime"] = double(endTime - debug->StartTime) / 1000000.0;
- stats["size"] = static_cast<int>(result.size());
- if (!debug->OutputFile.empty()) {
- stats["dumpFile"] = debug->OutputFile;
- }
-
- copy["zzzDebug"] = stats;
-
- result = writer.write(copy); // Update result to include debug info
- }
-
- if (!debug->OutputFile.empty()) {
- cmsys::ofstream myfile(debug->OutputFile.c_str());
- myfile << result;
- }
- }
-
- connection->WriteData(result);
-}
-
-cmServerProtocol* cmServer::FindMatchingProtocol(
- const std::vector<std::unique_ptr<cmServerProtocol>>& protocols, int major,
- int minor)
-{
- cmServerProtocol* bestMatch = nullptr;
- for (const auto& protocol : protocols) {
- auto version = protocol->ProtocolVersion();
- if (major != version.first) {
- continue;
- }
- if (minor == version.second) {
- return protocol.get();
- }
- if (!bestMatch || bestMatch->ProtocolVersion().second < version.second) {
- bestMatch = protocol.get();
- }
- }
- return minor < 0 ? bestMatch : nullptr;
-}
-
-void cmServer::WriteProgress(const cmServerRequest& request, int min,
- int current, int max,
- const std::string& message) const
-{
- assert(min <= current && current <= max);
- assert(message.length() != 0);
-
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kPROGRESS_TYPE;
- obj[kREPLY_TO_KEY] = request.Type;
- obj[kCOOKIE_KEY] = request.Cookie;
- obj[kPROGRESS_MESSAGE_KEY] = message;
- obj[kPROGRESS_MINIMUM_KEY] = min;
- obj[kPROGRESS_MAXIMUM_KEY] = max;
- obj[kPROGRESS_CURRENT_KEY] = current;
-
- this->WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteMessage(const cmServerRequest& request,
- const std::string& message,
- const std::string& title) const
-{
- if (message.empty()) {
- return;
- }
-
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kMESSAGE_TYPE;
- obj[kREPLY_TO_KEY] = request.Type;
- obj[kCOOKIE_KEY] = request.Cookie;
- obj[kMESSAGE_KEY] = message;
- if (!title.empty()) {
- obj[kTITLE_KEY] = title;
- }
-
- WriteJsonObject(request.Connection, obj, nullptr);
-}
-
-void cmServer::WriteParseError(cmConnection* connection,
- const std::string& message) const
-{
- Json::Value obj = Json::objectValue;
- obj[kTYPE_KEY] = kERROR_TYPE;
- obj[kERROR_MESSAGE_KEY] = message;
- obj[kREPLY_TO_KEY] = "";
- obj[kCOOKIE_KEY] = "";
-
- this->WriteJsonObject(connection, obj, nullptr);
-}
-
-void cmServer::WriteSignal(const std::string& name,
- const Json::Value& data) const
-{
- assert(data.isObject());
- Json::Value obj = data;
- obj[kTYPE_KEY] = kSIGNAL_TYPE;
- obj[kREPLY_TO_KEY] = "";
- obj[kCOOKIE_KEY] = "";
- obj[kNAME_KEY] = name;
-
- WriteJsonObject(obj, nullptr);
-}
-
-void cmServer::WriteResponse(cmConnection* connection,
- const cmServerResponse& response,
- const DebugInfo* debug) const
-{
- assert(response.IsComplete());
-
- Json::Value obj = response.Data();
- obj[kCOOKIE_KEY] = response.Cookie;
- obj[kTYPE_KEY] = response.IsError() ? kERROR_TYPE : kREPLY_TYPE;
- obj[kREPLY_TO_KEY] = response.Type;
- if (response.IsError()) {
- obj[kERROR_MESSAGE_KEY] = response.ErrorMessage();
- }
-
- this->WriteJsonObject(connection, obj, debug);
-}
-
-void cmServer::OnConnected(cmConnection* connection)
-{
- PrintHello(connection);
-}
-
-void cmServer::OnServeStart()
-{
- cmServerBase::OnServeStart();
- fileMonitor = std::make_shared<cmFileMonitor>(GetLoop());
-}
-
-void cmServer::StartShutDown()
-{
- if (fileMonitor) {
- fileMonitor->StopMonitoring();
- fileMonitor.reset();
- }
- cmServerBase::StartShutDown();
-}
-
-static void __start_thread(void* arg)
-{
- auto server = static_cast<cmServerBase*>(arg);
- std::string error;
- bool success = server->Serve(&error);
- if (!success || !error.empty()) {
- std::cerr << "Error during serve: " << error << std::endl;
- }
-}
-
-bool cmServerBase::StartServeThread()
-{
- ServeThreadRunning = true;
- uv_thread_create(&ServeThread, __start_thread, this);
- return true;
-}
-
-static void __shutdownThread(uv_async_t* arg)
-{
- auto server = static_cast<cmServerBase*>(arg->data);
- server->StartShutDown();
-}
-
-bool cmServerBase::Serve(std::string* errorMessage)
-{
-#ifndef NDEBUG
- uv_thread_t blank_thread_t = {};
- assert(uv_thread_equal(&blank_thread_t, &ServeThreadId));
- ServeThreadId = uv_thread_self();
-#endif
-
- errorMessage->clear();
-
- ShutdownSignal.init(Loop, __shutdownThread, this);
-
- SIGINTHandler.init(Loop, this);
- SIGHUPHandler.init(Loop, this);
-
- SIGINTHandler.start(&on_signal, SIGINT);
- SIGHUPHandler.start(&on_signal, SIGHUP);
-
- OnServeStart();
-
- {
- cm::shared_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : Connections) {
- if (!connection->OnServeStart(errorMessage)) {
- return false;
- }
- }
- }
-
- if (uv_run(&Loop, UV_RUN_DEFAULT) != 0) {
- // It is important we don't ever let the event loop exit with open handles
- // at best this is a memory leak, but it can also introduce race conditions
- // which can hang the program.
- assert(false && "Event loop stopped in unclean state.");
-
- *errorMessage = "Internal Error: Event loop stopped in unclean state.";
- return false;
- }
-
- return true;
-}
-
-void cmServerBase::OnConnected(cmConnection*)
-{
-}
-
-void cmServerBase::OnServeStart()
-{
-}
-
-void cmServerBase::StartShutDown()
-{
- ShutdownSignal.reset();
- SIGINTHandler.reset();
- SIGHUPHandler.reset();
-
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- for (auto& connection : Connections) {
- connection->OnConnectionShuttingDown();
- }
- Connections.clear();
- }
-
- uv_walk(&Loop, on_walk_to_shutdown, nullptr);
-}
-
-bool cmServerBase::OnSignal(int signum)
-{
- (void)signum;
- StartShutDown();
- return true;
-}
-
-cmServerBase::cmServerBase(cmConnection* connection)
-{
- auto err = uv_loop_init(&Loop);
- (void)err;
- Loop.data = this;
- assert(err == 0);
-
- AddNewConnection(connection);
-}
-
-void cmServerBase::Close()
-{
- if (Loop.data) {
- if (ServeThreadRunning) {
- this->ShutdownSignal.send();
- uv_thread_join(&ServeThread);
- }
-
- uv_loop_close(&Loop);
- Loop.data = nullptr;
- }
-}
-cmServerBase::~cmServerBase()
-{
- Close();
-}
-
-void cmServerBase::AddNewConnection(cmConnection* ownedConnection)
-{
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- Connections.emplace_back(ownedConnection);
- }
- ownedConnection->SetServer(this);
-}
-
-uv_loop_t* cmServerBase::GetLoop()
-{
- return &Loop;
-}
-
-void cmServerBase::OnDisconnect(cmConnection* pConnection)
-{
- auto pred = [pConnection](const std::unique_ptr<cmConnection>& m) {
- return m.get() == pConnection;
- };
- {
- std::unique_lock<cm::shared_mutex> lock(ConnectionsMutex);
- Connections.erase(
- std::remove_if(Connections.begin(), Connections.end(), pred),
- Connections.end());
- }
-
- if (Connections.empty()) {
- this->ShutdownSignal.send();
- }
-}