|
@@ -0,0 +1,181 @@
|
|
|
+#include "vendor_base.h"
|
|
|
+#include "vendor_global.h"
|
|
|
+#include <event.h>
|
|
|
+#include <signal.h>
|
|
|
+
|
|
|
+namespace vendor {
|
|
|
+
|
|
|
+struct event_base *eventBase_ = nullptr;
|
|
|
+
|
|
|
+LongOpts::LongOpts(const MyOpt opts[], const int size)
|
|
|
+{
|
|
|
+ myOpt = opts;
|
|
|
+ sizeOpt = size;
|
|
|
+}
|
|
|
+
|
|
|
+void LongOpts::GetOptions(option *opts, std::string &shorts)
|
|
|
+{
|
|
|
+ for (int i = 0; i < sizeOpt; i++) {
|
|
|
+ // printf("val: %d(%c) ", myOpt[i].val, myOpt[i].val);
|
|
|
+ opts[i].name = strdup(myOpt[i].name);
|
|
|
+ opts[i].has_arg = myOpt[i].has_arg;
|
|
|
+ opts[i].flag = NULL;
|
|
|
+ opts[i].val = myOpt[i].val;
|
|
|
+ if (myOpt[i].val == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (myOpt[i].has_arg == no_argument) {
|
|
|
+ shorts.push_back(static_cast<char>(myOpt[i].val));
|
|
|
+ } else if (myOpt[i].has_arg == required_argument) {
|
|
|
+ shorts.push_back(static_cast<char>(myOpt[i].val));
|
|
|
+ shorts.push_back(':');
|
|
|
+ } else {
|
|
|
+ shorts.push_back(static_cast<char>(myOpt[i].val));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+MyOpt LongOpts::GetOption(char ch, int index)
|
|
|
+{
|
|
|
+ if (ch == 0) {
|
|
|
+ return myOpt[index];
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < sizeOpt; i++) {
|
|
|
+ if (myOpt[i].val == ch) {
|
|
|
+ return myOpt[i];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return myOpt[0];
|
|
|
+}
|
|
|
+
|
|
|
+VendorBase::VendorBase()
|
|
|
+{
|
|
|
+ HTELINK_LOG_ENABLE(true);
|
|
|
+ eventBase_ = event_base_new();
|
|
|
+ if (eventBase_ == nullptr) {
|
|
|
+ HTELINK_LOG_ERR("event new failed, %s", strerror(errno));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+VendorBase::~VendorBase()
|
|
|
+{
|
|
|
+ if (eventBase_ == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ Exit(SIGINT);
|
|
|
+ event_base_free(eventBase_);
|
|
|
+}
|
|
|
+
|
|
|
+int VendorBase::Exec()
|
|
|
+{
|
|
|
+ HTELINK_LOG_INFO("register event...");
|
|
|
+ // 注册信号事件
|
|
|
+ event_add(evsignal_new(eventBase_, SIGSEGV, VendorBase::SignalHandler, this), NULL);
|
|
|
+ event_add(evsignal_new(eventBase_, SIGFPE, VendorBase::SignalHandler, this), NULL);
|
|
|
+ event_add(evsignal_new(eventBase_, SIGINT, VendorBase::SignalHandler, this), NULL);
|
|
|
+ event_add(evsignal_new(eventBase_, SIGTERM, VendorBase::SignalHandler, this), NULL);
|
|
|
+ event_add(evsignal_new(eventBase_, SIGTSTP, VendorBase::SignalHandler, this), NULL);
|
|
|
+
|
|
|
+ signal(SIGPIPE, SIG_IGN);
|
|
|
+
|
|
|
+ HTELINK_LOG_INFO("start to Run");
|
|
|
+ // struct event *timer_ev = event_new(
|
|
|
+ // eventBase_, -1, EV_PERSIST,
|
|
|
+ // [](evutil_socket_t ev, short e, void *arg) {
|
|
|
+ // VendorBase *vendorBase = static_cast<VendorBase *>(arg);
|
|
|
+ // vendorBase->Run();
|
|
|
+ // },
|
|
|
+ // this);
|
|
|
+ // event_add(timer_ev, NULL);
|
|
|
+ std::thread fn([this] {
|
|
|
+ Run();
|
|
|
+ });
|
|
|
+ fn.detach();
|
|
|
+ // 其他业务
|
|
|
+ HTELINK_LOG_INFO("start to deamon...");
|
|
|
+ return event_base_dispatch(eventBase_);
|
|
|
+}
|
|
|
+
|
|
|
+void VendorBase::Exit(int signal)
|
|
|
+{
|
|
|
+ Stop(signal);
|
|
|
+ if (eventBase_ == nullptr) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ char dumpFile[VENDOR_MAX_PATH_SIZE];
|
|
|
+ sprintf(dumpFile, "%s/event_stat_%s.txt", VENDOR_LOG_PATH.c_str(), utils::nowtostr().c_str());
|
|
|
+ FILE *fp = fopen(dumpFile, "a");
|
|
|
+ event_base_dump_events(eventBase_, fp);
|
|
|
+ fclose(fp);
|
|
|
+ event_base_loopbreak(eventBase_);
|
|
|
+}
|
|
|
+
|
|
|
+void VendorBase::SignalHandler(int fd, short event, void *arg)
|
|
|
+{
|
|
|
+ if (event != EV_SIGNAL) {
|
|
|
+ HTELINK_LOG_ERR("fd: %d, event: %d occur", fd, event);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ void *l_buffer[512];
|
|
|
+ char **l_ptrace;
|
|
|
+
|
|
|
+ int signal = fd;
|
|
|
+
|
|
|
+ VendorBase *vendorBase = static_cast<VendorBase *>(arg);
|
|
|
+ if (vendorBase) {
|
|
|
+ vendorBase->Exit(signal);
|
|
|
+ }
|
|
|
+
|
|
|
+ HTELINK_LOG_ERR("\r\n=========>>>catch signal %d <<<=========", signal);
|
|
|
+ HTELINK_LOG_ERR("Dump stack start...");
|
|
|
+
|
|
|
+ int size = backtrace(l_buffer, 512);
|
|
|
+ l_ptrace = backtrace_symbols(l_buffer, size);
|
|
|
+ if (NULL == l_ptrace) {
|
|
|
+ HTELINK_LOG_ERR("backtrace_symbols");
|
|
|
+ exit(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ HTELINK_LOG_ERR(" [%02d] %s", i, l_ptrace[i]);
|
|
|
+ }
|
|
|
+ HTELINK_LOG_ERR("Dump stack end...");
|
|
|
+ free(l_ptrace);
|
|
|
+ exit(signal);
|
|
|
+}
|
|
|
+
|
|
|
+int32_t VendorBase::ParseOptionArgs(VendorBase *vendor, int argc, char *argv[])
|
|
|
+{
|
|
|
+ int longindex = 0;
|
|
|
+ std::string shorts;
|
|
|
+ struct option longopts[vendor->GetOptSize()];
|
|
|
+ LongOpts longOpts(vendor->GetOpts(), vendor->GetOptSize());
|
|
|
+ longOpts.GetOptions(longopts, shorts);
|
|
|
+ int ch;
|
|
|
+ while ((ch = getopt_long(argc, argv, shorts.c_str(), longopts, &longindex)) != -1) {
|
|
|
+ MyOpt myOpt = longOpts.GetOption(ch, longindex);
|
|
|
+ printf("longindex :%d, opt %d(%c), name:%s , optarg :%s\n", longindex, myOpt.val, myOpt.val, myOpt.name,
|
|
|
+ optarg == nullptr ? "nullptr" : optarg);
|
|
|
+ if (strcmp(myOpt.name, "help") == 0) {
|
|
|
+ MyOpt *myOpts = vendor->GetOpts();
|
|
|
+ printf("Usage: %s [OPTION] -l URL\n\nOPTIONS:\n", vendor->Name().c_str());
|
|
|
+ for (int i = 1; i < vendor->GetOptSize(); i++) {
|
|
|
+ if (myOpts[i].val == 0) {
|
|
|
+ printf("--%s: %s\n", myOpts[i].name, myOpts[i].desc);
|
|
|
+ } else {
|
|
|
+ printf("-%c, --%s: %s\n", myOpts[i].val, myOpts[i].name, myOpts[i].desc);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (vendor->ParseCmdline(myOpt.name, optarg == nullptr ? "" : optarg) != 0) {
|
|
|
+ printf("parse failed!!!\n");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+}; // namespace vendor
|