Browse Source

optimize hmain

hewei.it 5 years ago
parent
commit
7c34c3a779
6 changed files with 113 additions and 74 deletions
  1. 6 0
      base/hthread.h
  2. 0 0
      etc/hmain_test.conf
  3. 0 4
      examples/hmain_test.cpp
  4. 24 0
      examples/httpd/httpd.cpp
  5. 53 49
      utils/hmain.cpp
  6. 30 21
      utils/hmain.h

+ 6 - 0
base/hthread.h

@@ -16,6 +16,12 @@
 #elif defined(OS_LINUX)
 #include <sys/syscall.h>
 #define hv_gettid() (long)syscall(SYS_gettid)
+#elif defined(OS_DARWIN)
+static inline long hv_gettid() {
+    uint64_t tid = 0;
+    pthread_threadid_np(NULL, &tid);
+    return tid;
+}
 #elif HAVE_PTHREAD_H
 #define hv_gettid   (long)pthread_self
 #else

+ 0 - 0
etc/test.conf → etc/hmain_test.conf


+ 0 - 4
examples/hmain_test.cpp

@@ -200,7 +200,6 @@ int main(int argc, char** argv) {
         exit(ret);
     }
 
-    /*
     printf("---------------arg------------------------------\n");
     printf("%s\n", g_main_ctx.cmdline);
     for (auto& pair : g_main_ctx.arg_kv) {
@@ -210,15 +209,12 @@ int main(int argc, char** argv) {
         printf("%s\n", item.c_str());
     }
     printf("================================================\n");
-    */
 
-    /*
     printf("---------------env------------------------------\n");
     for (auto& pair : g_main_ctx.env_kv) {
         printf("%s=%s\n", pair.first.c_str(), pair.second.c_str());
     }
     printf("================================================\n");
-    */
 
     // help
     if (get_arg("h")) {

+ 24 - 0
examples/httpd/httpd.cpp

@@ -81,6 +81,27 @@ int parse_confile(const char* confile) {
         loglevel = LOG_LEVEL_VERBOSE;
     }
     hlog_set_level(loglevel);
+    // log_filesize
+    str = ini.GetValue("log_filesize");
+    if (!str.empty()) {
+        int num = atoi(str.c_str());
+        if (num > 0) {
+            // 16 16M 16MB
+            const char* p = str.c_str() + str.size() - 1;
+            char unit;
+            if (*p >= '0' && *p <= '9') unit = 'M';
+            else if (*p == 'B')         unit = *(p-1);
+            else                        unit = *p;
+            unsigned long long filesize = num;
+            switch (unit) {
+            case 'K': filesize <<= 10; break;
+            case 'M': filesize <<= 20; break;
+            case 'G': filesize <<= 30; break;
+            default:  filesize <<= 20; break;
+            }
+            hlog_set_max_filesize(filesize);
+        }
+    }
     // log_remain_days
     str = ini.GetValue("log_remain_days");
     if (!str.empty()) {
@@ -101,6 +122,9 @@ int parse_confile(const char* confile) {
         }
     }
     g_http_server.worker_processes = LIMIT(0, worker_processes, MAXNUM_WORKER_PROCESSES);
+    // worker_threads
+    int worker_threads = ini.Get<int>("worker_threads");
+    g_http_server.worker_threads = LIMIT(0, worker_threads, 16);
 
     // port
     int port = 0;

+ 53 - 49
utils/hmain.cpp

@@ -12,11 +12,6 @@
 #endif
 
 main_ctx_t  g_main_ctx;
-int         g_worker_processes_num = 0;
-int         g_worker_threads_num = 0;
-proc_ctx_t* g_worker_processes = NULL;
-procedure_t g_worker_fn = NULL;
-void*       g_worker_userdata = NULL;
 
 int main_ctx_init(int argc, char** argv) {
     if (argc == 0 || argv == NULL) {
@@ -36,9 +31,9 @@ int main_ctx_init(int argc, char** argv) {
     }
 #endif
     //printf("program_name=%s\n", g_main_ctx.program_name);
-    char logpath[MAX_PATH] = {0};
-    snprintf(logpath, sizeof(logpath), "%s/logs", g_main_ctx.run_dir);
-    hv_mkdir(logpath);;
+    char logdir[MAX_PATH] = {0};
+    snprintf(logdir, sizeof(logdir), "%s/logs", g_main_ctx.run_dir);
+    hv_mkdir(logdir);;
     snprintf(g_main_ctx.confile, sizeof(g_main_ctx.confile), "%s/etc/%s.conf", g_main_ctx.run_dir, g_main_ctx.program_name);
     snprintf(g_main_ctx.pidfile, sizeof(g_main_ctx.pidfile), "%s/logs/%s.pid", g_main_ctx.run_dir, g_main_ctx.program_name);
     snprintf(g_main_ctx.logfile, sizeof(g_main_ctx.confile), "%s/logs/%s.log", g_main_ctx.run_dir, g_main_ctx.program_name);
@@ -117,6 +112,17 @@ int main_ctx_init(int argc, char** argv) {
     }
 #endif
 
+    // signals
+    g_main_ctx.reload_fn = NULL;
+    g_main_ctx.reload_userdata = NULL;
+
+    // master workers
+    g_main_ctx.worker_processes = 0;
+    g_main_ctx.worker_threads = 0;
+    g_main_ctx.worker_fn = 0;
+    g_main_ctx.worker_userdata = 0;
+    g_main_ctx.proc_ctxs = NULL;
+
     return 0;
 }
 
@@ -325,8 +331,6 @@ pid_t getpid_from_pidfile() {
     return readbytes <= 0 ? -1 : atoi(pid);
 }
 
-static procedure_t s_reload_fn = NULL;
-static void*       s_reload_userdata = NULL;
 #ifdef OS_UNIX
 // unix use signal
 #include <sys/wait.h>
@@ -339,49 +343,49 @@ void signal_handler(int signo) {
         hlogi("killall processes");
         signal(SIGCHLD, SIG_IGN);
         // master send SIGKILL => workers
-        for (int i = 0; i < g_worker_processes_num; ++i) {
-            if (g_worker_processes[i].pid <= 0) break;
-            kill(g_worker_processes[i].pid, SIGKILL);
-            g_worker_processes[i].pid = -1;
+        for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
+            if (g_main_ctx.proc_ctxs[i].pid <= 0) break;
+            kill(g_main_ctx.proc_ctxs[i].pid, SIGKILL);
+            g_main_ctx.proc_ctxs[i].pid = -1;
         }
         exit(0);
         break;
-    case SIGNAL_RELOAD:
-        if (s_reload_fn) {
-            s_reload_fn(s_reload_userdata);
-            if (getpid_from_pidfile() == getpid()) {
-                // master send SIGNAL_RELOAD => workers
-                for (int i = 0; i < g_worker_processes_num; ++i) {
-                    if (g_worker_processes[i].pid <= 0) break;
-                    kill(g_worker_processes[i].pid, SIGNAL_RELOAD);
-                }
-            }
-        }
-        break;
     case SIGCHLD:
     {
         pid_t pid = 0;
         int status = 0;
         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
             hlogw("proc stop/waiting, pid=%d status=%d", pid, status);
-            for (int i = 0; i < g_worker_processes_num; ++i) {
-                if (g_worker_processes[i].pid == pid) {
-                    g_worker_processes[i].pid = -1;
-                    hproc_spawn(&g_worker_processes[i]);
+            for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
+                if (g_main_ctx.proc_ctxs[i].pid == pid) {
+                    g_main_ctx.proc_ctxs[i].pid = -1;
+                    hproc_spawn(&g_main_ctx.proc_ctxs[i]);
                     break;
                 }
             }
         }
     }
         break;
+    case SIGNAL_RELOAD:
+        if (g_main_ctx.reload_fn) {
+            g_main_ctx.reload_fn(g_main_ctx.reload_userdata);
+            if (getpid_from_pidfile() == getpid()) {
+                // master send SIGNAL_RELOAD => workers
+                for (int i = 0; i < g_main_ctx.worker_processes; ++i) {
+                    if (g_main_ctx.proc_ctxs[i].pid <= 0) break;
+                    kill(g_main_ctx.proc_ctxs[i].pid, SIGNAL_RELOAD);
+                }
+            }
+        }
+        break;
     default:
         break;
     }
 }
 
 int signal_init(procedure_t reload_fn, void* reload_userdata) {
-    s_reload_fn = reload_fn;
-    s_reload_userdata = reload_userdata;
+    g_main_ctx.reload_fn = reload_fn;
+    g_main_ctx.reload_userdata = reload_userdata;
 
     signal(SIGINT, signal_handler);
     signal(SIGCHLD, signal_handler);
@@ -414,8 +418,8 @@ void WINAPI on_timer(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1,
     ret = WaitForSingleObject(s_hEventReload, 0);
     if (ret == WAIT_OBJECT_0) {
         hlogi("pid=%d recv event [RELOAD]", getpid());
-        if (s_reload_fn) {
-            s_reload_fn(s_reload_userdata);
+        if (g_main_ctx.reload_fn) {
+            g_main_ctx.reload_fn(g_main_ctx.reload_userdata);
         }
     }
 }
@@ -428,8 +432,8 @@ void signal_cleanup() {
 }
 
 int signal_init(procedure_t reload_fn, void* reload_userdata) {
-    s_reload_fn = reload_fn;
-    s_reload_userdata = reload_userdata;
+    g_main_ctx.reload_fn = reload_fn;
+    g_main_ctx.reload_userdata = reload_userdata;
 
     char eventname[MAX_PATH] = {0};
     //snprintf(eventname, sizeof(eventname), "%s_term_event", g_main_ctx.program_name);
@@ -507,8 +511,8 @@ void signal_handle(const char* signal) {
 // master-workers processes
 static HTHREAD_ROUTINE(worker_thread) {
     hlogi("worker_thread pid=%ld tid=%ld", hv_getpid(), hv_gettid());
-    if (g_worker_fn) {
-        g_worker_fn(g_worker_userdata);
+    if (g_main_ctx.worker_fn) {
+        g_main_ctx.worker_fn(g_main_ctx.worker_userdata);
     }
     return 0;
 }
@@ -523,7 +527,7 @@ static void worker_init(void* userdata) {
 }
 
 static void worker_proc(void* userdata) {
-    for (int i = 1; i < g_worker_threads_num; ++i) {
+    for (int i = 1; i < g_main_ctx.worker_threads; ++i) {
         hthread_create(worker_thread, NULL);
     }
     worker_thread(NULL);
@@ -541,9 +545,9 @@ int master_workers_run(procedure_t worker_fn, void* worker_userdata,
 #endif
     if (worker_threads == 0) worker_threads = 1;
 
-    g_worker_threads_num = worker_threads;
-    g_worker_fn = worker_fn;
-    g_worker_userdata = worker_userdata;
+    g_main_ctx.worker_threads = worker_threads;
+    g_main_ctx.worker_fn = worker_fn;
+    g_main_ctx.worker_userdata = worker_userdata;
 
     if (worker_processes == 0) {
         // single process
@@ -560,7 +564,7 @@ int master_workers_run(procedure_t worker_fn, void* worker_userdata,
         }
     }
     else {
-        if (g_worker_processes_num != 0) {
+        if (g_main_ctx.worker_processes != 0) {
             return ERR_OVER_LIMIT;
         }
         // master-workers processes
@@ -570,12 +574,12 @@ int master_workers_run(procedure_t worker_fn, void* worker_userdata,
         setproctitle(proctitle);
         signal(SIGNAL_RELOAD, signal_handler);
 #endif
-        g_worker_processes_num = worker_processes;
-        int bytes = g_worker_processes_num * sizeof(proc_ctx_t);
-        g_worker_processes = (proc_ctx_t*)malloc(bytes);
-        memset(g_worker_processes, 0, bytes);
-        proc_ctx_t* ctx = g_worker_processes;
-        for (int i = 0; i < g_worker_processes_num; ++i, ++ctx) {
+        g_main_ctx.worker_processes = worker_processes;
+        int bytes = g_main_ctx.worker_processes * sizeof(proc_ctx_t);
+        g_main_ctx.proc_ctxs = (proc_ctx_t*)malloc(bytes);
+        memset(g_main_ctx.proc_ctxs, 0, bytes);
+        proc_ctx_t* ctx = g_main_ctx.proc_ctxs;
+        for (int i = 0; i < g_main_ctx.worker_processes; ++i, ++ctx) {
             ctx->init = worker_init;
             ctx->proc = worker_proc;
             hproc_spawn(ctx);

+ 30 - 21
utils/hmain.h

@@ -13,6 +13,7 @@
 typedef struct main_ctx_s {
     char    run_dir[MAX_PATH];
     char    program_name[MAX_PATH];
+
     char    confile[MAX_PATH]; // default etc/${program}.conf
     char    pidfile[MAX_PATH]; // default logs/${program}.pid
     char    logfile[MAX_PATH]; // default logs/${program}.log
@@ -20,20 +21,31 @@ typedef struct main_ctx_s {
     pid_t   pid;    // getpid
     pid_t   oldpid; // getpid_from_pidfile
 
+    // arg
     int     argc;
     int     arg_len;
     char**  os_argv;
     char**  save_argv;
     char*   cmdline;
+    keyval_t    arg_kv;
+    StringList  arg_list;
 
+    // env
     int     envc;
     int     env_len;
     char**  os_envp;
     char**  save_envp;
-
-    keyval_t    arg_kv;
-    StringList  arg_list;
     keyval_t    env_kv;
+
+    // signals
+    procedure_t reload_fn;
+    void*       reload_userdata;
+    // master workers model
+    int             worker_processes;
+    int             worker_threads;
+    procedure_t     worker_fn;
+    void*           worker_userdata;
+    proc_ctx_t*     proc_ctxs;
 } main_ctx_t;
 
 // arg_type
@@ -51,29 +63,29 @@ typedef struct option_s {
     int         arg_type;
 } option_t;
 
-int main_ctx_init(int argc, char** argv);
+HV_EXPORT int main_ctx_init(int argc, char** argv);
 // ls -a -l
 // ls -al
 // watch -n 10 ls
 // watch -n10 ls
-int parse_opt(int argc, char** argv, const char* opt);
+HV_EXPORT int parse_opt(int argc, char** argv, const char* opt);
 // gcc -g -Wall -O3 -std=cpp main.c
-int parse_opt_long(int argc, char** argv, const option_t* long_options, int size);
-const char* get_arg(const char* key);
-const char* get_env(const char* key);
+HV_EXPORT int parse_opt_long(int argc, char** argv, const option_t* long_options, int size);
+HV_EXPORT const char* get_arg(const char* key);
+HV_EXPORT const char* get_env(const char* key);
 
 #ifdef OS_UNIX
-void setproctitle(const char* title);
+HV_EXPORT void setproctitle(const char* title);
 #endif
 
 // pidfile
-int      create_pidfile();
-void     delete_pidfile();
-pid_t    getpid_from_pidfile();
+HV_EXPORT int   create_pidfile();
+HV_EXPORT void  delete_pidfile();
+HV_EXPORT pid_t getpid_from_pidfile();
 
 // signal=[start,stop,restart,status,reload]
-int signal_init(procedure_t reload_fn = NULL, void* reload_userdata = NULL);
-void signal_handle(const char* signal);
+HV_EXPORT int  signal_init(procedure_t reload_fn = NULL, void* reload_userdata = NULL);
+HV_EXPORT void signal_handle(const char* signal);
 #ifdef OS_UNIX
 // we use SIGTERM to quit process, SIGUSR1 to reload confile
 #define SIGNAL_TERMINATE    SIGTERM
@@ -84,15 +96,12 @@ void signal_handler(int signo);
 // global var
 #define DEFAULT_WORKER_PROCESSES    4
 #define MAXNUM_WORKER_PROCESSES     1024
-extern main_ctx_t   g_main_ctx;
-extern int          g_worker_processes_num;
-extern int          g_worker_threads_num;
-extern proc_ctx_t*  g_worker_processes;
-extern procedure_t  g_worker_fn;
-extern void*        g_worker_userdata;
+HV_EXPORT extern main_ctx_t   g_main_ctx;
 
 // master-workers processes
-int master_workers_run(procedure_t worker_fn, void* worker_userdata,
+HV_EXPORT int master_workers_run(
+        procedure_t worker_fn,
+        void* worker_userdata = NULL,
         int worker_processes = DEFAULT_WORKER_PROCESSES,
         int worker_threads = 0,
         bool wait = true);