mirror of
https://github.com/HardySimpson/zlog
synced 2025-03-28 21:13:21 +00:00
216 lines
5.3 KiB
C
216 lines
5.3 KiB
C
/* Copyright (c) Hardy Simpson
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <pthread.h>
|
|
#include <signal.h>
|
|
#include "zlog.h"
|
|
|
|
#define CONFIG "test_multithread.conf"
|
|
#define NB_THREADS 200
|
|
#define THREAD_LOOP_DELAY 10000 /* 0.01" */
|
|
#define RELOAD_DELAY 10
|
|
|
|
enum {
|
|
ZLOG_LEVEL_TRACE = 10,
|
|
ZLOG_LEVEL_SECURITY = 150,
|
|
/* must equals conf file setting */
|
|
};
|
|
|
|
#define zlog_trace(cat, format, args...) \
|
|
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
|
|
ZLOG_LEVEL_TRACE, format, ##args)
|
|
|
|
#define zlog_security(cat, format, args...) \
|
|
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
|
|
ZLOG_LEVEL_SECURITY, format, ##args)
|
|
|
|
|
|
struct thread_info { /* Used as argument to thread_start() */
|
|
pthread_t thread_id; /* ID returned by pthread_create() */
|
|
int thread_num; /* Application-defined thread # */
|
|
zlog_category_t *zc; /* The logger category struc address; (All threads will use the same category, so he same address) */
|
|
long long int loop; /* Counter incremented to check the thread's health */
|
|
};
|
|
|
|
struct thread_info *tinfo;
|
|
|
|
|
|
void intercept(int sig)
|
|
{
|
|
int i;
|
|
|
|
printf("\nIntercept signal %d\n\n", sig);
|
|
|
|
signal (sig, SIG_DFL);
|
|
raise (sig);
|
|
|
|
printf("You can import datas below in a spreadsheat and check if any thread stopped increment the Loop counter during the test.\n\n");
|
|
printf("Thread;Loop\n");
|
|
for (i=0; i<NB_THREADS; i++)
|
|
{
|
|
printf("%d;%lld\n", tinfo[i].thread_num, tinfo[i].loop);
|
|
}
|
|
|
|
free(tinfo);
|
|
|
|
zlog_fini();
|
|
}
|
|
|
|
void *myThread(void *arg)
|
|
{
|
|
struct thread_info *tinfo = arg;
|
|
|
|
tinfo->zc = zlog_get_category("thrd");
|
|
if (!tinfo->zc) {
|
|
printf("get thrd %d cat fail\n", tinfo->thread_num);
|
|
}
|
|
else
|
|
{
|
|
while(1)
|
|
{
|
|
usleep(THREAD_LOOP_DELAY);
|
|
zlog_info(tinfo->zc, "%d;%lld", tinfo->thread_num, tinfo->loop++);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int main(int argc, char** argv)
|
|
{
|
|
int rc;
|
|
zlog_category_t *zc;
|
|
zlog_category_t *mc;
|
|
zlog_category_t *hl;
|
|
int i = 0;
|
|
struct stat stat_0, stat_1;
|
|
|
|
/* Create the logging directory if not yet ceated */
|
|
mkdir("./test_multithread-logs", 0777);
|
|
|
|
if (stat(CONFIG, &stat_0))
|
|
{
|
|
printf("Configuration file not found\n");
|
|
return -1;
|
|
}
|
|
|
|
rc = zlog_init(CONFIG);
|
|
if (rc) {
|
|
printf("main init failed\n");
|
|
return -2;
|
|
}
|
|
|
|
zc = zlog_get_category("main");
|
|
if (!zc) {
|
|
printf("main get cat fail\n");
|
|
zlog_fini();
|
|
return -3;
|
|
}
|
|
|
|
mc = zlog_get_category("clsn");
|
|
if (!mc) {
|
|
printf("clsn get cat fail\n");
|
|
zlog_fini();
|
|
return -3;
|
|
}
|
|
|
|
hl = zlog_get_category("high");
|
|
if (!hl) {
|
|
printf("high get cat fail\n");
|
|
zlog_fini();
|
|
return -3;
|
|
}
|
|
|
|
/* Interrupt (ANSI). <Ctrl-C> */
|
|
if (signal(SIGINT, intercept) == SIG_IGN )
|
|
{
|
|
zlog_fatal(zc, "Can't caught the signal SIGINT, Interrupt (ANSI)");
|
|
signal(SIGINT, SIG_IGN );
|
|
return -4;
|
|
}
|
|
|
|
// start threads
|
|
tinfo = calloc(NB_THREADS, sizeof(struct thread_info));
|
|
for (i=0; i<NB_THREADS; i++)
|
|
{
|
|
tinfo[i].thread_num = i + 1;
|
|
tinfo[i].loop = 0;
|
|
tinfo[i].zc = zc;
|
|
if(pthread_create(&tinfo[i].thread_id, NULL, myThread, &tinfo[i]) != 0)
|
|
{
|
|
zlog_fatal(zc, "Unable to start thread %d", i);
|
|
zlog_fini();
|
|
return(-5);
|
|
}
|
|
}
|
|
|
|
/* Wait and log thread informations */
|
|
sleep(1);
|
|
for (i=0; i<NB_THREADS; i++)
|
|
{
|
|
zlog_info(zc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, tinfo[i].zc);
|
|
zlog_fatal(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_error(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_warn(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_notice(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_info(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_trace(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_debug(mc, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, mc);
|
|
zlog_security(hl, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, hl);
|
|
zlog_warn(hl, "Thread [%d], zlog_category:@%p", tinfo[i].thread_num, hl);
|
|
}
|
|
|
|
/* Log main loop status */
|
|
i=0;
|
|
while(1)
|
|
{
|
|
int reload;
|
|
|
|
sleep(1);
|
|
i++;
|
|
zlog_info(zc, "Running time: %02d:%02d:%02d", i/3600, (i/60)%60, i%60);
|
|
|
|
/* Check configuration file update */
|
|
stat(CONFIG, &stat_1);
|
|
|
|
/* Is configuration file modified */
|
|
reload = (stat_0.st_mtime != stat_1.st_mtime);
|
|
|
|
/* Or do we want to reload periodicaly the configuration file */
|
|
if ( ! reload)
|
|
if ( RELOAD_DELAY > 0)
|
|
reload = (i % RELOAD_DELAY == 0);
|
|
|
|
if (reload)
|
|
{
|
|
zlog_info(zc, "Will reload configuration...");
|
|
rc = zlog_reload(CONFIG);
|
|
if (rc) {
|
|
printf("main init failed\n");
|
|
return -6;
|
|
}
|
|
zlog_info(zc, "Configuration reloaded :)");
|
|
stat(CONFIG, &stat_0);
|
|
}
|
|
}
|
|
|
|
exit(EXIT_SUCCESS);
|
|
}
|