用cmake来组织

main
wangchunlin 3 years ago
parent f8439d8dc9
commit 5676995840

@ -0,0 +1,125 @@
cmake_minimum_required (VERSION 3.10)
#
option (USE_CROSS
"Use CROSSCOMPILE" OFF)
if (USE_CROSS)
# targetARMLinux"Linux",Windows"Windows",OS"Generic",CMAKE_SYSTEM_NAMECMakeCMAKE_CROSSCOMPILINGTRUE.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1.0)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
# TOOLSCHAIN_PATH bin lib include aarch64-...
set(TOOLSCHAIN_PATH "/home/wcl/emd_dev/n1/openwrt-toolchain-armvirt-64_gcc-8.4.0_musl.Linux-x86_64/toolchain-aarch64_cortex-a53_gcc-8.4.0_musl/")
set(TOOLCHAIN_HOST "${TOOLSCHAIN_PATH}/bin/aarch64-openwrt-linux")
# CCMakelinker,binutilsarm-elfCMake
set(CMAKE_C_COMPILER ${TOOLCHAIN_HOST}-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_HOST}-g++)
SET(CMAKE_BUILD_TYPE "Release")
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g2 -ggdb")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
# /opt/arm/,Find_xxx.cmake/usr/lib,/lib/usr/lib/lib/opt/armCMAKE_FIND_ROOT_PATH,set(CMAKE_FIND_ROOT_PATH /opt/arm /opt/inst)
set(CMAKE_FIND_ROOT_PATH ${TOOLSCHAIN_PATH})
# FIND_PROGRAM(),NEVER,ONLY,BOTH,CMAKE_FIND_ROOT_PATH宿NEVER
SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# FIND_LIBRARY()ONLY.
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
# FIND_PATH()FIND_FILE()ONLY,FINDoptionNO_CMAKE_FIND_ROOT_PATH,ONLY_CMAKE_FIND_ROOT_PATH,BOTH_CMAKE_FIND_ROOT_PATH
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# Qtqmakeqmakeqmake
# SET(QT_QMAKE_EXECUTABLE /opt/qt-embedded/qmake)
# boostboostARMboostincludelib
# SET(BOOST_ROOT /opt/boost_arm)
# cmake
endif (USE_CROSS)
#
project (dehazing)
# The version number.
set (DEHAZE_VERSION_MAJOR 5)
set (DEHAZE_VERSION_MINOR 0)
# configure a header file to pass some of the CMake settings
# to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/VersionConfig.h.in"
"${PROJECT_SOURCE_DIR}/VersionConfig.h"
)
#
set(CMAKE_INSTALL_PREFIX "${PROJECT_BINARY_DIR}/install")
#
set(INSTALL_LIB_DIR $ORIGIN "../lib" "./lib") # lib
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
set(CMAKE_INSTALL_RPATH "${INSTALL_LIB_DIR}")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE) #
# Try to find OpenCV
find_package(OpenCV 3.4)
if (OpenCV_FOUND)
# If the package has been found, several variables will
# be set, you can find the full list with descriptions
# in the OpenCVConfig.cmake file.
# Print some message showing some of them
message(STATUS "OpenCV library status:")
message(STATUS " version: ${OpenCV_VERSION}")
message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")
else ()
message(FATAL_ERROR "Could not locate OpenCV")
endif()
# zlog
option (USE_ZLOG
"Use tutorial provided math implementation" ON)
if (USE_ZLOG)
add_subdirectory (zlog_manager)
set (EXTRA_INCS ${EXTRA_INCS} ${ZLOG_INCLUDE_DIR})
message (">>> value = ${EXTRA_INCS}")
set (EXTRA_LIBS ${EXTRA_LIBS} zlog_manager)
message (">>> value = ${EXTRA_LIBS}")
endif (USE_ZLOG)
#
option (USE_DEHAZE01
"Use No. 1 alg" ON)
if (USE_DEHAZE01)
add_subdirectory(dehazing01)
set (EXTRA_INCS ${EXTRA_INCS} ${DEHAZE01_INCLUDE_DIR})
message (">>> value = ${EXTRA_INCS}")
set (EXTRA_LIBS ${EXTRA_LIBS} LIB_DEHAZE01)
message (">>> value = ${EXTRA_LIBS}")
endif (USE_DEHAZE01)
#
include_directories("${PROJECT_SOURCE_DIR}")
include_directories("${PROJECT_SOURCE_DIR}/zlog_manager/")
include_directories("${EXTRA_INCS}")
# 使add_subdirectorylink_directories
add_executable (dehazing main.cpp)
target_link_libraries (dehazing ${EXTRA_LIBS} ${OpenCV_LIBS})
# cmake
install (TARGETS dehazing DESTINATION bin)
install (FILES "VersionConfig.h" DESTINATION include)
#
# enable_testing()
# #define a macro to simplify adding tests, then use it
# macro (do_test arg result)
# add_test (TutorialComp${arg} Tutorial ${arg})
# set_tests_properties (TutorialComp${arg}
# PROPERTIES PASS_REGULAR_EXPRESSION ${result})
# endmacro (do_test)
# # do a bunch of result based tests
# do_test (25 "25 is 5")
# do_test (-25 "-25 is 0")

@ -0,0 +1,5 @@
// the configured options and settings for Tutorial
#define DEHAZE_VERSION_MAJOR 5
#define DEHAZE_VERSION_MINOR 0
// 必须加入-DUSE_MYMATH才能在.h文件中生成对应宏或者执行两次cmake也可以生成此宏
#define USE_DEHAZE01

@ -0,0 +1,5 @@
// the configured options and settings for Tutorial
#define DEHAZE_VERSION_MAJOR @DEHAZE_VERSION_MAJOR@
#define DEHAZE_VERSION_MINOR @DEHAZE_VERSION_MINOR@
// 必须加入-DUSE_MYMATH才能在.h文件中生成对应宏或者执行两次cmake也可以生成此宏
#cmakedefine USE_DEHAZE01

@ -0,0 +1,13 @@
include_directories("${OpenCV_INCLUDE_DIRS}")
set(DEHAZE01_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
set(DEHAZE01_INCLUDE_DIR ${DEHAZE01_INCLUDE_DIR} PARENT_SCOPE)
add_library( # Sets the name of the library.
LIB_DEHAZE01
SHARED
dehazing.cpp
Transmission.cpp
guidedfilter.cpp
functions.cpp
)
install (TARGETS LIB_DEHAZE01 DESTINATION lib)
install (FILES dehazing.h DESTINATION include)

@ -12,12 +12,25 @@
Author: Jin-Hwan, Kim. Author: Jin-Hwan, Kim.
*/ */
#include "dehazing.h"
#include <time.h> #include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "VersionConfig.h"
#include "log_manager.h"
#ifdef USE_DEHAZE01
#include "dehazing.h"
#endif
using namespace cv; using namespace cv;
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
fprintf(stdout,"%s Version %d.%d\n", argv[0],
DEHAZE_VERSION_MAJOR,
DEHAZE_VERSION_MINOR);
fprintf(stdout,"Usage: %s number\n",argv[0]);
log_info("Start");
CvCapture* cvSequence = cvCaptureFromFile(argv[1]); CvCapture* cvSequence = cvCaptureFromFile(argv[1]);
int nWid = (int)cvGetCaptureProperty(cvSequence,CV_CAP_PROP_FRAME_WIDTH); //atoi(argv[3]); int nWid = (int)cvGetCaptureProperty(cvSequence,CV_CAP_PROP_FRAME_WIDTH); //atoi(argv[3]);
@ -50,6 +63,7 @@ int main(int argc, char** argv)
cvReleaseCapture(&cvSequence); cvReleaseCapture(&cvSequence);
cvReleaseImage(&imOutput); cvReleaseImage(&imOutput);
log_info("End");
return 0; return 0;
} }

BIN
out

Binary file not shown.

@ -0,0 +1,32 @@
# zlogmakefile
# zlog
set(ZLOG_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/zlog)
set(ZLOG_LIBRARY ${ZLOG_SOURCE_DIR}/src/libzlog.a)
add_custom_target(build_zlog ALL
#
COMMAND ${CMAKE_MAKE_PROGRAM} -e CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER}
WORKING_DIRECTORY ${ZLOG_SOURCE_DIR}
COMMENT "Original zlog makefile target")
add_library(zlog STATIC IMPORTED)
set_property(TARGET zlog APPEND PROPERTY IMPORTED_CONFIGURATIONS NOCONFIG)
set_target_properties(zlog PROPERTIES IMPORTED_LOCATION_NOCONFIG "${ZLOG_LIBRARY}")
add_dependencies(zlog build_zlog)
# zlog
# cmake
set(ZLOG_INCLUDE_DIR "${ZLOG_SOURCE_DIR}/src/")
set(ZLOG_INCLUDE_DIR ${ZLOG_INCLUDE_DIR} PARENT_SCOPE)
# cmake
include_directories (${ZLOG_INCLUDE_DIR})
add_library(zlog_manager SHARED log_manager.cxx)
set(EXTRA_LIBS
pthread
#"-Wl,--whole-archive" #sozlogmanager
zlog
#"-Wl,--no-whole-archive" #so
)
target_link_libraries(zlog_manager
${EXTRA_LIBS}
)
install (TARGETS zlog_manager DESTINATION lib)
install (FILES log_manager.h DESTINATION include)

@ -0,0 +1,145 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include "log_manager.h"
/*********************************************************/
/*常量****************************************************/
const char* ConfigText =
"[global]\n"
"strict init = true\n"
"buffer min = 1024\n"
"buffer max = 2048\n"
"file perms = 600\n"
"[formats]\n"
"simple = \"%d.%-8.8us %-5V [%-8.8p.%-8.8t %F %L] %m%n\"\n"
"[rules]\n"
"my_cat.* >stderr;\n"
"my_cat.INFO \"info.txt\",10kb * 3 ~ \"info.txt.#r\";simple\n";
//优先级从低到高 debug info notice warn error fatal debug大于等于debug的优先级都能给通过debug输出。
/*********************************************************/
static zlog_category_t * logHandler_m = NULL;
static int DetectConfigFile(const char *File);
/*****************************************************************************
: LogMgr.LogMgr
:
:
:
:
:
1. : 20121219
: fensjoy
:
*****************************************************************************/
zlog_category_t * Init_zlog()
{
DetectConfigFile(LOG_CONFIG);
zlog_init(LOG_CONFIG);
logHandler_m = zlog_get_category(LOG_CAT);
if (!logHandler_m)
{
printf("%s in Init_zlog, get cat fail! line = %d\n",PRO_NAME, __LINE__);
zlog_fini();
remove(LOG_CONFIG);
exit(-1);
}
return logHandler_m;
};
/*****************************************************************************
: DetectConfigFile
:
: const char *File
:
: static
:
1. : 20121220
: fensjoy
:
*****************************************************************************/
static int DetectConfigFile(const char *File)
{
FILE *fp = NULL;
int iRet = 0;
DIR *log_p = NULL;
char *cmd_buf = NULL;
/*判断日志文件保存目录是否存在,不存在则创建*/
log_p = opendir(LOG_PATH);
if ( log_p == NULL )
{
printf("%s in DetectConfigFile, the log dir is not exist, now creat: %s!\n", PRO_NAME,LOG_PATH);
cmd_buf = new char[64];
printf("%s in DetectConfigFile, the log dir is not exist, now creat!\n", PRO_NAME);
snprintf(cmd_buf, 64, "mkdir -p %s &", LOG_PATH);
iRet = system(cmd_buf);
delete [] cmd_buf;
}
else
{
closedir(log_p);
}
if ( access(File, F_OK) != 0 )
{
printf("%s log config file not exist,now creat!\n", PRO_NAME);
fp = fopen(File, "w+");
if(fp == NULL)
{
perror("#[db]: in DetectConfigFile, fopen config file error!");
return -1;
}
iRet = fwrite(ConfigText, 1, strlen(ConfigText), fp);
if ( iRet < 0 )
{
perror("#[para]: in DetectConfigFile, fwrite error!");
fclose(fp);
return -1;
}
fclose(fp);
}
return 0;
}
/*****************************************************************************
: getZlogHandler
: zlog
:
:
: zlog_category_t
:
1. : 2014124
: fensjoy
:
*****************************************************************************/
zlog_category_t * getZlogHandler()
{
if ( NULL == logHandler_m )
{
logHandler_m = Init_zlog();
}
return logHandler_m;
}

@ -0,0 +1,35 @@
/******************************************************************************
(C), 2001-2014,
******************************************************************************
: log_manger.h
: 稿
: fensjoy
: 201365
:
: log_manger.cpp
:
:
1. : 201365
: fensjoy
:
******************************************************************************/
#ifndef __LOG_MANGER_H__
#define ___LOG_MANGER_H__
#include <iostream>
#include "zlog.h"
#define PRO_NAME "#[db]: "
#define LOG_CONFIG "zlog.conf"
#define LOG_PATH "./"
#define LOG_CAT "my_cat" //注意这里要与配置文件中保持一致,否则无法输出
//extern zlog_category_t * logHandler_m;
zlog_category_t * Init_zlog();
zlog_category_t * getZlogHandler();
zlog_category_t *log_c = Init_zlog();
#define log_fatal(arg...) zlog_fatal(log_c,##arg)
#define log_notice(arg...) zlog_notice(log_c,##arg)
#define log_info(arg...) zlog_info(log_c,##arg)
#define log_debug(arg...) zlog_debug(log_c,##arg)
#define log_warn(arg...) zlog_warn(log_c,##arg)
#define log_error(arg...) zlog_error(log_c,##arg)
#endif /* __LOG_MANGER_H__ */

@ -0,0 +1,56 @@
.*
!.gitignore
*.o
*.lo
*.la
*.gcda
*.gcno
aclocal.m4
autom4te.cache
build
compile
config.guess
config.h
config.h.in
config.h.in~
config.log
config.status
config.sub
configure
depcomp
.deps
install-sh
.libs
libtool
libzlog.so*
libzlog.a*
ltmain.sh
Makefile
Makefile.in
missing
stamp-h1
tags
TAGS
zlog-chk-conf
zlog-*.tar.gz
zlog.pc
callgrind*
err.log
test_*
!test_*.c
!test_*.conf
!test_*.h
doc/*.lyx~
doc/*.pdf
doc/obj.think
doc/zlog.3
doc/zlogtest.xls
doc/*.haux
doc/*.html
doc/*.htoc
doc/*.tex
test/press*
test/*.png
release.h
*.dylib

@ -0,0 +1,502 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

@ -0,0 +1,117 @@
--- 1.2.12 ---
[o] bugfix for avoid segmentation fault if call zlog_init() many times
[o] static file rule to emulate python's WatchedFileHandler mode when used with external log rotation
--- 1.2.10 ---
[o] bugfix, LGPL v3 -> LGPL v2.1
--- 1.2.8 ---
[o] gcc __attribute__宏用于检查zlog的format输出格式
[o] 支持配置文件行中带#注释
--- 1.2.5 ---
[o] 保证在单个线程退出的时候自动删除thread, 用atexit来注册函数解决主线程退出的问题
[o] 缓存多个时间,保证所有的%d在strftime的时候都能每秒缓存达到和原先%D一样的速度
[o] 鉴于上面那点,去掉%D的使用虽然库还支持但文档和实例代码都用%d
[o] 修复makefile静态链接zlog-chk-conf
--- 1.2.4 ---
[o] 不再维持thread_list链表每次写日志时判断配置有无更新来刷新每线程的缓存大小
--- 1.2.0 ---
[o] rotate和zip的方案
[o] 把一部分static变量化为全局变量减少接口参数
[o] fstat64
[o] pipe, cronolog
[o] record忽略第二参数
[o] __VA_ARGS__的跨平台
[o] 增加git/版本在代码中的标志(redis)
[o] 去除auto tools的使用自行makefile[redis]
[o] 宏都小写化
[o] const
[x] 每线程内置rule-> file fd write time
[x] 用时间作为判断重载配置reload conf period而不是次数需要每次取时间计算暂不考虑
[x] zlog_set_conf("section", "command");
[x] format,spec,level采用直接数组的方式重写性能提高不大
[x] 增加manpage, df, 案例
--- 1.1.3 ---
[o] zlog_record动态一点
--- 1.1.2 ---
[o] 修正rule.c, path_buf封顶
--- 1.1.1 ---
[o] 修正rule.c, 不使用FILE*, 避免日志交错
--- 1.1.0 ---
[x] spec改为switch循环, 如果可能的话rule也照样--发现switch的效率不如函数指针
[x] 把__LINE__ 变成string--需要改接口
[o] 建立bit位来判断,无锁判断
[o] 寻找快速的方法把us, srcline变成字符串
[o] 在一开始就判断是否需要输出,
[o] 使用pthread_key_t线程私有变量来存储zlog_thread_t仅有1%不到的提高
[o] 增加%D缓存strftime的结果
[o] 缓存pid, tid的字符串形式
[o] 去掉rc的使用[redis]
[o] 对ZLOG_FMT和ZLOG_HEX清算,部分成功
--- 1.0.7 ---
[x] 自己实现部分的strftime进一步提高效率--替换后发现vsnprintf消耗增加未能超越原有strftime的效率
[o] %t显示为16进制
[o] 零碎的性能优化10%把
--- 1.0.6 ---
[o] 每秒取一次localtime_r加速1倍以上
--- 1.0.5 ---
[o] 修复1.0.4的问题reopen文件时用读写锁保护
--- 1.0.4 ---
[o] 测试多线程的效率
[o] 缓存静态文件的FILE*和fd优化加速3倍
--- 1.0.3 ---
[o] 基于日志笔数自动刷新配置
[o] 基于日志笔数自动做sync到硬盘操作
--- 1.0.2 ---
[o] 增加同步写入到硬盘选项,打开后极为费时
--- 1.0.1 ---
[o] 采用配置文件作为锁文件
--- 1.0.0 ---
[o] 改变配置文件的布局,去掉@ &这种符号,改用[global],[format]这样的形式来
[o] 把reload改成原子性的失败用旧的
[o] 优化spec_gen_msg部分, spec内采用自己写的buf_append对齐来代替buf_sprintf
[o] 引入__func__
[o] 文件的权限设置
[o] 输出函数自定义
--- 0.9 ---
[o] 采用更加面向对象的方法来写
[o] 使用arraylist来代替linklist为内部数据结构
[o] 改进配置文件的格式
[o] 打造线程安全的日志函数库
[o] 解决微秒毫秒在配置中的表示
[o] 把event并到thread内避免开内存
[o] 增加init读取配置文件的api
[o] default] format的解析初始化全无的时候的输出zlog_chk_conf的编写
[o] 把category独立出来
[o] 增加update接口
[o] buf的大小无法通过zlog_init动态的改变可以zlog_update重建所有缓存解决呵呵
[o] 调整文件创建权限采用类似fopen的办法为0666&(~umask)
[o] syslog输出搞定但发现syslog暴慢
[o] 转档的模式,是否需要轮询等,解决为传统模式
[o] 增加zlog_profile接口诊断配置内存
[o] 增加MDC,可配置的增加字段
[o] 测试buf被重写的时候是否会导致后面的\0没加
[o] xlog要改名为zlog....
[o] 取一次ZLOG_ERROR_LOG和ZLOG_DEBUG_LOG避免多次getenv
[o] zc_assert一般关闭调试打开
[o] 增加!.*, 匹配未被匹配的分类
[o] priority->level
[o] level自定义
[o] rule syslog open
[o] default format移到全局配置
[o] reset level, 用arraylist来做试试看
[o] ylog, 更简单的接口, 改名为dzlog的一堆接口来解决
[o] zlog-gen-conf
[o] rotate控制个数
--- 废弃想法 ---
[x] 使用writev来写日志提高效率达到一次形成多次输出的目的, writev内部也是开buffermemcpy
[x] 尝试信号量的方法来打成线程安全的转档互斥问题
[x] zlog.h变长参数宏的问题参考glib的log解决
[x] rule的dynamic] file可以从format获取
[x] 修改arraylist的读取长度循环等
[x] 运行期间指定是否采用线程
[x] buf_append 优化——为了安全,不优化这个
[x] 用某种自动编译器以及文档生成器
[x] 输出到管道,有名管道和文件一样
[x] 打印堆栈。。可能需要语言支持
[x] zlog-input -c category -p priority -f conf
[x] 采用精细的reo en方法来建立用fo en来智能判断需不需要重开文件,操作系统本身已经做得够好,无须做

@ -0,0 +1,121 @@
0. What is zlog?
-------------
zlog is a reliable, high-performance, thread safe, flexible, clear-model, pure C logging library.
Actually, in the C world there was NO good logging library for applications like logback in java or log4cxx in c++. Using printf can work, but can not be redirected or reformatted easily. syslog is slow and is designed for system use.
So I wrote zlog.
It is faster, safer and more powerful than log4c. So it can be widely used.
1. Install
-------------
Downloads: https://github.com/HardySimpson/zlog/releases
$ tar -zxvf zlog-latest-stable.tar.gz
$ cd zlog-latest-stable/
$ make
$ sudo make install
or
$ make PREFIX=/usr/local/
$ sudo make PREFIX=/usr/local/ install
PREFIX indicates the installation destination for zlog. After installation, refresh your dynamic linker to make sure your program can find zlog library.
$ sudo vi /etc/ld.so.conf
/usr/local/lib
$ sudo ldconfig
Before running a real program, make sure libzlog.so is in the directory where the system's dynamic lib loader can find it. The command metioned above are for linux. Other systems will need a similar set of actions.
2. Introduce configure file
-------------
There are 3 important concepts in zlog: categories, formats and rules.
Categories specify different kinds of log entries. In the zlog source code, category is a (zlog_cateogory_t *) variable. In your program, different categories for the log entries will distinguish them from each other.
Formats describe log patterns, such as: with or without time stamp, source file, source line.
Rules consist of category, level, output file (or other channel) and format. In brief, if the category string in a rule in the configuration file equals the name of a category variable in the source, then they match. Still there is complex match range of category. Rule decouples variable conditions. For example, log4j must specify a level for each logger(or inherit from father logger). That's not convenient when each grade of logger has its own level for output(child logger output at the level of debug, when father logger output at the level of error)
Now create a configuration file. The function zlog_init takes the files path as its only argument.
$ cat /etc/zlog.conf
[formats]
simple = "%m%n"
[rules]
my_cat.DEBUG >stdout; simple
In the configuration file log messages in the category "my_cat" and a level of DEBUG or higher are output to standard output, with the format of simple(%m - usermessage %n - newline). If you want to direct out to a file and limit the files maximum size, use this configuration
my_cat.DEBUG "/var/log/aa.log", 1M; simple
3. Using zlog API in C source file
-------------
$ vi test_hello.c
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *c;
rc = zlog_init("/etc/zlog.conf");
if (rc) {
printf("init failed\n");
return -1;
}
c = zlog_get_category("my_cat");
if (!c) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(c, "hello, zlog");
zlog_fini();
return 0;
}
4. Compile, and run it!
-------------
$ cc -c -o test_hello.o test_hello.c -I/usr/local/include
$ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread
$ ./test_hello
hello, zlog
5. Advanced Usage
-------------
* syslog model, better than log4j model
* log format customization
* multiple output destinations including static file path, dynamic file path, stdout, stderr, syslog, user-defined ouput
* runtime manually or automatically refresh configure(safely)
* high-performance, 250'000 logs/second on my laptop, about 1000 times faster than syslog(3) with rsyslogd
* user-defined log level
* thread-safe and process-safe log file rotation
* microsecond accuracy
* dzlog, a default category log API for easy use
* MDC, a log4j style key-value map
* self debuggable, can output zlog's self debug&error log at runtime
* No external dependencies, just based on a POSIX system and a C99 compliant vsnprintf.
6.Links:
-------------
* Homepage: http://hardysimpson.github.com/zlog
* Downloads: https://github.com/HardySimpson/zlog/releases
* Author's Email: HardySimpson1984@gmail.com
* auto tools version: https://github.com/bmanojlovic/zlog
* cmake verion: https://github.com/lisongmin/zlog
* windows version: https://github.com/lopsd07/WinZlog

@ -0,0 +1,17 @@
[p] 使用valgrind测试性能
[ ] 更好的错误展现,当系统出问题的时候直接报错
[ ] hzlog的可定制
[ ] hex那段重写,内置到buf内,参考od的设计
[ ] 分类匹配的可定制化, rcat
[ ] 自行管理文件缓存替代stdio
[ ] 减少dynamic文件名open的次数通过日期改变智能推断, file_table?
[ ] async file输出的增加
[ ] 兼容性问题 zlog.h内
[ ] 增加trace级别
[ ] gettid()
[ ] 性能对比, log4x, pantheios, glog
[ ] perl, python, go, c++支持
[ ] redis对接,协议设计
[ ] 和rsyslog对接的问题
[x] linux fsync->fdatasync, open..

@ -0,0 +1,111 @@
0. zlog是什么
zlog是一个高可靠性、高性能、线程安全、灵活、概念清晰的纯C日志函数库。
事实上在C的世界里面没有特别好的日志函数库就像JAVA里面的的log4j或者C++的log4cxx。C程序员都喜欢用自己的轮子。printf就是个挺好的轮子但没办法通过配置改变日志的格式或者输出文件。syslog是个系统级别的轮子不过速度慢而且功能比较单调。
所以我写了zlog。
zlog在效率、功能、安全性上大大超过了log4c并且是用c写成的具有比较好的通用性。
1.安装
下载https://github.com/HardySimpson/zlog/releases
$ tar -zxvf zlog-latest-stable.tar.gz
$ cd zlog-latest-stable/
$ make
$ sudo make install
or
$ make PREFIX=/usr/local/
$ sudo make PREFIX=/usr/local/ install
PREFIX指明了安装的路径安转完之后为了让你的程序能找到zlog动态库
$ sudo vi /etc/ld.so.conf
/usr/local/lib
$ sudo ldconfig
在你的程序运行之前保证libzlog.so在系统的动态链接库加载器可以找到的目录下。上面的命令适用于linux别的系统自己想办法。
2.介绍一下配置文件
zlog里面有三个重要的概念,category,formatrule
分类(Category)用于区分不同的输入代码中的分类变量的名字是一个字符串在一个程序里面可以通过获取不同的分类名的category用来后面输出不同分类的日志用于不同的目的。
格式(Format)是用来描述输出日志的格式,比如是否有带有时间戳, 是否包含文件位置信息等上面的例子里面的格式simple就配置成简单的用户输入的信息+换行符。
规则(Rule)则是把分类、级别、输出文件、格式组合起来决定一条代码中的日志是否输出输出到哪里以什么格式输出。简单而言规则里面的分类字符串和代码里面的分类变量的名字一样就匹配当然还有更高级的纲目分类匹配。规则彻底解耦了各个元素之间的强绑定例如log4j就必须为每个分类指定一个级别或者从父分类那里继承这在多层系统需要每一层都有自己的级别要求的时候非常不方便。
现在试着写配置文件配置文件名无所谓放在哪里也无所谓反正在zlog_init()的时候可以指定
$ cat /etc/zlog.conf
[formats]
simple = "%m%n"
[rules]
my_cat.DEBUG >stdout; simple
在目前的配置文件的例子里面可以看到my_cat分类>=debug等级的日志会被输出到stdout(标准输出)并且输出的格式是simple这个格式也就是用户输入信息+换行符。如果要输出到文件并控制文件大小为1兆规则的配置应该是
my_cat.DEBUG "/var/log/aa.log", 1M; simple
3.在代码中使用
$ vi test_hello.c
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *c;
rc = zlog_init("/etc/zlog.conf");
if (rc) {
printf("init failed\n");
return -1;
}
c = zlog_get_category("my_cat");
if (!c) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(c, "hello, zlog");
zlog_fini();
return 0;
}
4.编译、然后运行!
$ cc -c -o test_hello.o test_hello.c -I/usr/local/include
$ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread
$ ./test_hello
hello, zlog
5.高级使用
* syslog分类模型比log4j模型更加直接了当
* 日志格式定制类似于log4j的pattern layout
* 多种输出包括动态文件、静态文件、stdout、stderr、syslog、用户自定义输出函数
* 运行时手动、自动刷新配置文件(同时保证安全)
* 高性能在我的笔记本上达到25万条日志每秒, 大概是syslog(3)配合rsyslogd的1000倍速度
* 用户自定义等级
* 多线程和多进程环境下保证安全转档
* 精确到微秒
* 简单调用包装dzlog一个程序默认只用一个分类
* MDC线程键-值对的表,可以扩展用户自定义的字段
* 自诊断可以在运行时输出zlog自己的日志和配置状态
* 不依赖其他库只要是个POSIX系统就成(当然还要一个C99兼容的vsnprintf)
6.相关链接
主页http://hardysimpson.github.com/zlog/
软件下载https://github.com/HardySimpson/zlog/releases
作者邮箱HardySimpson1984@gmail.com
auto tools版本: https://github.com/bmanojlovic/zlog
cmake版本: https://github.com/lisongmin/zlog
windows版本: https://github.com/lopsd07/WinZlog

@ -0,0 +1,114 @@
0. What is zlog?
zlog is a reliable, high-performance, thread safe, flexible, clear-model, pure C logging library.
Actually, in the C world there was NO good logging library for applications like logback in java or log4cxx in c++. Using printf can work, but can not be redirected or reformatted easily. syslog is slow and is designed for system use.
So I wrote zlog.
It is faster, safer and more powerful than log4c. So it can be widely used.
1. Install
Downloads: https://github.com/HardySimpson/zlog/releases
$ tar -zxvf zlog-latest-stable.tar.gz
$ cd zlog-latest-stable/
$ make
$ sudo make install
or
$ make PREFIX=/usr/local/
$ sudo make PREFIX=/usr/local/ install
PREFIX indicates the installation destination for zlog. After installation, refresh your dynamic linker to make sure your program can find zlog library.
$ sudo vi /etc/ld.so.conf
/usr/local/lib
$ sudo ldconfig
Before running a real program, make sure libzlog.so is in the directory where the system's dynamic lib loader can find it. The command metioned above are for linux. Other systems will need a similar set of actions.
2. Introduce configure file
There are 3 important concepts in zlog: categories, formats and rules.
Categories specify different kinds of log entries. In the zlog source code, category is a (zlog_cateogory_t *) variable. In your program, different categories for the log entries will distinguish them from each other.
Formats describe log patterns, such as: with or without time stamp, source file, source line.
Rules consist of category, level, output file (or other channel) and format. In brief, if the category string in a rule in the configuration file equals the name of a category variable in the source, then they match. Still there is complex match range of category. Rule decouples variable conditions. For example, log4j must specify a level for each logger(or inherit from father logger). That's not convenient when each grade of logger has its own level for output(child logger output at the level of debug, when father logger output at the level of error)
Now create a configuration file. The function zlog_init takes the files path as its only argument.
$ cat /etc/zlog.conf
[formats]
simple = "%m%n"
[rules]
my_cat.DEBUG >stdout; simple
In the configuration file log messages in the category "my_cat" and a level of DEBUG or higher are output to standard output, with the format of simple(%m - usermessage %n - newline). If you want to direct out to a file and limit the files maximum size, use this configuration
my_cat.DEBUG "/var/log/aa.log", 1M; simple
3. Using zlog API in C source file
$ vi test_hello.c
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *c;
rc = zlog_init("/etc/zlog.conf");
if (rc) {
printf("init failed\n");
return -1;
}
c = zlog_get_category("my_cat");
if (!c) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(c, "hello, zlog");
zlog_fini();
return 0;
}
4. Complie, and run it!s
$ cc -c -o test_hello.o test_hello.c -I/usr/local/include
$ cc -o test_hello test_hello.o -L/usr/local/lib -lzlog -lpthread
$ ./test_hello
hello, zlog
5. Advanced Usage
* syslog model, better than log4j model
* log format customization
* multiple output destinations including static file path, dynamic file path, stdout, stderr, syslog, user-defined ouput
* runtime manually or automatically refresh configure(safely)
* high-performance, 250'000 logs/second on my laptop, about 1000 times faster than syslog(3) with rsyslogd
* user-defined log level
* thread-safe and process-safe log file rotation
* microsecond accuracy
* dzlog, a default category log API for easy use
* MDC, a log4j style key-value map
* self debuggable, can output zlog's self debug&error log at runtime
* No external dependencies, just based on a POSIX system and a C99 compliant vsnprintf.
6. Links:
Homepage: http://hardysimpson.github.com/zlog
Downloads: https://github.com/HardySimpson/zlog/releases
Author's Email: HardySimpson1984@gmail.com
auto tools version: https://github.com/bmanojlovic/zlog
cmake verion: https://github.com/lisongmin/zlog
windows version: https://github.com/lopsd07/WinZlog

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,27 @@
doc = \
UsersGuide-EN.pdf \
UsersGuide-CN.pdf \
UsersGuide-EN.tex \
UsersGuide-CN.tex \
UsersGuide-EN.html \
UsersGuide-CN.html \
GettingStart-EN.txt \
GettingStart-CN.txt
all : $(doc)
UsersGuide-EN.pdf : UsersGuide-EN.lyx
lyx -f -e pdf2 $^
UsersGuide-CN.pdf : UsersGuide-CN.lyx
lyx -f -e pdf4 $^
%.tex : %.lyx
lyx -f -e pdflatex $<
%.html : %.tex
hevea book.hva -s $<
hevea book.hva -s $<
clean :
-rm -f *.pdf *.haux *.html *.htoc *.tex *.lyx~

@ -0,0 +1,92 @@
-------------------------------------------------
using makefile.linux for test, libzlog compile in O2
-------------------------------------------------
[direct write, no logging library] - The Sky!
$ time ./test_press_write 1 10 100000
real 0m1.872s
user 0m0.140s
sys 0m3.290s
$ time ./test_press_write2 1 10 100000
real 0m0.909s
user 0m0.080s
sys 0m1.710s
-------------------------------------------------
v1.1.1 (fwrite is not atomic, so backup to write)
$ time ./test_press_zlog 1 10 100000
real 0m2.334s
user 0m1.780s
sys 0m2.710s
$ time ./test_press_zlog2 1 10 100000
real 0m2.134s
user 0m1.840s
sys 0m1.990s
-------------------------------------------------
v1.1.0
$ time ./test_press_zlog 1 10 100000
real 0m1.107s
user 0m1.500s
sys 0m0.340s
$ time ./test_press_zlog2 1 10 100000
real 0m0.898s
user 0m1.480s
sys 0m0.150s
-------------------------------------------------
v1.0.7
$ time ./test_press_zlog 1 10 100000
real 0m1.783s
user 0m3.000s
sys 0m0.300s
$ time ./test_press_zlog2 1 10 100000
real 0m1.621s
user 0m2.980s
sys 0m0.120s
-------------------------------------------------
v1.0.6
$ time ./test_press_zlog 1 10 100000
real 0m1.814s
user 0m3.060s
sys 0m0.270s
$ time ./test_press_zlog2 1 10 100000
real 0m1.605s
user 0m2.990s
sys 0m0.140s
-------------------------------------------------
v1.0.5
$ time ./test_press_zlog 1 10 100000
real 0m2.779s
user 0m4.170s
sys 0m0.560s
$ time ./test_press_zlog2 1 10 100000
real 0m2.713s
user 0m4.410s
sys 0m0.900s
-------------------------------------------------
v1.0.3
$ time ./test_press_zlog 1 10 100000
real 0m6.349s
user 0m6.300s
sys 0m5.950s
$ time ./test_press_zlog2 1 10 100000
real 0m6.377s
user 0m6.240s
sys 0m6.090s
-------------------------------------------------
v1.0.0
$ time ./test_press_zlog 1 10 100000
real 0m6.364s
user 0m6.040s
sys 0m6.270s
$ time ./test_press_zlog2 1 10 100000
real 0m6.361s
user 0m6.150s
sys 0m6.020s
-------------------------------------------------

@ -0,0 +1,36 @@
[global]
strict init = true
reload conf period = 10M
buffer min = 1024
buffer max = 2MB
#rotate lock file = /tmp/zlog.lock
rotate lock file = self
default format = "%d(%F %T.%l) %-6V (%c:%F:%L) - %m%n"
file perms = 600
fsync period = 1K
[levels]
TRACE = 10
CRIT = 130, LOG_CRIT
[formats]
simple = "%m%n"
normal = "%d(%F %T.%l) %m%n"
[rules]
default.* >stdout; simple
*.* -"%12.2E(HOME)/log/%c.log", \
1MB * 12 ~ "%E(HOME)/log/%c.%D(%F) #2r #3s.log"; \
simple
my_.INFO >stderr;
my_cat.!ERROR "aa.log"
my_dog.=DEBUG >syslog, LOG_LOCAL0; simple
my_dog.=DEBUG | /usr/bin/cronolog /www/logs/example_%Y%m%d.log ; normal
my_mice.* $record_func , "record_path%c"; normal

@ -0,0 +1,33 @@
# Top level makefile, the real shit is at src/makefile
TARGETS=noopt 32bit
all:
cd src && $(MAKE) $@
install:
cd src && $(MAKE) $@
$(TARGETS):
cd src && $(MAKE) $@
doc:
cd doc && $(MAKE)
test:
cd test && $(MAKE)
TAGS:
find . -type f -name "*.[ch]" | xargs etags -
clean:
cd src && $(MAKE) $@
cd test && $(MAKE) $@
cd doc && $(MAKE) $@
rm -f TAGS
distclean: clean
dummy:
.PHONY: doc install test TAGS

@ -0,0 +1,649 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>
#include <stdint.h>
#include "zc_defs.h"
#include "buf.h"
/*******************************************************************************/
/* Author's Note
* This buf.c is base on C99, that is, if buffer size is not enough,
* the return value of vsnprintf(3) is a number tell how many character should
* be output. vsnprintf in glibc 2.1 conforms to C99 , but glibc 2.0 doesn't.
* see manpage of vsnprintf(3) on you platform for more detail.
* So, what should you do if you want to using zlog on the platform that doesn't
* conform C99? My Answer is, crack zlog with a portable C99-vsnprintf, like this
* http://sourceforge.net/projects/ctrio/
* http://www.jhweiss.de/software/snprintf.html
* If you can see this note, you can fix it yourself? Aren't you? ^_^
* Oh, I put the snprintf in C99 standard here,
* vsnprintf is the same on return value.
7.19.6.5 The snprintf function
Synopsis
[#1]
#include <stdio.h>
int snprintf(char * restrict s, size_t n,
const char * restrict format, ...);
Description
[#2] The snprintf function is equivalent to fprintf, except
that the output is written into an array (specified by
argument s) rather than to a stream. If n is zero, nothing
is written, and s may be a null pointer. Otherwise, output
characters beyond the n-1st are discarded rather than being
written to the array, and a null character is written at the
end of the characters actually written into the array. If
copying takes place between objects that overlap, the
behavior is undefined.
Returns
[#3] The snprintf function returns the number of characters
that would have been written had n been sufficiently large,
not counting the terminating null character, or a negative
value if an encoding error occurred. Thus, the null-
terminated output has been completely written if and only if
the returned value is nonnegative and less than n.
*/
/*******************************************************************************/
void zlog_buf_profile(zlog_buf_t * a_buf, int flag)
{
//zc_assert(a_buf,);
zc_profile(flag, "---buf[%p][%ld-%ld][%ld][%s][%p:%ld]---",
a_buf,
a_buf->size_min, a_buf->size_max,
a_buf->size_real,
a_buf->truncate_str,
a_buf->start, a_buf->tail - a_buf->start);
return;
}
/*******************************************************************************/
void zlog_buf_del(zlog_buf_t * a_buf)
{
//zc_assert(a_buf,);
if (a_buf->start) free(a_buf->start);
zc_debug("zlog_buf_del[%p]", a_buf);
free(a_buf);
return;
}
zlog_buf_t *zlog_buf_new(size_t buf_size_min, size_t buf_size_max, const char *truncate_str)
{
zlog_buf_t *a_buf;
if (buf_size_min == 0) {
zc_error("buf_size_min == 0, not allowed");
return NULL;
}
if (buf_size_max != 0 && buf_size_max < buf_size_min) {
zc_error("buf_size_max[%lu] < buf_size_min[%lu] && buf_size_max != 0",
(unsigned long)buf_size_max, (unsigned long)buf_size_min);
return NULL;
}
a_buf = calloc(1, sizeof(*a_buf));
if (!a_buf) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
if (truncate_str) {
if (strlen(truncate_str) > sizeof(a_buf->truncate_str) - 1) {
zc_error("truncate_str[%s] overflow", truncate_str);
goto err;
} else {
strcpy(a_buf->truncate_str, truncate_str);
}
a_buf->truncate_str_len = strlen(truncate_str);
}
a_buf->size_min = buf_size_min;
a_buf->size_max = buf_size_max;
a_buf->size_real = a_buf->size_min;
a_buf->start = calloc(1, a_buf->size_real);
if (!a_buf->start) {
zc_error("calloc fail, errno[%d]", errno);
goto err;
}
a_buf->tail = a_buf->start;
a_buf->end_plus_1 = a_buf->start + a_buf->size_real;
a_buf->end = a_buf->end_plus_1 - 1;
//zlog_buf_profile(a_buf, ZC_DEBUG);
return a_buf;
err:
zlog_buf_del(a_buf);
return NULL;
}
/*******************************************************************************/
static void zlog_buf_truncate(zlog_buf_t * a_buf)
{
char *p;
size_t len;
if ((a_buf->truncate_str)[0] == '\0') return;
p = (a_buf->tail - a_buf->truncate_str_len);
if (p < a_buf->start) p = a_buf->start;
len = a_buf->tail - p;
memcpy(p, a_buf->truncate_str, len);
return;
}
/*******************************************************************************/
/* return 0: success
* return <0: fail, set size_real to -1;
* return >0: by conf limit, can't extend size
* increment must > 0
*/
static int zlog_buf_resize(zlog_buf_t * a_buf, size_t increment)
{
int rc = 0;
size_t new_size = 0;
size_t len = 0;
char *p = NULL;
if (a_buf->size_max != 0 && a_buf->size_real >= a_buf->size_max) {
zc_error("a_buf->size_real[%ld] >= a_buf->size_max[%ld]",
a_buf->size_real, a_buf->size_max);
return 1;
}
if (a_buf->size_max == 0) {
/* unlimit */
new_size = a_buf->size_real + 1.5 * increment;
} else {
/* limited */
if (a_buf->size_real + increment <= a_buf->size_max) {
new_size = a_buf->size_real + increment;
} else {
new_size = a_buf->size_max;
rc = 1;
}
}
len = a_buf->tail - a_buf->start;
p = realloc(a_buf->start, new_size);
if (!p) {
zc_error("realloc fail, errno[%d]", errno);
free(a_buf->start);
a_buf->start = NULL;
a_buf->tail = NULL;
a_buf->end = NULL;
a_buf->end_plus_1 = NULL;
return -1;
} else {
a_buf->start = p;
a_buf->tail = p + len;
a_buf->size_real = new_size;
a_buf->end_plus_1 = a_buf->start + new_size;
a_buf->end = a_buf->end_plus_1 - 1;
}
return rc;
}
int zlog_buf_vprintf(zlog_buf_t * a_buf, const char *format, va_list args)
{
va_list ap;
size_t size_left;
int nwrite;
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
va_copy(ap, args);
size_left = a_buf->end_plus_1 - a_buf->tail;
nwrite = vsnprintf(a_buf->tail, size_left, format, ap);
if (nwrite >= 0 && nwrite < size_left) {
a_buf->tail += nwrite;
//*(a_buf->tail) = '\0';
return 0;
} else if (nwrite < 0) {
zc_error("vsnprintf fail, errno[%d]", errno);
zc_error("nwrite[%d], size_left[%ld], format[%s]", nwrite, size_left, format);
return -1;
} else if (nwrite >= size_left) {
int rc;
//zc_debug("nwrite[%d]>=size_left[%ld],format[%s],resize", nwrite, size_left, format);
rc = zlog_buf_resize(a_buf, nwrite - size_left + 1);
if (rc > 0) {
zc_error("conf limit to %ld, can't extend, so truncate", a_buf->size_max);
va_copy(ap, args);
size_left = a_buf->end_plus_1 - a_buf->tail;
vsnprintf(a_buf->tail, size_left, format, ap);
a_buf->tail += size_left - 1;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
va_copy(ap, args);
size_left = a_buf->end_plus_1 - a_buf->tail;
nwrite = vsnprintf(a_buf->tail, size_left, format, ap);
if (nwrite < 0) {
zc_error("vsnprintf fail, errno[%d]", errno);
zc_error("nwrite[%d], size_left[%ld], format[%s]", nwrite, size_left, format);
return -1;
} else {
a_buf->tail += nwrite;
//*(a_buf->tail) = '\0';
return 0;
}
}
}
return 0;
}
/*******************************************************************************/
/* if width > num_len, 0 padding, else output num */
int zlog_buf_printf_dec32(zlog_buf_t * a_buf, uint32_t ui32, int width)
{
unsigned char *p;
char *q;
unsigned char tmp[ZLOG_INT32_LEN + 1];
size_t num_len, zero_len, out_len;
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
p = tmp + ZLOG_INT32_LEN;
do {
*--p = (unsigned char) (ui32 % 10 + '0');
} while (ui32 /= 10);
/* zero or space padding */
num_len = (tmp + ZLOG_INT32_LEN) - p;
if (width > num_len) {
zero_len = width - num_len;
out_len = width;
} else {
zero_len = 0;
out_len = num_len;
}
if ((q = a_buf->tail + out_len) > a_buf->end) {
int rc;
//zc_debug("size_left not enough, resize");
rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
if (rc > 0) {
size_t len_left;
zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
len_left = a_buf->end - a_buf->tail;
if (len_left <= zero_len) {
zero_len = len_left;
num_len = 0;
} else if (len_left > zero_len) {
/* zero_len not changed */
num_len = len_left - zero_len;
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail += len_left;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
q = a_buf->tail + out_len; /* re-calculate p*/
}
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail = q;
//*(a_buf->tail) = '\0';
return 0;
}
/*******************************************************************************/
int zlog_buf_printf_dec64(zlog_buf_t * a_buf, uint64_t ui64, int width)
{
unsigned char *p;
char *q;
unsigned char tmp[ZLOG_INT64_LEN + 1];
size_t num_len, zero_len, out_len;
uint32_t ui32;
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
p = tmp + ZLOG_INT64_LEN;
if (ui64 <= ZLOG_MAX_UINT32_VALUE) {
/*
* To divide 64-bit numbers and to find remainders
* on the x86 platform gcc and icc call the libc functions
* [u]divdi3() and [u]moddi3(), they call another function
* in its turn. On FreeBSD it is the qdivrem() function,
* its source code is about 170 lines of the code.
* The glibc counterpart is about 150 lines of the code.
*
* For 32-bit numbers and some divisors gcc and icc use
* a inlined multiplication and shifts. For example,
* unsigned "i32 / 10" is compiled to
*
* (i32 * 0xCCCCCCCD) >> 35
*/
ui32 = (uint32_t) ui64;
do {
*--p = (unsigned char) (ui32 % 10 + '0');
} while (ui32 /= 10);
} else {
do {
*--p = (unsigned char) (ui64 % 10 + '0');
} while (ui64 /= 10);
}
/* zero or space padding */
num_len = (tmp + ZLOG_INT64_LEN) - p;
if (width > num_len) {
zero_len = width - num_len;
out_len = width;
} else {
zero_len = 0;
out_len = num_len;
}
if ((q = a_buf->tail + out_len) > a_buf->end) {
int rc;
//zc_debug("size_left not enough, resize");
rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
if (rc > 0) {
size_t len_left;
zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
len_left = a_buf->end - a_buf->tail;
if (len_left <= zero_len) {
zero_len = len_left;
num_len = 0;
} else if (len_left > zero_len) {
/* zero_len not changed */
num_len = len_left - zero_len;
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail += len_left;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
q = a_buf->tail + out_len; /* re-calculate p*/
}
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail = q;
//*(a_buf->tail) = '\0';
return 0;
}
/*******************************************************************************/
int zlog_buf_printf_hex(zlog_buf_t * a_buf, uint32_t ui32, int width)
{
unsigned char *p;
char *q;
unsigned char tmp[ZLOG_INT32_LEN + 1];
size_t num_len, zero_len, out_len;
static unsigned char hex[] = "0123456789abcdef";
//static unsigned char HEX[] = "0123456789ABCDEF";
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
p = tmp + ZLOG_INT32_LEN;
do {
/* the "(uint32_t)" cast disables the BCC's warning */
*--p = hex[(uint32_t) (ui32 & 0xf)];
} while (ui32 >>= 4);
#if 0
} else { /* is_hex == 2 */
do {
/* the "(uint32_t)" cast disables the BCC's warning */
*--p = HEX[(uint32_t) (ui64 & 0xf)];
} while (ui64 >>= 4);
}
#endif
/* zero or space padding */
num_len = (tmp + ZLOG_INT32_LEN) - p;
if (width > num_len) {
zero_len = width - num_len;
out_len = width;
} else {
zero_len = 0;
out_len = num_len;
}
if ((q = a_buf->tail + out_len) > a_buf->end) {
int rc;
//zc_debug("size_left not enough, resize");
rc = zlog_buf_resize(a_buf, out_len - (a_buf->end - a_buf->tail));
if (rc > 0) {
size_t len_left;
zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
len_left = a_buf->end - a_buf->tail;
if (len_left <= zero_len) {
zero_len = len_left;
num_len = 0;
} else if (len_left > zero_len) {
/* zero_len not changed */
num_len = len_left - zero_len;
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail += len_left;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
q = a_buf->tail + out_len; /* re-calculate p*/
}
}
if (zero_len) memset(a_buf->tail, '0', zero_len);
memcpy(a_buf->tail + zero_len, p, num_len);
a_buf->tail = q;
//*(a_buf->tail) = '\0';
return 0;
}
/*******************************************************************************/
int zlog_buf_append(zlog_buf_t * a_buf, const char *str, size_t str_len)
{
char *p;
#if 0
if (str_len <= 0 || str == NULL) {
return 0;
}
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
#endif
if ((p = a_buf->tail + str_len) > a_buf->end) {
int rc;
//zc_debug("size_left not enough, resize");
rc = zlog_buf_resize(a_buf, str_len - (a_buf->end - a_buf->tail));
if (rc > 0) {
size_t len_left;
zc_error("conf limit to %ld, can't extend, so output",
a_buf->size_max);
len_left = a_buf->end - a_buf->tail;
memcpy(a_buf->tail, str, len_left);
a_buf->tail += len_left;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
p = a_buf->tail + str_len; /* re-calculate p*/
}
}
memcpy(a_buf->tail, str, str_len);
a_buf->tail = p;
// *(a_buf->tail) = '\0';
return 0;
}
/*******************************************************************************/
int zlog_buf_adjust_append(zlog_buf_t * a_buf, const char *str, size_t str_len,
int left_adjust, int zero_pad, size_t in_width, size_t out_width)
{
size_t append_len = 0;
size_t source_len = 0;
size_t space_len = 0;
#if 0
if (str_len <= 0 || str == NULL) {
return 0;
}
#endif
if (!a_buf->start) {
zc_error("pre-use of zlog_buf_resize fail, so can't convert");
return -1;
}
/* calculate how many character will be got from str */
if (out_width == 0 || str_len < out_width) {
source_len = str_len;
} else {
source_len = out_width;
}
/* calculate how many character will be output */
if (in_width == 0 || source_len >= in_width ) {
append_len = source_len;
space_len = 0;
} else {
append_len = in_width;
space_len = in_width - source_len;
}
/* |-----append_len-----------| */
/* |-source_len---|-space_len-| left_adjust */
/* |-space_len---|-source_len-| right_adjust */
/* |-(size_real-1)---| size not enough */
if (append_len > a_buf->end - a_buf->tail) {
int rc = 0;
//zc_debug("size_left not enough, resize");
rc = zlog_buf_resize(a_buf, append_len - (a_buf->end -a_buf->tail));
if (rc > 0) {
zc_error("conf limit to %ld, can't extend, so output", a_buf->size_max);
append_len = (a_buf->end - a_buf->tail);
if (left_adjust) {
if (source_len < append_len) {
space_len = append_len - source_len;
} else {
source_len = append_len;
space_len = 0;
}
if (space_len) memset(a_buf->tail + source_len, ' ', space_len);
memcpy(a_buf->tail, str, source_len);
} else {
if (space_len < append_len) {
source_len = append_len - space_len;
} else {
space_len = append_len;
source_len = 0;
}
if (space_len) {
if (zero_pad) {
memset(a_buf->tail, '0', space_len);
} else {
memset(a_buf->tail, ' ', space_len);
}
}
memcpy(a_buf->tail + space_len, str, source_len);
}
a_buf->tail += append_len;
//*(a_buf->tail) = '\0';
zlog_buf_truncate(a_buf);
return 1;
} else if (rc < 0) {
zc_error("zlog_buf_resize fail");
return -1;
} else {
//zc_debug("zlog_buf_resize succ, to[%ld]", a_buf->size_real);
}
}
if (left_adjust) {
if (space_len) memset(a_buf->tail + source_len, ' ', space_len);
memcpy(a_buf->tail, str, source_len);
} else {
if (space_len) {
if (zero_pad) {
memset(a_buf->tail, '0', space_len);
} else {
memset(a_buf->tail, ' ', space_len);
}
}
memcpy(a_buf->tail + space_len, str, source_len);
}
a_buf->tail += append_len;
//*(a_buf->tail) = '\0';
return 0;
}
/*******************************************************************************/

@ -0,0 +1,56 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_buf_h
#define __zlog_buf_h
/* buf, is a dynamic expand buffer for one single log,
* as one single log will interlace if use multiple write() to file.
* and buf is always keep in a thread, to make each thread has its
* own buffer to avoid lock.
*/
#include <stdarg.h>
#include <stdint.h>
typedef struct zlog_buf_s {
char *start;
char *tail;
char *end;
char *end_plus_1;
size_t size_min;
size_t size_max;
size_t size_real;
char truncate_str[MAXLEN_PATH + 1];
size_t truncate_str_len;
} zlog_buf_t;
zlog_buf_t *zlog_buf_new(size_t min, size_t max, const char *truncate_str);
void zlog_buf_del(zlog_buf_t * a_buf);
void zlog_buf_profile(zlog_buf_t * a_buf, int flag);
int zlog_buf_vprintf(zlog_buf_t * a_buf, const char *format, va_list args);
int zlog_buf_append(zlog_buf_t * a_buf, const char *str, size_t str_len);
int zlog_buf_adjust_append(zlog_buf_t * a_buf, const char *str, size_t str_len,
int left_adjust, int zero_pad, size_t in_width, size_t out_width);
int zlog_buf_printf_dec32(zlog_buf_t * a_buf, uint32_t ui32, int width);
int zlog_buf_printf_dec64(zlog_buf_t * a_buf, uint64_t ui64, int width);
int zlog_buf_printf_hex(zlog_buf_t * a_buf, uint32_t ui32, int width);
#define zlog_buf_restart(a_buf) do { \
a_buf->tail = a_buf->start; \
} while(0)
#define zlog_buf_len(a_buf) (a_buf->tail - a_buf->start)
#define zlog_buf_str(a_buf) (a_buf->start)
#define zlog_buf_seal(a_buf) do {*(a_buf)->tail = '\0';} while (0)
#endif

@ -0,0 +1,233 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "fmacros.h"
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "category.h"
#include "rule.h"
#include "zc_defs.h"
void zlog_category_profile(zlog_category_t *a_category, int flag)
{
int i;
zlog_rule_t *a_rule;
zc_assert(a_category,);
zc_profile(flag, "--category[%p][%s][%p]--",
a_category,
a_category->name,
a_category->fit_rules);
if (a_category->fit_rules) {
zc_arraylist_foreach(a_category->fit_rules, i, a_rule) {
zlog_rule_profile(a_rule, flag);
}
}
return;
}
/*******************************************************************************/
void zlog_category_del(zlog_category_t * a_category)
{
zc_assert(a_category,);
if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules);
zc_debug("zlog_category_del[%p]", a_category);
free(a_category);
return;
}
/* overlap one rule's level bitmap to cateogry,
* so category can judge whether a log level will be output by itself
* It is safe when configure is reloaded, when rule will be released an recreated
*/
static void zlog_cateogry_overlap_bitmap(zlog_category_t * a_category, zlog_rule_t *a_rule)
{
int i;
for(i = 0; i < sizeof(a_rule->level_bitmap); i++) {
a_category->level_bitmap[i] |= a_rule->level_bitmap[i];
}
}
static int zlog_category_obtain_rules(zlog_category_t * a_category, zc_arraylist_t * rules)
{
int i;
int count = 0;
int fit = 0;
zlog_rule_t *a_rule;
zlog_rule_t *wastebin_rule = NULL;
/* before set, clean last fit rules first */
if (a_category->fit_rules) zc_arraylist_del(a_category->fit_rules);
memset(a_category->level_bitmap, 0x00, sizeof(a_category->level_bitmap));
a_category->fit_rules = zc_arraylist_new(NULL);
if (!(a_category->fit_rules)) {
zc_error("zc_arraylist_new fail");
return -1;
}
/* get match rules from all rules */
zc_arraylist_foreach(rules, i, a_rule) {
fit = zlog_rule_match_category(a_rule, a_category->name);
if (fit) {
if (zc_arraylist_add(a_category->fit_rules, a_rule)) {
zc_error("zc_arrylist_add fail");
goto err;
}
zlog_cateogry_overlap_bitmap(a_category, a_rule);
count++;
}
if (zlog_rule_is_wastebin(a_rule)) {
wastebin_rule = a_rule;
}
}
if (count == 0) {
if (wastebin_rule) {
zc_debug("category[%s], no match rules, use wastebin_rule", a_category->name);
if (zc_arraylist_add(a_category->fit_rules, wastebin_rule)) {
zc_error("zc_arrylist_add fail");
goto err;
}
zlog_cateogry_overlap_bitmap(a_category, wastebin_rule);
count++;
} else {
zc_debug("category[%s], no match rules & no wastebin_rule", a_category->name);
}
}
return 0;
err:
zc_arraylist_del(a_category->fit_rules);
a_category->fit_rules = NULL;
return -1;
}
zlog_category_t *zlog_category_new(const char *name, zc_arraylist_t * rules)
{
size_t len;
zlog_category_t *a_category;
zc_assert(name, NULL);
zc_assert(rules, NULL);
len = strlen(name);
if (len > sizeof(a_category->name) - 1) {
zc_error("name[%s] too long", name);
return NULL;
}
a_category = calloc(1, sizeof(zlog_category_t));
if (!a_category) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
strcpy(a_category->name, name);
a_category->name_len = len;
if (zlog_category_obtain_rules(a_category, rules)) {
zc_error("zlog_category_fit_rules fail");
goto err;
}
zlog_category_profile(a_category, ZC_DEBUG);
return a_category;
err:
zlog_category_del(a_category);
return NULL;
}
/*******************************************************************************/
/* update success: fit_rules 1, fit_rules_backup 1 */
/* update fail: fit_rules 0, fit_rules_backup 1 */
int zlog_category_update_rules(zlog_category_t * a_category, zc_arraylist_t * new_rules)
{
zc_assert(a_category, -1);
zc_assert(new_rules, -1);
/* 1st, mv fit_rules fit_rules_backup */
if (a_category->fit_rules_backup) zc_arraylist_del(a_category->fit_rules_backup);
a_category->fit_rules_backup = a_category->fit_rules;
a_category->fit_rules = NULL;
memcpy(a_category->level_bitmap_backup, a_category->level_bitmap,
sizeof(a_category->level_bitmap));
/* 2nd, obtain new_rules to fit_rules */
if (zlog_category_obtain_rules(a_category, new_rules)) {
zc_error("zlog_category_obtain_rules fail");
a_category->fit_rules = NULL;
return -1;
}
/* keep the fit_rules_backup not change, return */
return 0;
}
/* commit fail: fit_rules_backup != 0 */
/* commit success: fit_rules 1, fit_rules_backup 0 */
void zlog_category_commit_rules(zlog_category_t * a_category)
{
zc_assert(a_category,);
if (!a_category->fit_rules_backup) {
zc_warn("a_category->fit_rules_backup is NULL, never update before");
return;
}
zc_arraylist_del(a_category->fit_rules_backup);
a_category->fit_rules_backup = NULL;
memset(a_category->level_bitmap_backup, 0x00,
sizeof(a_category->level_bitmap_backup));
return;
}
/* rollback fail: fit_rules_backup != 0 */
/* rollback success: fit_rules 1, fit_rules_backup 0 */
/* so whether update succes or not, make things back to old */
void zlog_category_rollback_rules(zlog_category_t * a_category)
{
zc_assert(a_category,);
if (!a_category->fit_rules_backup) {
zc_warn("a_category->fit_rules_backup in NULL, never update before");
return;
}
if (a_category->fit_rules) {
/* update success, rm new and backup */
zc_arraylist_del(a_category->fit_rules);
a_category->fit_rules = a_category->fit_rules_backup;
a_category->fit_rules_backup = NULL;
} else {
/* update fail, just backup */
a_category->fit_rules = a_category->fit_rules_backup;
a_category->fit_rules_backup = NULL;
}
memcpy(a_category->level_bitmap, a_category->level_bitmap_backup,
sizeof(a_category->level_bitmap));
memset(a_category->level_bitmap_backup, 0x00,
sizeof(a_category->level_bitmap_backup));
return; /* always success */
}
/*******************************************************************************/
int zlog_category_output(zlog_category_t * a_category, zlog_thread_t * a_thread)
{
int i;
int rc = 0;
zlog_rule_t *a_rule;
/* go through all match rules to output */
zc_arraylist_foreach(a_category->fit_rules, i, a_rule) {
rc = zlog_rule_output(a_rule, a_thread);
}
return rc;
}

@ -0,0 +1,38 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_category_h
#define __zlog_category_h
#include "zc_defs.h"
#include "thread.h"
typedef struct zlog_category_s {
char name[MAXLEN_PATH + 1];
size_t name_len;
unsigned char level_bitmap[32];
unsigned char level_bitmap_backup[32];
zc_arraylist_t *fit_rules;
zc_arraylist_t *fit_rules_backup;
} zlog_category_t;
zlog_category_t *zlog_category_new(const char *name, zc_arraylist_t * rules);
void zlog_category_del(zlog_category_t * a_category);
void zlog_category_profile(zlog_category_t *a_category, int flag);
int zlog_category_update_rules(zlog_category_t * a_category, zc_arraylist_t * new_rules);
void zlog_category_commit_rules(zlog_category_t * a_category);
void zlog_category_rollback_rules(zlog_category_t * a_category);
int zlog_category_output(zlog_category_t * a_category, zlog_thread_t * a_thread);
#define zlog_category_needless_level(a_category, lv) \
a_category && !((a_category->level_bitmap[lv/8] >> (7 - lv % 8)) & 0x01)
#endif

@ -0,0 +1,129 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "zc_defs.h"
#include "category_table.h"
void zlog_category_table_profile(zc_hashtable_t * categories, int flag)
{
zc_hashtable_entry_t *a_entry;
zlog_category_t *a_category;
zc_assert(categories,);
zc_profile(flag, "-category_table[%p]-", categories);
zc_hashtable_foreach(categories, a_entry) {
a_category = (zlog_category_t *) a_entry->value;
zlog_category_profile(a_category, flag);
}
return;
}
/*******************************************************************************/
void zlog_category_table_del(zc_hashtable_t * categories)
{
zc_assert(categories,);
zc_hashtable_del(categories);
zc_debug("zlog_category_table_del[%p]", categories);
return;
}
zc_hashtable_t *zlog_category_table_new(void)
{
zc_hashtable_t *categories;
categories = zc_hashtable_new(20,
(zc_hashtable_hash_fn) zc_hashtable_str_hash,
(zc_hashtable_equal_fn) zc_hashtable_str_equal,
NULL, (zc_hashtable_del_fn) zlog_category_del);
if (!categories) {
zc_error("zc_hashtable_new fail");
return NULL;
} else {
zlog_category_table_profile(categories, ZC_DEBUG);
return categories;
}
}
/*******************************************************************************/
int zlog_category_table_update_rules(zc_hashtable_t * categories, zc_arraylist_t * new_rules)
{
zc_hashtable_entry_t *a_entry;
zlog_category_t *a_category;
zc_assert(categories, -1);
zc_hashtable_foreach(categories, a_entry) {
a_category = (zlog_category_t *) a_entry->value;
if (zlog_category_update_rules(a_category, new_rules)) {
zc_error("zlog_category_update_rules fail, try rollback");
return -1;
}
}
return 0;
}
void zlog_category_table_commit_rules(zc_hashtable_t * categories)
{
zc_hashtable_entry_t *a_entry;
zlog_category_t *a_category;
zc_assert(categories,);
zc_hashtable_foreach(categories, a_entry) {
a_category = (zlog_category_t *) a_entry->value;
zlog_category_commit_rules(a_category);
}
return;
}
void zlog_category_table_rollback_rules(zc_hashtable_t * categories)
{
zc_hashtable_entry_t *a_entry;
zlog_category_t *a_category;
zc_assert(categories,);
zc_hashtable_foreach(categories, a_entry) {
a_category = (zlog_category_t *) a_entry->value;
zlog_category_rollback_rules(a_category);
}
return;
}
/*******************************************************************************/
zlog_category_t *zlog_category_table_fetch_category(zc_hashtable_t * categories,
const char *category_name, zc_arraylist_t * rules)
{
zlog_category_t *a_category;
zc_assert(categories, NULL);
/* 1st find category in global category map */
a_category = zc_hashtable_get(categories, category_name);
if (a_category) return a_category;
/* else not found, create one */
a_category = zlog_category_new(category_name, rules);
if (!a_category) {
zc_error("zc_category_new fail");
return NULL;
}
if(zc_hashtable_put(categories, a_category->name, a_category)) {
zc_error("zc_hashtable_put fail");
goto err;
}
return a_category;
err:
zlog_category_del(a_category);
return NULL;
}
/*******************************************************************************/

@ -0,0 +1,28 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_category_table_h
#define __zlog_category_table_h
#include "zc_defs.h"
#include "category.h"
zc_hashtable_t *zlog_category_table_new(void);
void zlog_category_table_del(zc_hashtable_t * categories);
void zlog_category_table_profile(zc_hashtable_t * categories, int flag);
/* if none, create new and return */
zlog_category_t *zlog_category_table_fetch_category(
zc_hashtable_t * categories,
const char *category_name, zc_arraylist_t * rules);
int zlog_category_table_update_rules(zc_hashtable_t * categories, zc_arraylist_t * new_rules);
void zlog_category_table_commit_rules(zc_hashtable_t * categories);
void zlog_category_table_rollback_rules(zc_hashtable_t * categories);
#endif

@ -0,0 +1,555 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "fmacros.h"
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include "conf.h"
#include "rule.h"
#include "format.h"
#include "level_list.h"
#include "rotater.h"
#include "zc_defs.h"
/*******************************************************************************/
#define ZLOG_CONF_DEFAULT_FORMAT "default = \"%D %V [%p:%F:%L] %m%n\""
#define ZLOG_CONF_DEFAULT_RULE "*.* >stdout"
#define ZLOG_CONF_DEFAULT_BUF_SIZE_MIN 1024
#define ZLOG_CONF_DEFAULT_BUF_SIZE_MAX (2 * 1024 * 1024)
#define ZLOG_CONF_DEFAULT_FILE_PERMS 0600
#define ZLOG_CONF_DEFAULT_RELOAD_CONF_PERIOD 0
#define ZLOG_CONF_DEFAULT_FSYNC_PERIOD 0
#define ZLOG_CONF_BACKUP_ROTATE_LOCK_FILE "/tmp/zlog.lock"
/*******************************************************************************/
void zlog_conf_profile(zlog_conf_t * a_conf, int flag)
{
int i;
zlog_rule_t *a_rule;
zlog_format_t *a_format;
zc_assert(a_conf,);
zc_profile(flag, "-conf[%p]-", a_conf);
zc_profile(flag, "--global--");
zc_profile(flag, "---file[%s],mtime[%s]---", a_conf->file, a_conf->mtime);
zc_profile(flag, "---in-memory conf[%s]---", a_conf->cfg_ptr);
zc_profile(flag, "---strict init[%d]---", a_conf->strict_init);
zc_profile(flag, "---buffer min[%ld]---", a_conf->buf_size_min);
zc_profile(flag, "---buffer max[%ld]---", a_conf->buf_size_max);
if (a_conf->default_format) {
zc_profile(flag, "---default_format---");
zlog_format_profile(a_conf->default_format, flag);
}
zc_profile(flag, "---file perms[0%o]---", a_conf->file_perms);
zc_profile(flag, "---reload conf period[%ld]---", a_conf->reload_conf_period);
zc_profile(flag, "---fsync period[%ld]---", a_conf->fsync_period);
zc_profile(flag, "---rotate lock file[%s]---", a_conf->rotate_lock_file);
if (a_conf->rotater) zlog_rotater_profile(a_conf->rotater, flag);
if (a_conf->levels) zlog_level_list_profile(a_conf->levels, flag);
if (a_conf->formats) {
zc_profile(flag, "--format list[%p]--", a_conf->formats);
zc_arraylist_foreach(a_conf->formats, i, a_format) {
zlog_format_profile(a_format, flag);
}
}
if (a_conf->rules) {
zc_profile(flag, "--rule_list[%p]--", a_conf->rules);
zc_arraylist_foreach(a_conf->rules, i, a_rule) {
zlog_rule_profile(a_rule, flag);
}
}
return;
}
/*******************************************************************************/
void zlog_conf_del(zlog_conf_t * a_conf)
{
zc_assert(a_conf,);
if (a_conf->rotater) zlog_rotater_del(a_conf->rotater);
if (a_conf->levels) zlog_level_list_del(a_conf->levels);
if (a_conf->default_format) zlog_format_del(a_conf->default_format);
if (a_conf->formats) zc_arraylist_del(a_conf->formats);
if (a_conf->rules) zc_arraylist_del(a_conf->rules);
free(a_conf);
zc_debug("zlog_conf_del[%p]");
return;
}
static int zlog_conf_build_without_file(zlog_conf_t * a_conf);
static int zlog_conf_build_with_file(zlog_conf_t * a_conf);
static int zlog_conf_build_with_in_memory(zlog_conf_t * a_conf);
enum{
NO_CFG,
FILE_CFG,
IN_MEMORY_CFG
};
zlog_conf_t *zlog_conf_new(const char *config)
{
int nwrite = 0;
int cfg_source = 0;
zlog_conf_t *a_conf = NULL;
a_conf = calloc(1, sizeof(zlog_conf_t));
if (!a_conf) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
// Find content of pointer. If it starts with '[' then content are configurations.
if (config && config[0] != '\0' && config[0] != '[') {
nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", config);
cfg_source = FILE_CFG;
} else if (getenv("ZLOG_CONF_PATH") != NULL) {
nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", getenv("ZLOG_CONF_PATH"));
cfg_source = FILE_CFG;
} else if (config[0]=='[') {
memset(a_conf->file, 0x00, sizeof(a_conf->file));
nwrite = snprintf(a_conf->cfg_ptr, sizeof(a_conf->cfg_ptr), "%s", config);
cfg_source = IN_MEMORY_CFG;
if (nwrite < 0 || nwrite >= sizeof(a_conf->file)) {
zc_error("not enough space for configurations, nwrite=[%d], errno[%d]", nwrite, errno);
goto err;
}
} else {
memset(a_conf->file, 0x00, sizeof(a_conf->file));
cfg_source = NO_CFG;
}
if (nwrite < 0 || nwrite >= sizeof(a_conf->file) && cfg_source == FILE_CFG) {
zc_error("not enough space for path name, nwrite=[%d], errno[%d]", nwrite, errno);
goto err;
}
/* set default configuration start */
a_conf->strict_init = 1;
a_conf->buf_size_min = ZLOG_CONF_DEFAULT_BUF_SIZE_MIN;
a_conf->buf_size_max = ZLOG_CONF_DEFAULT_BUF_SIZE_MAX;
if (cfg_source == FILE_CFG) {
/* configure file as default lock file */
strcpy(a_conf->rotate_lock_file, a_conf->file);
} else {
strcpy(a_conf->rotate_lock_file, ZLOG_CONF_BACKUP_ROTATE_LOCK_FILE);
}
strcpy(a_conf->default_format_line, ZLOG_CONF_DEFAULT_FORMAT);
a_conf->file_perms = ZLOG_CONF_DEFAULT_FILE_PERMS;
a_conf->reload_conf_period = ZLOG_CONF_DEFAULT_RELOAD_CONF_PERIOD;
a_conf->fsync_period = ZLOG_CONF_DEFAULT_FSYNC_PERIOD;
/* set default configuration end */
a_conf->levels = zlog_level_list_new();
if (!a_conf->levels) {
zc_error("zlog_level_list_new fail");
goto err;
}
a_conf->formats = zc_arraylist_new((zc_arraylist_del_fn) zlog_format_del);
if (!a_conf->formats) {
zc_error("zc_arraylist_new fail");
goto err;
}
a_conf->rules = zc_arraylist_new((zc_arraylist_del_fn) zlog_rule_del);
if (!a_conf->rules) {
zc_error("init rule_list fail");
goto err;
}
if (cfg_source == FILE_CFG) {
if (zlog_conf_build_with_file(a_conf)) {
zc_error("zlog_conf_build_with_file fail");
goto err;
}
} else if (cfg_source == IN_MEMORY_CFG) {
if(zlog_conf_build_with_in_memory(a_conf)){
zc_error("zlog_conf_build_with_in_memory fail");
goto err;
}
} else {
if (zlog_conf_build_without_file(a_conf)) {
zc_error("zlog_conf_build_without_file fail");
goto err;
}
}
zlog_conf_profile(a_conf, ZC_DEBUG);
return a_conf;
err:
zlog_conf_del(a_conf);
return NULL;
}
/*******************************************************************************/
static int zlog_conf_build_without_file(zlog_conf_t * a_conf)
{
zlog_rule_t *default_rule;
a_conf->default_format = zlog_format_new(a_conf->default_format_line, &(a_conf->time_cache_count));
if (!a_conf->default_format) {
zc_error("zlog_format_new fail");
return -1;
}
a_conf->rotater = zlog_rotater_new(a_conf->rotate_lock_file);
if (!a_conf->rotater) {
zc_error("zlog_rotater_new fail");
return -1;
}
default_rule = zlog_rule_new(
ZLOG_CONF_DEFAULT_RULE,
a_conf->levels,
a_conf->default_format,
a_conf->formats,
a_conf->file_perms,
a_conf->fsync_period,
&(a_conf->time_cache_count));
if (!default_rule) {
zc_error("zlog_rule_new fail");
return -1;
}
/* add default rule */
if (zc_arraylist_add(a_conf->rules, default_rule)) {
zlog_rule_del(default_rule);
zc_error("zc_arraylist_add fail");
return -1;
}
return 0;
}
/*******************************************************************************/
static int zlog_conf_parse_line(zlog_conf_t * a_conf, char *line, int *section);
static int zlog_conf_build_with_file(zlog_conf_t * a_conf)
{
int rc = 0;
struct zlog_stat a_stat;
struct tm local_time;
FILE *fp = NULL;
char line[MAXLEN_CFG_LINE + 1];
size_t line_len;
char *pline = NULL;
char *p = NULL;
int line_no = 0;
int i = 0;
int in_quotation = 0;
int section = 0;
/* [global:1] [levels:2] [formats:3] [rules:4] */
if (lstat(a_conf->file, &a_stat)) {
zc_error("lstat conf file[%s] fail, errno[%d]", a_conf->file,
errno);
return -1;
}
localtime_r(&(a_stat.st_mtime), &local_time);
strftime(a_conf->mtime, sizeof(a_conf->mtime), "%F %T", &local_time);
if ((fp = fopen(a_conf->file, "r")) == NULL) {
zc_error("open configure file[%s] fail", a_conf->file);
return -1;
}
/* Now process the file.
*/
pline = line;
memset(&line, 0x00, sizeof(line));
while (fgets((char *)pline, sizeof(line) - (pline - line), fp) != NULL) {
++line_no;
line_len = strlen(pline);
if (0 == line_len) {
continue;
}
if (pline[line_len - 1] == '\n') {
pline[line_len - 1] = '\0';
}
/* check for end-of-section, comments, strip off trailing
* spaces and newline character.
*/
p = pline;
while (*p && isspace((int)*p))
++p;
if (*p == '\0' || *p == '#')
continue;
for (i = 0; p[i] != '\0'; ++i) {
pline[i] = p[i];
}
pline[i] = '\0';
for (p = pline + strlen(pline) - 1; isspace((int)*p); --p)
/*EMPTY*/;
if (*p == '\\') {
if ((p - line) > MAXLEN_CFG_LINE - 30) {
/* Oops the buffer is full - what now? */
pline = line;
} else {
for (p--; isspace((int)*p); --p)
/*EMPTY*/;
p++;
*p = 0;
pline = p;
continue;
}
} else
pline = line;
*++p = '\0';
/* clean the tail comments start from # and not in quotation */
in_quotation = 0;
for (p = line; *p != '\0'; p++) {
if (*p == '"') {
in_quotation ^= 1;
continue;
}
if (*p == '#' && !in_quotation) {
*p = '\0';
break;
}
}
/* we now have the complete line,
* and are positioned at the first non-whitespace
* character. So let's process it
*/
rc = zlog_conf_parse_line(a_conf, line, &section);
if (rc < 0) {
zc_error("parse configure file[%s]line_no[%ld] fail", a_conf->file, line_no);
zc_error("line[%s]", line);
goto exit;
} else if (rc > 0) {
zc_warn("parse configure file[%s]line_no[%ld] fail", a_conf->file, line_no);
zc_warn("line[%s]", line);
zc_warn("as strict init is set to false, ignore and go on");
rc = 0;
continue;
}
}
exit:
fclose(fp);
return rc;
}
/**********************************************************************/
static int zlog_conf_build_with_in_memory(zlog_conf_t * a_conf)
{
int rc = 0;
char line[MAXLEN_CFG_LINE + 1];
char *pline = NULL;
int section = 0;
pline = line;
memset(&line, 0x00, sizeof(line));
pline = strtok((char *)a_conf->cfg_ptr, "\n");
while (pline != NULL) {
rc = zlog_conf_parse_line(a_conf, pline, &section);
if (rc < 0) {
zc_error("parse in-memory configurations[%s] line [%s] fail", a_conf->cfg_ptr, pline);
break;
} else if (rc > 0) {
zc_error("parse in-memory configurations[%s] line [%s] fail", a_conf->cfg_ptr, pline);
zc_warn("as strict init is set to false, ignore and go on");
rc = 0;
continue;
}
pline = strtok(NULL, "\n");
}
return rc;
}
/* section [global:1] [levels:2] [formats:3] [rules:4] */
static int zlog_conf_parse_line(zlog_conf_t * a_conf, char *line, int *section)
{
int nscan;
int nread;
char name[MAXLEN_CFG_LINE + 1];
char word_1[MAXLEN_CFG_LINE + 1];
char word_2[MAXLEN_CFG_LINE + 1];
char word_3[MAXLEN_CFG_LINE + 1];
char value[MAXLEN_CFG_LINE + 1];
zlog_format_t *a_format = NULL;
zlog_rule_t *a_rule = NULL;
if (strlen(line) > MAXLEN_CFG_LINE) {
zc_error ("line_len[%ld] > MAXLEN_CFG_LINE[%ld], may cause overflow",
strlen(line), MAXLEN_CFG_LINE);
return -1;
}
/* get and set outer section flag, so it is a closure? haha */
if (line[0] == '[') {
int last_section = *section;
nscan = sscanf(line, "[ %[^] \t]", name);
if (STRCMP(name, ==, "global")) {
*section = 1;
} else if (STRCMP(name, ==, "levels")) {
*section = 2;
} else if (STRCMP(name, ==, "formats")) {
*section = 3;
} else if (STRCMP(name, ==, "rules")) {
*section = 4;
} else {
zc_error("wrong section name[%s]", name);
return -1;
}
/* check the sequence of section, must increase */
if (last_section >= *section) {
zc_error("wrong sequence of section, must follow global->levels->formats->rules");
return -1;
}
if (*section == 4) {
if (a_conf->reload_conf_period != 0
&& a_conf->fsync_period >= a_conf->reload_conf_period) {
/* as all rule will be rebuilt when conf is reload,
* so fsync_period > reload_conf_period will never
* cause rule to fsync it's file.
* fsync_period will be meaningless and down speed,
* so make it zero.
*/
zc_warn("fsync_period[%ld] >= reload_conf_period[%ld],"
"set fsync_period to zero");
a_conf->fsync_period = 0;
}
/* now build rotater and default_format
* from the unchanging global setting,
* for zlog_rule_new() */
a_conf->rotater = zlog_rotater_new(a_conf->rotate_lock_file);
if (!a_conf->rotater) {
zc_error("zlog_rotater_new fail");
return -1;
}
a_conf->default_format = zlog_format_new(a_conf->default_format_line,
&(a_conf->time_cache_count));
if (!a_conf->default_format) {
zc_error("zlog_format_new fail");
return -1;
}
}
return 0;
}
/* process detail */
switch (*section) {
case 1:
memset(name, 0x00, sizeof(name));
memset(value, 0x00, sizeof(value));
nscan = sscanf(line, " %[^=]= %s ", name, value);
if (nscan != 2) {
zc_error("sscanf [%s] fail, name or value is null", line);
return -1;
}
memset(word_1, 0x00, sizeof(word_1));
memset(word_2, 0x00, sizeof(word_2));
memset(word_3, 0x00, sizeof(word_3));
nread = 0;
nscan = sscanf(name, "%s%n%s%s", word_1, &nread, word_2, word_3);
if (STRCMP(word_1, ==, "strict") && STRCMP(word_2, ==, "init")) {
/* if environment variable ZLOG_STRICT_INIT is set
* then always make it strict
*/
if (STRICMP(value, ==, "false") && !getenv("ZLOG_STRICT_INIT")) {
a_conf->strict_init = 0;
} else {
a_conf->strict_init = 1;
}
} else if (STRCMP(word_1, ==, "buffer") && STRCMP(word_2, ==, "min")) {
a_conf->buf_size_min = zc_parse_byte_size(value);
} else if (STRCMP(word_1, ==, "buffer") && STRCMP(word_2, ==, "max")) {
a_conf->buf_size_max = zc_parse_byte_size(value);
} else if (STRCMP(word_1, ==, "file") && STRCMP(word_2, ==, "perms")) {
sscanf(value, "%o", &(a_conf->file_perms));
} else if (STRCMP(word_1, ==, "rotate") &&
STRCMP(word_2, ==, "lock") && STRCMP(word_3, ==, "file")) {
/* may overwrite the inner default value, or last value */
if (STRCMP(value, ==, "self")) {
strcpy(a_conf->rotate_lock_file, a_conf->file);
} else {
strcpy(a_conf->rotate_lock_file, value);
}
} else if (STRCMP(word_1, ==, "default") && STRCMP(word_2, ==, "format")) {
/* so the input now is [format = "xxyy"], fit format's style */
strcpy(a_conf->default_format_line, line + nread);
} else if (STRCMP(word_1, ==, "reload") &&
STRCMP(word_2, ==, "conf") && STRCMP(word_3, ==, "period")) {
a_conf->reload_conf_period = zc_parse_byte_size(value);
} else if (STRCMP(word_1, ==, "fsync") && STRCMP(word_2, ==, "period")) {
a_conf->fsync_period = zc_parse_byte_size(value);
} else {
zc_error("name[%s] is not any one of global options", name);
if (a_conf->strict_init) return -1;
}
break;
case 2:
if (zlog_level_list_set(a_conf->levels, line)) {
zc_error("zlog_level_list_set fail");
if (a_conf->strict_init) return -1;
}
break;
case 3:
a_format = zlog_format_new(line, &(a_conf->time_cache_count));
if (!a_format) {
zc_error("zlog_format_new fail [%s]", line);
if (a_conf->strict_init) return -1;
else break;
}
if (zc_arraylist_add(a_conf->formats, a_format)) {
zlog_format_del(a_format);
zc_error("zc_arraylist_add fail");
return -1;
}
break;
case 4:
a_rule = zlog_rule_new(line,
a_conf->levels,
a_conf->default_format,
a_conf->formats,
a_conf->file_perms,
a_conf->fsync_period,
&(a_conf->time_cache_count));
if (!a_rule) {
zc_error("zlog_rule_new fail [%s]", line);
if (a_conf->strict_init) return -1;
else break;
}
if (zc_arraylist_add(a_conf->rules, a_rule)) {
zlog_rule_del(a_rule);
zc_error("zc_arraylist_add fail");
return -1;
}
break;
default:
zc_error("not in any section");
return -1;
}
return 0;
}
/*******************************************************************************/

@ -0,0 +1,47 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_conf_h
#define __zlog_conf_h
#include "zc_defs.h"
#include "format.h"
#include "rotater.h"
typedef struct zlog_conf_s {
char file[MAXLEN_PATH + 1];
char cfg_ptr[MAXLEN_CFG_LINE*MAXLINES_NO];
char mtime[20 + 1];
int strict_init;
size_t buf_size_min;
size_t buf_size_max;
char rotate_lock_file[MAXLEN_CFG_LINE + 1];
zlog_rotater_t *rotater;
char default_format_line[MAXLEN_CFG_LINE + 1];
zlog_format_t *default_format;
unsigned int file_perms;
size_t fsync_period;
size_t reload_conf_period;
zc_arraylist_t *levels;
zc_arraylist_t *formats;
zc_arraylist_t *rules;
int time_cache_count;
} zlog_conf_t;
extern zlog_conf_t * zlog_env_conf;
zlog_conf_t *zlog_conf_new(const char *config);
void zlog_conf_del(zlog_conf_t * a_conf);
void zlog_conf_profile(zlog_conf_t * a_conf, int flag);
#endif

@ -0,0 +1,182 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#define _GNU_SOURCE // For distros like Centos for syscall interface
#include "fmacros.h"
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include "zc_defs.h"
#include "event.h"
void zlog_event_profile(zlog_event_t * a_event, int flag)
{
zc_assert(a_event,);
zc_profile(flag, "---event[%p][%s,%s][%s(%ld),%s(%ld),%ld,%d][%p,%s][%ld,%ld][%ld,%ld][%d]---",
a_event,
a_event->category_name, a_event->host_name,
a_event->file, a_event->file_len,
a_event->func, a_event->func_len,
a_event->line, a_event->level,
a_event->hex_buf, a_event->str_format,
a_event->time_stamp.tv_sec, a_event->time_stamp.tv_usec,
(long)a_event->pid, (long)a_event->tid,
a_event->time_cache_count);
return;
}
/*******************************************************************************/
void zlog_event_del(zlog_event_t * a_event)
{
zc_assert(a_event,);
if (a_event->time_caches) free(a_event->time_caches);
zc_debug("zlog_event_del[%p]", a_event);
free(a_event);
return;
}
zlog_event_t *zlog_event_new(int time_cache_count)
{
zlog_event_t *a_event;
a_event = calloc(1, sizeof(zlog_event_t));
if (!a_event) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_event->time_caches = calloc(time_cache_count, sizeof(zlog_time_cache_t));
if (!a_event->time_caches) {
zc_error("calloc fail, errno[%d]", errno);
free(a_event);
return NULL;
}
a_event->time_cache_count = time_cache_count;
/*
* at the zlog_init we gethostname,
* u don't always change your hostname, eh?
*/
if (gethostname(a_event->host_name, sizeof(a_event->host_name) - 1)) {
zc_error("gethostname fail, errno[%d]", errno);
goto err;
}
a_event->host_name_len = strlen(a_event->host_name);
/* tid is bound to a_event
* as in whole lifecycle event persists
* even fork to oth pid, tid not change
*/
a_event->tid = pthread_self();
a_event->tid_str_len = sprintf(a_event->tid_str, "%lu", (unsigned long)a_event->tid);
a_event->tid_hex_str_len = sprintf(a_event->tid_hex_str, "%x", (unsigned int)a_event->tid);
#ifdef __linux__
a_event->ktid = syscall(SYS_gettid);
#elif __APPLE__
uint64_t tid64;
pthread_threadid_np(NULL, &tid64);
a_event->tid = (pid_t)tid64;
#endif
#if defined __linux__ || __APPLE__
a_event->ktid_str_len = sprintf(a_event->ktid_str, "%u", (unsigned int)a_event->ktid);
#endif
//zlog_event_profile(a_event, ZC_DEBUG);
return a_event;
err:
zlog_event_del(a_event);
return NULL;
}
/*******************************************************************************/
void zlog_event_set_fmt(zlog_event_t * a_event,
char *category_name, size_t category_name_len,
const char *file, size_t file_len, const char *func, size_t func_len, long line, int level,
const char *str_format, va_list str_args)
{
/*
* category_name point to zlog_category_output's category.name
*/
a_event->category_name = category_name;
a_event->category_name_len = category_name_len;
a_event->file = (char *) file;
a_event->file_len = file_len;
a_event->func = (char *) func;
a_event->func_len = func_len;
a_event->line = line;
a_event->level = level;
a_event->generate_cmd = ZLOG_FMT;
a_event->str_format = str_format;
va_copy(a_event->str_args, str_args);
/* pid should fetch eveytime, as no one knows,
* when does user fork his process
* so clean here, and fetch at spec.c
*/
a_event->pid = (pid_t) 0;
/* in a event's life cycle, time will be get when spec need,
* and keep unchange though all event's life cycle
* zlog_spec_write_time gettimeofday
*/
a_event->time_stamp.tv_sec = 0;
return;
}
void zlog_event_set_hex(zlog_event_t * a_event,
char *category_name, size_t category_name_len,
const char *file, size_t file_len, const char *func, size_t func_len, long line, int level,
const void *hex_buf, size_t hex_buf_len)
{
/*
* category_name point to zlog_category_output's category.name
*/
a_event->category_name = category_name;
a_event->category_name_len = category_name_len;
a_event->file = (char *) file;
a_event->file_len = file_len;
a_event->func = (char *) func;
a_event->func_len = func_len;
a_event->line = line;
a_event->level = level;
a_event->generate_cmd = ZLOG_HEX;
a_event->hex_buf = hex_buf;
a_event->hex_buf_len = hex_buf_len;
/* pid should fetch eveytime, as no one knows,
* when does user fork his process
* so clean here, and fetch at spec.c
*/
a_event->pid = (pid_t) 0;
/* in a event's life cycle, time will be get when spec need,
* and keep unchange though all event's life cycle
*/
a_event->time_stamp.tv_sec = 0;
return;
}

@ -0,0 +1,90 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_event_h
#define __zlog_event_h
#include <sys/types.h> /* for pid_t */
#include <sys/time.h> /* for struct timeval */
#include <pthread.h> /* for pthread_t */
#include <stdarg.h> /* for va_list */
#include "zc_defs.h"
typedef enum {
ZLOG_FMT = 0,
ZLOG_HEX = 1,
} zlog_event_cmd;
typedef struct zlog_time_cache_s {
char str[MAXLEN_CFG_LINE + 1];
size_t len;
time_t sec;
} zlog_time_cache_t;
typedef struct {
char *category_name;
size_t category_name_len;
char host_name[256 + 1];
size_t host_name_len;
const char *file;
size_t file_len;
const char *func;
size_t func_len;
long line;
int level;
const void *hex_buf;
size_t hex_buf_len;
const char *str_format;
va_list str_args;
zlog_event_cmd generate_cmd;
struct timeval time_stamp;
time_t time_local_sec;
struct tm time_local;
zlog_time_cache_t *time_caches;
int time_cache_count;
pid_t pid;
pid_t last_pid;
char pid_str[30 + 1];
size_t pid_str_len;
pthread_t tid;
char tid_str[30 + 1];
size_t tid_str_len;
char tid_hex_str[30 + 1];
size_t tid_hex_str_len;
#if defined __linux__ || __APPLE__
pid_t ktid;
char ktid_str[30+1];
size_t ktid_str_len;
#endif
} zlog_event_t;
zlog_event_t *zlog_event_new(int time_cache_count);
void zlog_event_del(zlog_event_t * a_event);
void zlog_event_profile(zlog_event_t * a_event, int flag);
void zlog_event_set_fmt(zlog_event_t * a_event,
char *category_name, size_t category_name_len,
const char *file, size_t file_len, const char *func, size_t func_len, long line, int level,
const char *str_format, va_list str_args);
void zlog_event_set_hex(zlog_event_t * a_event,
char *category_name, size_t category_name_len,
const char *file, size_t file_len, const char *func, size_t func_len, long line, int level,
const void *hex_buf, size_t hex_buf_len);
#endif

@ -0,0 +1,24 @@
#ifndef __zlog_fmacro_h
#define __zlog_fmacro_h
#define _DEFAULT_SOURCE
#if defined(__linux__) || defined(__OpenBSD__) || defined(_AIX)
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 700
#endif
#ifndef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED
#endif
#else
#define _XOPEN_SOURCE
#endif
#ifndef _LARGEFILE_SOURCE
#define _LARGEFILE_SOURCE
#endif
#ifndef _FILE_OFFSET_BITS
#define _FILE_OFFSET_BITS 64
#endif
#endif

@ -0,0 +1,164 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include "zc_defs.h"
#include "thread.h"
#include "spec.h"
#include "format.h"
void zlog_format_profile(zlog_format_t * a_format, int flag)
{
zc_assert(a_format,);
zc_profile(flag, "---format[%p][%s = %s(%p)]---",
a_format,
a_format->name,
a_format->pattern,
a_format->pattern_specs);
#if 0
int i;
zlog_spec_t *a_spec;
zc_arraylist_foreach(a_format->pattern_specs, i, a_spec) {
zlog_spec_profile(a_spec, flag);
}
#endif
return;
}
/*******************************************************************************/
void zlog_format_del(zlog_format_t * a_format)
{
zc_assert(a_format,);
if (a_format->pattern_specs) {
zc_arraylist_del(a_format->pattern_specs);
}
zc_debug("zlog_format_del[%p]", a_format);
free(a_format);
return;
}
zlog_format_t *zlog_format_new(char *line, int * time_cache_count)
{
int nscan = 0;
zlog_format_t *a_format = NULL;
int nread = 0;
const char *p_start;
const char *p_end;
char *p;
char *q;
zlog_spec_t *a_spec;
zc_assert(line, NULL);
a_format = calloc(1, sizeof(zlog_format_t));
if (!a_format) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
/* line default = "%d(%F %X.%l) %-6V (%c:%F:%L) - %m%n"
* name default
* pattern %d(%F %X.%l) %-6V (%c:%F:%L) - %m%n
*/
memset(a_format->name, 0x00, sizeof(a_format->name));
nread = 0;
nscan = sscanf(line, " %[^= \t] = %n", a_format->name, &nread);
if (nscan != 1) {
zc_error("format[%s], syntax wrong", line);
goto err;
}
if (*(line + nread) != '"') {
zc_error("the 1st char of pattern is not \", line+nread[%s]", line+nread);
goto err;
}
for (p = a_format->name; *p != '\0'; p++) {
if ((!isalnum(*p)) && (*p != '_')) {
zc_error("a_format->name[%s] character is not in [a-Z][0-9][_]", a_format->name);
goto err;
}
}
p_start = line + nread + 1;
p_end = strrchr(p_start, '"');
if (!p_end) {
zc_error("there is no \" at end of pattern, line[%s]", line);
goto err;
}
if (p_end - p_start > sizeof(a_format->pattern) - 1) {
zc_error("pattern is too long");
goto err;
}
memset(a_format->pattern, 0x00, sizeof(a_format->pattern));
memcpy(a_format->pattern, p_start, p_end - p_start);
if (zc_str_replace_env(a_format->pattern, sizeof(a_format->pattern))) {
zc_error("zc_str_replace_env fail");
goto err;
}
a_format->pattern_specs =
zc_arraylist_new((zc_arraylist_del_fn) zlog_spec_del);
if (!(a_format->pattern_specs)) {
zc_error("zc_arraylist_new fail");
goto err;
}
for (p = a_format->pattern; *p != '\0'; p = q) {
a_spec = zlog_spec_new(p, &q, time_cache_count);
if (!a_spec) {
zc_error("zlog_spec_new fail");
goto err;
}
if (zc_arraylist_add(a_format->pattern_specs, a_spec)) {
zlog_spec_del(a_spec);
zc_error("zc_arraylist_add fail");
goto err;
}
}
zlog_format_profile(a_format, ZC_DEBUG);
return a_format;
err:
zlog_format_del(a_format);
return NULL;
}
/*******************************************************************************/
/* return 0 success, or buf is full
* return -1 fail
*/
int zlog_format_gen_msg(zlog_format_t * a_format, zlog_thread_t * a_thread)
{
int i;
zlog_spec_t *a_spec;
zlog_buf_restart(a_thread->msg_buf);
zc_arraylist_foreach(a_format->pattern_specs, i, a_spec) {
if (zlog_spec_gen_msg(a_spec, a_thread) == 0) {
continue;
} else {
return -1;
}
}
return 0;
}

@ -0,0 +1,32 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_format_h
#define __zlog_format_h
#include "thread.h"
#include "zc_defs.h"
typedef struct zlog_format_s zlog_format_t;
struct zlog_format_s {
char name[MAXLEN_CFG_LINE + 1];
char pattern[MAXLEN_CFG_LINE + 1];
zc_arraylist_t *pattern_specs;
};
zlog_format_t *zlog_format_new(char *line, int * time_cache_count);
void zlog_format_del(zlog_format_t * a_format);
void zlog_format_profile(zlog_format_t * a_format, int flag);
int zlog_format_gen_msg(zlog_format_t * a_format, zlog_thread_t * a_thread);
#define zlog_format_has_name(a_format, fname) \
STRCMP(a_format->name, ==, fname)
#endif

@ -0,0 +1,141 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "syslog.h"
#include "zc_defs.h"
#include "level.h"
void zlog_level_profile(zlog_level_t *a_level, int flag)
{
zc_assert(a_level,);
zc_profile(flag, "---level[%p][%d,%s,%s,%d,%d]---",
a_level,
a_level->int_level,
a_level->str_uppercase,
a_level->str_lowercase,
(int) a_level->str_len,
a_level->syslog_level);
return;
}
/*******************************************************************************/
void zlog_level_del(zlog_level_t *a_level)
{
zc_assert(a_level,);
zc_debug("zlog_level_del[%p]", a_level);
free(a_level);
return;
}
static int syslog_level_atoi(char *str)
{
/* guess no unix system will choose -187
* as its syslog level, so it is a safe return value
*/
zc_assert(str, -187);
if (STRICMP(str, ==, "LOG_EMERG"))
return LOG_EMERG;
if (STRICMP(str, ==, "LOG_ALERT"))
return LOG_ALERT;
if (STRICMP(str, ==, "LOG_CRIT"))
return LOG_CRIT;
if (STRICMP(str, ==, "LOG_ERR"))
return LOG_ERR;
if (STRICMP(str, ==, "LOG_WARNING"))
return LOG_WARNING;
if (STRICMP(str, ==, "LOG_NOTICE"))
return LOG_NOTICE;
if (STRICMP(str, ==, "LOG_INFO"))
return LOG_INFO;
if (STRICMP(str, ==, "LOG_DEBUG"))
return LOG_DEBUG;
zc_error("wrong syslog level[%s]", str);
return -187;
}
/* line: TRACE = 10, LOG_ERR */
zlog_level_t *zlog_level_new(char *line)
{
zlog_level_t *a_level = NULL;
int i;
int nscan;
char str[MAXLEN_CFG_LINE + 1];
int l = 0;
char sl[MAXLEN_CFG_LINE + 1];
zc_assert(line, NULL);
memset(str, 0x00, sizeof(str));
memset(sl, 0x00, sizeof(sl));
nscan = sscanf(line, " %[^= \t] = %d ,%s", str, &l, sl);
if (nscan < 2) {
zc_error("level[%s], syntax wrong", line);
return NULL;
}
/* check level and str */
if ((l < 0) || (l > 255)) {
zc_error("l[%d] not in [0,255], wrong", l);
return NULL;
}
if (str[0] == '\0') {
zc_error("str[0] = 0");
return NULL;
}
a_level = calloc(1, sizeof(zlog_level_t));
if (!a_level) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_level->int_level = l;
/* fill syslog level */
if (sl[0] == '\0') {
a_level->syslog_level = LOG_DEBUG;
} else {
a_level->syslog_level = syslog_level_atoi(sl);
if (a_level->syslog_level == -187) {
zc_error("syslog_level_atoi fail");
goto err;
}
}
/* strncpy and toupper(str) */
for (i = 0; (i < sizeof(a_level->str_uppercase) - 1) && str[i] != '\0'; i++) {
(a_level->str_uppercase)[i] = toupper(str[i]);
(a_level->str_lowercase)[i] = tolower(str[i]);
}
if (str[i] != '\0') {
/* overflow */
zc_error("not enough space for str, str[%s] > %d", str, i);
goto err;
} else {
(a_level->str_uppercase)[i] = '\0';
(a_level->str_lowercase)[i] = '\0';
}
a_level->str_len = i;
//zlog_level_profile(a_level, ZC_DEBUG);
return a_level;
err:
zc_error("line[%s]", line);
zlog_level_del(a_level);
return NULL;
}

@ -0,0 +1,26 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_level_h
#define __zlog_level_h
#include "zc_defs.h"
typedef struct zlog_level_s {
int int_level;
char str_uppercase[MAXLEN_PATH + 1];
char str_lowercase[MAXLEN_PATH + 1];
size_t str_len;
int syslog_level;
} zlog_level_t;
zlog_level_t *zlog_level_new(char *line);
void zlog_level_del(zlog_level_t *a_level);
void zlog_level_profile(zlog_level_t *a_level, int flag);
#endif

@ -0,0 +1,145 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include "syslog.h"
#include "zc_defs.h"
#include "level.h"
#include "level_list.h"
/* zlog_level_list == zc_arraylist_t<zlog_level_t> */
void zlog_level_list_profile(zc_arraylist_t *levels, int flag)
{
int i;
zlog_level_t *a_level;
zc_assert(levels,);
zc_profile(flag, "--level_list[%p]--", levels);
zc_arraylist_foreach(levels, i, a_level) {
/* skip empty slots */
if (a_level) zlog_level_profile(a_level, flag);
}
return;
}
/*******************************************************************************/
void zlog_level_list_del(zc_arraylist_t *levels)
{
zc_assert(levels,);
zc_arraylist_del(levels);
zc_debug("zc_level_list_del[%p]", levels);
return;
}
static int zlog_level_list_set_default(zc_arraylist_t *levels)
{
return zlog_level_list_set(levels, "* = 0, LOG_INFO")
|| zlog_level_list_set(levels, "DEBUG = 20, LOG_DEBUG")
|| zlog_level_list_set(levels, "INFO = 40, LOG_INFO")
|| zlog_level_list_set(levels, "NOTICE = 60, LOG_NOTICE")
|| zlog_level_list_set(levels, "WARN = 80, LOG_WARNING")
|| zlog_level_list_set(levels, "ERROR = 100, LOG_ERR")
|| zlog_level_list_set(levels, "FATAL = 120, LOG_ALERT")
|| zlog_level_list_set(levels, "UNKNOWN = 254, LOG_ERR")
|| zlog_level_list_set(levels, "! = 255, LOG_INFO");
}
zc_arraylist_t *zlog_level_list_new(void)
{
zc_arraylist_t *levels;
levels = zc_arraylist_new((zc_arraylist_del_fn)zlog_level_del);
if (!levels) {
zc_error("zc_arraylist_new fail");
return NULL;
}
if (zlog_level_list_set_default(levels)) {
zc_error("zlog_level_set_default fail");
goto err;
}
//zlog_level_list_profile(levels, ZC_DEBUG);
return levels;
err:
zc_arraylist_del(levels);
return NULL;
}
/*******************************************************************************/
int zlog_level_list_set(zc_arraylist_t *levels, char *line)
{
zlog_level_t *a_level;
a_level = zlog_level_new(line);
if (!a_level) {
zc_error("zlog_level_new fail");
return -1;
}
if (zc_arraylist_set(levels, a_level->int_level, a_level)) {
zc_error("zc_arraylist_set fail");
goto err;
}
return 0;
err:
zc_error("line[%s]", line);
zlog_level_del(a_level);
return -1;
}
zlog_level_t *zlog_level_list_get(zc_arraylist_t *levels, int l)
{
zlog_level_t *a_level;
#if 0
if ((l <= 0) || (l > 254)) {
/* illegal input from zlog() */
zc_error("l[%d] not in (0,254), set to UNKOWN", l);
l = 254;
}
#endif
a_level = zc_arraylist_get(levels, l);
if (a_level) {
return a_level;
} else {
/* empty slot */
zc_error("l[%d] not in (0,254), or has no level defined,"
"see configure file define, set to UNKOWN", l);
return zc_arraylist_get(levels, 254);
}
}
/*******************************************************************************/
int zlog_level_list_atoi(zc_arraylist_t *levels, char *str)
{
int i;
zlog_level_t *a_level;
if (str == NULL || *str == '\0') {
zc_error("str is [%s], can't find level", str);
return -1;
}
zc_arraylist_foreach(levels, i, a_level) {
if (a_level && STRICMP(str, ==, a_level->str_uppercase)) {
return i;
}
}
zc_error("str[%s] can't found in level list", str);
return -1;
}

@ -0,0 +1,33 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_level_list_h
#define __zlog_level_list_h
#include "zc_defs.h"
#include "level.h"
zc_arraylist_t *zlog_level_list_new(void);
void zlog_level_list_del(zc_arraylist_t *levels);
void zlog_level_list_profile(zc_arraylist_t *levels, int flag);
/* conf init use, slow */
/* if l is wrong or str=="", return -1 */
int zlog_level_list_set(zc_arraylist_t *levels, char *line);
/* spec ouput use, fast */
/* rule output use, fast */
/* if not found, return levels[254] */
zlog_level_t *zlog_level_list_get(zc_arraylist_t *levels, int l);
/* rule init use, slow */
/* if not found, return -1 */
int zlog_level_list_atoi(zc_arraylist_t *levels, char *str);
#endif

@ -0,0 +1,204 @@
# zlog makefile
# Copyright (C) 2010-2012 Hardy Simpson <HardySimpson1984@gmail.com>
# This file is released under the LGPL 2.1 license, see the COPYING file
OBJ= \
buf.o \
category.o \
category_table.o \
conf.o \
event.o \
format.o \
level.o \
level_list.o \
mdc.o \
record.o \
record_table.o \
rotater.o \
rule.o \
spec.o \
thread.o \
zc_arraylist.o \
zc_hashtable.o \
zc_profile.o \
zc_util.o \
zlog.o
BINS=zlog-chk-conf
LIBNAME=libzlog
ZLOG_MAJOR=1
ZLOG_MINOR=2
# Fallback to gcc when $CC is not in $PATH.
CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
OPTIMIZATION?=-O2
WARNINGS=-Wall -Wstrict-prototypes -fwrapv
DEBUG?= -g -ggdb
REAL_CFLAGS=$(OPTIMIZATION) -fPIC -pthread $(CFLAGS) $(WARNINGS) $(DEBUG)
REAL_LDFLAGS=$(LDFLAGS) -pthread
DYLIBSUFFIX=so
STLIBSUFFIX=a
DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(ZLOG_MAJOR).$(ZLOG_MINOR)
DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(ZLOG_MAJOR)
DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
# Installation related variables
PREFIX?=/usr/local
INCLUDE_PATH=include
LIBRARY_PATH=lib
BINARY_PATH=bin
INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
INSTALL_BINARY_PATH= $(PREFIX)/$(BINARY_PATH)
# Platform-specific overrides
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
compiler_platform := $(shell sh -c '$(CC) --version|grep -i apple')
ifeq ($(uname_S),SunOS)
# REAL_LDFLAGS+= -ldl -lnsl -lsocket
DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
INSTALL= cp -r
endif
# For Darwin builds, check the compiler platform above is not empty. The covers cross compilation on Linux
ifneq ($(compiler_platform),)
DYLIBSUFFIX=dylib
DYLIB_MINOR_NAME=$(LIBNAME).$(ZLOG_MAJOR).$(ZLOG_MINOR).$(DYLIBSUFFIX)
DYLIB_MAJOR_NAME=$(LIBNAME).$(ZLOG_MAJOR).$(DYLIBSUFFIX)
DYLIB_MAKE_CMD=$(CC) -dynamiclib -install_name $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
endif
ifeq ($(uname_S),AIX)
# this logic of minor major is not relevant on AIX or at least not widely used
# not to mention dynamic linker .a preference...
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-G,-b64 -maix64 -pthread -o $(DYLIBNAME) $(LDFLAGS)
REAL_CFLAGS+= -maix64
STLIB_MAKE_CMD=OBJECT_MODE=64 ar rcs $(STLIBNAME) $(DYLIB_MAJOR_NAME)
endif
all: $(DYLIBNAME) $(BINS)
# Deps (use make dep to generate this)
buf.o: buf.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h buf.h
category.o: category.c fmacros.h category.h zc_defs.h zc_profile.h \
zc_arraylist.h zc_hashtable.h zc_xplatform.h zc_util.h thread.h event.h \
buf.h mdc.h rule.h format.h rotater.h record.h
category_table.o: category_table.c zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h category_table.h category.h \
thread.h event.h buf.h mdc.h
conf.o: conf.c fmacros.h conf.h zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \
mdc.h rotater.h rule.h record.h level_list.h level.h
event.o: event.c fmacros.h zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h event.h
format.o: format.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h thread.h event.h buf.h mdc.h spec.h format.h
level.o: level.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h level.h
level_list.o: level_list.c zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h level.h level_list.h
mdc.o: mdc.c mdc.h zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h
record.o: record.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h record.h
record_table.o: record_table.c zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h record_table.h record.h
rotater.o: rotater.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h rotater.h
rule.o: rule.c fmacros.h rule.h zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \
mdc.h rotater.h record.h level_list.h level.h spec.h
spec.o: spec.c fmacros.h spec.h event.h zc_defs.h zc_profile.h \
zc_arraylist.h zc_hashtable.h zc_xplatform.h zc_util.h buf.h thread.h \
mdc.h level_list.h level.h
thread.o: thread.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h event.h buf.h thread.h mdc.h
zc_arraylist.o: zc_arraylist.c zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h
zc_hashtable.o: zc_hashtable.c zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h
zc_profile.o: zc_profile.c fmacros.h zc_profile.h zc_xplatform.h
zc_util.o: zc_util.c zc_defs.h zc_profile.h zc_arraylist.h zc_hashtable.h \
zc_xplatform.h zc_util.h
zlog-chk-conf.o: zlog-chk-conf.c fmacros.h zlog.h
zlog.o: zlog.c fmacros.h conf.h zc_defs.h zc_profile.h zc_arraylist.h \
zc_hashtable.h zc_xplatform.h zc_util.h format.h thread.h event.h buf.h \
mdc.h rotater.h category_table.h category.h record_table.h \
record.h rule.h
$(DYLIBNAME): $(OBJ)
$(DYLIB_MAKE_CMD) $(OBJ) $(REAL_LDFLAGS)
# for use in test folder - linux and requirement for aix runtime
# resolving
cp -f $(DYLIBNAME) $(DYLIB_MAJOR_NAME)
cp -f $(DYLIBNAME) $(DYLIB_MINOR_NAME)
$(STLIBNAME): $(OBJ)
$(STLIB_MAKE_CMD) $(OBJ)
dynamic: $(DYLIBNAME)
static: $(STLIBNAME)
# Binaries:
zlog-chk-conf: zlog-chk-conf.o $(STLIBNAME) $(DYLIBNAME)
$(CC) -o $@ zlog-chk-conf.o -L. -lzlog $(REAL_LDFLAGS)
.c.o:
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
clean:
rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) *.o *.gcda *.gcno *.gcov $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
dep:
$(CC) -MM *.c
# Installation target
ifeq ($(uname_S),SunOS)
INSTALL?= cp -r
endif
ifeq ($(uname_S),AIX)
INSTALL?= cp -r
endif
INSTALL?= cp -a
install: $(DYLIBNAME) $(STLIBNAME)
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) $(INSTALL_BINARY_PATH)
$(INSTALL) zlog.h $(INSTALL_INCLUDE_PATH)
$(INSTALL) zlog-chk-conf $(INSTALL_BINARY_PATH)
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)
$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
32bit:
@echo ""
@echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"
@echo ""
$(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
gprof:
$(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
gcov:
$(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs"
coverage: gcov
make check
mkdir -p tmp/lcov
lcov -d . -c -o tmp/lcov/hiredis.info
genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info
noopt:
$(MAKE) OPTIMIZATION=""
.PHONY: all clean dep install 32bit gprof gcov noopt

@ -0,0 +1,145 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "mdc.h"
#include "zc_defs.h"
void zlog_mdc_profile(zlog_mdc_t *a_mdc, int flag)
{
zc_hashtable_entry_t *a_entry;
zlog_mdc_kv_t *a_mdc_kv;
zc_assert(a_mdc,);
zc_profile(flag, "---mdc[%p]---", a_mdc);
zc_hashtable_foreach(a_mdc->tab, a_entry) {
a_mdc_kv = a_entry->value;
zc_profile(flag, "----mdc_kv[%p][%s]-[%s]----",
a_mdc_kv,
a_mdc_kv->key, a_mdc_kv->value);
}
return;
}
/*******************************************************************************/
void zlog_mdc_del(zlog_mdc_t * a_mdc)
{
zc_assert(a_mdc,);
if (a_mdc->tab) zc_hashtable_del(a_mdc->tab);
zc_debug("zlog_mdc_del[%p]", a_mdc);
free(a_mdc);
return;
}
static void zlog_mdc_kv_del(zlog_mdc_kv_t * a_mdc_kv)
{
zc_debug("zlog_mdc_kv_del[%p]", a_mdc_kv);
free(a_mdc_kv);
}
static zlog_mdc_kv_t *zlog_mdc_kv_new(const char *key, const char *value)
{
zlog_mdc_kv_t *a_mdc_kv;
a_mdc_kv = calloc(1, sizeof(zlog_mdc_kv_t));
if (!a_mdc_kv) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
snprintf(a_mdc_kv->key, sizeof(a_mdc_kv->key), "%s", key);
a_mdc_kv->value_len = snprintf(a_mdc_kv->value, sizeof(a_mdc_kv->value), "%s", value);
return a_mdc_kv;
}
zlog_mdc_t *zlog_mdc_new(void)
{
zlog_mdc_t *a_mdc;
a_mdc = calloc(1, sizeof(zlog_mdc_t));
if (!a_mdc) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_mdc->tab = zc_hashtable_new(20,
zc_hashtable_str_hash,
zc_hashtable_str_equal, NULL,
(zc_hashtable_del_fn) zlog_mdc_kv_del);
if (!a_mdc->tab) {
zc_error("zc_hashtable_new fail");
goto err;
}
//zlog_mdc_profile(a_mdc, ZC_DEBUG);
return a_mdc;
err:
zlog_mdc_del(a_mdc);
return NULL;
}
/*******************************************************************************/
int zlog_mdc_put(zlog_mdc_t * a_mdc, const char *key, const char *value)
{
zlog_mdc_kv_t *a_mdc_kv;
a_mdc_kv = zlog_mdc_kv_new(key, value);
if (!a_mdc_kv) {
zc_error("zlog_mdc_kv_new failed");
return -1;
}
if (zc_hashtable_put(a_mdc->tab, a_mdc_kv->key, a_mdc_kv)) {
zc_error("zc_hashtable_put fail");
zlog_mdc_kv_del(a_mdc_kv);
return -1;
}
return 0;
}
void zlog_mdc_clean(zlog_mdc_t * a_mdc)
{
zc_hashtable_clean(a_mdc->tab);
return;
}
char *zlog_mdc_get(zlog_mdc_t * a_mdc, const char *key)
{
zlog_mdc_kv_t *a_mdc_kv;
a_mdc_kv = zc_hashtable_get(a_mdc->tab, key);
if (!a_mdc_kv) {
zc_error("zc_hashtable_get fail");
return NULL;
} else {
return a_mdc_kv->value;
}
}
zlog_mdc_kv_t *zlog_mdc_get_kv(zlog_mdc_t * a_mdc, const char *key)
{
zlog_mdc_kv_t *a_mdc_kv;
a_mdc_kv = zc_hashtable_get(a_mdc->tab, key);
if (!a_mdc_kv) {
zc_error("zc_hashtable_get fail");
return NULL;
} else {
return a_mdc_kv;
}
}
void zlog_mdc_remove(zlog_mdc_t * a_mdc, const char *key)
{
zc_hashtable_remove(a_mdc->tab, key);
return;
}

@ -0,0 +1,36 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_mdc_h
#define __zlog_mdc_h
#include "zc_defs.h"
typedef struct zlog_mdc_s zlog_mdc_t;
struct zlog_mdc_s {
zc_hashtable_t *tab;
};
zlog_mdc_t *zlog_mdc_new(void);
void zlog_mdc_del(zlog_mdc_t * a_mdc);
void zlog_mdc_profile(zlog_mdc_t *a_mdc, int flag);
void zlog_mdc_clean(zlog_mdc_t * a_mdc);
int zlog_mdc_put(zlog_mdc_t * a_mdc, const char *key, const char *value);
char *zlog_mdc_get(zlog_mdc_t * a_mdc, const char *key);
void zlog_mdc_remove(zlog_mdc_t * a_mdc, const char *key);
typedef struct zlog_mdc_kv_s {
char key[MAXLEN_PATH + 1];
char value[MAXLEN_PATH + 1];
size_t value_len;
} zlog_mdc_kv_t;
zlog_mdc_kv_t *zlog_mdc_get_kv(zlog_mdc_t * a_mdc, const char *key);
#endif

@ -0,0 +1,53 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "errno.h"
#include "zc_defs.h"
#include "record.h"
void zlog_record_profile(zlog_record_t *a_record, int flag)
{
zc_assert(a_record,);
zc_profile(flag, "--record:[%p][%s:%p]--", a_record, a_record->name, a_record->output);
return;
}
void zlog_record_del(zlog_record_t *a_record)
{
zc_assert(a_record,);
zc_debug("zlog_record_del[%p]", a_record);
free(a_record);
return;
}
zlog_record_t *zlog_record_new(const char *name, zlog_record_fn output)
{
zlog_record_t *a_record;
zc_assert(name, NULL);
zc_assert(output, NULL);
a_record = calloc(1, sizeof(zlog_record_t));
if (!a_record) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
if (strlen(name) > sizeof(a_record->name) - 1) {
zc_error("name[%s] is too long", name);
goto err;
}
strcpy(a_record->name, name);
a_record->output = output;
zlog_record_profile(a_record, ZC_DEBUG);
return a_record;
err:
zlog_record_del(a_record);
return NULL;
}

@ -0,0 +1,32 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_record_h
#define __zlog_record_h
#include "zc_defs.h"
/* record is user-defined output function and it's name from configure file */
typedef struct zlog_msg_s {
char *buf;
size_t len;
char *path;
} zlog_msg_t; /* 3 of this first, see need thread or not later */
typedef int (*zlog_record_fn)(zlog_msg_t * msg);
typedef struct zlog_record_s {
char name[MAXLEN_PATH + 1];
zlog_record_fn output;
} zlog_record_t;
zlog_record_t *zlog_record_new(const char *name, zlog_record_fn output);
void zlog_record_del(zlog_record_t *a_record);
void zlog_record_profile(zlog_record_t *a_record, int flag);
#endif

@ -0,0 +1,56 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include "zc_defs.h"
#include "record_table.h"
void zlog_record_table_profile(zc_hashtable_t * records, int flag)
{
zc_hashtable_entry_t *a_entry;
zlog_record_t *a_record;
zc_assert(records,);
zc_profile(flag, "-record_table[%p]-", records);
zc_hashtable_foreach(records, a_entry) {
a_record = (zlog_record_t *) a_entry->value;
zlog_record_profile(a_record, flag);
}
return;
}
/*******************************************************************************/
void zlog_record_table_del(zc_hashtable_t * records)
{
zc_assert(records,);
zc_hashtable_del(records);
zc_debug("zlog_record_table_del[%p]", records);
return;
}
zc_hashtable_t *zlog_record_table_new(void)
{
zc_hashtable_t *records;
records = zc_hashtable_new(20,
(zc_hashtable_hash_fn) zc_hashtable_str_hash,
(zc_hashtable_equal_fn) zc_hashtable_str_equal,
NULL, (zc_hashtable_del_fn) zlog_record_del);
if (!records) {
zc_error("zc_hashtable_new fail");
return NULL;
} else {
zlog_record_table_profile(records, ZC_DEBUG);
return records;
}
}
/*******************************************************************************/

@ -0,0 +1,19 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_record_table_h
#define __zlog_record_table_h
#include "zc_defs.h"
#include "record.h"
zc_hashtable_t *zlog_record_table_new(void);
void zlog_record_table_del(zc_hashtable_t * records);
void zlog_record_table_profile(zc_hashtable_t * records, int flag);
#endif

@ -0,0 +1,575 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <string.h>
#include <glob.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include "zc_defs.h"
#include "rotater.h"
#define ROLLING 1 /* aa.02->aa.03, aa.01->aa.02, aa->aa.01 */
#define SEQUENCE 2 /* aa->aa.03 */
typedef struct {
int index;
char path[MAXLEN_PATH + 1];
} zlog_file_t;
void zlog_rotater_profile(zlog_rotater_t * a_rotater, int flag)
{
zc_assert(a_rotater,);
zc_profile(flag, "--rotater[%p][%p,%s,%d][%s,%s,%s,%ld,%ld,%d,%d,%d]--",
a_rotater,
&(a_rotater->lock_mutex),
a_rotater->lock_file,
a_rotater->lock_fd,
a_rotater->base_path,
a_rotater->archive_path,
a_rotater->glob_path,
(long)a_rotater->num_start_len,
(long)a_rotater->num_end_len,
a_rotater->num_width,
a_rotater->mv_type,
a_rotater->max_count
);
if (a_rotater->files) {
int i;
zlog_file_t *a_file;
zc_arraylist_foreach(a_rotater->files, i, a_file) {
zc_profile(flag, "[%s,%d]->", a_file->path, a_file->index);
}
}
return;
}
/*******************************************************************************/
void zlog_rotater_del(zlog_rotater_t *a_rotater)
{
zc_assert(a_rotater,);
if (a_rotater->lock_fd) {
if (close(a_rotater->lock_fd)) {
zc_error("close fail, errno[%d]", errno);
}
}
if (pthread_mutex_destroy(&(a_rotater->lock_mutex))) {
zc_error("pthread_mutex_destroy fail, errno[%d]", errno);
}
zc_debug("zlog_rotater_del[%p]", a_rotater);
free(a_rotater);
return;
}
zlog_rotater_t *zlog_rotater_new(char *lock_file)
{
int fd = 0;
zlog_rotater_t *a_rotater;
zc_assert(lock_file, NULL);
a_rotater = calloc(1, sizeof(zlog_rotater_t));
if (!a_rotater) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
if (pthread_mutex_init(&(a_rotater->lock_mutex), NULL)) {
zc_error("pthread_mutex_init fail, errno[%d]", errno);
free(a_rotater);
return NULL;
}
/* depends on umask of the user here
* if user A create /tmp/zlog.lock 0600
* user B is unable to read /tmp/zlog.lock
* B has to choose another lock file except /tmp/zlog.lock
*/
fd = open(lock_file, O_RDWR | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
if (fd < 0) {
zc_error("open file[%s] fail, errno[%d]", lock_file, errno);
goto err;
}
a_rotater->lock_fd = fd;
a_rotater->lock_file = lock_file;
//zlog_rotater_profile(a_rotater, ZC_DEBUG);
return a_rotater;
err:
zlog_rotater_del(a_rotater);
return NULL;
}
/*******************************************************************************/
static void zlog_file_del(zlog_file_t * a_file)
{
zc_debug("del onefile[%p]", a_file);
zc_debug("a_file->path[%s]", a_file->path);
free(a_file);
}
static zlog_file_t *zlog_file_check_new(zlog_rotater_t * a_rotater, const char *path)
{
int nwrite;
int nread;
zlog_file_t *a_file;
/* base_path will not be in list */
if (STRCMP(a_rotater->base_path, ==, path)) {
return NULL;
}
/* omit dirs */
if ((path)[strlen(path) - 1] == '/') {
return NULL;
}
a_file = calloc(1, sizeof(zlog_file_t));
if (!a_file) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
nwrite = snprintf(a_file->path, sizeof(a_file->path), "%s", path);
if (nwrite < 0 || nwrite >= sizeof(a_file->path)) {
zc_error("snprintf fail or overflow, nwrite=[%d], errno[%d]", nwrite, errno);
goto err;
}
nread = 0;
sscanf(a_file->path + a_rotater->num_start_len, "%d%n", &(a_file->index), &(nread));
if (a_rotater->num_width != 0) {
if (nread < a_rotater->num_width) {
zc_warn("aa.1.log is not expect, need aa.01.log");
goto err;
}
} /* else all file is ok */
return a_file;
err:
free(a_file);
return NULL;
}
static int zlog_file_cmp(zlog_file_t * a_file_1, zlog_file_t * a_file_2)
{
return (a_file_1->index > a_file_2->index);
}
static int zlog_rotater_add_archive_files(zlog_rotater_t * a_rotater)
{
int rc = 0;
glob_t glob_buf;
size_t pathc;
char **pathv;
zlog_file_t *a_file;
a_rotater->files = zc_arraylist_new((zc_arraylist_del_fn)zlog_file_del);
if (!a_rotater->files) {
zc_error("zc_arraylist_new fail");
return -1;
}
/* scan file which is aa.*.log and aa */
rc = glob(a_rotater->glob_path, GLOB_ERR | GLOB_MARK | GLOB_NOSORT, NULL, &glob_buf);
if (rc == GLOB_NOMATCH) {
goto exit;
} else if (rc) {
zc_error("glob err, rc=[%d], errno[%d]", rc, errno);
return -1;
}
pathv = glob_buf.gl_pathv;
pathc = glob_buf.gl_pathc;
/* check and find match aa.[0-9]*.log, depend on num_width */
for (; pathc-- > 0; pathv++) {
a_file = zlog_file_check_new(a_rotater, *pathv);
if (!a_file) {
zc_warn("not the expect pattern file");
continue;
}
/* file in list aa.00, aa.01, aa.02... */
rc = zc_arraylist_sortadd(a_rotater->files,
(zc_arraylist_cmp_fn)zlog_file_cmp, a_file);
if (rc) {
zc_error("zc_arraylist_sortadd fail");
goto err;
}
}
exit:
globfree(&glob_buf);
return 0;
err:
globfree(&glob_buf);
return -1;
}
static int zlog_rotater_seq_files(zlog_rotater_t * a_rotater)
{
int rc = 0;
int nwrite = 0;
int i, j;
zlog_file_t *a_file;
char new_path[MAXLEN_PATH + 1];
zc_arraylist_foreach(a_rotater->files, i, a_file) {
if (a_rotater->max_count > 0
&& i < zc_arraylist_len(a_rotater->files) - a_rotater->max_count) {
/* unlink aa.0 aa.1 .. aa.(n-c) */
rc = unlink(a_file->path);
if (rc) {
zc_error("unlink[%s] fail, errno[%d]",a_file->path , errno);
return -1;
}
continue;
}
}
if (zc_arraylist_len(a_rotater->files) > 0) { /* list is not empty */
a_file = zc_arraylist_get(a_rotater->files, zc_arraylist_len(a_rotater->files)-1);
if (!a_file) {
zc_error("zc_arraylist_get fail");
return -1;
}
j = zc_max(zc_arraylist_len(a_rotater->files)-1, a_file->index) + 1;
} else {
j = 0;
}
/* do the base_path mv */
memset(new_path, 0x00, sizeof(new_path));
nwrite = snprintf(new_path, sizeof(new_path), "%.*s%0*d%s",
(int) a_rotater->num_start_len, a_rotater->glob_path,
a_rotater->num_width, j,
a_rotater->glob_path + a_rotater->num_end_len);
if (nwrite < 0 || nwrite >= sizeof(new_path)) {
zc_error("nwirte[%d], overflow or errno[%d]", nwrite, errno);
return -1;
}
if (rename(a_rotater->base_path, new_path)) {
zc_error("rename[%s]->[%s] fail, errno[%d]", a_rotater->base_path, new_path, errno);
return -1;
}
return 0;
}
static int zlog_rotater_roll_files(zlog_rotater_t * a_rotater)
{
int i;
int rc = 0;
int nwrite;
char new_path[MAXLEN_PATH + 1];
zlog_file_t *a_file;
/* now in the list, aa.0 aa.1 aa.2 aa.02... */
for (i = zc_arraylist_len(a_rotater->files) - 1; i > -1; i--) {
a_file = zc_arraylist_get(a_rotater->files, i);
if (!a_file) {
zc_error("zc_arraylist_get fail");
return -1;
}
if (a_rotater->max_count > 0 && i >= a_rotater->max_count - 1) {
/* remove file.3 >= 3*/
rc = unlink(a_file->path);
if (rc) {
zc_error("unlink[%s] fail, errno[%d]",a_file->path , errno);
return -1;
}
continue;
}
/* begin rename aa.01.log -> aa.02.log , using i, as index in list maybe repeat */
memset(new_path, 0x00, sizeof(new_path));
nwrite = snprintf(new_path, sizeof(new_path), "%.*s%0*d%s",
(int) a_rotater->num_start_len, a_rotater->glob_path,
a_rotater->num_width, i + 1,
a_rotater->glob_path + a_rotater->num_end_len);
if (nwrite < 0 || nwrite >= sizeof(new_path)) {
zc_error("nwirte[%d], overflow or errno[%d]", nwrite, errno);
return -1;
}
if (rename(a_file->path, new_path)) {
zc_error("rename[%s]->[%s] fail, errno[%d]", a_file->path, new_path, errno);
return -1;
}
}
/* do the base_path mv */
memset(new_path, 0x00, sizeof(new_path));
nwrite = snprintf(new_path, sizeof(new_path), "%.*s%0*d%s",
(int) a_rotater->num_start_len, a_rotater->glob_path,
a_rotater->num_width, 0,
a_rotater->glob_path + a_rotater->num_end_len);
if (nwrite < 0 || nwrite >= sizeof(new_path)) {
zc_error("nwirte[%d], overflow or errno[%d]", nwrite, errno);
return -1;
}
if (rename(a_rotater->base_path, new_path)) {
zc_error("rename[%s]->[%s] fail, errno[%d]", a_rotater->base_path, new_path, errno);
return -1;
}
return 0;
}
static int zlog_rotater_parse_archive_path(zlog_rotater_t * a_rotater)
{
int nwrite;
int nread;
char *p;
size_t len;
/* no archive path is set */
if (a_rotater->archive_path[0] == '\0') {
nwrite = snprintf(a_rotater->glob_path, sizeof(a_rotater->glob_path),
"%s.*", a_rotater->base_path);
if (nwrite < 0 || nwrite > sizeof(a_rotater->glob_path)) {
zc_error("nwirte[%d], overflow or errno[%d]", nwrite, errno);
return -1;
}
a_rotater->mv_type = ROLLING;
a_rotater->num_width = 0;
a_rotater->num_start_len = strlen(a_rotater->base_path) + 1;
a_rotater->num_end_len = strlen(a_rotater->base_path) + 2;
return 0;
} else {
/* find the 1st # */
p = strchr(a_rotater->archive_path, '#');
if (!p) {
zc_error("no # in archive_path[%s]", a_rotater->archive_path);
return -1;
}
nread = 0;
sscanf(p, "#%d%n", &(a_rotater->num_width), &nread);
if (nread == 0) nread = 1;
if (*(p+nread) == 'r') {
a_rotater->mv_type = ROLLING;
} else if (*(p+nread) == 's') {
a_rotater->mv_type = SEQUENCE;
} else {
zc_error("#r or #s not found");
return -1;
}
/* copy and substitue #i to * in glob_path*/
len = p - a_rotater->archive_path;
if (len > sizeof(a_rotater->glob_path) - 1) {
zc_error("sizeof glob_path not enough,len[%ld]", (long) len);
return -1;
}
memcpy(a_rotater->glob_path, a_rotater->archive_path, len);
nwrite = snprintf(a_rotater->glob_path + len, sizeof(a_rotater->glob_path) - len,
"*%s", p + nread + 1);
if (nwrite < 0 || nwrite > sizeof(a_rotater->glob_path) - len) {
zc_error("nwirte[%d], overflow or errno[%d]", nwrite, errno);
return -1;
}
a_rotater->num_start_len = len;
a_rotater->num_end_len = len + 1;
}
return 0;
}
static void zlog_rotater_clean(zlog_rotater_t *a_rotater)
{
a_rotater->base_path = NULL;
a_rotater->archive_path = NULL;
a_rotater->max_count = 0;
a_rotater->mv_type = 0;
a_rotater->num_width = 0;
a_rotater->num_start_len = 0;
a_rotater->num_end_len = 0;
memset(a_rotater->glob_path, 0x00, sizeof(a_rotater->glob_path));
if (a_rotater->files) zc_arraylist_del(a_rotater->files);
a_rotater->files = NULL;
}
static int zlog_rotater_lsmv(zlog_rotater_t *a_rotater,
char *base_path, char *archive_path, int archive_max_count)
{
int rc = 0;
a_rotater->base_path = base_path;
a_rotater->archive_path = archive_path;
a_rotater->max_count = archive_max_count;
rc = zlog_rotater_parse_archive_path(a_rotater);
if (rc) {
zc_error("zlog_rotater_parse_archive_path fail");
goto err;
}
rc = zlog_rotater_add_archive_files(a_rotater);
if (rc) {
zc_error("zlog_rotater_add_archive_files fail");
goto err;
}
if (a_rotater->mv_type == ROLLING) {
rc = zlog_rotater_roll_files(a_rotater);
if (rc) {
zc_error("zlog_rotater_roll_files fail");
goto err;
}
} else if (a_rotater->mv_type == SEQUENCE) {
rc = zlog_rotater_seq_files(a_rotater);
if (rc) {
zc_error("zlog_rotater_seq_files fail");
goto err;
}
}
zlog_rotater_clean(a_rotater);
return 0;
err:
zlog_rotater_clean(a_rotater);
return -1;
}
/*******************************************************************************/
static int zlog_rotater_trylock(zlog_rotater_t *a_rotater)
{
int rc;
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
rc = pthread_mutex_trylock(&(a_rotater->lock_mutex));
if (rc == EBUSY) {
zc_warn("pthread_mutex_trylock fail, as lock_mutex is locked by other threads");
return -1;
} else if (rc != 0) {
zc_error("pthread_mutex_trylock fail, rc[%d]", rc);
return -1;
}
if (fcntl(a_rotater->lock_fd, F_SETLK, &fl)) {
if (errno == EAGAIN || errno == EACCES) {
/* lock by other process, that's right, go on */
/* EAGAIN on linux */
/* EACCES on AIX */
zc_warn("fcntl lock fail, as file is lock by other process");
} else {
zc_error("lock fd[%d] fail, errno[%d]", a_rotater->lock_fd, errno);
}
if (pthread_mutex_unlock(&(a_rotater->lock_mutex))) {
zc_error("pthread_mutex_unlock fail, errno[%d]", errno);
}
return -1;
}
return 0;
}
static int zlog_rotater_unlock(zlog_rotater_t *a_rotater)
{
int rc = 0;
struct flock fl;
fl.l_type = F_UNLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
if (fcntl(a_rotater->lock_fd, F_SETLK, &fl)) {
rc = -1;
zc_error("unlock fd[%s] fail, errno[%d]", a_rotater->lock_fd, errno);
}
if (pthread_mutex_unlock(&(a_rotater->lock_mutex))) {
rc = -1;
zc_error("pthread_mutext_unlock fail, errno[%d]", errno);
}
return rc;
}
int zlog_rotater_rotate(zlog_rotater_t *a_rotater,
char *base_path, size_t msg_len,
char *archive_path, long archive_max_size, int archive_max_count)
{
int rc = 0;
struct zlog_stat info;
zc_assert(base_path, -1);
if (zlog_rotater_trylock(a_rotater)) {
zc_warn("zlog_rotater_trylock fail, maybe lock by other process or threads");
return 0;
}
if (stat(base_path, &info)) {
rc = -1;
zc_error("stat [%s] fail, errno[%d]", base_path, errno);
goto exit;
}
if (info.st_size + msg_len <= archive_max_size) {
/* file not so big,
* may alread rotate by oth process or thread,
* return */
rc = 0;
goto exit;
}
/* begin list and move files */
rc = zlog_rotater_lsmv(a_rotater, base_path, archive_path, archive_max_count);
if (rc) {
zc_error("zlog_rotater_lsmv [%s] fail, return", base_path);
rc = -1;
} /* else if (rc == 0) */
//zc_debug("zlog_rotater_file_ls_mv success");
exit:
/* unlock file */
if (zlog_rotater_unlock(a_rotater)) {
zc_error("zlog_rotater_unlock fail");
}
return rc;
}
/*******************************************************************************/

@ -0,0 +1,45 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_rotater_h
#define __zlog_rotater_h
#include "zc_defs.h"
typedef struct zlog_rotater_s {
pthread_mutex_t lock_mutex;
char *lock_file;
int lock_fd;
/* single-use members */
char *base_path; /* aa.log */
char *archive_path; /* aa.#5i.log */
char glob_path[MAXLEN_PATH + 1]; /* aa.*.log */
size_t num_start_len; /* 3, offset to glob_path */
size_t num_end_len; /* 6, offset to glob_path */
int num_width; /* 5 */
int mv_type; /* ROLLING or SEQUENCE */
int max_count;
zc_arraylist_t *files;
} zlog_rotater_t;
zlog_rotater_t *zlog_rotater_new(char *lock_file);
void zlog_rotater_del(zlog_rotater_t *a_rotater);
/*
* return
* -1 fail
* 0 no rotate, or rotate and success
*/
int zlog_rotater_rotate(zlog_rotater_t *a_rotater,
char *base_path, size_t msg_len,
char *archive_path, long archive_max_size, int archive_max_count);
void zlog_rotater_profile(zlog_rotater_t *a_rotater, int flag);
#endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,88 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
/**
* @file rule.h
* @brief rule decide to output in format by category & level
*/
#ifndef __zlog_rule_h
#define __zlog_rule_h
#include <stdio.h>
#include <pthread.h>
#include "zc_defs.h"
#include "format.h"
#include "thread.h"
#include "rotater.h"
#include "record.h"
typedef struct zlog_rule_s zlog_rule_t;
typedef int (*zlog_rule_output_fn) (zlog_rule_t * a_rule, zlog_thread_t * a_thread);
struct zlog_rule_s {
char category[MAXLEN_CFG_LINE + 1];
char compare_char;
/*
* [*] log all level
* [.] log level >= rule level, default
* [=] log level == rule level
* [!] log level != rule level
*/
int level;
unsigned char level_bitmap[32]; /* for category determine whether ouput or not */
unsigned int file_perms;
int file_open_flags;
char file_path[MAXLEN_PATH + 1];
zc_arraylist_t *dynamic_specs;
int static_fd;
dev_t static_dev;
ino_t static_ino;
long archive_max_size;
int archive_max_count;
char archive_path[MAXLEN_PATH + 1];
zc_arraylist_t *archive_specs;
FILE *pipe_fp;
int pipe_fd;
size_t fsync_period;
size_t fsync_count;
zc_arraylist_t *levels;
int syslog_facility;
zlog_format_t *format;
zlog_rule_output_fn output;
char record_name[MAXLEN_PATH + 1];
char record_path[MAXLEN_PATH + 1];
zlog_record_fn record_func;
};
zlog_rule_t *zlog_rule_new(char * line,
zc_arraylist_t * levels,
zlog_format_t * default_format,
zc_arraylist_t * formats,
unsigned int file_perms,
size_t fsync_period,
int * time_cache_count);
void zlog_rule_del(zlog_rule_t * a_rule);
void zlog_rule_profile(zlog_rule_t * a_rule, int flag);
int zlog_rule_match_category(zlog_rule_t * a_rule, char *category);
int zlog_rule_is_wastebin(zlog_rule_t * a_rule);
int zlog_rule_set_record(zlog_rule_t * a_rule, zc_hashtable_t *records);
int zlog_rule_output(zlog_rule_t * a_rule, zlog_thread_t * a_thread);
#endif

@ -0,0 +1,667 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "fmacros.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <sys/time.h>
#include <time.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
#include "conf.h"
#include "spec.h"
#include "level_list.h"
#include "zc_defs.h"
#define ZLOG_DEFAULT_TIME_FMT "%F %T"
#define ZLOG_HEX_HEAD \
"\n 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF"
/*******************************************************************************/
void zlog_spec_profile(zlog_spec_t * a_spec, int flag)
{
zc_assert(a_spec,);
zc_profile(flag, "----spec[%p][%.*s][%s|%d][%s,%ld,%ld,%s][%s]----",
a_spec,
a_spec->len, a_spec->str,
a_spec->time_fmt,
a_spec->time_cache_index,
a_spec->print_fmt, (long)a_spec->max_width, (long)a_spec->min_width, a_spec->left_fill_zeros ? "true" : "false",
a_spec->mdc_key);
return;
}
/*******************************************************************************/
/* implementation of write function */
static int zlog_spec_write_time(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
zlog_time_cache_t * a_cache = a_thread->event->time_caches + a_spec->time_cache_index;
time_t now_sec = a_thread->event->time_stamp.tv_sec;
struct tm *time_local = &(a_thread->event->time_local);
/* the event meet the 1st time_spec in his life cycle */
if (!now_sec) {
gettimeofday(&(a_thread->event->time_stamp), NULL);
now_sec = a_thread->event->time_stamp.tv_sec;
}
/* When this event's last cached time_local is not now */
if (a_thread->event->time_local_sec != now_sec) {
localtime_r(&(now_sec), time_local);
a_thread->event->time_local_sec = now_sec;
}
/* When this spec's last cache time string is not now */
if (a_cache->sec != now_sec) {
a_cache->len = strftime(a_cache->str, sizeof(a_cache->str), a_spec->time_fmt, time_local);
a_cache->sec = now_sec;
}
return zlog_buf_append(a_buf, a_cache->str, a_cache->len);
}
#if 0
static int zlog_spec_write_time_D(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (!a_thread->event->time_stamp.tv_sec) {
gettimeofday(&(a_thread->event->time_stamp), NULL);
}
/*
* It is modified when time slips one second.
* So it is a strong cache, as Default time format is always %F %T.
* That's why I said %D is faster than %d()
*/
if (a_thread->event->time_stamp.tv_sec != a_thread->event->time_last_D) {
a_thread->event->time_last_D = a_thread->event->time_stamp.tv_sec;
localtime_r(&(a_thread->event->time_stamp.tv_sec),
&(a_thread->event->time_local));
strftime(a_thread->event->time_cache_D,
sizeof(a_thread->event->time_cache_D),
ZLOG_DEFAULT_TIME_FMT, &(a_thread->event->time_local) );
}
return zlog_buf_append(a_buf, a_thread->event->time_cache_D, sizeof(a_thread->event->time_cache_D) - 1);
}
#endif
static int zlog_spec_write_ms(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (!a_thread->event->time_stamp.tv_sec) {
gettimeofday(&(a_thread->event->time_stamp), NULL);
}
return zlog_buf_printf_dec32(a_buf, (a_thread->event->time_stamp.tv_usec / 1000), 3);
}
static int zlog_spec_write_us(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (!a_thread->event->time_stamp.tv_sec) {
gettimeofday(&(a_thread->event->time_stamp), NULL);
}
return zlog_buf_printf_dec32(a_buf, a_thread->event->time_stamp.tv_usec, 6);
}
static int zlog_spec_write_mdc(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
zlog_mdc_kv_t *a_mdc_kv;
a_mdc_kv = zlog_mdc_get_kv(a_thread->mdc, a_spec->mdc_key);
if (!a_mdc_kv) {
zc_error("zlog_mdc_get_kv key[%s] fail", a_spec->mdc_key);
return 0;
}
return zlog_buf_append(a_buf, a_mdc_kv->value, a_mdc_kv->value_len);
}
static int zlog_spec_write_str(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, a_spec->str, a_spec->len);
}
static int zlog_spec_write_category(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, a_thread->event->category_name, a_thread->event->category_name_len);
}
static int zlog_spec_write_srcfile(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (!a_thread->event->file) {
return zlog_buf_append(a_buf, "(file=null)", sizeof("(file=null)") - 1);
} else {
return zlog_buf_append(a_buf, a_thread->event->file, a_thread->event->file_len);
}
}
static int zlog_spec_write_srcfile_neat(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
char *p;
if ((p = strrchr(a_thread->event->file, '/')) != NULL) {
return zlog_buf_append(a_buf, p + 1,
(char*)a_thread->event->file + a_thread->event->file_len - p - 1);
} else {
if (!a_thread->event->file) {
return zlog_buf_append(a_buf, "(file=null)", sizeof("(file=null)") - 1);
} else {
return zlog_buf_append(a_buf, a_thread->event->file, a_thread->event->file_len);
}
}
}
static int zlog_spec_write_srcline(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_printf_dec64(a_buf, a_thread->event->line, 0);
}
static int zlog_spec_write_srcfunc(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (!a_thread->event->file) {
return zlog_buf_append(a_buf, "(func=null)", sizeof("(func=null)") - 1);
} else {
return zlog_buf_append(a_buf, a_thread->event->func, a_thread->event->func_len);
}
}
static int zlog_spec_write_hostname(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, a_thread->event->host_name, a_thread->event->host_name_len);
}
static int zlog_spec_write_newline(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, FILE_NEWLINE, FILE_NEWLINE_LEN);
}
static int zlog_spec_write_cr(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, "\r", 1);
}
static int zlog_spec_write_percent(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
return zlog_buf_append(a_buf, "%", 1);
}
static int zlog_spec_write_pid(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
/* 1st in event lifecycle */
if (!a_thread->event->pid) {
a_thread->event->pid = getpid();
/* compare with previous event */
if (a_thread->event->pid != a_thread->event->last_pid) {
a_thread->event->last_pid = a_thread->event->pid;
a_thread->event->pid_str_len
= sprintf(a_thread->event->pid_str, "%u", a_thread->event->pid);
}
}
return zlog_buf_append(a_buf, a_thread->event->pid_str, a_thread->event->pid_str_len);
}
static int zlog_spec_write_tid_hex(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
/* don't need to get tid again, as tmap_new_thread fetched it already */
/* and fork not change tid */
return zlog_buf_append(a_buf, a_thread->event->tid_hex_str, a_thread->event->tid_hex_str_len);
}
static int zlog_spec_write_tid_long(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
/* don't need to get tid again, as tmap_new_thread fetched it already */
/* and fork not change tid */
return zlog_buf_append(a_buf, a_thread->event->tid_str, a_thread->event->tid_str_len);
}
static int zlog_spec_write_ktid(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
/* don't need to get ktid again, as tmap_new_thread fetched it already */
/* and fork not change tid */
return zlog_buf_append(a_buf, a_thread->event->ktid_str, a_thread->event->ktid_str_len);
}
static int zlog_spec_write_level_lowercase(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
zlog_level_t *a_level;
a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level);
return zlog_buf_append(a_buf, a_level->str_lowercase, a_level->str_len);
}
static int zlog_spec_write_level_uppercase(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
zlog_level_t *a_level;
a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level);
return zlog_buf_append(a_buf, a_level->str_uppercase, a_level->str_len);
}
static int zlog_spec_write_usrmsg(zlog_spec_t * a_spec, zlog_thread_t * a_thread, zlog_buf_t * a_buf)
{
if (a_thread->event->generate_cmd == ZLOG_FMT) {
if (a_thread->event->str_format) {
return zlog_buf_vprintf(a_buf,
a_thread->event->str_format,
a_thread->event->str_args);
} else {
return zlog_buf_append(a_buf, "format=(null)", sizeof("format=(null)")-1);
}
} else if (a_thread->event->generate_cmd == ZLOG_HEX) {
int rc;
long line_offset;
long byte_offset;
/* thread buf start == null or len <= 0 */
if (a_thread->event->hex_buf == NULL) {
rc = zlog_buf_append(a_buf, "buf=(null)", sizeof("buf=(null)")-1);
goto zlog_hex_exit;
}
rc = zlog_buf_append(a_buf, ZLOG_HEX_HEAD, sizeof(ZLOG_HEX_HEAD)-1);
if (rc) {
goto zlog_hex_exit;
}
line_offset = 0;
//byte_offset = 0;
while (1) {
unsigned char c;
rc = zlog_buf_append(a_buf, "\n", 1);
if (rc) goto zlog_hex_exit;
rc = zlog_buf_printf_dec64(a_buf, line_offset + 1, 10);
if (rc) goto zlog_hex_exit;
rc = zlog_buf_append(a_buf, " ", 3);
if (rc) goto zlog_hex_exit;
for (byte_offset = 0; byte_offset < 16; byte_offset++) {
if (line_offset * 16 + byte_offset < a_thread->event->hex_buf_len) {
c = *((unsigned char *)a_thread->event->hex_buf
+ line_offset * 16 + byte_offset);
rc = zlog_buf_printf_hex(a_buf, c, 2);
if (rc) goto zlog_hex_exit;
rc = zlog_buf_append(a_buf, " ", 1);
if (rc) goto zlog_hex_exit;
} else {
rc = zlog_buf_append(a_buf, " ", 3);
if (rc) goto zlog_hex_exit;
}
}
rc = zlog_buf_append(a_buf, " ", 2);
if (rc) goto zlog_hex_exit;
for (byte_offset = 0; byte_offset < 16; byte_offset++) {
if (line_offset * 16 + byte_offset < a_thread->event->hex_buf_len) {
c = *((unsigned char *)a_thread->event->hex_buf
+ line_offset * 16 + byte_offset);
if (c >= 32 && c <= 126) {
rc = zlog_buf_append(a_buf,(char*)&c, 1);
if (rc) goto zlog_hex_exit;
} else {
rc = zlog_buf_append(a_buf, ".", 1);
if (rc) goto zlog_hex_exit;
}
} else {
rc = zlog_buf_append(a_buf, " ", 1);
if (rc) goto zlog_hex_exit;
}
}
if (line_offset * 16 + byte_offset >= a_thread->event->hex_buf_len) {
break;
}
line_offset++;
}
zlog_hex_exit:
if (rc < 0) {
zc_error("write hex msg fail");
return -1;
} else if (rc > 0) {
zc_error("write hex msg, buf is full");
return 1;
}
return 0;
}
return 0;
}
/*******************************************************************************/
/* implementation of gen function */
static int zlog_spec_gen_msg_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
/* no need to reprint %1.2d here */
return a_spec->write_buf(a_spec, a_thread, a_thread->msg_buf);
}
static int zlog_spec_gen_msg_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
int rc;
zlog_buf_restart(a_thread->pre_msg_buf);
rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_msg_buf);
if (rc < 0) {
zc_error("a_spec->gen_buf fail");
return -1;
} else if (rc > 0) {
/* buf is full, try printf */
}
return zlog_buf_adjust_append(a_thread->msg_buf,
zlog_buf_str(a_thread->pre_msg_buf), zlog_buf_len(a_thread->pre_msg_buf),
a_spec->left_adjust, a_spec->left_fill_zeros, a_spec->min_width, a_spec->max_width);
}
/*******************************************************************************/
static int zlog_spec_gen_path_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
/* no need to reprint %1.2d here */
return a_spec->write_buf(a_spec, a_thread, a_thread->path_buf);
}
static int zlog_spec_gen_path_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
int rc;
zlog_buf_restart(a_thread->pre_path_buf);
rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_path_buf);
if (rc < 0) {
zc_error("a_spec->gen_buf fail");
return -1;
} else if (rc > 0) {
/* buf is full, try printf */
}
return zlog_buf_adjust_append(a_thread->path_buf,
zlog_buf_str(a_thread->pre_path_buf), zlog_buf_len(a_thread->pre_path_buf),
a_spec->left_adjust, a_spec->left_fill_zeros, a_spec->min_width, a_spec->max_width);
}
/*******************************************************************************/
static int zlog_spec_gen_archive_path_direct(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
/* no need to reprint %1.2d here */
return a_spec->write_buf(a_spec, a_thread, a_thread->archive_path_buf);
}
static int zlog_spec_gen_archive_path_reformat(zlog_spec_t * a_spec, zlog_thread_t * a_thread)
{
int rc;
zlog_buf_restart(a_thread->pre_path_buf);
rc = a_spec->write_buf(a_spec, a_thread, a_thread->pre_path_buf);
if (rc < 0) {
zc_error("a_spec->gen_buf fail");
return -1;
} else if (rc > 0) {
/* buf is full, try printf */
}
return zlog_buf_adjust_append(a_thread->archive_path_buf,
zlog_buf_str(a_thread->pre_path_buf), zlog_buf_len(a_thread->pre_path_buf),
a_spec->left_adjust, a_spec->left_fill_zeros, a_spec->min_width, a_spec->max_width);
}
/*******************************************************************************/
static int zlog_spec_parse_print_fmt(zlog_spec_t * a_spec)
{
/* -12.35 12 .35 */
char *p, *q;
long i, j;
p = a_spec->print_fmt;
if (*p == '-') {
a_spec->left_adjust = 1;
p++;
} else {
if (*p == '0') {
a_spec->left_fill_zeros = 1;
}
a_spec->left_adjust = 0;
}
i = j = 0;
sscanf(p, "%ld.", &i);
q = strchr(p, '.');
if (q) sscanf(q, ".%ld", &j);
a_spec->min_width = (size_t) i;
a_spec->max_width = (size_t) j;
return 0;
}
/*******************************************************************************/
void zlog_spec_del(zlog_spec_t * a_spec)
{
zc_assert(a_spec,);
zc_debug("zlog_spec_del[%p]", a_spec);
free(a_spec);
}
/* a spec may consist of
* a const string: /home/bb
* a string begin with %: %12.35d(%F %X,%l)
*/
zlog_spec_t *zlog_spec_new(char *pattern_start, char **pattern_next, int *time_cache_count)
{
char *p;
int nscan = 0;
int nread = 0;
zlog_spec_t *a_spec;
zc_assert(pattern_start, NULL);
zc_assert(pattern_next, NULL);
a_spec = calloc(1, sizeof(zlog_spec_t));
if (!a_spec) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_spec->str = p = pattern_start;
switch (*p) {
case '%':
/* a string begin with %: %12.35d(%F %X) */
/* process width and precision char in %-12.35P */
nread = 0;
nscan = sscanf(p, "%%%[.0-9-]%n", a_spec->print_fmt, &nread);
if (nscan == 1) {
a_spec->gen_msg = zlog_spec_gen_msg_reformat;
a_spec->gen_path = zlog_spec_gen_path_reformat;
a_spec->gen_archive_path = zlog_spec_gen_archive_path_reformat;
if (zlog_spec_parse_print_fmt(a_spec)) {
zc_error("zlog_spec_parse_print_fmt fail");
goto err;
}
} else {
nread = 1; /* skip the % char */
a_spec->gen_msg = zlog_spec_gen_msg_direct;
a_spec->gen_path = zlog_spec_gen_path_direct;
a_spec->gen_archive_path = zlog_spec_gen_archive_path_direct;
}
p += nread;
if (*p == 'd') {
if (*(p+1) != '(') {
/* without '(' , use default */
strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
p++;
} else if (STRNCMP(p, ==, "d()", 3)) {
/* with () but without detail time format,
* keep a_spec->time_fmt=="" */
strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
p += 3;
} else {
nread = 0;
nscan = sscanf(p, "d(%[^)])%n", a_spec->time_fmt, &nread);
if (nscan != 1) {
nread = 0;
}
p += nread;
if (*(p - 1) != ')') {
zc_error("in string[%s] can't find match \')\'", a_spec->str);
goto err;
}
}
a_spec->time_cache_index = *time_cache_count;
(*time_cache_count)++;
a_spec->write_buf = zlog_spec_write_time;
*pattern_next = p;
a_spec->len = p - a_spec->str;
break;
}
if (*p == 'M') {
nread = 0;
nscan = sscanf(p, "M(%[^)])%n", a_spec->mdc_key, &nread);
if (nscan != 1) {
nread = 0;
if (STRNCMP(p, ==, "M()", 3)) {
nread = 3;
}
}
p += nread;
if (*(p - 1) != ')') {
zc_error("in string[%s] can't find match \')\'", a_spec->str);
goto err;
}
*pattern_next = p;
a_spec->len = p - a_spec->str;
a_spec->write_buf = zlog_spec_write_mdc;
break;
}
if (STRNCMP(p, ==, "ms", 2)) {
p += 2;
*pattern_next = p;
a_spec->len = p - a_spec->str;
a_spec->write_buf = zlog_spec_write_ms;
break;
} else if (STRNCMP(p, ==, "us", 2)) {
p += 2;
*pattern_next = p;
a_spec->len = p - a_spec->str;
a_spec->write_buf = zlog_spec_write_us;
break;
}
*pattern_next = p + 1;
a_spec->len = p - a_spec->str + 1;
switch (*p) {
case 'c':
a_spec->write_buf = zlog_spec_write_category;
break;
case 'D':
strcpy(a_spec->time_fmt, ZLOG_DEFAULT_TIME_FMT);
a_spec->time_cache_index = *time_cache_count;
(*time_cache_count)++;
a_spec->write_buf = zlog_spec_write_time;
break;
case 'F':
a_spec->write_buf = zlog_spec_write_srcfile;
break;
case 'f':
a_spec->write_buf = zlog_spec_write_srcfile_neat;
break;
case 'H':
a_spec->write_buf = zlog_spec_write_hostname;
break;
case 'k':
a_spec->write_buf = zlog_spec_write_ktid;
break;
case 'L':
a_spec->write_buf = zlog_spec_write_srcline;
break;
case 'm':
a_spec->write_buf = zlog_spec_write_usrmsg;
break;
case 'n':
a_spec->write_buf = zlog_spec_write_newline;
break;
case 'r':
a_spec->write_buf = zlog_spec_write_cr;
break;
case 'p':
a_spec->write_buf = zlog_spec_write_pid;
break;
case 'U':
a_spec->write_buf = zlog_spec_write_srcfunc;
break;
case 'v':
a_spec->write_buf = zlog_spec_write_level_lowercase;
break;
case 'V':
a_spec->write_buf = zlog_spec_write_level_uppercase;
break;
case 't':
a_spec->write_buf = zlog_spec_write_tid_hex;
break;
case 'T':
a_spec->write_buf = zlog_spec_write_tid_long;
break;
case '%':
a_spec->write_buf = zlog_spec_write_percent;
break;
default:
zc_error("str[%s] in wrong format, p[%c]", a_spec->str, *p);
goto err;
}
break;
default:
/* a const string: /home/bb */
*pattern_next = strchr(p, '%');
if (*pattern_next) {
a_spec->len = *pattern_next - p;
} else {
a_spec->len = strlen(p);
*pattern_next = p + a_spec->len;
}
a_spec->write_buf = zlog_spec_write_str;
a_spec->gen_msg = zlog_spec_gen_msg_direct;
a_spec->gen_path = zlog_spec_gen_path_direct;
a_spec->gen_archive_path = zlog_spec_gen_archive_path_direct;
}
zlog_spec_profile(a_spec, ZC_DEBUG);
return a_spec;
err:
zlog_spec_del(a_spec);
return NULL;
}

@ -0,0 +1,60 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_spec_h
#define __zlog_spec_h
#include "event.h"
#include "buf.h"
#include "thread.h"
typedef struct zlog_spec_s zlog_spec_t;
/* write buf, according to each spec's Conversion Characters */
typedef int (*zlog_spec_write_fn) (zlog_spec_t * a_spec,
zlog_thread_t * a_thread,
zlog_buf_t * a_buf);
/* gen a_thread->msg or gen a_thread->path by using write_fn */
typedef int (*zlog_spec_gen_fn) (zlog_spec_t * a_spec,
zlog_thread_t * a_thread);
struct zlog_spec_s {
char *str;
int len;
char time_fmt[MAXLEN_CFG_LINE + 1];
int time_cache_index;
char mdc_key[MAXLEN_PATH + 1];
char print_fmt[MAXLEN_CFG_LINE + 1];
int left_adjust;
int left_fill_zeros;
size_t max_width;
size_t min_width;
zlog_spec_write_fn write_buf;
zlog_spec_gen_fn gen_msg;
zlog_spec_gen_fn gen_path;
zlog_spec_gen_fn gen_archive_path;
};
zlog_spec_t *zlog_spec_new(char *pattern_start, char **pattern_end, int * time_cache_count);
void zlog_spec_del(zlog_spec_t * a_spec);
void zlog_spec_profile(zlog_spec_t * a_spec, int flag);
#define zlog_spec_gen_msg(a_spec, a_thread) \
a_spec->gen_msg(a_spec, a_thread)
#define zlog_spec_gen_path(a_spec, a_thread) \
a_spec->gen_path(a_spec, a_thread)
#define zlog_spec_gen_archive_path(a_spec, a_thread) \
a_spec->gen_archive_path(a_spec, a_thread)
#endif

@ -0,0 +1,184 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <pthread.h>
#include <errno.h>
#include "zc_defs.h"
#include "event.h"
#include "buf.h"
#include "thread.h"
#include "mdc.h"
void zlog_thread_profile(zlog_thread_t * a_thread, int flag)
{
zc_assert(a_thread,);
zc_profile(flag, "--thread[%p][%p][%p][%p,%p,%p,%p,%p]--",
a_thread,
a_thread->mdc,
a_thread->event,
a_thread->pre_path_buf,
a_thread->path_buf,
a_thread->archive_path_buf,
a_thread->pre_msg_buf,
a_thread->msg_buf);
zlog_mdc_profile(a_thread->mdc, flag);
zlog_event_profile(a_thread->event, flag);
zlog_buf_profile(a_thread->pre_path_buf, flag);
zlog_buf_profile(a_thread->path_buf, flag);
zlog_buf_profile(a_thread->archive_path_buf, flag);
zlog_buf_profile(a_thread->pre_msg_buf, flag);
zlog_buf_profile(a_thread->msg_buf, flag);
return;
}
/*******************************************************************************/
void zlog_thread_del(zlog_thread_t * a_thread)
{
zc_assert(a_thread,);
if (a_thread->mdc)
zlog_mdc_del(a_thread->mdc);
if (a_thread->event)
zlog_event_del(a_thread->event);
if (a_thread->pre_path_buf)
zlog_buf_del(a_thread->pre_path_buf);
if (a_thread->path_buf)
zlog_buf_del(a_thread->path_buf);
if (a_thread->archive_path_buf)
zlog_buf_del(a_thread->archive_path_buf);
if (a_thread->pre_msg_buf)
zlog_buf_del(a_thread->pre_msg_buf);
if (a_thread->msg_buf)
zlog_buf_del(a_thread->msg_buf);
zc_debug("zlog_thread_del[%p]", a_thread);
free(a_thread);
return;
}
zlog_thread_t *zlog_thread_new(int init_version, size_t buf_size_min, size_t buf_size_max, int time_cache_count)
{
zlog_thread_t *a_thread;
a_thread = calloc(1, sizeof(zlog_thread_t));
if (!a_thread) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_thread->init_version = init_version;
a_thread->mdc = zlog_mdc_new();
if (!a_thread->mdc) {
zc_error("zlog_mdc_new fail");
goto err;
}
a_thread->event = zlog_event_new(time_cache_count);
if (!a_thread->event) {
zc_error("zlog_event_new fail");
goto err;
}
a_thread->pre_path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL);
if (!a_thread->pre_path_buf) {
zc_error("zlog_buf_new fail");
goto err;
}
a_thread->path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL);
if (!a_thread->path_buf) {
zc_error("zlog_buf_new fail");
goto err;
}
a_thread->archive_path_buf = zlog_buf_new(MAXLEN_PATH + 1, MAXLEN_PATH + 1, NULL);
if (!a_thread->archive_path_buf) {
zc_error("zlog_buf_new fail");
goto err;
}
a_thread->pre_msg_buf = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE);
if (!a_thread->pre_msg_buf) {
zc_error("zlog_buf_new fail");
goto err;
}
a_thread->msg_buf = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE);
if (!a_thread->msg_buf) {
zc_error("zlog_buf_new fail");
goto err;
}
//zlog_thread_profile(a_thread, ZC_DEBUG);
return a_thread;
err:
zlog_thread_del(a_thread);
return NULL;
}
/*******************************************************************************/
int zlog_thread_rebuild_msg_buf(zlog_thread_t * a_thread, size_t buf_size_min, size_t buf_size_max)
{
zlog_buf_t *pre_msg_buf_new = NULL;
zlog_buf_t *msg_buf_new = NULL;
zc_assert(a_thread, -1);
if ( (a_thread->msg_buf->size_min == buf_size_min)
&& (a_thread->msg_buf->size_max == buf_size_max)) {
zc_debug("buf size not changed, no need rebuild");
return 0;
}
pre_msg_buf_new = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE);
if (!pre_msg_buf_new) {
zc_error("zlog_buf_new fail");
goto err;
}
msg_buf_new = zlog_buf_new(buf_size_min, buf_size_max, "..." FILE_NEWLINE);
if (!msg_buf_new) {
zc_error("zlog_buf_new fail");
goto err;
}
zlog_buf_del(a_thread->pre_msg_buf);
a_thread->pre_msg_buf = pre_msg_buf_new;
zlog_buf_del(a_thread->msg_buf);
a_thread->msg_buf = msg_buf_new;
return 0;
err:
if (pre_msg_buf_new) zlog_buf_del(pre_msg_buf_new);
if (msg_buf_new) zlog_buf_del(msg_buf_new);
return -1;
}
int zlog_thread_rebuild_event(zlog_thread_t * a_thread, int time_cache_count)
{
zlog_event_t *event_new = NULL;
zc_assert(a_thread, -1);
event_new = zlog_event_new(time_cache_count);
if (!event_new) {
zc_error("zlog_event_new fail");
goto err;
}
zlog_event_del(a_thread->event);
a_thread->event = event_new;
return 0;
err:
if (event_new) zlog_event_del(event_new);
return -1;
}
/*******************************************************************************/

@ -0,0 +1,38 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_thread_h
#define __zlog_thread_h
#include "zc_defs.h"
#include "event.h"
#include "buf.h"
#include "mdc.h"
typedef struct {
int init_version;
zlog_mdc_t *mdc;
zlog_event_t *event;
zlog_buf_t *pre_path_buf;
zlog_buf_t *path_buf;
zlog_buf_t *archive_path_buf;
zlog_buf_t *pre_msg_buf;
zlog_buf_t *msg_buf;
} zlog_thread_t;
void zlog_thread_del(zlog_thread_t * a_thread);
void zlog_thread_profile(zlog_thread_t * a_thread, int flag);
zlog_thread_t *zlog_thread_new(int init_version,
size_t buf_size_min, size_t buf_size_max, int time_cache_count);
int zlog_thread_rebuild_msg_buf(zlog_thread_t * a_thread, size_t buf_size_min, size_t buf_size_max);
int zlog_thread_rebuild_event(zlog_thread_t * a_thread, int time_cache_count);
#endif

@ -0,0 +1 @@
#define ZLOG_VERSION "1.2.12"

@ -0,0 +1,132 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include "zc_defs.h"
zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del)
{
zc_arraylist_t *a_list;
a_list = (zc_arraylist_t *) calloc(1, sizeof(zc_arraylist_t));
if (!a_list) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_list->size = ARRAY_LIST_DEFAULT_SIZE;
a_list->len = 0;
/* this could be NULL */
a_list->del = del;
a_list->array = (void **)calloc(a_list->size, sizeof(void *));
if (!a_list->array) {
zc_error("calloc fail, errno[%d]", errno);
free(a_list);
return NULL;
}
return a_list;
}
void zc_arraylist_del(zc_arraylist_t * a_list)
{
int i;
if (!a_list)
return;
if (a_list->del) {
for (i = 0; i < a_list->len; i++) {
if (a_list->array[i])
a_list->del(a_list->array[i]);
}
}
if (a_list->array)
free(a_list->array);
free(a_list);
return;
}
static int zc_arraylist_expand_inner(zc_arraylist_t * a_list, int max)
{
void *tmp;
int new_size;
int diff_size;
new_size = zc_max(a_list->size * 2, max);
tmp = realloc(a_list->array, new_size * sizeof(void *));
if (!tmp) {
zc_error("realloc fail, errno[%d]", errno);
return -1;
}
a_list->array = (void **)tmp;
diff_size = new_size - a_list->size;
if (diff_size) memset(a_list->array + a_list->size, 0x00, diff_size * sizeof(void *));
a_list->size = new_size;
return 0;
}
int zc_arraylist_set(zc_arraylist_t * a_list, int idx, void *data)
{
if (idx > a_list->size - 1) {
if (zc_arraylist_expand_inner(a_list, idx)) {
zc_error("expand_internal fail");
return -1;
}
}
if (a_list->array[idx] && a_list->del) a_list->del(a_list->array[idx]);
a_list->array[idx] = data;
if (a_list->len <= idx)
a_list->len = idx + 1;
return 0;
}
int zc_arraylist_add(zc_arraylist_t * a_list, void *data)
{
return zc_arraylist_set(a_list, a_list->len, data);
}
/* assum idx < len */
static int zc_arraylist_insert_inner(zc_arraylist_t * a_list, int idx,
void *data)
{
if (a_list->array[idx] == NULL) {
a_list->array[idx] = data;
return 0;
}
if (a_list->len > a_list->size - 1) {
if (zc_arraylist_expand_inner(a_list, 0)) {
zc_error("expand_internal fail");
return -1;
}
}
memmove(a_list->array + idx + 1, a_list->array + idx,
(a_list->len - idx) * sizeof(void *));
a_list->array[idx] = data;
a_list->len++;
return 0;
}
int zc_arraylist_sortadd(zc_arraylist_t * a_list, zc_arraylist_cmp_fn cmp,
void *data)
{
int i;
for (i = 0; i < a_list->len; i++) {
if ((*cmp) (a_list->array[i], data) > 0)
break;
}
if (i == a_list->len)
return zc_arraylist_add(a_list, data);
else
return zc_arraylist_insert_inner(a_list, i, data);
}

@ -0,0 +1,41 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_arraylist_h
#define __zc_arraylist_h
#define ARRAY_LIST_DEFAULT_SIZE 32
typedef void (*zc_arraylist_del_fn) (void *data);
typedef int (*zc_arraylist_cmp_fn) (void *data1, void *data2);
/* make zc_arraylist_foreach speed up, so keep struct defination here */
typedef struct {
void **array;
int len;
int size;
zc_arraylist_del_fn del;
} zc_arraylist_t;
zc_arraylist_t *zc_arraylist_new(zc_arraylist_del_fn del);
void zc_arraylist_del(zc_arraylist_t * a_list);
int zc_arraylist_set(zc_arraylist_t * a_list, int i, void *data);
int zc_arraylist_add(zc_arraylist_t * a_list, void *data);
int zc_arraylist_sortadd(zc_arraylist_t * a_list, zc_arraylist_cmp_fn cmp,
void *data);
#define zc_arraylist_len(a_list) (a_list->len)
#define zc_arraylist_get(a_list, i) \
((i >= a_list->len) ? NULL : a_list->array[i])
#define zc_arraylist_foreach(a_list, i, a_unit) \
for(i = 0, a_unit = a_list->array[0]; (i < a_list->len) && (a_unit = a_list->array[i], 1) ; i++)
#endif

@ -0,0 +1,18 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_defs_h
#define __zc_defs_h
#include "zc_profile.h"
#include "zc_arraylist.h"
#include "zc_hashtable.h"
#include "zc_xplatform.h"
#include "zc_util.h"
#endif

@ -0,0 +1,330 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdlib.h>
#include <errno.h>
#include <pthread.h>
#include "zc_defs.h"
#include "zc_hashtable.h"
struct zc_hashtable_s {
size_t nelem;
zc_hashtable_entry_t **tab;
size_t tab_size;
zc_hashtable_hash_fn hash;
zc_hashtable_equal_fn equal;
zc_hashtable_del_fn key_del;
zc_hashtable_del_fn value_del;
};
zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash,
zc_hashtable_equal_fn equal,
zc_hashtable_del_fn key_del,
zc_hashtable_del_fn value_del)
{
zc_hashtable_t *a_table;
a_table = calloc(1, sizeof(*a_table));
if (!a_table) {
zc_error("calloc fail, errno[%d]", errno);
return NULL;
}
a_table->tab = calloc(a_size, sizeof(*(a_table->tab)));
if (!a_table->tab) {
zc_error("calloc fail, errno[%d]", errno);
free(a_table);
return NULL;
}
a_table->tab_size = a_size;
a_table->nelem = 0;
a_table->hash = hash;
a_table->equal = equal;
/* these two could be NULL */
a_table->key_del = key_del;
a_table->value_del = value_del;
return a_table;
}
void zc_hashtable_del(zc_hashtable_t * a_table)
{
size_t i;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q;
if (!a_table) {
zc_error("a_table[%p] is NULL, just do nothing", a_table);
return;
}
for (i = 0; i < a_table->tab_size; i++) {
for (p = (a_table->tab)[i]; p; p = q) {
q = p->next;
if (a_table->key_del) {
a_table->key_del(p->key);
}
if (a_table->value_del) {
a_table->value_del(p->value);
}
free(p);
}
}
if (a_table->tab)
free(a_table->tab);
free(a_table);
return;
}
void zc_hashtable_clean(zc_hashtable_t * a_table)
{
size_t i;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q;
for (i = 0; i < a_table->tab_size; i++) {
for (p = (a_table->tab)[i]; p; p = q) {
q = p->next;
if (a_table->key_del) {
a_table->key_del(p->key);
}
if (a_table->value_del) {
a_table->value_del(p->value);
}
free(p);
}
(a_table->tab)[i] = NULL;
}
a_table->nelem = 0;
return;
}
static int zc_hashtable_rehash(zc_hashtable_t * a_table)
{
size_t i;
size_t j;
size_t tab_size;
zc_hashtable_entry_t **tab;
zc_hashtable_entry_t *p;
zc_hashtable_entry_t *q;
tab_size = 2 * a_table->tab_size;
tab = calloc(tab_size, sizeof(*tab));
if (!tab) {
zc_error("calloc fail, errno[%d]", errno);
return -1;
}
for (i = 0; i < a_table->tab_size; i++) {
for (p = (a_table->tab)[i]; p; p = q) {
q = p->next;
p->next = NULL;
p->prev = NULL;
j = p->hash_key % tab_size;
if (tab[j]) {
tab[j]->prev = p;
p->next = tab[j];
}
tab[j] = p;
}
}
free(a_table->tab);
a_table->tab = tab;
a_table->tab_size = tab_size;
return 0;
}
zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t * a_table, const void *a_key)
{
unsigned int i;
zc_hashtable_entry_t *p;
i = a_table->hash(a_key) % a_table->tab_size;
for (p = (a_table->tab)[i]; p; p = p->next) {
if (a_table->equal(a_key, p->key))
return p;
}
return NULL;
}
void *zc_hashtable_get(zc_hashtable_t * a_table, const void *a_key)
{
unsigned int i;
zc_hashtable_entry_t *p;
i = a_table->hash(a_key) % a_table->tab_size;
for (p = (a_table->tab)[i]; p; p = p->next) {
if (a_table->equal(a_key, p->key))
return p->value;
}
return NULL;
}
int zc_hashtable_put(zc_hashtable_t * a_table, void *a_key, void *a_value)
{
int rc = 0;
unsigned int i;
zc_hashtable_entry_t *p = NULL;
i = a_table->hash(a_key) % a_table->tab_size;
for (p = (a_table->tab)[i]; p; p = p->next) {
if (a_table->equal(a_key, p->key))
break;
}
if (p) {
if (a_table->key_del) {
a_table->key_del(p->key);
}
if (a_table->value_del) {
a_table->value_del(p->value);
}
p->key = a_key;
p->value = a_value;
return 0;
} else {
if (a_table->nelem > a_table->tab_size * 1.3) {
rc = zc_hashtable_rehash(a_table);
if (rc) {
zc_error("rehash fail");
return -1;
}
}
p = calloc(1, sizeof(*p));
if (!p) {
zc_error("calloc fail, errno[%d]", errno);
return -1;
}
p->hash_key = a_table->hash(a_key);
p->key = a_key;
p->value = a_value;
p->next = NULL;
p->prev = NULL;
i = p->hash_key % a_table->tab_size;
if ((a_table->tab)[i]) {
(a_table->tab)[i]->prev = p;
p->next = (a_table->tab)[i];
}
(a_table->tab)[i] = p;
a_table->nelem++;
}
return 0;
}
void zc_hashtable_remove(zc_hashtable_t * a_table, const void *a_key)
{
zc_hashtable_entry_t *p;
unsigned int i;
if (!a_table || !a_key) {
zc_error("a_table[%p] or a_key[%p] is NULL, just do nothing", a_table, a_key);
return;
}
i = a_table->hash(a_key) % a_table->tab_size;
for (p = (a_table->tab)[i]; p; p = p->next) {
if (a_table->equal(a_key, p->key))
break;
}
if (!p) {
zc_error("p[%p] not found in hashtable", p);
return;
}
if (a_table->key_del) {
a_table->key_del(p->key);
}
if (a_table->value_del) {
a_table->value_del(p->value);
}
if (p->next) {
p->next->prev = p->prev;
}
if (p->prev) {
p->prev->next = p->next;
} else {
unsigned int i;
i = p->hash_key % a_table->tab_size;
a_table->tab[i] = p->next;
}
free(p);
a_table->nelem--;
return;
}
zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t * a_table)
{
size_t i;
zc_hashtable_entry_t *p;
for (i = 0; i < a_table->tab_size; i++) {
for (p = (a_table->tab)[i]; p; p = p->next) {
if (p)
return p;
}
}
return NULL;
}
zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t * a_table, zc_hashtable_entry_t * a_entry)
{
size_t i;
size_t j;
if (a_entry->next)
return a_entry->next;
i = a_entry->hash_key % a_table->tab_size;
for (j = i + 1; j < a_table->tab_size; j++) {
if ((a_table->tab)[j]) {
return (a_table->tab)[j];
}
}
return NULL;
}
/*******************************************************************************/
unsigned int zc_hashtable_str_hash(const void *str)
{
unsigned int h = 5381;
const char *p = (const char *)str;
while (*p != '\0')
h = ((h << 5) + h) + (*p++); /* hash * 33 + c */
return h;
}
int zc_hashtable_str_equal(const void *key1, const void *key2)
{
return (STRCMP((const char *)key1, ==, (const char *)key2));
}

@ -0,0 +1,49 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_hashtalbe_h
#define __zc_hashtalbe_h
#include <stdlib.h>
typedef struct zc_hashtable_entry_s {
unsigned int hash_key;
void *key;
void *value;
struct zc_hashtable_entry_s *prev;
struct zc_hashtable_entry_s *next;
} zc_hashtable_entry_t;
typedef struct zc_hashtable_s zc_hashtable_t;
typedef unsigned int (*zc_hashtable_hash_fn) (const void *key);
typedef int (*zc_hashtable_equal_fn) (const void *key1, const void *key2);
typedef void (*zc_hashtable_del_fn) (void *kv);
zc_hashtable_t *zc_hashtable_new(size_t a_size,
zc_hashtable_hash_fn hash_fn,
zc_hashtable_equal_fn equal_fn,
zc_hashtable_del_fn key_del_fn,
zc_hashtable_del_fn value_del_fn);
void zc_hashtable_del(zc_hashtable_t * a_table);
void zc_hashtable_clean(zc_hashtable_t * a_table);
int zc_hashtable_put(zc_hashtable_t * a_table, void *a_key, void *a_value);
zc_hashtable_entry_t *zc_hashtable_get_entry(zc_hashtable_t * a_table, const void *a_key);
void *zc_hashtable_get(zc_hashtable_t * a_table, const void *a_key);
void zc_hashtable_remove(zc_hashtable_t * a_table, const void *a_key);
zc_hashtable_entry_t *zc_hashtable_begin(zc_hashtable_t * a_table);
zc_hashtable_entry_t *zc_hashtable_next(zc_hashtable_t * a_table, zc_hashtable_entry_t * a_entry);
#define zc_hashtable_foreach(a_table, a_entry) \
for(a_entry = zc_hashtable_begin(a_table); a_entry; a_entry = zc_hashtable_next(a_table, a_entry))
unsigned int zc_hashtable_str_hash(const void *str);
int zc_hashtable_str_equal(const void *key1, const void *key2);
#endif

@ -0,0 +1,86 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "fmacros.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include "zc_profile.h"
#include "zc_xplatform.h"
static void zc_time(char *time_str, size_t time_str_size)
{
time_t tt;
struct tm local_time;
time(&tt);
localtime_r(&tt, &local_time);
strftime(time_str, time_str_size, "%m-%d %T", &local_time);
return;
}
int zc_profile_inner(int flag, const char *file, const long line, const char *fmt, ...)
{
va_list args;
char time_str[20 + 1];
FILE *fp = NULL;
static char *debug_log = NULL;
static char *error_log = NULL;
static size_t init_flag = 0;
if (!init_flag) {
init_flag = 1;
debug_log = getenv("ZLOG_PROFILE_DEBUG");
error_log = getenv("ZLOG_PROFILE_ERROR");
}
switch (flag) {
case ZC_DEBUG:
if (debug_log == NULL) return 0;
fp = fopen(debug_log, "a");
if (!fp) return -1;
zc_time(time_str, sizeof(time_str));
fprintf(fp, "%s DEBUG (%d:%s:%ld) ", time_str, getpid(), file, line);
break;
case ZC_WARN:
if (error_log == NULL) return 0;
fp = fopen(error_log, "a");
if (!fp) return -1;
zc_time(time_str, sizeof(time_str));
fprintf(fp, "%s WARN (%d:%s:%ld) ", time_str, getpid(), file, line);
break;
case ZC_ERROR:
if (error_log == NULL) return 0;
fp = fopen(error_log, "a");
if (!fp) return -1;
zc_time(time_str, sizeof(time_str));
fprintf(fp, "%s ERROR (%d:%s:%ld) ", time_str, getpid(), file, line);
break;
}
/* writing file twice(time & msg) is not atomic
* may cause cross
* but avoid log size limit */
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
fprintf(fp, "\n");
fclose(fp);
return 0;
}

@ -0,0 +1,53 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_profile_h
#define __zc_profile_h
#include <stdarg.h>
#define EMPTY()
#define zc_assert(expr, rv) \
if(!(expr)) { \
zc_error(#expr" is null or 0"); \
return rv; \
}
enum zc_profile_flag {
ZC_DEBUG = 0,
ZC_WARN = 1,
ZC_ERROR = 2
};
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
#define zc_debug(...) \
zc_profile_inner(ZC_DEBUG, __FILE__, __LINE__, __VA_ARGS__)
#define zc_warn(...) \
zc_profile_inner(ZC_WARN, __FILE__, __LINE__, __VA_ARGS__)
#define zc_error(...) \
zc_profile_inner(ZC_ERROR, __FILE__, __LINE__, __VA_ARGS__)
#define zc_profile(flag, ...) \
zc_profile_inner(flag, __FILE__, __LINE__, __VA_ARGS__)
#elif defined __GNUC__
#define zc_debug(fmt, args...) \
zc_profile_inner(ZC_DEBUG, __FILE__, __LINE__, fmt, ## args)
#define zc_warn(fmt, args...) \
zc_profile_inner(ZC_WARN, __FILE__, __LINE__, fmt, ## args)
#define zc_error(fmt, args...) \
zc_profile_inner(ZC_ERROR, __FILE__, __LINE__, fmt, ## args)
#define zc_profile(flag, fmt, args...) \
zc_profile_inner(flag, __FILE__, __LINE__, fmt, ## args)
#endif
int zc_profile_inner(int flag,
const char *file, const long line,
const char *fmt, ...);
#endif

@ -0,0 +1,147 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <string.h>
#include <syslog.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include "zc_defs.h"
size_t zc_parse_byte_size(char *astring)
{
/* Parse size in bytes depending on the suffix. Valid suffixes are KB, MB and GB */
char *p;
char *q;
size_t sz;
long res;
int c, m;
zc_assert(astring, 0);
/* clear space */
for (p = q = astring; *p != '\0'; p++) {
if (isspace(*p)) {
continue;
} else {
*q = *p;
q++;
}
}
*q = '\0';
sz = strlen(astring);
res = strtol(astring, (char **)NULL, 10);
if (res <= 0)
return 0;
if (astring[sz - 1] == 'B' || astring[sz - 1] == 'b') {
c = astring[sz - 2];
m = 1024;
} else {
c = astring[sz - 1];
m = 1000;
}
switch (c) {
case 'K':
case 'k':
res *= m;
break;
case 'M':
case 'm':
res *= m * m;
break;
case 'G':
case 'g':
res *= m * m * m;
break;
default:
if (!isdigit(c)) {
zc_error("Wrong suffix parsing " "size in bytes for string [%s], ignoring suffix",
astring);
}
break;
}
return (res);
}
/*******************************************************************************/
int zc_str_replace_env(char *str, size_t str_size)
{
char *p;
char *q;
char fmt[MAXLEN_CFG_LINE + 1];
char env_key[MAXLEN_CFG_LINE + 1];
char env_value[MAXLEN_CFG_LINE + 1];
int str_len;
int env_value_len;
int nscan;
int nread;
str_len = strlen(str);
q = str;
do {
p = strchr(q, '%');
if (!p) {
/* can't find more % */
break;
}
memset(fmt, 0x00, sizeof(fmt));
memset(env_key, 0x00, sizeof(env_key));
memset(env_value, 0x00, sizeof(env_value));
nread = 0;
nscan = sscanf(p + 1, "%[.0-9-]%n", fmt + 1, &nread);
if (nscan == 1) {
fmt[0] = '%';
fmt[nread + 1] = 's';
} else {
nread = 0;
strcpy(fmt, "%s");
}
q = p + 1 + nread;
nscan = sscanf(q, "E(%[^)])%n", env_key, &nread);
if (nscan == 0) {
continue;
}
q += nread;
if (*(q - 1) != ')') {
zc_error("in string[%s] can't find match )", p);
return -1;
}
env_value_len = snprintf(env_value, sizeof(env_value), fmt, getenv(env_key));
if (env_value_len < 0 || env_value_len >= sizeof(env_value)) {
zc_error("snprintf fail, errno[%d], evn_value_len[%d]",
errno, env_value_len);
return -1;
}
str_len = str_len - (q - p) + env_value_len;
if (str_len > str_size - 1) {
zc_error("repalce env_value[%s] cause overlap", env_value);
return -1;
}
memmove(p + env_value_len, q, strlen(q) + 1);
memcpy(p, env_value, env_value_len);
} while (1);
return 0;
}

@ -0,0 +1,17 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_util_h
#define __zc_util_h
size_t zc_parse_byte_size(char *astring);
int zc_str_replace_env(char *str, size_t str_size);
#define zc_max(a,b) ((a) > (b) ? (a) : (b))
#define zc_min(a,b) ((a) < (b) ? (a) : (b))
#endif

@ -0,0 +1,62 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zc_xplatform_h
#define __zc_xplatform_h
#include <limits.h>
#define ZLOG_INT32_LEN sizeof("-2147483648") - 1
#define ZLOG_INT64_LEN sizeof("-9223372036854775808") - 1
#if ((__GNU__ == 2) && (__GNUC_MINOR__ < 8))
#define ZLOG_MAX_UINT32_VALUE (uint32_t) 0xffffffffLL
#else
#define ZLOG_MAX_UINT32_VALUE (uint32_t) 0xffffffff
#endif
#define ZLOG_MAX_INT32_VALUE (uint32_t) 0x7fffffff
#define MAXLEN_PATH 1024
#define MAXLEN_CFG_LINE (MAXLEN_PATH * 4)
#define MAXLINES_NO 128
#define FILE_NEWLINE "\n"
#define FILE_NEWLINE_LEN 1
#include <string.h>
#include <strings.h>
#define STRCMP(_a_,_C_,_b_) ( strcmp(_a_,_b_) _C_ 0 )
#define STRNCMP(_a_,_C_,_b_,_n_) ( strncmp(_a_,_b_,_n_) _C_ 0 )
#define STRICMP(_a_,_C_,_b_) ( strcasecmp(_a_,_b_) _C_ 0 )
#define STRNICMP(_a_,_C_,_b_,_n_) ( strncasecmp(_a_,_b_,_n_) _C_ 0 )
#ifdef __APPLE__
#include <AvailabilityMacros.h>
#endif
/* Define zlog_fstat to fstat or fstat64() */
#if defined(__APPLE__) && !defined(MAC_OS_X_VERSION_10_6)
#define zlog_fstat fstat64
#define zlog_stat stat64
#else
#define zlog_fstat fstat
#define zlog_stat stat
#endif
/* Define zlog_fsync to fdatasync() in Linux and fsync() for all the rest */
#ifdef __linux__
#define zlog_fsync fdatasync
#else
#define zlog_fsync fsync
#endif
#endif

@ -0,0 +1,70 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include "fmacros.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include "zlog.h"
#include "version.h"
int main(int argc, char *argv[])
{
int rc = 0;
int op;
int quiet = 0;
static const char *help =
"usage: zlog-chk-conf [conf files]...\n"
"\t-q,\tsuppress non-error message\n"
"\t-h,\tshow help message\n"
"zlog version: " ZLOG_VERSION "\n";
while((op = getopt(argc, argv, "qhv")) > 0) {
if (op == 'h') {
fputs(help, stdout);
return 0;
} else if (op == 'q') {
quiet = 1;
}
}
argc -= optind;
argv += optind;
if (argc == 0) {
fputs(help, stdout);
return -1;
}
setenv("ZLOG_PROFILE_ERROR", "/dev/stderr", 1);
setenv("ZLOG_CHECK_FORMAT_RULE", "1", 1);
while (argc > 0) {
rc = zlog_init(*argv);
if (rc) {
printf("\n---[%s] syntax error, see error message above\n",
*argv);
exit(2);
} else {
zlog_fini();
if (!quiet) {
printf("--[%s] syntax right\n", *argv);
}
}
argc--;
argv++;
}
exit(0);
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,279 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#ifndef __zlog_h
#define __zlog_h
#ifdef __cplusplus
extern "C" {
#endif
#include <stdarg.h> /* for va_list */
#include <stdio.h> /* for size_t */
# if defined __GNUC__
# define ZLOG_CHECK_PRINTF(m,n) __attribute__((format(printf,m,n)))
# else
# define ZLOG_CHECK_PRINTF(m,n)
# endif
typedef struct zlog_category_s zlog_category_t;
int zlog_init(const char *config);
int zlog_reload(const char *config);
void zlog_fini(void);
void zlog_profile(void);
zlog_category_t *zlog_get_category(const char *cname);
int zlog_level_enabled(zlog_category_t *category, const int level);
int zlog_put_mdc(const char *key, const char *value);
char *zlog_get_mdc(const char *key);
void zlog_remove_mdc(const char *key);
void zlog_clean_mdc(void);
int zlog_level_switch(zlog_category_t * category, int level);
int zlog_level_enabled(zlog_category_t * category, int level);
void zlog(zlog_category_t * category,
const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const char *format, ...) ZLOG_CHECK_PRINTF(8,9);
void vzlog(zlog_category_t * category,
const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const char *format, va_list args);
void hzlog(zlog_category_t * category,
const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const void *buf, size_t buflen);
int dzlog_init(const char *confpath, const char *cname);
int dzlog_set_category(const char *cname);
void dzlog(const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const char *format, ...) ZLOG_CHECK_PRINTF(7,8);
void vdzlog(const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const char *format, va_list args);
void hdzlog(const char *file, size_t filelen,
const char *func, size_t funclen,
long line, int level,
const void *buf, size_t buflen);
typedef struct zlog_msg_s {
char *buf;
size_t len;
char *path;
} zlog_msg_t;
typedef int (*zlog_record_fn)(zlog_msg_t *msg);
int zlog_set_record(const char *rname, zlog_record_fn record);
const char *zlog_version(void);
/******* useful macros, can be redefined at user's h file **********/
typedef enum {
ZLOG_LEVEL_DEBUG = 20,
ZLOG_LEVEL_INFO = 40,
ZLOG_LEVEL_NOTICE = 60,
ZLOG_LEVEL_WARN = 80,
ZLOG_LEVEL_ERROR = 100,
ZLOG_LEVEL_FATAL = 120
} zlog_level;
#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
# if defined __GNUC__ && __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
#endif
#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
/* zlog macros */
#define zlog_fatal(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, __VA_ARGS__)
#define zlog_error(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, __VA_ARGS__)
#define zlog_warn(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, __VA_ARGS__)
#define zlog_notice(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, __VA_ARGS__)
#define zlog_info(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, __VA_ARGS__)
#define zlog_debug(cat, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, __VA_ARGS__)
/* dzlog macros */
#define dzlog_fatal(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, __VA_ARGS__)
#define dzlog_error(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, __VA_ARGS__)
#define dzlog_warn(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, __VA_ARGS__)
#define dzlog_notice(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, __VA_ARGS__)
#define dzlog_info(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, __VA_ARGS__)
#define dzlog_debug(...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, __VA_ARGS__)
#elif defined __GNUC__
/* zlog macros */
#define zlog_fatal(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, format, ##args)
#define zlog_error(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, format, ##args)
#define zlog_warn(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, format, ##args)
#define zlog_notice(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, format, ##args)
#define zlog_info(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, format, ##args)
#define zlog_debug(cat, format, args...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, format, ##args)
/* dzlog macros */
#define dzlog_fatal(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, format, ##args)
#define dzlog_error(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, format, ##args)
#define dzlog_warn(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, format, ##args)
#define dzlog_notice(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, format, ##args)
#define dzlog_info(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, format, ##args)
#define dzlog_debug(format, args...) \
dzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, format, ##args)
#endif
/* vzlog macros */
#define vzlog_fatal(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, format, args)
#define vzlog_error(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, format, args)
#define vzlog_warn(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, format, args)
#define vzlog_notice(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, format, args)
#define vzlog_info(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, format, args)
#define vzlog_debug(cat, format, args) \
vzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, format, args)
/* hzlog macros */
#define hzlog_fatal(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, buf, buf_len)
#define hzlog_error(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, buf, buf_len)
#define hzlog_warn(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, buf, buf_len)
#define hzlog_notice(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, buf, buf_len)
#define hzlog_info(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, buf, buf_len)
#define hzlog_debug(cat, buf, buf_len) \
hzlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, buf, buf_len)
/* vdzlog macros */
#define vdzlog_fatal(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, format, args)
#define vdzlog_error(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, format, args)
#define vdzlog_warn(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, format, args)
#define vdzlog_notice(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, format, args)
#define vdzlog_info(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, format, args)
#define vdzlog_debug(format, args) \
vdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, format, args)
/* hdzlog macros */
#define hdzlog_fatal(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_FATAL, buf, buf_len)
#define hdzlog_error(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_ERROR, buf, buf_len)
#define hdzlog_warn(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_WARN, buf, buf_len)
#define hdzlog_notice(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_NOTICE, buf, buf_len)
#define hdzlog_info(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_INFO, buf, buf_len)
#define hdzlog_debug(buf, buf_len) \
hdzlog(__FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_DEBUG, buf, buf_len)
/* enabled macros */
#define zlog_fatal_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_FATAL)
#define zlog_error_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_ERROR)
#define zlog_warn_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_WARN)
#define zlog_notice_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_NOTICE)
#define zlog_info_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_INFO)
#define zlog_debug_enabled(zc) zlog_level_enabled(zc, ZLOG_LEVEL_DEBUG)
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "zlog.h"
int
LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[256];
sprintf(filename, "/tmp/libfuzzer.%d", getpid());
FILE *fp = fopen(filename, "wb");
if (!fp)
return 0;
fwrite(data, size, 1, fp);
fclose(fp);
int rc = zlog_init(filename);
if (rc == 0)
{
zlog_fini();
}
unlink(filename);
return 0;
}

@ -0,0 +1,41 @@
exe = \
test_tmp \
test_longlog \
test_buf \
test_bitmap \
test_conf \
test_conf2 \
test_hashtable \
test_hello \
test_hex \
test_init \
test_level \
test_leak \
test_mdc \
test_multithread \
test_record \
test_pipe \
test_press_zlog \
test_press_zlog2 \
test_press_write \
test_press_write2 \
test_press_syslog \
test_syslog \
test_default \
test_profile \
test_category \
test_prompt \
test_enabled
all : $(exe)
$(exe) : %:%.o
gcc -O2 -g -o $@ $^ -L../src -lzlog -lpthread -Wl,-rpath ../src
.c.o :
gcc -O2 -g -Wall -D_GNU_SOURCE -o $@ -c $< -I. -I../src
clean :
rm -f press.log* *.o $(exe)
.PHONY : clean all

@ -0,0 +1,50 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "zlog.h"
int main(int argc, char** argv)
{
unsigned char aa[32];
int i, j;
if (argc != 3) {
printf("useage: test_bitmap i j\n");
exit(1);
}
dzlog_init(NULL, "AA");
i = atoi(argv[1]);
j = atoi(argv[2]);
memset(aa, 0x00, sizeof(aa));
/* 32 byte, 256 bit
* [11111..1100...00]
* i
*/
aa[i/8] |= ~(0xFF << (8 - i % 8));
memset(aa + i/8 + 1, 0xFF, sizeof(aa) - i/8 - 1);
hdzlog_info(aa, sizeof(aa));
dzlog_info("%0x", aa[j/8]);
dzlog_info("%0x", aa[j/8] >> 6);
/* see j of bits fits */
dzlog_info("%0x", ~((aa[j/8] >> (7 - j % 8)) & 0x01) );
zlog_fini();
return 0;
}

@ -0,0 +1,103 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "zc_defs.h"
#include "buf.h"
int main(int argc, char** argv)
{
zlog_buf_t *a_buf;
char *aa;
a_buf = zlog_buf_new(10, 20, "ABC");
if (!a_buf) {
zc_error("zlog_buf_new fail");
return -1;
}
aa = "123456789";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
fwrite(a_buf->start, zlog_buf_len(a_buf), 1, stdout);
zc_error("------------");
aa = "0";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "12345";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "6789";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "0";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "22345";
zlog_buf_append(a_buf, aa, strlen(aa));
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "abc";
int i,j;
for (i = 0; i <= 5; i++) {
for (j = 0; j <= 5; j++) {
zlog_buf_restart(a_buf);
zc_error("left[1],max[%d],min[%d]", i, j);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 1, 0, i, j);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("-----");
zlog_buf_restart(a_buf);
zc_error("left[0],max[%d],min[%d]", i, j);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, i, j);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
}
}
aa = "1234567890";
zc_error("left[0],max[%d],min[%d]", 15, 5);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 15, 5);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
aa = "1234567890";
zlog_buf_restart(a_buf);
zc_error("left[0],max[%d],min[%d]", 25, 5);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 1, 0, 25, 5);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
zlog_buf_restart(a_buf);
zc_error("left[0],max[%d],min[%d]", 19, 5);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 19, 5);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
zlog_buf_restart(a_buf);
zc_error("left[0],max[%d],min[%d]", 20, 5);
zlog_buf_adjust_append(a_buf, aa, strlen(aa), 0, 0, 20, 5);
zc_error("a_buf->start[%s]", a_buf->start);
zc_error("------------");
zlog_buf_del(a_buf);
return 0;
}

@ -0,0 +1,44 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("test_category.conf");
if (rc) {
printf("init failed\n");
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_debug(zc, "hello, zlog - debug");
zc = zlog_get_category("my-cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(zc, "hello, zlog - info");
zlog_fini();
return 0;
}

@ -0,0 +1,5 @@
[global]
default format = "%V %v %m%n"
[rules]
my_cat.* >stdout;
my-cat.* >stdout;

@ -0,0 +1,42 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("test_conf.conf");
if (rc) {
printf("init failed, try zlog-chk-conf test_conf.conf for more detail\n");
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(zc, "hello, zlog");
zlog_fini();
printf("log end\n");
return 0;
}

@ -0,0 +1,30 @@
[global]
strict init = true
buffer min= 1024
buffer max= 2MB
rotate lock file = /tmp/zlog.lock
default format = "defalut - %d(%F %X.%ms) %-6V (%c:%F:%U:%L) - %m%n"
[formats]
null = "%n"
print = "print - [%-10.3d(%F)]%n"
date = "date start%n%d(%a--Wed)%n%d(%A--Wednesday)%n%d(%b--Mar)%n%d(%B--March)%n%d(%c--WedMar211:45:262011)%n%d(%C--20)%n%d(%d--02)%n%d(%D--03/02/11)%n%d(%e--2)%n%d(%F--2011-03-02)%n%d(%g--11)%n%d(%G--2011)%n%d(%h--Mar)%n%d(%H--11)%n%d(%I--11)%n%d(%j--061)%n%d(%k-k)%n%d(%l-l)%n%d(%ms--500)%n%d(%m--03)%n%d(%M--45)%n%d(%us--500730)%n%d(%p--AM)%n%d(%r--11:45:26AM)%n%d(%R--11:45)%n%d(%s--epoch)%n%d(%S--26)%n%d(%t--)%n%d(%T--11:45:26)%n%d(%u--3)%n%d(%U--09)%n%d(%V--09)%n%d(%w--3)%n%d(%W--09)%n%d(%x--03/02/11)%n%d(%X--11:45:26)%n%d(%y--11)%n%d(%Y--2011)%n%d(%z--+0800)%n%d(%Z--CST)%n%d(%%--%)%n%d(%J--%J)%ndate end%n"
simple = "simple - %m%n"
text = "text - text%n"
ms = "ms - %d(%a--Wed)[%d(%ms)]%n"
msus = "msus - %d(%ms,%us,%ms,%us)%n"
[rules]
*.* >stderr;
*.* >stderr; null
*.* >stderr; print
*.* >stderr; date
*.* >stderr; simple
*.* >stderr; text
*.* >stderr; ms
*.* >stderr; msus

@ -0,0 +1,42 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zlog.h"
#include "test_conf2.conf.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init(test_conf2_conf);
if (rc) {
printf("init failed, save [] in a config file and try zlog-chk-conf for more detail [%s]\n", test_conf2_conf);
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(zc, "hello, zlog");
zlog_fini();
printf("log end\n");
return 0;
}

@ -0,0 +1 @@
#define test_conf2_conf "[global]\nstrict init = true\nbuffer min= 1024\nbuffer max= 2MB\nrotate lock file = /tmp/zlog.lock\ndefault format = \"defalut - %d(%F %X.%ms) %-6V (%c:%F:%U:%L) - %m%n\"\n\n[formats]\nnull = \"%n\"\nprint = \"print - [%-10.3d(%F)]%n\"\n\ndate = \"date start%n%d(%a--Wed)%n%d(%A--Wednesday)%n%d(%b--Mar)%n%d(%B--March)%n%d(%c--WedMar211:45:262011)%n%d(%C--20)%n%d(%d--02)%n%d(%D--03/02/11)%n%d(%e--2)%n%d(%F--2011-03-02)%n%d(%g--11)%n%d(%G--2011)%n%d(%h--Mar)%n%d(%H--11)%n%d(%I--11)%n%d(%j--061)%n%d(%k-k)%n%d(%l-l)%n%d(%ms--500)%n%d(%m--03)%n%d(%M--45)%n%d(%us--500730)%n%d(%p--AM)%n%d(%r--11:45:26AM)%n%d(%R--11:45)%n%d(%s--epoch)%n%d(%S--26)%n%d(%t--)%n%d(%T--11:45:26)%n%d(%u--3)%n%d(%U--09)%n%d(%V--09)%n%d(%w--3)%n%d(%W--09)%n%d(%x--03/02/11)%n%d(%X--11:45:26)%n%d(%y--11)%n%d(%Y--2011)%n%d(%z--+0800)%n%d(%Z--CST)%n%d(%%--%)%n%d(%J--%J)%ndate end%n\"\n\nsimple = \"simple - %m%n\"\n\ntext = \"text - text%n\"\n\nms = \"ms - %d(%a--Wed)[%d(%ms)]%n\"\n\nmsus = \"msus - %d(%ms,%us,%ms,%us)%n\"\n\n[rules]\n*.* >stderr;\n*.* >stderr; null\n*.* >stderr; print\n*.* >stderr; date\n*.* >stderr; simple\n*.* >stderr; text\n*.* >stderr; ms\n*.* >stderr; msus"

@ -0,0 +1,27 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
rc = dzlog_init("test_default.conf", "my_cat");
if (rc) {
printf("init failed\n");
return -1;
}
dzlog_info("hello, zlog");
zlog_fini();
return 0;
}

@ -0,0 +1,2 @@
[rules]
my_cat.* >stdout

@ -0,0 +1,48 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2018 by Teracom Telemática S/A
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "test_enabled.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("test_enabled.conf");
if (rc) {
printf("init failed\n");
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
if (zlog_trace_enabled(zc)) {
/* do something heavy to collect data */
zlog_trace(zc, "hello, zlog - trace");
}
if (zlog_debug_enabled(zc)) {
/* do something heavy to collect data */
zlog_debug(zc, "hello, zlog - debug");
}
if (zlog_info_enabled(zc)) {
/* do something heavy to collect data */
zlog_info(zc, "hello, zlog - info");
}
zlog_fini();
return 0;
}

@ -0,0 +1,6 @@
[global]
default format = "%V %v %m%n"
[levels]
TRACE = 30, LOG_DEBUG
[rules]
my_cat.TRACE >stdout;

@ -0,0 +1,36 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2018 by Teracom Telemática S/A
*
* The zlog Library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The zlog Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the zlog Library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __test_level_h
#define __test_level_h
#include "zlog.h"
enum {
ZLOG_LEVEL_TRACE = 30,
/* 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_trace_enabled(cat) zlog_level_enabled(cat, ZLOG_LEVEL_TRACE)
#endif

@ -0,0 +1,58 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zc_profile.c"
#include "zc_hashtable.h"
#include "zc_hashtable.c"
void myfree(void *kv)
{
}
int main(void)
{
zc_hashtable_t *a_table;
zc_hashtable_entry_t *a_entry;
a_table = zc_hashtable_new(20,
zc_hashtable_str_hash,
zc_hashtable_str_equal,
myfree, myfree);
zc_hashtable_put(a_table, "aaa", "bnbb");
zc_hashtable_put(a_table, "bbb", "bnbb");
zc_hashtable_put(a_table, "ccc", "bnbb");
zc_hashtable_put(a_table, "aaa", "123");
zc_hashtable_foreach(a_table, a_entry) {
printf("k[%s],v[%s]\n", (char*)a_entry->key, (char*)a_entry->value);
}
printf("getv[%s]\n", (char*)zc_hashtable_get(a_table, "ccc"));
zc_hashtable_remove(a_table, "ccc");
zc_hashtable_foreach(a_table, a_entry) {
printf("k[%s],v[%s]\n", (char*)a_entry->key, (char*)a_entry->value);
}
zc_hashtable_remove(a_table, NULL);
zc_hashtable_del(NULL);
zc_hashtable_del(a_table);
return 0;
}

@ -0,0 +1,35 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("test_hello.conf");
if (rc) {
printf("init failed\n");
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_info(zc, "hello, zlog");
zlog_fini();
return 0;
}

@ -0,0 +1,7 @@
[formats]
simple = "%d.%ms %m%n"
simple2 = "%d.%us %m%n"
[rules]
my_cat.* >stderr;
my_cat.* >stdout;simple
my_cat.* >stdout;simple2

@ -0,0 +1,112 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zlog.h"
#include "stdlib.h"
static int ReadTotalFile( FILE * fp , char ** ptr , long * len )
{
long fileLen ;
int nret ;
char * pStart ;
*ptr = NULL;
nret = fseek( fp , 0L , SEEK_END );
if( nret )
{
return -1;
}
fileLen = ftell( fp );
if( fileLen < 0 )
{
return -2;
}
if( ( pStart = calloc(1, fileLen+1) ) == NULL )
{
return -3;
}
nret = fseek( fp , 0L , SEEK_SET );
if( nret )
{
free( pStart );
return -4;
}
nret = fread( pStart , fileLen , 1 , fp );
if( ferror( fp ) )
{
free( pStart );
return -5;
}
*ptr = pStart;
*len = fileLen;
return 0;
}
int main(int argc, char** argv)
{
int rc;
FILE *fp;
char *dmp;
long dmp_len = 0;
int ntimes;
if (argc != 3) {
printf("useage: test_hex [file] [ntimes]\n");
exit(1);
}
fp = fopen(argv[1], "r");
if (!fp) {
printf("fopen[%s] fail\n", argv[1]);
exit(1);
}
ntimes = atoi(argv[2]);
zlog_category_t *zc;
rc = zlog_init("test_hex.conf");
if (rc) {
printf("init failed\n");
return -1;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("get category failed\n");
zlog_fini();
return -2;
}
rc = ReadTotalFile(fp, &dmp, &dmp_len);
while(ntimes--) hzlog_debug(zc, dmp, dmp_len);
fclose(fp);
free(dmp);
zlog_fini();
printf("hex log end\n");
return 0;
}

@ -0,0 +1,2 @@
[rules]
*.* "hex.log";

@ -0,0 +1,12 @@
[global]
buffer min = 2048
buffer max = 4096
default format = "%V %m%n"
[levels]
TEST = 40, LOG_INFO
[formats]
simple = "%m%n"
[rules]
my_cat.* >stderr;

@ -0,0 +1,56 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("test_init.conf");
if (rc) {
printf("init fail");
return -2;
}
zc = zlog_get_category("my_cat");
if (!zc) {
printf("zlog_get_category fail\n");
zlog_fini();
return -1;
}
zlog_info(zc, "before update");
sleep(1);
rc = zlog_reload("test_init.2.conf");
if (rc) {
printf("update fail\n");
}
zlog_info(zc, "after update");
zlog_profile();
zlog_fini();
sleep(1);
zlog_init("test_init.conf");
zc = zlog_get_category("my_cat");
if (!zc) {
printf("zlog_get_category fail\n");
zlog_fini();
return -1;
}
zlog_info(zc, "init again");
zlog_fini();
return 0;
}

@ -0,0 +1,8 @@
[ global ]
strict init = true
buffer min = 1024
buffer max = 2MB
rotate lock file= /tmp/zlog.lock
[ rules ]
my_cat.* >stderr;

@ -0,0 +1,8 @@
[global]
strict init = true
buffer min = 100
buffer max = 200
default format = "%m%n"
[rules ]
*.* >stdout;

@ -0,0 +1,56 @@
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
int k;
int i;
if (argc != 2) {
printf("test_leak ntime\n");
return -1;
}
rc = zlog_init("test_leak.conf");
k = atoi(argv[1]);
while (k-- > 0) {
i = rand();
switch (i % 4) {
case 0:
rc = dzlog_init("test_leak.conf", "xxx");
dzlog_info("init, rc=[%d]", rc);
break;
case 1:
rc = zlog_reload(NULL);
dzlog_info("reload null, rc=[%d]", rc);
break;
case 2:
rc = zlog_reload("test_leak.2.conf");
dzlog_info("reload 2, rc=[%d]", rc);
break;
case 3:
zlog_fini();
printf("fini\n");
// printf("zlog_finish\tj=[%d], rc=[%d]\n", j, rc);
break;
}
}
zlog_fini();
return 0;
}

@ -0,0 +1,12 @@
[global]
strict init = true
buffer min = 2048
buffer max = 4096
rotate lock file = /tmp/zlog.lock
default format = "%d(%F %T).%ms %-6V (%c:%F:%L) - %m%n"
[ levels ]
TEST = 40, LOG_INFO
[rules ]
*.* >stderr;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save