mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-20 20:23:03 +02:00
Shared memory refactoring and command line control options
Now client accept following options: --disable-shm - disable shared memory usage --enable-shm-uuid - use UUID for shared memory identifier UUID is useful when a lot of clients starting simultaneously. Needed for testing and was easier to implement than alternatives.
This commit is contained in:
parent
a2284c3209
commit
1a60c1a94b
3
Global.h
3
Global.h
@ -185,6 +185,9 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size.");
|
|||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <boost/math/special_functions/round.hpp>
|
#include <boost/math/special_functions/round.hpp>
|
||||||
#include <boost/multi_array.hpp>
|
#include <boost/multi_array.hpp>
|
||||||
|
#include <boost/uuid/uuid.hpp>
|
||||||
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
#include <boost/uuid/uuid_generators.hpp>
|
||||||
|
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
# define M_PI 3.14159265358979323846
|
# define M_PI 3.14159265358979323846
|
||||||
|
@ -260,6 +260,8 @@ int main(int argc, char** argv)
|
|||||||
opts.add_options()
|
opts.add_options()
|
||||||
("help,h", "display help and exit")
|
("help,h", "display help and exit")
|
||||||
("version,v", "display version information and exit")
|
("version,v", "display version information and exit")
|
||||||
|
("disable-shm", "force disable shared memory usage")
|
||||||
|
("enable-shm-uuid", "use UUID for shared memory identifier")
|
||||||
("battle,b", po::value<std::string>(), "runs game in duel mode (battle-only")
|
("battle,b", po::value<std::string>(), "runs game in duel mode (battle-only")
|
||||||
("start", po::value<bfs::path>(), "starts game from saved StartInfo file")
|
("start", po::value<bfs::path>(), "starts game from saved StartInfo file")
|
||||||
("testmap", po::value<std::string>(), "")
|
("testmap", po::value<std::string>(), "")
|
||||||
@ -345,6 +347,9 @@ int main(int argc, char** argv)
|
|||||||
session["headless"].Bool() = true;
|
session["headless"].Bool() = true;
|
||||||
session["onlyai"].Bool() = true;
|
session["onlyai"].Bool() = true;
|
||||||
}
|
}
|
||||||
|
// Shared memory options
|
||||||
|
session["disable-shm"].Bool() = vm.count("disable-shm");
|
||||||
|
session["enable-shm-uuid"].Bool() = vm.count("enable-shm-uuid");
|
||||||
|
|
||||||
// Init special testing settings
|
// Init special testing settings
|
||||||
session["serverport"].Integer() = vm.count("serverport") ? vm["serverport"].as<si64>() : 0;
|
session["serverport"].Integer() = vm.count("serverport") ? vm["serverport"].as<si64>() : 0;
|
||||||
|
@ -41,9 +41,7 @@
|
|||||||
#include "CMT.h"
|
#include "CMT.h"
|
||||||
|
|
||||||
extern std::string NAME;
|
extern std::string NAME;
|
||||||
#ifndef VCMI_ANDROID
|
#ifdef VCMI_ANDROID
|
||||||
namespace intpr = boost::interprocess;
|
|
||||||
#else
|
|
||||||
#include "lib/CAndroidVMHelper.h"
|
#include "lib/CAndroidVMHelper.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1019,13 +1017,7 @@ void CServerHandler::waitForServer()
|
|||||||
|
|
||||||
#ifndef VCMI_ANDROID
|
#ifndef VCMI_ANDROID
|
||||||
if(shared)
|
if(shared)
|
||||||
{
|
shared->sr->waitTillReady();
|
||||||
intpr::scoped_lock<intpr::interprocess_mutex> slock(shared->sr->mutex);
|
|
||||||
while(!shared->sr->ready)
|
|
||||||
{
|
|
||||||
shared->sr->cond.wait(slock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
logNetwork->infoStream() << "waiting for server";
|
logNetwork->infoStream() << "waiting for server";
|
||||||
while (!androidTestServerReadyFlag.load())
|
while (!androidTestServerReadyFlag.load())
|
||||||
@ -1042,15 +1034,7 @@ void CServerHandler::waitForServer()
|
|||||||
|
|
||||||
CConnection * CServerHandler::connectToServer()
|
CConnection * CServerHandler::connectToServer()
|
||||||
{
|
{
|
||||||
#ifndef VCMI_ANDROID
|
|
||||||
if(shared)
|
|
||||||
{
|
|
||||||
if(!shared->sr->ready)
|
|
||||||
waitForServer();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
waitForServer();
|
waitForServer();
|
||||||
#endif
|
|
||||||
|
|
||||||
th.update(); //put breakpoint here to attach to server before it does something stupid
|
th.update(); //put breakpoint here to attach to server before it does something stupid
|
||||||
|
|
||||||
@ -1084,15 +1068,21 @@ CServerHandler::CServerHandler(bool runServer /*= false*/)
|
|||||||
serverThread = nullptr;
|
serverThread = nullptr;
|
||||||
shared = nullptr;
|
shared = nullptr;
|
||||||
verbose = true;
|
verbose = true;
|
||||||
|
uuid = boost::uuids::to_string(boost::uuids::random_generator()());
|
||||||
|
|
||||||
#ifndef VCMI_ANDROID
|
#ifndef VCMI_ANDROID
|
||||||
if(DO_NOT_START_SERVER)
|
if(DO_NOT_START_SERVER || settings["session"]["disable-shm"].Bool())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
boost::interprocess::shared_memory_object::remove("vcmi_memory"); //if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it
|
std::string sharedMemoryName = "vcmi_memory";
|
||||||
|
if(settings["session"]["enable-shm-uuid"].Bool())
|
||||||
|
{
|
||||||
|
//used or automated testing when multiple clients start simultaneously
|
||||||
|
sharedMemoryName += "_" + uuid;
|
||||||
|
}
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
shared = new SharedMem();
|
shared = new SharedMemory(sharedMemoryName, true);
|
||||||
}
|
}
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
@ -1115,11 +1105,17 @@ void CServerHandler::callServer()
|
|||||||
#ifndef VCMI_ANDROID
|
#ifndef VCMI_ANDROID
|
||||||
setThreadName("CServerHandler::callServer");
|
setThreadName("CServerHandler::callServer");
|
||||||
const std::string logName = (VCMIDirs::get().userCachePath() / "server_log.txt").string();
|
const std::string logName = (VCMIDirs::get().userCachePath() / "server_log.txt").string();
|
||||||
const std::string comm = VCMIDirs::get().serverPath().string()
|
std::string comm = VCMIDirs::get().serverPath().string()
|
||||||
+ " --port=" + getDefaultPortStr()
|
+ " --port=" + getDefaultPortStr()
|
||||||
+ " --run-by-client"
|
+ " --run-by-client"
|
||||||
+ (shared ? " --use-shm" : "")
|
+ " --uuid=" + uuid;
|
||||||
+ " > \"" + logName + '\"';
|
if(shared)
|
||||||
|
{
|
||||||
|
comm += " --enable-shm";
|
||||||
|
if(settings["session"]["enable-shm-uuid"].Bool())
|
||||||
|
comm += " --enable-shm-uuid";
|
||||||
|
}
|
||||||
|
comm += " > \"" + logName + '\"';
|
||||||
|
|
||||||
int result = std::system(comm.c_str());
|
int result = std::system(comm.c_str());
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
|
@ -28,7 +28,7 @@ class CGameInterface;
|
|||||||
class CConnection;
|
class CConnection;
|
||||||
class CCallback;
|
class CCallback;
|
||||||
struct BattleAction;
|
struct BattleAction;
|
||||||
struct SharedMem;
|
struct SharedMemory;
|
||||||
class CClient;
|
class CClient;
|
||||||
class CScriptingModule;
|
class CScriptingModule;
|
||||||
struct CPathsInfo;
|
struct CPathsInfo;
|
||||||
@ -46,7 +46,8 @@ public:
|
|||||||
|
|
||||||
CStopWatch th;
|
CStopWatch th;
|
||||||
boost::thread *serverThread; //thread that called system to run server
|
boost::thread *serverThread; //thread that called system to run server
|
||||||
SharedMem *shared; //interprocess memory (for waiting for server)
|
SharedMemory * shared;
|
||||||
|
std::string uuid;
|
||||||
bool verbose; //whether to print log msgs
|
bool verbose; //whether to print log msgs
|
||||||
|
|
||||||
//functions setting up local server
|
//functions setting up local server
|
||||||
|
@ -20,8 +20,8 @@ struct ServerReady
|
|||||||
{
|
{
|
||||||
bool ready;
|
bool ready;
|
||||||
uint16_t port; //ui16?
|
uint16_t port; //ui16?
|
||||||
boost::interprocess::interprocess_mutex mutex;
|
boost::interprocess::interprocess_mutex mutex;
|
||||||
boost::interprocess::interprocess_condition cond;
|
boost::interprocess::interprocess_condition cond;
|
||||||
|
|
||||||
ServerReady()
|
ServerReady()
|
||||||
{
|
{
|
||||||
@ -29,7 +29,16 @@ struct ServerReady
|
|||||||
port = 0;
|
port = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setToTrueAndNotify(uint16_t Port)
|
void waitTillReady()
|
||||||
|
{
|
||||||
|
boost::interprocess::scoped_lock<boost::interprocess::interprocess_mutex> slock(mutex);
|
||||||
|
while(!ready)
|
||||||
|
{
|
||||||
|
cond.wait(slock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setToReadyAndNotify(const uint16_t Port)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
boost::unique_lock<boost::interprocess::interprocess_mutex> lock(mutex);
|
boost::unique_lock<boost::interprocess::interprocess_mutex> lock(mutex);
|
||||||
@ -40,22 +49,33 @@ struct ServerReady
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SharedMem
|
struct SharedMemory
|
||||||
{
|
{
|
||||||
|
const char * name;
|
||||||
boost::interprocess::shared_memory_object smo;
|
boost::interprocess::shared_memory_object smo;
|
||||||
boost::interprocess::mapped_region *mr;
|
boost::interprocess::mapped_region * mr;
|
||||||
ServerReady *sr;
|
ServerReady * sr;
|
||||||
|
|
||||||
SharedMem() //c-tor
|
SharedMemory(std::string Name, bool initialize = false)
|
||||||
:smo(boost::interprocess::open_or_create,"vcmi_memory",boost::interprocess::read_write)
|
: name(Name.c_str())
|
||||||
{
|
{
|
||||||
|
if(initialize)
|
||||||
|
{
|
||||||
|
//if the application has previously crashed, the memory may not have been removed. to avoid problems - try to destroy it
|
||||||
|
boost::interprocess::shared_memory_object::remove(name);
|
||||||
|
}
|
||||||
|
smo = boost::interprocess::shared_memory_object(boost::interprocess::open_or_create, name, boost::interprocess::read_write);
|
||||||
smo.truncate(sizeof(ServerReady));
|
smo.truncate(sizeof(ServerReady));
|
||||||
mr = new boost::interprocess::mapped_region(smo,boost::interprocess::read_write);
|
mr = new boost::interprocess::mapped_region(smo,boost::interprocess::read_write);
|
||||||
sr = new(mr->get_address())ServerReady();
|
if(initialize)
|
||||||
|
sr = new(mr->get_address())ServerReady();
|
||||||
|
else
|
||||||
|
sr = reinterpret_cast<ServerReady*>(mr->get_address());
|
||||||
};
|
};
|
||||||
~SharedMem() //d-tor
|
|
||||||
|
~SharedMemory()
|
||||||
{
|
{
|
||||||
delete mr;
|
delete mr;
|
||||||
boost::interprocess::shared_memory_object::remove("vcmi_memory");
|
boost::interprocess::shared_memory_object::remove(name);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -41,9 +41,6 @@
|
|||||||
|
|
||||||
std::string NAME_AFFIX = "server";
|
std::string NAME_AFFIX = "server";
|
||||||
std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')'; //application name
|
std::string NAME = GameConstants::VCMI_VERSION + std::string(" (") + NAME_AFFIX + ')'; //application name
|
||||||
#ifndef VCMI_ANDROID
|
|
||||||
namespace intpr = boost::interprocess;
|
|
||||||
#endif
|
|
||||||
std::atomic<bool> serverShuttingDown(false);
|
std::atomic<bool> serverShuttingDown(false);
|
||||||
|
|
||||||
boost::program_options::variables_map cmdLineOptions;
|
boost::program_options::variables_map cmdLineOptions;
|
||||||
@ -326,7 +323,7 @@ void CPregameServer::startListeningThread(CConnection * pc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
CVCMIServer::CVCMIServer()
|
CVCMIServer::CVCMIServer()
|
||||||
: port(3030), io(new boost::asio::io_service()), firstConnection(nullptr)
|
: port(3030), io(new boost::asio::io_service()), firstConnection(nullptr), shared(nullptr)
|
||||||
{
|
{
|
||||||
logNetwork->trace("CVCMIServer created!");
|
logNetwork->trace("CVCMIServer created!");
|
||||||
if(cmdLineOptions.count("port"))
|
if(cmdLineOptions.count("port"))
|
||||||
@ -339,7 +336,7 @@ CVCMIServer::CVCMIServer()
|
|||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
logNetwork->info("Port %d is busy, trying to use random port instead", port);
|
logNetwork->info("Port %d is busy, trying to use random port instead", port);
|
||||||
if(cmdLineOptions.count("run-by-client") && !cmdLineOptions.count("use-shm"))
|
if(cmdLineOptions.count("run-by-client") && !cmdLineOptions.count("enable-shm"))
|
||||||
{
|
{
|
||||||
logNetwork->error("Cant pass port number to client without shared memory!", port);
|
logNetwork->error("Cant pass port number to client without shared memory!", port);
|
||||||
exit(0);
|
exit(0);
|
||||||
@ -425,24 +422,14 @@ void CVCMIServer::newPregame()
|
|||||||
void CVCMIServer::start()
|
void CVCMIServer::start()
|
||||||
{
|
{
|
||||||
#ifndef VCMI_ANDROID
|
#ifndef VCMI_ANDROID
|
||||||
ServerReady *sr = nullptr;
|
if(cmdLineOptions.count("enable-shm"))
|
||||||
intpr::mapped_region *mr;
|
|
||||||
if(cmdLineOptions.count("use-shm"))
|
|
||||||
{
|
{
|
||||||
try
|
std::string sharedMemoryName = "vcmi_memory";
|
||||||
|
if(cmdLineOptions.count("enable-shm-uuid") && cmdLineOptions.count("uuid"))
|
||||||
{
|
{
|
||||||
intpr::shared_memory_object smo(intpr::open_only,"vcmi_memory",intpr::read_write);
|
sharedMemoryName += "_" + cmdLineOptions["uuid"].as<std::string>();
|
||||||
smo.truncate(sizeof(ServerReady));
|
|
||||||
mr = new intpr::mapped_region(smo,intpr::read_write);
|
|
||||||
sr = reinterpret_cast<ServerReady*>(mr->get_address());
|
|
||||||
}
|
|
||||||
catch(...)
|
|
||||||
{
|
|
||||||
intpr::shared_memory_object smo(intpr::create_only,"vcmi_memory",intpr::read_write);
|
|
||||||
smo.truncate(sizeof(ServerReady));
|
|
||||||
mr = new intpr::mapped_region(smo,intpr::read_write);
|
|
||||||
sr = new(mr->get_address())ServerReady();
|
|
||||||
}
|
}
|
||||||
|
shared = new SharedMemory(sharedMemoryName);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -460,10 +447,9 @@ void CVCMIServer::start()
|
|||||||
logNetwork->info("Sending server ready message to client");
|
logNetwork->info("Sending server ready message to client");
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if(cmdLineOptions.count("use-shm"))
|
if(shared)
|
||||||
{
|
{
|
||||||
sr->setToTrueAndNotify(port);
|
shared->sr->setToReadyAndNotify(port);
|
||||||
delete mr;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -557,7 +543,9 @@ static void handleCommandOptions(int argc, char *argv[])
|
|||||||
("help,h", "display help and exit")
|
("help,h", "display help and exit")
|
||||||
("version,v", "display version information and exit")
|
("version,v", "display version information and exit")
|
||||||
("run-by-client", "indicate that server launched by client on same machine")
|
("run-by-client", "indicate that server launched by client on same machine")
|
||||||
("use-shm", "enable usage of shared memory")
|
("uuid", po::value<std::string>(), "")
|
||||||
|
("enable-shm-uuid", "use UUID for shared memory identifier")
|
||||||
|
("enable-shm", "enable usage of shared memory")
|
||||||
("port", po::value<ui16>(), "port at which server will listen to connections from client")
|
("port", po::value<ui16>(), "port at which server will listen to connections from client")
|
||||||
("resultsFile", po::value<std::string>()->default_value("./results.txt"), "file to which the battle result will be appended. Used only in the DUEL mode.");
|
("resultsFile", po::value<std::string>()->default_value("./results.txt"), "file to which the battle result will be appended. Used only in the DUEL mode.");
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ class CMapInfo;
|
|||||||
class CConnection;
|
class CConnection;
|
||||||
struct CPackForSelectionScreen;
|
struct CPackForSelectionScreen;
|
||||||
class CGameHandler;
|
class CGameHandler;
|
||||||
|
struct SharedMemory;
|
||||||
|
|
||||||
namespace boost
|
namespace boost
|
||||||
{
|
{
|
||||||
@ -46,6 +47,7 @@ class CVCMIServer
|
|||||||
ui16 port;
|
ui16 port;
|
||||||
boost::asio::io_service *io;
|
boost::asio::io_service *io;
|
||||||
TAcceptor * acceptor;
|
TAcceptor * acceptor;
|
||||||
|
SharedMemory * shared;
|
||||||
|
|
||||||
CConnection *firstConnection;
|
CConnection *firstConnection;
|
||||||
public:
|
public:
|
||||||
|
Loading…
Reference in New Issue
Block a user