96 if (conf.forwardKine()) {
97 auto factory = fair::mq::TransportFactory::CreateTransportFactory(
"zeromq");
98 auto forwardchannel = fair::mq::Channel{
"kineforward",
"pair", factory};
100 forwardchannel.Bind(
address.c_str());
101 forwardchannel.Validate();
102 fair::mq::Parts parts;
103 fair::mq::MessagePtr payload(forwardchannel.NewMessage());
106 auto channelAlloc = o2::pmr::getTransportAllocator(forwardchannel.Transport());
108 parts.AddPart(std::move(
header));
109 parts.AddPart(std::move(payload));
110 int timeoutinMS = 1000;
111 if (forwardchannel.Send(parts, timeoutinMS) > 0) {
112 LOGP(info,
"SENDING END-OF-STREAM TO PROXY AT {}",
address.c_str());
114 LOGP(warn,
"SENDING END-OF-STREAM TIMED OUT; PEER PROBABLY NO LONGER CONNECTED");
122 if (getenv(
"ALICE_O2SIM_DUMPLOG")) {
123 std::cerr <<
"------------- START OF EVENTSERVER LOG ----------" << std::endl;
124 std::stringstream catcommand1;
126 if (system(catcommand1.str().c_str()) != 0) {
127 LOG(warn) <<
"error executing system call";
130 std::cerr <<
"------------- START OF SIM WORKER(S) LOG --------" << std::endl;
131 std::stringstream catcommand2;
133 if (system(catcommand2.str().c_str()) != 0) {
134 LOG(warn) <<
"error executing system call";
137 std::cerr <<
"------------- START OF MERGER LOG ---------------" << std::endl;
138 std::stringstream catcommand3;
140 if (system(catcommand3.str().c_str()) != 0) {
141 LOG(warn) <<
"error executing system call";
218 static std::vector<std::thread> threads;
221 LOG(info) <<
"Control address is: " << controladdress;
222 setenv(
"ALICE_O2SIMCONTROL", internalcontroladdress.c_str(), 1);
224 auto lambda = [controladdress, internalcontroladdress]() {
225 auto factory = fair::mq::TransportFactory::CreateTransportFactory(
"zeromq");
228 auto internalchannel = fair::mq::Channel{
"o2sim-internal",
"pub", factory};
229 internalchannel.Bind(internalcontroladdress);
230 internalchannel.Validate();
231 std::unique_ptr<fair::mq::Message>
message(internalchannel.NewMessage());
234 auto outsidechannel = fair::mq::Channel{
"o2sim-control",
"rep", factory};
235 outsidechannel.Bind(controladdress);
236 outsidechannel.Validate();
237 std::unique_ptr<fair::mq::Message> request(outsidechannel.NewMessage());
239 bool keepgoing =
true;
241 outsidechannel.Init();
242 outsidechannel.Bind(controladdress);
243 outsidechannel.Validate();
244 if (outsidechannel.Receive(request) > 0) {
245 std::string command(
reinterpret_cast<char const*
>(request->GetData()), request->GetSize());
246 LOG(info) <<
"Control message: " << command <<
" received ";
250 std::unique_ptr<fair::mq::Message> reply(outsidechannel.NewSimpleMessage(code));
251 outsidechannel.Send(reply);
258 LOG(warn) <<
"CONTROL REQUEST COULD NOT BE PARSED";
261 std::unique_ptr<fair::mq::Message> reply(outsidechannel.NewSimpleMessage(code));
262 outsidechannel.Send(reply);
269 internalchannel.Send(request);
270 keepgoing = !reconfig.
stop;
276 threads.push_back(std::thread(lambda));
277 threads.back().detach();
310 int pipefd, std::string text, std::vector<int>& eventcontainer,
311 std::function<
bool(std::vector<int>
const&)> callback = [](std::vector<int>
const&) {
return true; })
313 static std::vector<std::thread> threads;
314 auto lambda = [pipefd, text, callback, &eventcontainer]() {
317 ssize_t
count =
read(pipefd, &eventcounter,
sizeof(eventcounter));
319 LOG(info) <<
"ERROR READING";
320 if (errno == EINTR) {
325 }
else if (
count == 0) {
328 eventcontainer.push_back(eventcounter);
329 if (callback(eventcontainer)) {
330 LOG(info) << text.c_str() << eventcounter;
335 threads.push_back(std::thread(lambda));
336 threads.back().detach();
398 std::vector<std::string> modifiedArgs;
402 if (conf.resetFromArguments(argc, argv)) {
403 for (
int i = 0;
i < argc; ++
i) {
404 modifiedArgs.push_back(argv[
i]);
409 if (conf.getRunNumber() != -1) {
414 auto soreor = ccdbmgr.getRunDuration(conf.getRunNumber());
415 auto timestamp = conf.getTimestamp();
417 timestamp = soreor.first;
418 LOG(info) <<
"Fixing timestamp to " << timestamp <<
" based on run number";
419 modifiedArgs.push_back(
"--timestamp");
422 LOG(fatal) <<
"The given timestamp " << timestamp <<
" is incompatible with the given run number " << conf.getRunNumber() <<
" starting at " << soreor.first <<
" and ending at " << soreor.second;
426 std::vector<char*>
final(modifiedArgs.size(),
nullptr);
427 for (
int i = 0;
i < modifiedArgs.size(); ++
i) {
428 final[
i] =
new char[modifiedArgs[
i].size() + 1];
429 strcpy(
final[
i], modifiedArgs[
i].c_str());
436int main(
int argc,
char* argv[])
444 setenv(
"ALICE_SIMFORKINTERNAL",
"ON", 1);
447 if (setpgid(0, 0) == -1) {
454 auto o2env = getenv(
"O2_ROOT");
456 LOG(fatal) <<
"O2_ROOT environment not defined";
458 std::string rootpath(o2env);
459 std::string installpath = rootpath +
"/bin";
462 std::stringstream configss;
463 configss << rootpath <<
"/share/config/o2simtopology_template.json";
464 auto localconfig = std::string(
"o2simtopology_") +
std::to_string(getpid()) + std::string(
".json");
468 std::ifstream in(configss.str());
469 std::ofstream out(localconfig);
470 std::string wordToReplace(
"#PID#");
473 size_t len = wordToReplace.length();
474 while (std::getline(in, line)) {
475 size_t pos = line.find(wordToReplace);
476 if (
pos != std::string::npos) {
477 line.replace(
pos,
len, wordToReplaceWith);
490 if (finalArgs.size() == 0) {
498 if (!conf.resetFromArguments(finalArgs.size(), &finalArgs[0])) {
503 if (conf.getNEvents() <= 0 && !conf.asService()) {
504 LOG(info) <<
"No events to be simulated; Switching to non-distributed mode";
505 const int Nargs = finalArgs.size() + 1;
507 std::string
name(
"o2-sim-serial-run5");
509 std::string
name(
"o2-sim-serial");
513 for (
int i = 1;
i < finalArgs.size(); ++
i) {
517 std::string
path = installpath +
"/" +
name;
526 if (conf.asService()) {
533 int nworkers = conf.getNSimWorkers();
535 LOG(info) <<
"Running with " << nworkers <<
" sim workers ";
540 if (getenv(
"ALICE_NOSIMSHM")) {
544 int pipe_serverdriver_fd[2];
545 if (pipe(pipe_serverdriver_fd) != 0) {
546 perror(
"problem in creating pipe");
552 int fd = open(
getServerLogName().c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
553 setenv(
"ALICE_O2SIMSERVERTODRIVER_PIPE",
std::to_string(pipe_serverdriver_fd[1]).c_str(), 1);
558 close(pipe_serverdriver_fd[0]);
561 const std::string
name(
"o2-sim-primary-server-device-runner");
562 const std::string
path = installpath +
"/" +
name;
563 const std::string config = localconfig;
567 const int addNArgs = 12;
569 const int addNArgs = 11;
571 const int Nargs = finalArgs.size() + addNArgs;
587 for (
int i = 1;
i < finalArgs.size(); ++
i) {
591 for (
int i = 0;
i < Nargs; ++
i) {
596 std::cerr <<
"$$$$\n";
598 LOG(info) <<
"Starting the server"
607 close(pipe_serverdriver_fd[1]);
608 std::cout <<
"Spawning particle server on PID " <<
pid <<
"; Redirect output to " <<
getServerLogName() <<
"\n";
611 auto distributionCallback = [&conf, &externalpublishchannel](std::vector<int>
const&
v) {
612 std::stringstream
str;
613 if (
v.back() == -111) {
618 str <<
"EVENT " <<
v.back() <<
" DISTRIBUTED";
637 auto internalfork = getenv(
"ALICE_SIMFORKINTERNAL");
642 for (
int id = 0;
id < nworkers; ++
id) {
644 std::stringstream workerlogss;
648 std::stringstream workerss;
649 workerss <<
"worker" <<
id;
653 int fd = open(workerlogss.str().c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
659 const std::string
name(
"o2-sim-device-runner");
660 const std::string
path = installpath +
"/" +
name;
662 execl(
path.c_str(),
name.c_str(),
"--control",
"static",
"--id", workerss.str().c_str(),
"--config-key",
663 "worker",
"--mq-config", localconfig.c_str(),
"--severity",
"info", (
char*)
nullptr);
668 std::cout <<
"Spawning sim worker " <<
id <<
" on PID " <<
pid
669 <<
"; Redirect output to " << workerlogss.str() <<
"\n";
674 int pipe_mergerdriver_fd[2];
675 if (pipe(pipe_mergerdriver_fd) != 0) {
676 perror(
"problem in creating pipe");
681 std::atomic<bool> shutdown_initiated =
false;
683 int fd = open(
getMergerLogName().c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
688 close(pipe_mergerdriver_fd[0]);
689 setenv(
"ALICE_O2SIMMERGERTODRIVER_PIPE",
std::to_string(pipe_mergerdriver_fd[1]).c_str(), 1);
690 const std::string
name(
"o2-sim-hit-merger-runner");
691 const std::string
path = installpath +
"/" +
name;
692 execl(
path.c_str(),
name.c_str(),
"--control",
"static",
"--catch-signals",
"0",
"--id",
"hitmerger",
"--mq-config", localconfig.c_str(),
"--color",
"false",
696 std::cout <<
"Spawning hit merger on PID " <<
pid <<
"; Redirect output to " <<
getMergerLogName() <<
"\n";
699 close(pipe_mergerdriver_fd[1]);
704 auto finishCallback = [&shutdown_initiated, &conf, &externalpublishchannel](std::vector<int>
const&
v) {
705 std::stringstream
str;
710 if (!conf.asService()) {
711 LOG(info) <<
"SIMULATION IS DONE. INITIATING SHUTDOWN.";
712 if (!shutdown_initiated) {
713 shutdown_initiated =
true;
715 if (killpg(p, 0) == 0) {
721 LOG(info) <<
"SIMULATION DONE. STAYING AS DAEMON.";
735 bool errored =
false;
737 while ((cpid = wait(&status)) != -1) {
738 if (cpid == mergerpid) {
742 if (WEXITSTATUS(status) || WIFSIGNALED(status)) {
743 if (!shutdown_initiated) {
744 LOG(info) <<
"Process " << cpid <<
" EXITED WITH CODE " << WEXITSTATUS(status) <<
" SIGNALED "
745 << WIFSIGNALED(status) <<
" SIGNAL " << WTERMSIG(status);
749 LOG(info) <<
"Problem detected (or child received termination signal) ... shutting down whole system ";
751 LOG(info) <<
"TERMINATING " << p;
752 if (killpg(p, 0) == 0) {
756 LOG(error) <<
"SHUTTING DOWN DUE TO SIGNALED EXIT IN COMPONENT " << cpid;
764 if (cpid == mergerpid) {
765 if (WIFEXITED(status)) {
766 if (WEXITSTATUS(status) != 0 || WEXITSTATUS(status) != 128) {
767 LOG(error) <<
"Merger process exited with abnormal exit status " << WEXITSTATUS(status);
770 }
else if (WIFSIGNALED(status)) {
771 auto sig = WTERMSIG(status);
772 if (sig == SIGKILL || sig == SIGBUS || sig == SIGSEGV || sig == SIGABRT) {
773 LOG(error) <<
"Merger process terminated through abnormal signal " << WTERMSIG(status);
777 LOG(warning) <<
"Merger process exited with unexpected status.";
782 LOG(info) <<
"Merger process " << mergerpid <<
" returned";
783 LOG(info) <<
"Simulation process took " << timer.RealTime() <<
" s";
785 if (!errored && !shutdown_initiated) {
786 shutdown_initiated =
true;
789 if (p != mergerpid) {
790 LOG(info) <<
"SHUTTING DOWN CHILD PROCESS (normal thread)" << p;
791 if (killpg(p, 0) == 0) {
802 while ((cpid = wait(&status))) {
812 while (p != 0 && killpg(p, 0) == 0) {
825 if (returncode == 0) {
826 LOG(info) <<
"SIMULATION RETURNED SUCCESFULLY";