/*
|
* =====================================================================================
|
*
|
* Filename: center_main.cc
|
*
|
* Description:
|
*
|
* Version: 1.0
|
* Created: 2021年04月13日 16时16分26秒
|
* Revision: none
|
* Compiler: gcc
|
*
|
* Author: Li Chao (), lichao@aiotlink.com
|
* Organization:
|
*
|
* =====================================================================================
|
*/
|
#include "app_arg.h"
|
#include "box.h"
|
#include "center.h"
|
#include "defs.h"
|
#include "log.h"
|
#include "signalhandle.h"
|
#include <boost/interprocess/sync/named_mutex.hpp>
|
#include <chrono>
|
#include <thread>
|
using namespace std::chrono_literals;
|
using namespace bhome_shm;
|
|
namespace
|
{
|
const std::string kCenterRunningFlag = "bh_center_single_flag_0";
|
|
class InstanceFlag
|
{
|
|
public:
|
InstanceFlag(SharedMemory &shm, const std::string &name) :
|
shm_(shm), name_(name), run_(false) {}
|
~InstanceFlag() { Stop(); }
|
|
bool TryStartAsFirstInstance()
|
{
|
if (run_) {
|
return true;
|
}
|
|
auto mtx(shm_.FindOrCreate<Mutex>(name_ + "_mutex_0"));
|
auto time_stamp(shm_.FindOrCreate<int64_t>(name_ + "_timestamp_0", 0));
|
|
if (mtx && time_stamp) {
|
Guard lock(*mtx);
|
auto now = NowSec();
|
LOG_DEBUG() << "old: " << *time_stamp << ", now: " << now;
|
if (now > *time_stamp + 10) {
|
*time_stamp = now;
|
auto UpdateTime = [this, time_stamp]() {
|
while (run_) {
|
std::this_thread::sleep_for(1s);
|
*time_stamp = NowSec();
|
}
|
};
|
run_.store(true);
|
std::thread(UpdateTime).swap(worker_);
|
return true;
|
}
|
}
|
return false;
|
}
|
|
private:
|
void Stop()
|
{
|
run_.store(false);
|
if (worker_.joinable()) {
|
worker_.join();
|
}
|
}
|
|
std::thread worker_;
|
SharedMemory &shm_;
|
std::string name_;
|
std::atomic<bool> run_;
|
};
|
|
} // namespace
|
int center_main(int argc, const char *argv[])
|
{
|
AppArg args(argc, argv);
|
if (args.Has("remove")) {
|
SharedMemory::Remove(BHomeShmName());
|
return 0;
|
}
|
|
ns_log::AddLog("/tmp/bhshmq_center.log");
|
auto lvl = args.Get("log", "info");
|
if (strcasecmp(lvl.c_str(), "trace") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::trace); }
|
if (strcasecmp(lvl.c_str(), "debug") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::debug); }
|
if (strcasecmp(lvl.c_str(), "info") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::info); }
|
if (strcasecmp(lvl.c_str(), "warning") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::warning); }
|
if (strcasecmp(lvl.c_str(), "error") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::error); }
|
if (strcasecmp(lvl.c_str(), "fatal") == 0) { ns_log::ResetLogLevel(ns_log::LogLevel::fatal); }
|
|
auto &shm = BHomeShm();
|
GlobalInit(shm);
|
|
InstanceFlag inst(shm, kCenterRunningFlag);
|
if (!inst.TryStartAsFirstInstance()) {
|
LOG_INFO() << "another instance is running, exit.";
|
return 0;
|
}
|
|
if (args.Has("daemon") || args.Has("d")) {
|
int r = daemon(0, 0); // TODO center control msg to close itself.
|
}
|
|
BHCenter center(shm);
|
center.Start();
|
|
LOG_INFO() << "center started ...";
|
WaitForSignals({SIGINT, SIGTERM});
|
center.Stop();
|
LOG_INFO() << "center stopped.";
|
return 0;
|
}
|
|
namespace
|
{
|
static bool install = BoxInstall("bhshmq_center", center_main, "bhome center program.");
|
}
|