From 19911a962cbb83250e6ba1ecc7d8c1ee86d5db02 Mon Sep 17 00:00:00 2001 From: yangwei Date: Mon, 7 Sep 2020 12:54:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0zlog=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E4=B8=BAtar=E5=8C=85=E4=BD=BF=E7=94=A8Extern?= =?UTF-8?q?alProject=E7=BC=96=E8=AF=91=E8=A7=A3=E5=8E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitlab-ci.yml | 104 ++-- CMakeLists.txt | 5 +- ci/get-nprocessors.sh | 48 ++ ci/perpare_pulp3_netrc.sh | 3 + ci/travis.sh | 61 +++ cmake/Package.cmake | 50 +- cmake/Version.cmake | 15 +- zlog/CMakeLists.txt | 26 +- zlog/buf.c | 649 ----------------------- zlog/buf.h | 56 -- zlog/category.c | 233 -------- zlog/category.h | 38 -- zlog/category_table.c | 129 ----- zlog/category_table.h | 28 - zlog/conf.c | 504 ------------------ zlog/conf.h | 46 -- zlog/event.c | 182 ------- zlog/event.h | 90 ---- zlog/fmacros.h | 24 - zlog/format.c | 164 ------ zlog/format.h | 32 -- zlog/level.c | 141 ----- zlog/level.h | 26 - zlog/level_list.c | 145 ----- zlog/level_list.h | 33 -- zlog/makefile | 204 ------- zlog/mdc.c | 145 ----- zlog/mdc.h | 36 -- zlog/record.c | 53 -- zlog/record.h | 32 -- zlog/record_table.c | 56 -- zlog/record_table.h | 19 - zlog/rotater.c | 575 -------------------- zlog/rotater.h | 45 -- zlog/rule.c | 1058 ------------------------------------- zlog/rule.h | 88 --- zlog/spec.c | 659 ----------------------- zlog/spec.h | 60 --- zlog/thread.c | 184 ------- zlog/thread.h | 38 -- zlog/version.h | 1 - zlog/zc_arraylist.c | 132 ----- zlog/zc_arraylist.h | 41 -- zlog/zc_defs.h | 18 - zlog/zc_hashtable.c | 330 ------------ zlog/zc_hashtable.h | 49 -- zlog/zc_profile.c | 86 --- zlog/zc_profile.h | 53 -- zlog/zc_util.c | 147 ------ zlog/zc_util.h | 17 - zlog/zc_xplatform.h | 61 --- zlog/zlog-1.2.15.tar.gz | Bin 0 -> 124794 bytes zlog/zlog-chk-conf.c | 70 --- zlog/zlog.c | 1024 ----------------------------------- zlog/zlog.h | 279 ---------- 55 files changed, 252 insertions(+), 8140 deletions(-) create mode 100644 ci/get-nprocessors.sh create mode 100644 ci/perpare_pulp3_netrc.sh create mode 100644 ci/travis.sh delete mode 100644 zlog/buf.c delete mode 100644 zlog/buf.h delete mode 100644 zlog/category.c delete mode 100644 zlog/category.h delete mode 100644 zlog/category_table.c delete mode 100644 zlog/category_table.h delete mode 100644 zlog/conf.c delete mode 100644 zlog/conf.h delete mode 100644 zlog/event.c delete mode 100644 zlog/event.h delete mode 100644 zlog/fmacros.h delete mode 100644 zlog/format.c delete mode 100644 zlog/format.h delete mode 100644 zlog/level.c delete mode 100644 zlog/level.h delete mode 100644 zlog/level_list.c delete mode 100644 zlog/level_list.h delete mode 100644 zlog/makefile delete mode 100644 zlog/mdc.c delete mode 100644 zlog/mdc.h delete mode 100644 zlog/record.c delete mode 100644 zlog/record.h delete mode 100644 zlog/record_table.c delete mode 100644 zlog/record_table.h delete mode 100644 zlog/rotater.c delete mode 100644 zlog/rotater.h delete mode 100644 zlog/rule.c delete mode 100644 zlog/rule.h delete mode 100644 zlog/spec.c delete mode 100644 zlog/spec.h delete mode 100644 zlog/thread.c delete mode 100644 zlog/thread.h delete mode 100644 zlog/version.h delete mode 100644 zlog/zc_arraylist.c delete mode 100644 zlog/zc_arraylist.h delete mode 100644 zlog/zc_defs.h delete mode 100644 zlog/zc_hashtable.c delete mode 100644 zlog/zc_hashtable.h delete mode 100644 zlog/zc_profile.c delete mode 100644 zlog/zc_profile.h delete mode 100644 zlog/zc_util.c delete mode 100644 zlog/zc_util.h delete mode 100644 zlog/zc_xplatform.h create mode 100644 zlog/zlog-1.2.15.tar.gz delete mode 100644 zlog/zlog-chk-conf.c delete mode 100644 zlog/zlog.c delete mode 100644 zlog/zlog.h diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f33dced..cb4cbda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,42 +1,86 @@ -image: "git.mesalab.cn:7443/mesa_framework/framework-build-env:master" +image: "git.mesalab.cn:7443/mesa_platform/build-env:master" +variables: + GIT_STRATEGY: "clone" + BUILD_PADDING_PREFIX: /tmp/padding_for_CPACK_RPM_BUILD_SOURCE_DIRS_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX_PREFIX/ + INSTALL_PREFIX: "/opt/MESA/lib/" + stages: - build -#- test -#- package -- release -variables: - ARTIFACTS_JOB: "build" - -build: +.build_by_travis: + before_script: + - mkdir -p $BUILD_PADDING_PREFIX/$CI_PROJECT_NAMESPACE/ + - ln -s $CI_PROJECT_DIR $BUILD_PADDING_PREFIX/$CI_PROJECT_PATH + - cd $BUILD_PADDING_PREFIX/$CI_PROJECT_PATH + - chmod +x ./ci/travis.sh + script: + - yum makecache + - ./ci/travis.sh + - cd build + tags: + - share + +branch_build_debug: stage: build - script: - - mkdir -p build - - cd build - - cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_PREFIX_PATH=$BUILD_PREFIX - - make - - make package - tags: - - share + extends: .build_by_travis variables: - BUILD_TYPE: "Debug" - BUILD_PREFIX: "/opt/MESA/" - only: + BUILD_TYPE: Debug + except: + - /^develop.*$/i + - /^master.*$/i - tags - - pushes - - master +branch_build_release: + stage: build + variables: + BUILD_TYPE: RelWithDebInfo + extends: .build_by_travis + except: + - /^develop.*$/i + - /^master.*$/i + - tags + +develop_build_debug: + stage: build + extends: .build_by_travis + variables: + BUILD_TYPE: Debug + PACKAGE: 1 artifacts: - name: "$CI_JOB_NAME-$CI_COMMIT_REF_NAME-debug" + name: "MESA_handle_logger-$CI_COMMIT_REF_NAME-debug" paths: - - ./build/*.rpm + - build/*.rpm + only: + - /^develop.*$/i + - /^master.*$/i -release: - stage: release - tags: - - share +develop_build_release: + stage: build + extends: .build_by_travis + variables: + BUILD_TYPE: RelWithDebInfo + PACKAGE: 1 + artifacts: + name: "MESA_handle_logger-$CI_COMMIT_REF_NAME-release" + paths: + - build/*.rpm + only: + - /^develop.*$/i + - /^master.*$/i + + +release_build_release: + stage: build + variables: + BUILD_TYPE: RelWithDebInfo + PACKAGE: 1 + UPLOAD: 1 + PULP3_REPO_NAME: framework-stable-x86_64.el7 + PULP3_DIST_NAME: framework-stable-x86_64.el7 + extends: .build_by_travis + artifacts: + name: "MESA_handle_logger-$CI_COMMIT_REF_NAME-release" + paths: + - build/*.rpm only: - tags - - master - script: - - /bin/bash -x ./autorelease.sh $CI_API_V4_URL $CI_PROJECT_URL $CI_PROJECT_ID $CI_TOKEN $CI_COMMIT_TAG $ARTIFACTS_JOB $CI_PROJECT_NAME \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 69364bd..9ff3645 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,9 +40,10 @@ file(GLOB SRC # Shared Library Output add_library(${lib_name}_shared SHARED ${SRC}) -target_link_libraries(${lib_name}_shared -Wl,--whole-archive zlog_static -Wl,--no-whole-archive) +target_link_libraries(${lib_name}_shared zlog-static) set_target_properties(${lib_name}_shared PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_SOURCE_DIR}/src/version.map") + if(DEFINED MESA_SHARED_INSTALL_DIR) set_target_properties(${lib_name}_shared PROPERTIES OUTPUT_NAME ${lib_name} LIBRARY_OUTPUT_DIRECTORY ${MESA_SHARED_INSTALL_DIR}) else() @@ -51,7 +52,7 @@ endif() # static Library Output add_library(${lib_name}_static STATIC ${SRC}) -target_link_libraries(${lib_name}_static -Wl,--whole-archive zlog_static -Wl,--no-whole-archive) +target_link_libraries(${lib_name}_static -Wl,--whole-archive zlog-static -Wl,--no-whole-archive) set_target_properties(${lib_name}_static PROPERTIES OUTPUT_NAME ${lib_name}) set(CMAKE_INSTALL_PREFIX /opt/MESA) diff --git a/ci/get-nprocessors.sh b/ci/get-nprocessors.sh new file mode 100644 index 0000000..43635e7 --- /dev/null +++ b/ci/get-nprocessors.sh @@ -0,0 +1,48 @@ +#!/usr/bin/env bash +# Copyright 2017 Google Inc. +# All Rights Reserved. +# +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This file is typically sourced by another script. +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi + +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi diff --git a/ci/perpare_pulp3_netrc.sh b/ci/perpare_pulp3_netrc.sh new file mode 100644 index 0000000..8414bbb --- /dev/null +++ b/ci/perpare_pulp3_netrc.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +set -evx +echo "machine ${PULP3_SERVER_URL}\nlogin ${PULP3_SERVER_LOGIN}\npassword ${PULP3_SERVER_PASSWORD}\n" > ~/.netrc diff --git a/ci/travis.sh b/ci/travis.sh new file mode 100644 index 0000000..64780e4 --- /dev/null +++ b/ci/travis.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env sh +set -evx + +chmod +x ci/get-nprocessors.sh +. ci/get-nprocessors.sh + +# if possible, ask for the precise number of processors, +# otherwise take 2 processors as reasonable default; see +# https://docs.travis-ci.com/user/speeding-up-the-build/#Makefile-optimization +if [ -x /usr/bin/getconf ]; then + NPROCESSORS=$(/usr/bin/getconf _NPROCESSORS_ONLN) +else + NPROCESSORS=2 +fi + +# as of 2017-09-04 Travis CI reports 32 processors, but GCC build +# crashes if parallelized too much (maybe memory consumption problem), +# so limit to 4 processors for the time being. +if [ $NPROCESSORS -gt 4 ] ; then + echo "$0:Note: Limiting processors to use by make from $NPROCESSORS to 4." + NPROCESSORS=4 +fi + +# Tell make to use the processors. No preceding '-' required. +MAKEFLAGS="j${NPROCESSORS}" +export MAKEFLAGS + +env | sort + +# Set default values to OFF for these variables if not specified. +: "${NO_EXCEPTION:=OFF}" +: "${NO_RTTI:=OFF}" +: "${COMPILER_IS_GNUCXX:=OFF}" + +# Install dependency from YUM +#yum install -y mrzcpd framework numactl-devel zlib-devel librdkafka-devel systemd-devel +mkdir build || true +cd build + +cmake3 -DCMAKE_CXX_FLAGS=$CXX_FLAGS \ + -DCMAKE_BUILD_TYPE=$BUILD_TYPE \ + -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \ + -DENABLE_DEVEL=$ENABLE_DEVEL_SWITCH \ + .. + +make + +if [ -n "${PACKAGE}" ]; then + make package +fi + +if [ -n "${UPLOAD}" ]; then + cp ~/rpm_upload_tools.py ./ + python3 rpm_upload_tools.py ${PULP3_REPO_NAME} ${PULP3_DIST_NAME} *.rpm +fi + +#if [ -n "${UPLOAD_SYMBOL_FILES}" ]; then +# rpm -i tfe*debuginfo*.rpm +# cp /usr/lib/debug/opt/tsg/tfe/bin/tfe.debug /tmp/tfe.debuginfo.${CI_COMMIT_SHORT_SHA} +# sentry-cli upload-dif -t elf /tmp/tfe.debuginfo.${CI_COMMIT_SHORT_SHA} +#fi diff --git a/cmake/Package.cmake b/cmake/Package.cmake index daf7e42..2703138 100644 --- a/cmake/Package.cmake +++ b/cmake/Package.cmake @@ -1,36 +1,54 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CPACK_PACKAGE_NAME "${lib_name}-debug") + set(MY_RPM_NAME_PREFIX "lib${lib_name}-debug") else() - set(CPACK_PACKAGE_NAME ${lib_name}) + set(MY_RPM_NAME_PREFIX "lib${lib_name}") endif() -message(STATUS "Package: ${CPACK_PACKAGE_NAME}") +message(STATUS "Package: ${MY_RPM_NAME_PREFIX}") set(CPACK_PACKAGE_VECDOR "MESA") set(CPACK_PACKAGE_VERSION_MAJOR "${VERSION_MAJOR}") set(CPACK_PACKAGE_VERSION_MINOR "${VERSION_MINOR}") set(CPACK_PACKAGE_VERSION_PATCH "${VERSION_PATCH}.${VERSION_BUILD}") set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - -set(CPACK_RPM_PACKAGE_DEBUG 1) +set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}.${VERSION_BUILD}") +execute_process(COMMAND bash -c "echo -ne \"`uname -r | awk -F'.' '{print $5\".\"$6\".\"$7}'`\"" OUTPUT_VARIABLE SYSTEM_VERSION) # RPM Build set(CPACK_GENERATOR "RPM") -set(CPACK_RPM_AUTO_GENERATED_FILE_NAME ON) -set(CPACK_RPM_FILE_NAME "RPM-DEFAULT") set(CPACK_RPM_PACKAGE_VENDOR "MESA") -set(CPACK_RPM_PACKAGE_AUTOREQPROV "no") -set(CPACK_RPM_PACKAGE_RELEASE_DIST on) -set(CPACK_RPM_DEBUGINFO_PACKAGE on) +set(CPACK_RPM_PACKAGE_AUTOREQPROV "yes") +set(CPACK_RPM_PACKAGE_RELEASE_LIBRARY "on") +set(CPACK_RPM_DEBUGINFO_PACKAGE "on") +set(CPACK_RPM_PACKAGE_DEBUG 1) + +set(CPACK_RPM_COMPONENT_INSTALL ON) +set(CPACK_COMPONENTS_IGNORE_GROUPS 1) +set(CPACK_COMPONENTS_GROUPING ONE_PER_GROUP) +set(CPACK_COMPONENT_HEADER_DISPLAY_NAME "develop") +set(CPACK_COMPONENT_LIBRARY_REQUIRED TRUE) +set(CPACK_COMPONENT_HEADER_REQUIRED TRUE) +set(CPACK_RPM_HEADER_PACKAGE_NAME "${MY_RPM_NAME_PREFIX}-devel") +set(CPACK_RPM_LIBRARY_PACKAGE_NAME ${MY_RPM_NAME_PREFIX}) + +set(CPACK_RPM_FILE_NAME "${CPACK_RPM_LIBRARY_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${SYSTEM_VERSION}.rpm") +set(CPACK_RPM_LIBRARY_DEBUGINFO_FILE_NAME "${CPACK_RPM_LIBRARY_PACKAGE_NAME}-debuginfo-${CPACK_PACKAGE_VERSION}-${SYSTEM_VERSION}.rpm") +set(CPACK_COMPONENT_LIBRARY_GROUP "library") + +set(CPACK_RPM_HEADER_FILE_NAME "${CPACK_RPM_HEADER_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}-${SYSTEM_VERSION}.rpm") +set(CPACK_RPM_HEADER_DEBUGINFO_FILE_NAME "${CPACK_RPM_HEADER_PACKAGE_NAME}-debuginfo-${CPACK_PACKAGE_VERSION}-${SYSTEM_VERSION}.rpm") +set(CPACK_COMPONENT_HEADER_GROUP "header") + +set(CPACK_RPM_HEADER_PACKAGE_REQUIRES_PRE ${CPACK_RPM_LIBRARY_PACKAGE_NAME}) +set(CPACK_RPM_HEADER_PACKAGE_CONFLICTS ${CPACK_RPM_HEADER_PACKAGE_NAME}) + +set(CPACK_COMPONENTS_ALL LIBRARY HEADER) + set(CPACK_BUILD_SOURCE_DIRS "${CMAKE_SOURCE_DIR}") # Must uninstall the debug package before install release package -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(CPACK_RPM_PACKAGE_CONFLICTS "${lib_name}-debug") -else() - set(CPACK_RPM_PACKAGE_CONFLICTS ${lib_name}) - # set(CPACK_STRIP_FILES TRUE) -endif() +set(CPACK_RPM_PACKAGE_CONFLICTS ${MY_RPM_NAME_PREFIX}) +# set(CPACK_STRIP_FILES TRUE) include(CPack) diff --git a/cmake/Version.cmake b/cmake/Version.cmake index b4ac4a0..752f20f 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -36,13 +36,18 @@ set(VERSION "${VERSION_MAJOR}_${VERSION_MINOR}_${VERSION_PATCH}") set(VERSION_BUILD "${VCS_SHORT_HASH}") # print information -message(STATUS "VERSION: ${VERSION}-${VERSION_BUILD}") +message(STATUS "Version: ${VERSION}-${VERSION_BUILD}") + +if(NOT DEFINE_GIT_VERSION) + option(DEFINE_GIT_VERSION "Set DEFINE_GIT_VERSION to OFF" OFF) set(GIT_VERSION - "${VERSION}-${CMAKE_BUILD_TYPE}-${VERSION_BUILD}-${VCS_BRANCH}-${VCS_DATE}") - + "${VERSION}-${CMAKE_BUILD_TYPE}-${VERSION_BUILD}-${VCS_BRANCH}-${VCS_TAG}-${VCS_DATE}") string(REGEX REPLACE "[-:+/\\.]" "_" GIT_VERSION ${GIT_VERSION}) -add_definitions(-DGIT_VERSION=${GIT_VERSION}) +if(DEFINE_GIT_VERSION) + add_definitions(-DGIT_VERSION=${GIT_VERSION}) + option(DEFINE_GIT_VERSION "Set DEFINE_GIT_VERSION to OFF" ON) +endif() -message(STATUS "add GIT_VERSION: ${GIT_VERSION}") +endif() diff --git a/zlog/CMakeLists.txt b/zlog/CMakeLists.txt index fd8f607..9ff2601 100644 --- a/zlog/CMakeLists.txt +++ b/zlog/CMakeLists.txt @@ -1,11 +1,23 @@ -cmake_minimum_required (VERSION 2.8) +cmake_minimum_required (VERSION 3.5) -set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) +include(ExternalProject) -set(CMAKE_MACOSX_RPATH 0) +ExternalProject_Add(zlog + PREFIX zlog + URL ${CMAKE_CURRENT_SOURCE_DIR}/zlog-1.2.15.tar.gz + URL_MD5 155f841543f947bf21112ae4328e7152 + INSTALL_DIR /usr/local/ + CONFIGURE_COMMAND "" + BUILD_COMMAND make + BUILD_IN_SOURCE 1) -add_compile_options(-fPIC) +ExternalProject_Get_Property(zlog INSTALL_DIR) +file(MAKE_DIRECTORY ${INSTALL_DIR}/include) -# static Library Output -add_library(zlog_static STATIC buf.c category.c category_table.c conf.c event.c format.c level.c level_list.c mdc.c record.c record_table.c rotater.c rule.c spec.c thread.c zc_arraylist.c zc_hashtable.c zc_profile.c zc_util.c zlog.c) -set_target_properties(zlog_static PROPERTIES OUTPUT_NAME zlog) +add_library(zlog-static STATIC IMPORTED GLOBAL) +add_dependencies(zlog-static zlog) +set_property(TARGET zlog-static PROPERTY IMPORTED_LOCATION ${INSTALL_DIR}/lib/libzlog.a) +set_property(TARGET zlog-static PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${INSTALL_DIR}/include) + + +install(PROGRAMS ${INSTALL_DIR}/bin/zlog-chk-conf DESTINATION bin COMPONENT Program) diff --git a/zlog/buf.c b/zlog/buf.c deleted file mode 100644 index 662b2eb..0000000 --- a/zlog/buf.c +++ /dev/null @@ -1,649 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include -#include - -#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 - 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; -} -/*******************************************************************************/ - diff --git a/zlog/buf.h b/zlog/buf.h deleted file mode 100644 index ffa720e..0000000 --- a/zlog/buf.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 -#include - -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 diff --git a/zlog/category.c b/zlog/category.c deleted file mode 100644 index 8a91c3b..0000000 --- a/zlog/category.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ -#include "fmacros.h" -#include -#include -#include - -#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; -} diff --git a/zlog/category.h b/zlog/category.h deleted file mode 100644 index c86c6d9..0000000 --- a/zlog/category.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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->level_bitmap[lv/8] >> (7 - lv % 8)) & 0x01) - - -#endif diff --git a/zlog/category_table.c b/zlog/category_table.c deleted file mode 100644 index 9e2975b..0000000 --- a/zlog/category_table.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include - -#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; -} - -/*******************************************************************************/ diff --git a/zlog/category_table.h b/zlog/category_table.h deleted file mode 100644 index 34a2249..0000000 --- a/zlog/category_table.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/conf.c b/zlog/conf.c deleted file mode 100644 index a921984..0000000 --- a/zlog/conf.c +++ /dev/null @@ -1,504 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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, "---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); - -zlog_conf_t *zlog_conf_new(const char *confpath) -{ - int nwrite = 0; - int has_conf_file = 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; - } - - if (confpath && confpath[0] != '\0') { - nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", confpath); - has_conf_file = 1; - } else if (getenv("ZLOG_CONF_PATH") != NULL) { - nwrite = snprintf(a_conf->file, sizeof(a_conf->file), "%s", getenv("ZLOG_CONF_PATH")); - has_conf_file = 1; - } else { - memset(a_conf->file, 0x00, sizeof(a_conf->file)); - has_conf_file = 0; - } - if (nwrite < 0 || nwrite >= sizeof(a_conf->file)) { - 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 (has_conf_file) { - /* 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 (has_conf_file) { - if (zlog_conf_build_with_file(a_conf)) { - zc_error("zlog_conf_build_with_file 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 (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, §ion); - 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; -} - -/* 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; -} -/*******************************************************************************/ diff --git a/zlog/conf.h b/zlog/conf.h deleted file mode 100644 index 39a04e7..0000000 --- a/zlog/conf.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 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 *confpath); -void zlog_conf_del(zlog_conf_t * a_conf); -void zlog_conf_profile(zlog_conf_t * a_conf, int flag); - -#endif diff --git a/zlog/event.c b/zlog/event.c deleted file mode 100644 index b62590f..0000000 --- a/zlog/event.c +++ /dev/null @@ -1,182 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#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; -} diff --git a/zlog/event.h b/zlog/event.h deleted file mode 100644 index a375daa..0000000 --- a/zlog/event.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#ifndef __zlog_event_h -#define __zlog_event_h - -#include /* for pid_t */ -#include /* for struct timeval */ -#include /* for pthread_t */ -#include /* 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 diff --git a/zlog/fmacros.h b/zlog/fmacros.h deleted file mode 100644 index b92bae1..0000000 --- a/zlog/fmacros.h +++ /dev/null @@ -1,24 +0,0 @@ -#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 diff --git a/zlog/format.c b/zlog/format.c deleted file mode 100644 index 0712ede..0000000 --- a/zlog/format.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/zlog/format.h b/zlog/format.h deleted file mode 100644 index 604bf94..0000000 --- a/zlog/format.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/level.c b/zlog/level.c deleted file mode 100644 index 0d39a3a..0000000 --- a/zlog/level.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#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; -} diff --git a/zlog/level.h b/zlog/level.h deleted file mode 100644 index 7077fc7..0000000 --- a/zlog/level.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/level_list.c b/zlog/level_list.c deleted file mode 100644 index ee47a85..0000000 --- a/zlog/level_list.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include "syslog.h" - -#include "zc_defs.h" -#include "level.h" -#include "level_list.h" - -/* zlog_level_list == zc_arraylist_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; -} - diff --git a/zlog/level_list.h b/zlog/level_list.h deleted file mode 100644 index 9c5332c..0000000 --- a/zlog/level_list.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/makefile b/zlog/makefile deleted file mode 100644 index 4ece5b1..0000000 --- a/zlog/makefile +++ /dev/null @@ -1,204 +0,0 @@ -# zlog makefile -# Copyright (C) 2010-2012 Hardy Simpson -# 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 diff --git a/zlog/mdc.c b/zlog/mdc.c deleted file mode 100644 index 41df8e7..0000000 --- a/zlog/mdc.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include - -#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; -} diff --git a/zlog/mdc.h b/zlog/mdc.h deleted file mode 100644 index 07ba5ae..0000000 --- a/zlog/mdc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/record.c b/zlog/record.c deleted file mode 100644 index a245e06..0000000 --- a/zlog/record.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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; -} diff --git a/zlog/record.h b/zlog/record.h deleted file mode 100644 index 4b67353..0000000 --- a/zlog/record.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/record_table.c b/zlog/record_table.c deleted file mode 100644 index df45a37..0000000 --- a/zlog/record_table.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include - -#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; - } -} -/*******************************************************************************/ diff --git a/zlog/record_table.h b/zlog/record_table.h deleted file mode 100644 index d1ab3e1..0000000 --- a/zlog/record_table.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/rotater.c b/zlog/rotater.c deleted file mode 100644 index ca6ca2b..0000000 --- a/zlog/rotater.c +++ /dev/null @@ -1,575 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#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; -} - -/*******************************************************************************/ diff --git a/zlog/rotater.h b/zlog/rotater.h deleted file mode 100644 index 2a8bf97..0000000 --- a/zlog/rotater.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/rule.c b/zlog/rule.c deleted file mode 100644 index a9b2700..0000000 --- a/zlog/rule.c +++ /dev/null @@ -1,1058 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rule.h" -#include "format.h" -#include "buf.h" -#include "thread.h" -#include "level_list.h" -#include "rotater.h" -#include "spec.h" -#include "conf.h" - -#include "zc_defs.h" - - -void zlog_rule_profile(zlog_rule_t * a_rule, int flag) -{ - int i; - zlog_spec_t *a_spec; - - zc_assert(a_rule,); - zc_profile(flag, "---rule:[%p][%s%c%d]-[%d,%d][%s,%p,%d:%ld*%d~%s][%d][%d][%s:%s:%p];[%p]---", - a_rule, - - a_rule->category, - a_rule->compare_char, - a_rule->level, - - a_rule->file_perms, - a_rule->file_open_flags, - - a_rule->file_path, - a_rule->dynamic_specs, - a_rule->static_fd, - - a_rule->archive_max_size, - a_rule->archive_max_count, - a_rule->archive_path, - - a_rule->pipe_fd, - - a_rule->syslog_facility, - - a_rule->record_name, - a_rule->record_path, - a_rule->record_func, - a_rule->format); - - if (a_rule->dynamic_specs) { - zc_arraylist_foreach(a_rule->dynamic_specs, i, a_spec) { - zlog_spec_profile(a_spec, flag); - } - } - return; -} - -/*******************************************************************************/ - -static int zlog_rule_output_static_file_single(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - struct stat stb; - int do_file_reload = 0; - int redo_inode_stat = 0; - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - /* check if the output file was changed by an external tool by comparing the inode to our saved off one */ - if (stat(a_rule->file_path, &stb)) { - if (errno != ENOENT) { - zc_error("stat fail on [%s], errno[%d]", a_rule->file_path, errno); - return -1; - } else { - do_file_reload = 1; - redo_inode_stat = 1; /* we'll have to restat the newly created file to get the inode info */ - } - } else { - do_file_reload = (stb.st_ino != a_rule->static_ino || stb.st_dev != a_rule->static_dev); - } - - if (do_file_reload) { - close(a_rule->static_fd); - a_rule->static_fd = open(a_rule->file_path, - O_WRONLY | O_APPEND | O_CREAT | a_rule->file_open_flags, - a_rule->file_perms); - if (a_rule->static_fd < 0) { - zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno); - return -1; - } - - /* save off the new dev/inode info from the stat call we already did */ - if (redo_inode_stat) { - if (stat(a_rule->file_path, &stb)) { - zc_error("stat fail on new file[%s], errno[%d]", a_rule->file_path, errno); - return -1; - } - } - a_rule->static_dev = stb.st_dev; - a_rule->static_ino = stb.st_ino; - } - - if (write(a_rule->static_fd, - zlog_buf_str(a_thread->msg_buf), - zlog_buf_len(a_thread->msg_buf)) < 0) { - zc_error("write fail, errno[%d]", errno); - return -1; - } - - /* not so thread safe here, as multiple thread may ++fsync_count at the same time */ - if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) { - a_rule->fsync_count = 0; - if (fsync(a_rule->static_fd)) { - zc_error("fsync[%d] fail, errno[%d]", a_rule->static_fd, errno); - } - } - - return 0; -} - -static char * zlog_rule_gen_archive_path(zlog_rule_t *a_rule, zlog_thread_t *a_thread) -{ - int i; - zlog_spec_t *a_spec; - - if (!a_rule->archive_specs) return a_rule->archive_path; - - zlog_buf_restart(a_thread->archive_path_buf); - - zc_arraylist_foreach(a_rule->archive_specs, i, a_spec) { - if (zlog_spec_gen_archive_path(a_spec, a_thread)) { - zc_error("zlog_spec_gen_path fail"); - return NULL; - } - } - - zlog_buf_seal(a_thread->archive_path_buf); - return zlog_buf_str(a_thread->archive_path_buf); -} - -static int zlog_rule_output_static_file_rotate(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - size_t len; - struct zlog_stat info; - int fd; - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - fd = open(a_rule->file_path, - a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms); - if (fd < 0) { - zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno); - return -1; - } - - len = zlog_buf_len(a_thread->msg_buf); - if (write(fd, zlog_buf_str(a_thread->msg_buf), len) < 0) { - zc_error("write fail, errno[%d]", errno); - close(fd); - return -1; - } - - if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) { - a_rule->fsync_count = 0; - if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno); - } - - if (close(fd) < 0) { - zc_error("close fail, maybe cause by write, errno[%d]", errno); - return -1; - } - - if (len > a_rule->archive_max_size) { - zc_debug("one msg's len[%ld] > archive_max_size[%ld], no rotate", - (long)len, (long)a_rule->archive_max_size); - return 0; - } - - if (stat(a_rule->file_path, &info)) { - zc_warn("stat [%s] fail, errno[%d], maybe in rotating", a_rule->file_path, errno); - return 0; - } - - /* file not so big, return */ - if (info.st_size + len < a_rule->archive_max_size) return 0; - - if (zlog_rotater_rotate(zlog_env_conf->rotater, - a_rule->file_path, len, - zlog_rule_gen_archive_path(a_rule, a_thread), - a_rule->archive_max_size, a_rule->archive_max_count) - ) { - zc_error("zlog_rotater_rotate fail"); - return -1; - } /* success or no rotation do nothing */ - - return 0; -} - -/* return path success - * return NULL fail - */ -#define zlog_rule_gen_path(a_rule, a_thread) do { \ - int i; \ - zlog_spec_t *a_spec; \ - \ - zlog_buf_restart(a_thread->path_buf); \ - \ - zc_arraylist_foreach(a_rule->dynamic_specs, i, a_spec) { \ - if (zlog_spec_gen_path(a_spec, a_thread)) { \ - zc_error("zlog_spec_gen_path fail"); \ - return -1; \ - } \ - } \ - \ - zlog_buf_seal(a_thread->path_buf); \ -} while(0) - - -static int zlog_rule_output_dynamic_file_single(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - int fd; - - zlog_rule_gen_path(a_rule, a_thread); - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_output fail"); - return -1; - } - - fd = open(zlog_buf_str(a_thread->path_buf), - a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms); - if (fd < 0) { - zc_error("open file[%s] fail, errno[%d]", zlog_buf_str(a_thread->path_buf), errno); - return -1; - } - - if (write(fd, zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) { - zc_error("write fail, errno[%d]", errno); - close(fd); - return -1; - } - - if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) { - a_rule->fsync_count = 0; - if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno); - } - - if (close(fd) < 0) { - zc_error("close fail, maybe cause by write, errno[%d]", errno); - return -1; - } - - return 0; -} - -static int zlog_rule_output_dynamic_file_rotate(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - int fd; - char *path; - size_t len; - struct zlog_stat info; - - zlog_rule_gen_path(a_rule, a_thread); - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_output fail"); - return -1; - } - - path = zlog_buf_str(a_thread->path_buf); - fd = open(path, a_rule->file_open_flags | O_WRONLY | O_APPEND | O_CREAT, a_rule->file_perms); - if (fd < 0) { - zc_error("open file[%s] fail, errno[%d]", zlog_buf_str(a_thread->path_buf), errno); - return -1; - } - - len = zlog_buf_len(a_thread->msg_buf); - if (write(fd, zlog_buf_str(a_thread->msg_buf), len) < 0) { - zc_error("write fail, errno[%d]", errno); - close(fd); - return -1; - } - - if (a_rule->fsync_period && ++a_rule->fsync_count >= a_rule->fsync_period) { - a_rule->fsync_count = 0; - if (fsync(fd)) zc_error("fsync[%d] fail, errno[%d]", fd, errno); - } - - if (close(fd) < 0) { - zc_error("write fail, maybe cause by write, errno[%d]", errno); - return -1; - } - - if (len > a_rule->archive_max_size) { - zc_debug("one msg's len[%ld] > archive_max_size[%ld], no rotate", - (long)len, (long) a_rule->archive_max_size); - return 0; - } - - if (stat(path, &info)) { - zc_warn("stat [%s] fail, errno[%d], maybe in rotating", path, errno); - return 0; - } - - /* file not so big, return */ - if (info.st_size + len < a_rule->archive_max_size) return 0; - - if (zlog_rotater_rotate(zlog_env_conf->rotater, - path, len, - zlog_rule_gen_archive_path(a_rule, a_thread), - a_rule->archive_max_size, a_rule->archive_max_count) - ) { - zc_error("zlog_rotater_rotate fail"); - return -1; - } /* success or no rotation do nothing */ - - return 0; -} - -static int zlog_rule_output_pipe(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - if (write(a_rule->pipe_fd, - zlog_buf_str(a_thread->msg_buf), - zlog_buf_len(a_thread->msg_buf)) < 0) { - zc_error("write fail, errno[%d]", errno); - return -1; - } - - return 0; -} - -static int zlog_rule_output_syslog(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - zlog_level_t *a_level; - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - /* - msg = a_thread->msg_buf->start; - msg_len = a_thread->msg_buf->end - a_thread->msg_buf->start; - */ - - a_level = zlog_level_list_get(zlog_env_conf->levels, a_thread->event->level); - zlog_buf_seal(a_thread->msg_buf); - syslog(a_rule->syslog_facility | a_level->syslog_level, - "%s", zlog_buf_str(a_thread->msg_buf)); - return 0; -} - -static int zlog_rule_output_static_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - zlog_msg_t msg; - - if (!a_rule->record_func) { - zc_error("user defined record funcion for [%s] not set, no output", - a_rule->record_name); - return -1; - } - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - zlog_buf_seal(a_thread->msg_buf); - - msg.buf = zlog_buf_str(a_thread->msg_buf); - msg.len = zlog_buf_len(a_thread->msg_buf); - msg.path = a_rule->record_path; - - if (a_rule->record_func(&msg)) { - zc_error("a_rule->record fail"); - return -1; - } - return 0; -} - -static int zlog_rule_output_dynamic_record(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - zlog_msg_t msg; - - if (!a_rule->record_func) { - zc_error("user defined record funcion for [%s] not set, no output", - a_rule->record_name); - return -1; - } - - zlog_rule_gen_path(a_rule, a_thread); - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - zlog_buf_seal(a_thread->msg_buf); - - msg.buf = zlog_buf_str(a_thread->msg_buf); - msg.len = zlog_buf_len(a_thread->msg_buf); - msg.path = zlog_buf_str(a_thread->path_buf); - - if (a_rule->record_func(&msg)) { - zc_error("a_rule->record fail"); - return -1; - } - return 0; -} - -static int zlog_rule_output_stdout(zlog_rule_t * a_rule, - zlog_thread_t * a_thread) -{ - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - if (write(STDOUT_FILENO, - zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) { - zc_error("write fail, errno[%d]", errno); - return -1; - } - - return 0; -} - -static int zlog_rule_output_stderr(zlog_rule_t * a_rule, - zlog_thread_t * a_thread) -{ - - if (zlog_format_gen_msg(a_rule->format, a_thread)) { - zc_error("zlog_format_gen_msg fail"); - return -1; - } - - if (write(STDERR_FILENO, - zlog_buf_str(a_thread->msg_buf), zlog_buf_len(a_thread->msg_buf)) < 0) { - zc_error("write fail, errno[%d]", errno); - return -1; - } - - return 0; -} -/*******************************************************************************/ -static int syslog_facility_atoi(char *facility) -{ - /* guess no unix system will choose -187 - * as its syslog facility, so it is a safe return value - */ - zc_assert(facility, -187); - - if (STRICMP(facility, ==, "LOG_LOCAL0")) return LOG_LOCAL0; - if (STRICMP(facility, ==, "LOG_LOCAL1")) return LOG_LOCAL1; - if (STRICMP(facility, ==, "LOG_LOCAL2")) return LOG_LOCAL2; - if (STRICMP(facility, ==, "LOG_LOCAL3")) return LOG_LOCAL3; - if (STRICMP(facility, ==, "LOG_LOCAL4")) return LOG_LOCAL4; - if (STRICMP(facility, ==, "LOG_LOCAL5")) return LOG_LOCAL5; - if (STRICMP(facility, ==, "LOG_LOCAL6")) return LOG_LOCAL6; - if (STRICMP(facility, ==, "LOG_LOCAL7")) return LOG_LOCAL7; - if (STRICMP(facility, ==, "LOG_USER")) return LOG_USER; - if (STRICMP(facility, ==, "LOG_AUTHPRIV")) return LOG_AUTHPRIV; - if (STRICMP(facility, ==, "LOG_CRON")) return LOG_CRON; - if (STRICMP(facility, ==, "LOG_DAEMON")) return LOG_DAEMON; - if (STRICMP(facility, ==, "LOG_FTP")) return LOG_FTP; - if (STRICMP(facility, ==, "LOG_KERN")) return LOG_KERN; - if (STRICMP(facility, ==, "LOG_LPR")) return LOG_LPR; - if (STRICMP(facility, ==, "LOG_MAIL")) return LOG_MAIL; - if (STRICMP(facility, ==, "LOG_NEWS")) return LOG_NEWS; - if (STRICMP(facility, ==, "LOG_SYSLOG")) return LOG_SYSLOG; - return LOG_AUTHPRIV; - - zc_error("wrong syslog facility[%s], must in LOG_LOCAL[0-7] or LOG_USER", facility); - return -187; -} - -static int zlog_rule_parse_path(char *path_start, /* start with a " */ - char *path_str, size_t path_size, zc_arraylist_t **path_specs, - int *time_cache_count) -{ - char *p, *q; - size_t len; - zlog_spec_t *a_spec; - zc_arraylist_t *specs; - - p = path_start + 1; - - q = strrchr(p, '"'); - if (!q) { - zc_error("matching \" not found in conf line[%s]", path_start); - return -1; - } - len = q - p; - if (len > path_size - 1) { - zc_error("file_path too long %ld > %ld", len, path_size - 1); - return -1; - } - memcpy(path_str, p, len); - - /* replace any environment variables like %E(HOME) */ - if (zc_str_replace_env(path_str, path_size)) { - zc_error("zc_str_replace_env fail"); - return -1; - } - - if (strchr(path_str, '%') == NULL) { - /* static, no need create specs */ - return 0; - } - - specs = zc_arraylist_new((zc_arraylist_del_fn)zlog_spec_del); - if (!path_specs) { - zc_error("zc_arraylist_new fail"); - return -1; - } - - for (p = path_str; *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(specs, a_spec)) { - zc_error("zc_arraylist_add fail"); - goto err; - } - } - - *path_specs = specs; - return 0; -err: - if (specs) zc_arraylist_del(specs); - if (a_spec) zlog_spec_del(a_spec); - return -1; -} - -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) -{ - int rc = 0; - int nscan = 0; - int nread = 0; - zlog_rule_t *a_rule; - - char selector[MAXLEN_CFG_LINE + 1]; - char category[MAXLEN_CFG_LINE + 1]; - char level[MAXLEN_CFG_LINE + 1]; - - char *action; - char output[MAXLEN_CFG_LINE + 1]; - char format_name[MAXLEN_CFG_LINE + 1]; - char file_path[MAXLEN_CFG_LINE + 1]; - char archive_max_size[MAXLEN_CFG_LINE + 1]; - char *file_limit; - - char *p; - char *q; - size_t len; - - zc_assert(line, NULL); - zc_assert(default_format, NULL); - zc_assert(formats, NULL); - - a_rule = calloc(1, sizeof(zlog_rule_t)); - if (!a_rule) { - zc_error("calloc fail, errno[%d]", errno); - return NULL; - } - - a_rule->file_perms = file_perms; - a_rule->fsync_period = fsync_period; - - /* line [f.INFO "%H/log/aa.log", 20MB * 12; MyTemplate] - * selector [f.INFO] - * *action ["%H/log/aa.log", 20MB * 12; MyTemplate] - */ - memset(&selector, 0x00, sizeof(selector)); - nscan = sscanf(line, "%s %n", selector, &nread); - if (nscan != 1) { - zc_error("sscanf [%s] fail, selector", line); - goto err; - } - action = line + nread; - - /* - * selector [f.INFO] - * category [f] - * level [.INFO] - */ - memset(category, 0x00, sizeof(category)); - memset(level, 0x00, sizeof(level)); - nscan = sscanf(selector, " %[^.].%s", category, level); - if (nscan != 2) { - zc_error("sscanf [%s] fail, category or level is null", - selector); - goto err; - } - - /* check and set category */ - for (p = category; *p != '\0'; p++) { - if ((!isalnum(*p)) && (*p != '_') && (*p != '-') && (*p != '*') && (*p != '!')) { - zc_error("category name[%s] character is not in [a-Z][0-9][_!*-]", category); - goto err; - } - } - - /* as one line can't be longer than MAXLEN_CFG_LINE, same as category */ - strcpy(a_rule->category, category); - - /* check and set level */ - switch (level[0]) { - case '=': - /* aa.=debug */ - a_rule->compare_char = '='; - p = level + 1; - break; - case '!': - /* aa.!debug */ - a_rule->compare_char = '!'; - p = level + 1; - break; - case '*': - /* aa.* */ - a_rule->compare_char = '*'; - p = level; - break; - default: - /* aa.debug */ - a_rule->compare_char = '.'; - p = level; - break; - } - - a_rule->level = zlog_level_list_atoi(levels, p); - - /* level_bit is a bitmap represents which level can be output - * 32bytes, [0-255] levels, see level.c - * which bit field is 1 means allow output and 0 not - */ - switch (a_rule->compare_char) { - case '=': - memset(a_rule->level_bitmap, 0x00, sizeof(a_rule->level_bitmap)); - a_rule->level_bitmap[a_rule->level / 8] |= (1 << (7 - a_rule->level % 8)); - break; - case '!': - memset(a_rule->level_bitmap, 0xFF, sizeof(a_rule->level_bitmap)); - a_rule->level_bitmap[a_rule->level / 8] &= ~(1 << (7 - a_rule->level % 8)); - break; - case '*': - memset(a_rule->level_bitmap, 0xFF, sizeof(a_rule->level_bitmap)); - break; - case '.': - memset(a_rule->level_bitmap, 0x00, sizeof(a_rule->level_bitmap)); - a_rule->level_bitmap[a_rule->level / 8] |= ~(0xFF << (8 - a_rule->level % 8)); - memset(a_rule->level_bitmap + a_rule->level / 8 + 1, 0xFF, - sizeof(a_rule->level_bitmap) - a_rule->level / 8 - 1); - break; - } - - /* action ["%H/log/aa.log", 20MB * 12 ; MyTemplate] - * output ["%H/log/aa.log", 20MB * 12] - * format [MyTemplate] - */ - memset(output, 0x00, sizeof(output)); - memset(format_name, 0x00, sizeof(format_name)); - nscan = sscanf(action, " %[^;];%s", output, format_name); - if (nscan < 1) { - zc_error("sscanf [%s] fail", action); - goto err; - } - - /* check and get format */ - if (STRCMP(format_name, ==, "")) { - zc_debug("no format specified, use default"); - a_rule->format = default_format; - } else { - int i; - int find_flag = 0; - zlog_format_t *a_format; - - zc_arraylist_foreach(formats, i, a_format) { - if (zlog_format_has_name(a_format, format_name)) { - a_rule->format = a_format; - find_flag = 1; - break; - } - } - if (!find_flag) { - zc_error("in conf file can't find format[%s], pls check", - format_name); - goto err; - } - } - - /* output [-"%E(HOME)/log/aa.log" , 20MB*12] [>syslog , LOG_LOCAL0 ] - * file_path [-"%E(HOME)/log/aa.log" ] [>syslog ] - * *file_limit [20MB * 12 ~ "aa.#i.log" ] [LOG_LOCAL0] - */ - memset(file_path, 0x00, sizeof(file_path)); - nscan = sscanf(output, " %[^,],", file_path); - if (nscan < 1) { - zc_error("sscanf [%s] fail", action); - goto err; - } - - file_limit = strchr(output, ','); - if (file_limit) { - file_limit++; /* skip the , */ - while( isspace(*file_limit) ) { - file_limit++; - } - } - - p = NULL; - switch (file_path[0]) { - case '-' : - /* sync file each time write log */ - if (file_path[1] != '"') { - zc_error(" - must set before a file output"); - goto err; - } - - /* no need to fsync, as file is opened by O_SYNC, write immediately */ - a_rule->fsync_period = 0; - - p = file_path + 1; - a_rule->file_open_flags = O_SYNC; - /* fall through */ - case '"' : - if (!p) p = file_path; - - rc = zlog_rule_parse_path(p, a_rule->file_path, sizeof(a_rule->file_path), - &(a_rule->dynamic_specs), time_cache_count); - if (rc) { - zc_error("zlog_rule_parse_path fail"); - goto err; - } - - if (file_limit) { - memset(archive_max_size, 0x00, sizeof(archive_max_size)); - nscan = sscanf(file_limit, " %[0-9MmKkBb] * %d ~", - archive_max_size, &(a_rule->archive_max_count)); - if (nscan) { - a_rule->archive_max_size = zc_parse_byte_size(archive_max_size); - } - p = strchr(file_limit, '"'); - if (p) { /* archive file path exist */ - rc = zlog_rule_parse_path(p, - a_rule->archive_path, sizeof(a_rule->file_path), - &(a_rule->archive_specs), time_cache_count); - if (rc) { - zc_error("zlog_rule_parse_path fail"); - goto err; - } - - p = strchr(a_rule->archive_path, '#'); - if ( (p == NULL) || ((strchr(p, 'r') == NULL) && (strchr(p, 's') == NULL))) { - zc_error("archive_path must contain #r or #s"); - goto err; - } - } - } - - /* try to figure out if the log file path is dynamic or static */ - if (a_rule->dynamic_specs) { - if (a_rule->archive_max_size <= 0) { - a_rule->output = zlog_rule_output_dynamic_file_single; - } else { - a_rule->output = zlog_rule_output_dynamic_file_rotate; - } - } else { - struct stat stb; - - if (a_rule->archive_max_size <= 0) { - a_rule->output = zlog_rule_output_static_file_single; - } else { - /* as rotate, so need to reopen everytime */ - a_rule->output = zlog_rule_output_static_file_rotate; - } - - a_rule->static_fd = open(a_rule->file_path, - O_WRONLY | O_APPEND | O_CREAT | a_rule->file_open_flags, - a_rule->file_perms); - if (a_rule->static_fd < 0) { - zc_error("open file[%s] fail, errno[%d]", a_rule->file_path, errno); - goto err; - } - - /* save off the inode information for checking for a changed file later on */ - if (fstat(a_rule->static_fd, &stb)) { - zc_error("stat [%s] fail, errno[%d], failing to open static_fd", a_rule->file_path, errno); - goto err; - } - - if (a_rule->archive_max_size > 0) { - close(a_rule->static_fd); - a_rule->static_fd = -1; - } - - a_rule->static_dev = stb.st_dev; - a_rule->static_ino = stb.st_ino; - } - break; - case '|' : - a_rule->pipe_fp = popen(output + 1, "w"); - if (!a_rule->pipe_fp) { - zc_error("popen fail, errno[%d]", errno); - goto err; - } - a_rule->pipe_fd = fileno(a_rule->pipe_fp); - if (a_rule->pipe_fd < 0 ) { - zc_error("fileno fail, errno[%d]", errno); - goto err; - } - a_rule->output = zlog_rule_output_pipe; - break; - case '>' : - if (STRNCMP(file_path + 1, ==, "syslog", 6)) { - a_rule->syslog_facility = syslog_facility_atoi(file_limit); - if (a_rule->syslog_facility == -187) { - zc_error("-187 get"); - goto err; - } - a_rule->output = zlog_rule_output_syslog; - openlog(NULL, LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_USER); - } else if (STRNCMP(file_path + 1, ==, "stdout", 6)) { - a_rule->output = zlog_rule_output_stdout; - } else if (STRNCMP(file_path + 1, ==, "stderr", 6)) { - a_rule->output = zlog_rule_output_stderr; - } else { - zc_error - ("[%s]the string after is not syslog, stdout or stderr", output); - goto err; - } - break; - case '$' : - sscanf(file_path + 1, "%s", a_rule->record_name); - - if (file_limit) { /* record path exists */ - p = strchr(file_limit, '"'); - if (!p) { - zc_error("record_path not start with \", [%s]", file_limit); - goto err; - } - p++; /* skip 1st " */ - - q = strrchr(p, '"'); - if (!q) { - zc_error("matching \" not found in conf line[%s]", p); - goto err; - } - len = q - p; - if (len > sizeof(a_rule->record_path) - 1) { - zc_error("record_path too long %ld > %ld", len, sizeof(a_rule->record_path) - 1); - goto err; - } - memcpy(a_rule->record_path, p, len); - } - - /* replace any environment variables like %E(HOME) */ - rc = zc_str_replace_env(a_rule->record_path, sizeof(a_rule->record_path)); - if (rc) { - zc_error("zc_str_replace_env fail"); - goto err; - } - - /* try to figure out if the log file path is dynamic or static */ - if (strchr(a_rule->record_path, '%') == NULL) { - a_rule->output = zlog_rule_output_static_record; - } else { - zlog_spec_t *a_spec; - - a_rule->output = zlog_rule_output_dynamic_record; - - a_rule->dynamic_specs = zc_arraylist_new((zc_arraylist_del_fn)zlog_spec_del); - if (!(a_rule->dynamic_specs)) { - zc_error("zc_arraylist_new fail"); - goto err; - } - for (p = a_rule->record_path; *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; - } - - rc = zc_arraylist_add(a_rule->dynamic_specs, a_spec); - if (rc) { - zlog_spec_del(a_spec); - zc_error("zc_arraylist_add fail"); - goto err; - } - } - } - break; - default : - zc_error("the 1st char[%c] of file_path[%s] is wrong", - file_path[0], file_path); - goto err; - } - - return a_rule; -err: - zlog_rule_del(a_rule); - return NULL; -} - -void zlog_rule_del(zlog_rule_t * a_rule) -{ - zc_assert(a_rule,); - if (a_rule->dynamic_specs) { - zc_arraylist_del(a_rule->dynamic_specs); - a_rule->dynamic_specs = NULL; - } - if (a_rule->static_fd) { - if (close(a_rule->static_fd)) { - zc_error("close fail, maybe cause by write, errno[%d]", errno); - } - } - if (a_rule->pipe_fp) { - if (pclose(a_rule->pipe_fp) == -1) { - zc_error("pclose fail, errno[%d]", errno); - } - } - if (a_rule->archive_specs) { - zc_arraylist_del(a_rule->archive_specs); - a_rule->archive_specs = NULL; - } - zc_debug("zlog_rule_del[%p]", a_rule); - free(a_rule); - return; -} - -/*******************************************************************************/ -int zlog_rule_output(zlog_rule_t * a_rule, zlog_thread_t * a_thread) -{ - switch (a_rule->compare_char) { - case '*' : - return a_rule->output(a_rule, a_thread); - break; - case '.' : - if (a_thread->event->level >= a_rule->level) { - return a_rule->output(a_rule, a_thread); - } else { - return 0; - } - break; - case '=' : - if (a_thread->event->level == a_rule->level) { - return a_rule->output(a_rule, a_thread); - } else { - return 0; - } - break; - case '!' : - if (a_thread->event->level != a_rule->level) { - return a_rule->output(a_rule, a_thread); - } else { - return 0; - } - break; - } - - return 0; -} - -/*******************************************************************************/ -int zlog_rule_is_wastebin(zlog_rule_t * a_rule) -{ - zc_assert(a_rule, -1); - - if (STRCMP(a_rule->category, ==, "!")) { - return 1; - } - - return 0; -} - -/*******************************************************************************/ -int zlog_rule_match_category(zlog_rule_t * a_rule, char *category) -{ - zc_assert(a_rule, -1); - zc_assert(category, -1); - - if (STRCMP(a_rule->category, ==, "*")) { - /* '*' match anything, so go on */ - return 1; - } else if (STRCMP(a_rule->category, ==, category)) { - /* accurate compare */ - return 1; - } else { - /* aa_ match aa_xx & aa, but not match aa1_xx */ - size_t len; - len = strlen(a_rule->category); - - if (a_rule->category[len - 1] == '_') { - if (strlen(category) == len - 1) { - len--; - } - - if (STRNCMP(a_rule->category, ==, category, len)) { - return 1; - } - } - } - - return 0; -} - -/*******************************************************************************/ - -int zlog_rule_set_record(zlog_rule_t * a_rule, zc_hashtable_t *records) -{ - zlog_record_t *a_record; - - if (a_rule->output != zlog_rule_output_static_record - && a_rule->output != zlog_rule_output_dynamic_record) { - return 0; /* fliter, may go through not record rule */ - } - - a_record = zc_hashtable_get(records, a_rule->record_name); - if (a_record) { - a_rule->record_func = a_record->output; - } - return 0; -} diff --git a/zlog/rule.h b/zlog/rule.h deleted file mode 100644 index e562185..0000000 --- a/zlog/rule.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 -#include - -#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 diff --git a/zlog/spec.c b/zlog/spec.c deleted file mode 100644 index b047605..0000000 --- a/zlog/spec.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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_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 '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; -} - diff --git a/zlog/spec.h b/zlog/spec.h deleted file mode 100644 index c3d78a2..0000000 --- a/zlog/spec.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/thread.c b/zlog/thread.c deleted file mode 100644 index 3cd112c..0000000 --- a/zlog/thread.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include - -#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; -} - - -/*******************************************************************************/ diff --git a/zlog/thread.h b/zlog/thread.h deleted file mode 100644 index 8548bbd..0000000 --- a/zlog/thread.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/version.h b/zlog/version.h deleted file mode 100644 index 98adba7..0000000 --- a/zlog/version.h +++ /dev/null @@ -1 +0,0 @@ -#define ZLOG_VERSION "1.2.12" diff --git a/zlog/zc_arraylist.c b/zlog/zc_arraylist.c deleted file mode 100644 index b1625a1..0000000 --- a/zlog/zc_arraylist.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include - -#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); -} diff --git a/zlog/zc_arraylist.h b/zlog/zc_arraylist.h deleted file mode 100644 index 50f3f77..0000000 --- a/zlog/zc_arraylist.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/zc_defs.h b/zlog/zc_defs.h deleted file mode 100644 index 9524999..0000000 --- a/zlog/zc_defs.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/zc_hashtable.c b/zlog/zc_hashtable.c deleted file mode 100644 index 00ce20f..0000000 --- a/zlog/zc_hashtable.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include - -#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)); -} diff --git a/zlog/zc_hashtable.h b/zlog/zc_hashtable.h deleted file mode 100644 index 0f1c529..0000000 --- a/zlog/zc_hashtable.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#ifndef __zc_hashtalbe_h -#define __zc_hashtalbe_h - -#include - -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 diff --git a/zlog/zc_profile.c b/zlog/zc_profile.c deleted file mode 100644 index ff0f606..0000000 --- a/zlog/zc_profile.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#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; -} - diff --git a/zlog/zc_profile.h b/zlog/zc_profile.h deleted file mode 100644 index e629ef1..0000000 --- a/zlog/zc_profile.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#ifndef __zc_profile_h -#define __zc_profile_h - -#include - -#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 diff --git a/zlog/zc_util.c b/zlog/zc_util.c deleted file mode 100644 index 07deb22..0000000 --- a/zlog/zc_util.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include -#include -#include -#include -#include -#include - -#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; -} diff --git a/zlog/zc_util.h b/zlog/zc_util.h deleted file mode 100644 index 3f032cd..0000000 --- a/zlog/zc_util.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 diff --git a/zlog/zc_xplatform.h b/zlog/zc_xplatform.h deleted file mode 100644 index ecfa7df..0000000 --- a/zlog/zc_xplatform.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ -#ifndef __zc_xplatform_h -#define __zc_xplatform_h - -#include - -#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 FILE_NEWLINE "\n" -#define FILE_NEWLINE_LEN 1 - -#include -#include - -#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 -#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 diff --git a/zlog/zlog-1.2.15.tar.gz b/zlog/zlog-1.2.15.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..20e10dc8cd21dc396f5de37bea0c2139eaa63af7 GIT binary patch literal 124794 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
{VmGL+tYx3C{)bMQCcT11jUuDZf%X; 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�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
``}gmr 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 literal 0 HcmV?d00001 diff --git a/zlog/zlog-chk-conf.c b/zlog/zlog-chk-conf.c deleted file mode 100644 index 0a4f630..0000000 --- a/zlog/zlog-chk-conf.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" - -#include -#include -#include -#include - -#include - -#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); -} diff --git a/zlog/zlog.c b/zlog/zlog.c deleted file mode 100644 index 0bff453..0000000 --- a/zlog/zlog.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * Licensed under the LGPL v2.1, see the file COPYING in base directory. - */ - -#include "fmacros.h" - -#include -#include -#include -#include -#include - -#include "conf.h" -#include "category_table.h" -#include "record_table.h" -#include "mdc.h" -#include "zc_defs.h" -#include "rule.h" -#include "version.h" - -/*******************************************************************************/ -extern char *zlog_git_sha1; -/*******************************************************************************/ -static pthread_rwlock_t zlog_env_lock = PTHREAD_RWLOCK_INITIALIZER; -zlog_conf_t *zlog_env_conf; -static pthread_key_t zlog_thread_key; -static zc_hashtable_t *zlog_env_categories; -static zc_hashtable_t *zlog_env_records; -static zlog_category_t *zlog_default_category; -static size_t zlog_env_reload_conf_count; -static int zlog_env_is_init = 0; -static int zlog_env_init_version = 0; -/*******************************************************************************/ -/* inner no need thread-safe */ -static void zlog_fini_inner(void) -{ - /* pthread_key_delete(zlog_thread_key); */ - /* never use pthread_key_delete, - * it will cause other thread can't release zlog_thread_t - * after one thread call pthread_key_delete - * also key not init will cause a core dump - */ - - if (zlog_env_categories) zlog_category_table_del(zlog_env_categories); - zlog_env_categories = NULL; - zlog_default_category = NULL; - if (zlog_env_records) zlog_record_table_del(zlog_env_records); - zlog_env_records = NULL; - if (zlog_env_conf) zlog_conf_del(zlog_env_conf); - zlog_env_conf = NULL; - return; -} - -static void zlog_clean_rest_thread(void) -{ - zlog_thread_t *a_thread; - a_thread = pthread_getspecific(zlog_thread_key); - if (!a_thread) return; - zlog_thread_del(a_thread); - return; -} - -static int zlog_init_inner(const char *confpath) -{ - int rc = 0; - - /* the 1st time in the whole process do init */ - if (zlog_env_init_version == 0) { - /* clean up is done by OS when a thread call pthread_exit */ - rc = pthread_key_create(&zlog_thread_key, (void (*) (void *)) zlog_thread_del); - if (rc) { - zc_error("pthread_key_create fail, rc[%d]", rc); - goto err; - } - - /* if some thread do not call pthread_exit, like main thread - * atexit will clean it - */ - rc = atexit(zlog_clean_rest_thread); - if (rc) { - zc_error("atexit fail, rc[%d]", rc); - goto err; - } - zlog_env_init_version++; - } /* else maybe after zlog_fini() and need not create pthread_key */ - - zlog_env_conf = zlog_conf_new(confpath); - if (!zlog_env_conf) { - zc_error("zlog_conf_new[%s] fail", confpath); - goto err; - } - - zlog_env_categories = zlog_category_table_new(); - if (!zlog_env_categories) { - zc_error("zlog_category_table_new fail"); - goto err; - } - - zlog_env_records = zlog_record_table_new(); - if (!zlog_env_records) { - zc_error("zlog_record_table_new fail"); - goto err; - } - - return 0; -err: - zlog_fini_inner(); - return -1; -} - -/*******************************************************************************/ -int zlog_init(const char *confpath) -{ - int rc; - zc_debug("------zlog_init start------"); - zc_debug("------compile time[%s %s], version[%s]------", __DATE__, __TIME__, ZLOG_VERSION); - - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return -1; - } - - if (zlog_env_is_init) { - zc_error("already init, use zlog_reload pls"); - goto err; - } - - - if (zlog_init_inner(confpath)) { - zc_error("zlog_init_inner[%s] fail", confpath); - goto err; - } - - zlog_env_is_init = 1; - zlog_env_init_version++; - - zc_debug("------zlog_init success end------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -err: - zc_error("------zlog_init fail end------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return -1; -} - -int dzlog_init(const char *confpath, const char *cname) -{ - int rc = 0; - zc_debug("------dzlog_init start------"); - zc_debug("------compile time[%s %s], version[%s]------", - __DATE__, __TIME__, ZLOG_VERSION); - - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return -1; - } - - if (zlog_env_is_init) { - zc_error("already init, use zlog_reload pls"); - goto err; - } - - if (zlog_init_inner(confpath)) { - zc_error("zlog_init_inner[%s] fail", confpath); - goto err; - } - - zlog_default_category = zlog_category_table_fetch_category( - zlog_env_categories, - cname, - zlog_env_conf->rules); - if (!zlog_default_category) { - zc_error("zlog_category_table_fetch_category[%s] fail", cname); - goto err; - } - - zlog_env_is_init = 1; - zlog_env_init_version++; - - zc_debug("------dzlog_init success end------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -err: - zc_error("------dzlog_init fail end------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return -1; -} -/*******************************************************************************/ -int zlog_reload(const char *confpath) -{ - int rc = 0; - int i = 0; - zlog_conf_t *new_conf = NULL; - zlog_rule_t *a_rule; - int c_up = 0; - - zc_debug("------zlog_reload start------"); - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return -1; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto quit; - } - - /* use last conf file */ - if (confpath == NULL) confpath = zlog_env_conf->file; - - /* reach reload period */ - if (confpath == (char*)-1) { - /* test again, avoid other threads already reloaded */ - if (zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period) { - confpath = zlog_env_conf->file; - } else { - /* do nothing, already done */ - goto quit; - } - } - - /* reset counter, whether automaticlly or mannually */ - zlog_env_reload_conf_count = 0; - - new_conf = zlog_conf_new(confpath); - if (!new_conf) { - zc_error("zlog_conf_new fail"); - goto err; - } - - zc_arraylist_foreach(new_conf->rules, i, a_rule) { - zlog_rule_set_record(a_rule, zlog_env_records); - } - - if (zlog_category_table_update_rules(zlog_env_categories, new_conf->rules)) { - c_up = 0; - zc_error("zlog_category_table_update fail"); - goto err; - } else { - c_up = 1; - } - - zlog_env_init_version++; - - if (c_up) zlog_category_table_commit_rules(zlog_env_categories); - zlog_conf_del(zlog_env_conf); - zlog_env_conf = new_conf; - zc_debug("------zlog_reload success, total init verison[%d] ------", zlog_env_init_version); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -err: - /* fail, roll back everything */ - zc_warn("zlog_reload fail, use old conf file, still working"); - if (new_conf) zlog_conf_del(new_conf); - if (c_up) zlog_category_table_rollback_rules(zlog_env_categories); - zc_error("------zlog_reload fail, total init version[%d] ------", zlog_env_init_version); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return -1; -quit: - zc_debug("------zlog_reload do nothing------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -} -/*******************************************************************************/ -void zlog_fini(void) -{ - int rc = 0; - - zc_debug("------zlog_fini start------"); - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return; - } - - if (!zlog_env_is_init) { - zc_error("before finish, must zlog_init() or dzlog_init() fisrt"); - goto exit; - } - - zlog_fini_inner(); - zlog_env_is_init = 0; - -exit: - zc_debug("------zlog_fini end------"); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return; - } - return; -} -/*******************************************************************************/ -zlog_category_t *zlog_get_category(const char *cname) -{ - int rc = 0; - zlog_category_t *a_category = NULL; - - zc_assert(cname, NULL); - zc_debug("------zlog_get_category[%s] start------", cname); - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return NULL; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - a_category = NULL; - goto err; - } - - a_category = zlog_category_table_fetch_category( - zlog_env_categories, - cname, - zlog_env_conf->rules); - if (!a_category) { - zc_error("zlog_category_table_fetch_category[%s] fail", cname); - goto err; - } - - zc_debug("------zlog_get_category[%s] success, end------ ", cname); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return NULL; - } - return a_category; -err: - zc_error("------zlog_get_category[%s] fail, end------ ", cname); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return NULL; - } - return NULL; -} - -int dzlog_set_category(const char *cname) -{ - int rc = 0; - zc_assert(cname, -1); - - zc_debug("------dzlog_set_category[%s] start------", cname); - rc = pthread_rwlock_wrlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return -1; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto err; - } - - zlog_default_category = zlog_category_table_fetch_category( - zlog_env_categories, - cname, - zlog_env_conf->rules); - if (!zlog_default_category) { - zc_error("zlog_category_table_fetch_category[%s] fail", cname); - goto err; - } - - zc_debug("------dzlog_set_category[%s] end, success------ ", cname); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -err: - zc_error("------dzlog_set_category[%s] end, fail------ ", cname); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return -1; -} -/*******************************************************************************/ -#define zlog_fetch_thread(a_thread, fail_goto) do { \ - int rd = 0; \ - a_thread = pthread_getspecific(zlog_thread_key); \ - if (!a_thread) { \ - a_thread = zlog_thread_new(zlog_env_init_version, \ - zlog_env_conf->buf_size_min, zlog_env_conf->buf_size_max, \ - zlog_env_conf->time_cache_count); \ - if (!a_thread) { \ - zc_error("zlog_thread_new fail"); \ - goto fail_goto; \ - } \ - \ - rd = pthread_setspecific(zlog_thread_key, a_thread); \ - if (rd) { \ - zlog_thread_del(a_thread); \ - zc_error("pthread_setspecific fail, rd[%d]", rd); \ - goto fail_goto; \ - } \ - } \ - \ - if (a_thread->init_version != zlog_env_init_version) { \ - /* as mdc is still here, so can not easily del and new */ \ - rd = zlog_thread_rebuild_msg_buf(a_thread, \ - zlog_env_conf->buf_size_min, \ - zlog_env_conf->buf_size_max); \ - if (rd) { \ - zc_error("zlog_thread_resize_msg_buf fail, rd[%d]", rd); \ - goto fail_goto; \ - } \ - \ - rd = zlog_thread_rebuild_event(a_thread, zlog_env_conf->time_cache_count); \ - if (rd) { \ - zc_error("zlog_thread_resize_msg_buf fail, rd[%d]", rd); \ - goto fail_goto; \ - } \ - a_thread->init_version = zlog_env_init_version; \ - } \ -} while (0) - -/*******************************************************************************/ -int zlog_put_mdc(const char *key, const char *value) -{ - int rc = 0; - zlog_thread_t *a_thread; - - zc_assert(key, -1); - zc_assert(value, -1); - - rc = pthread_rwlock_rdlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return -1; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto err; - } - - zlog_fetch_thread(a_thread, err); - - if (zlog_mdc_put(a_thread->mdc, key, value)) { - zc_error("zlog_mdc_put fail, key[%s], value[%s]", key, value); - goto err; - } - - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return 0; -err: - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return -1; - } - return -1; -} - -char *zlog_get_mdc(char *key) -{ - int rc = 0; - char *value = NULL; - zlog_thread_t *a_thread; - - zc_assert(key, NULL); - - rc = pthread_rwlock_rdlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc); - return NULL; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto err; - } - - a_thread = pthread_getspecific(zlog_thread_key); - if (!a_thread) { - zc_error("thread not found, maybe not use zlog_put_mdc before"); - goto err; - } - - value = zlog_mdc_get(a_thread->mdc, key); - if (!value) { - zc_error("key[%s] not found in mdc", key); - goto err; - } - - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return NULL; - } - return value; -err: - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return NULL; - } - return NULL; -} - -void zlog_remove_mdc(char *key) -{ - int rc = 0; - zlog_thread_t *a_thread; - - zc_assert(key, ); - - rc = pthread_rwlock_rdlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc); - return; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - a_thread = pthread_getspecific(zlog_thread_key); - if (!a_thread) { - zc_error("thread not found, maybe not use zlog_put_mdc before"); - goto exit; - } - - zlog_mdc_remove(a_thread->mdc, key); - -exit: - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return; - } - return; -} - -void zlog_clean_mdc(void) -{ - int rc = 0; - zlog_thread_t *a_thread; - - rc = pthread_rwlock_rdlock(&zlog_env_lock); - if (rc) {; - zc_error("pthread_rwlock_rdlock fail, rc[%d]", rc); - return; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - a_thread = pthread_getspecific(zlog_thread_key); - if (!a_thread) { - zc_error("thread not found, maybe not use zlog_put_mdc before"); - goto exit; - } - - zlog_mdc_clean(a_thread->mdc); - -exit: - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return; - } - return; -} - -int zlog_level_switch(zlog_category_t * category, int level) -{ - // This is NOT thread safe. - memset(category->level_bitmap, 0x00, sizeof(category->level_bitmap)); - category->level_bitmap[level / 8] |= ~(0xFF << (8 - level % 8)); - memset(category->level_bitmap + level / 8 + 1, 0xFF, - sizeof(category->level_bitmap) - level / 8 - 1); - - return 0; -} - -/*******************************************************************************/ -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) -{ - zlog_thread_t *a_thread; - - /* The bitmap determination here is not under the protection of rdlock. - * It may be changed by other CPU by zlog_reload() halfway. - * - * Old or strange value may be read here, - * but it is safe, the bitmap is valid as long as category exist, - * And will be the right value after zlog_reload() - * - * For speed up, if one log will not be ouput, - * There is no need to aquire rdlock. - */ - if (zlog_category_needless_level(category, level)) return; - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - zlog_fetch_thread(a_thread, exit); - - zlog_event_set_fmt(a_thread->event, - category->name, category->name_len, - file, filelen, func, funclen, line, level, - format, args); - - if (zlog_category_output(category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - goto exit; - } - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -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) -{ - zlog_thread_t *a_thread; - - if (zlog_category_needless_level(category, level)) return; - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - zlog_fetch_thread(a_thread, exit); - - zlog_event_set_hex(a_thread->event, - category->name, category->name_len, - file, filelen, func, funclen, line, level, - buf, buflen); - - if (zlog_category_output(category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - goto exit; - } - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -/*******************************************************************************/ -/* for speed up, copy from vzlog */ -void vdzlog(const char *file, size_t filelen, - const char *func, size_t funclen, - long line, int level, - const char *format, va_list args) -{ - zlog_thread_t *a_thread; - - if (zlog_category_needless_level(zlog_default_category, level)) return; - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - /* that's the differnce, must judge default_category in lock */ - if (!zlog_default_category) { - zc_error("zlog_default_category is null," - "dzlog_init() or dzlog_set_cateogry() is not called above"); - goto exit; - } - - zlog_fetch_thread(a_thread, exit); - - zlog_event_set_fmt(a_thread->event, - zlog_default_category->name, zlog_default_category->name_len, - file, filelen, func, funclen, line, level, - format, args); - - if (zlog_category_output(zlog_default_category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - goto exit; - } - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -void hdzlog(const char *file, size_t filelen, - const char *func, size_t funclen, - long line, int level, - const void *buf, size_t buflen) -{ - zlog_thread_t *a_thread; - - if (zlog_category_needless_level(zlog_default_category, level)) return; - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - /* that's the differnce, must judge default_category in lock */ - if (!zlog_default_category) { - zc_error("zlog_default_category is null," - "dzlog_init() or dzlog_set_cateogry() is not called above"); - goto exit; - } - - zlog_fetch_thread(a_thread, exit); - - zlog_event_set_hex(a_thread->event, - zlog_default_category->name, zlog_default_category->name_len, - file, filelen, func, funclen, line, level, - buf, buflen); - - if (zlog_category_output(zlog_default_category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - goto exit; - } - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -/*******************************************************************************/ -void zlog(zlog_category_t * category, - const char *file, size_t filelen, const char *func, size_t funclen, - long line, const int level, - const char *format, ...) -{ - zlog_thread_t *a_thread; - va_list args; - - if (category && zlog_category_needless_level(category, level)) return; - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - zlog_fetch_thread(a_thread, exit); - - va_start(args, format); - zlog_event_set_fmt(a_thread->event, category->name, category->name_len, - file, filelen, func, funclen, line, level, - format, args); - if (zlog_category_output(category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - va_end(args); - goto exit; - } - va_end(args); - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -/*******************************************************************************/ -void dzlog(const char *file, size_t filelen, const char *func, size_t funclen, long line, int level, - const char *format, ...) -{ - zlog_thread_t *a_thread; - va_list args; - - - pthread_rwlock_rdlock(&zlog_env_lock); - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto exit; - } - - /* that's the differnce, must judge default_category in lock */ - if (!zlog_default_category) { - zc_error("zlog_default_category is null," - "dzlog_init() or dzlog_set_cateogry() is not called above"); - goto exit; - } - - if (zlog_category_needless_level(zlog_default_category, level)) goto exit; - - zlog_fetch_thread(a_thread, exit); - - va_start(args, format); - zlog_event_set_fmt(a_thread->event, - zlog_default_category->name, zlog_default_category->name_len, - file, filelen, func, funclen, line, level, - format, args); - - if (zlog_category_output(zlog_default_category, a_thread)) { - zc_error("zlog_output fail, srcfile[%s], srcline[%ld]", file, line); - va_end(args); - goto exit; - } - va_end(args); - - if (zlog_env_conf->reload_conf_period && - ++zlog_env_reload_conf_count > zlog_env_conf->reload_conf_period ) { - /* under the protection of lock read env conf */ - goto reload; - } - -exit: - pthread_rwlock_unlock(&zlog_env_lock); - return; -reload: - pthread_rwlock_unlock(&zlog_env_lock); - /* will be wrlock, so after unlock */ - if (zlog_reload((char *)-1)) { - zc_error("reach reload-conf-period but zlog_reload fail, zlog-chk-conf [file] see detail"); - } - return; -} - -/*******************************************************************************/ -void zlog_profile(void) -{ - int rc = 0; - rc = pthread_rwlock_rdlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_wrlock fail, rc[%d]", rc); - return; - } - zc_warn("------zlog_profile start------ "); - zc_warn("is init:[%d]", zlog_env_is_init); - zc_warn("init version:[%d]", zlog_env_init_version); - zlog_conf_profile(zlog_env_conf, ZC_WARN); - zlog_record_table_profile(zlog_env_records, ZC_WARN); - zlog_category_table_profile(zlog_env_categories, ZC_WARN); - if (zlog_default_category) { - zc_warn("-default_category-"); - zlog_category_profile(zlog_default_category, ZC_WARN); - } - zc_warn("------zlog_profile end------ "); - rc = pthread_rwlock_unlock(&zlog_env_lock); - if (rc) { - zc_error("pthread_rwlock_unlock fail, rc=[%d]", rc); - return; - } - return; -} -/*******************************************************************************/ -int zlog_set_record(const char *rname, zlog_record_fn record_output) -{ - int rc = 0; - int rd = 0; - zlog_rule_t *a_rule; - zlog_record_t *a_record; - int i = 0; - - zc_assert(rname, -1); - zc_assert(record_output, -1); - - rd = pthread_rwlock_wrlock(&zlog_env_lock); - if (rd) { - zc_error("pthread_rwlock_rdlock fail, rd[%d]", rd); - return -1; - } - - if (!zlog_env_is_init) { - zc_error("never call zlog_init() or dzlog_init() before"); - goto zlog_set_record_exit; - } - - a_record = zlog_record_new(rname, record_output); - if (!a_record) { - rc = -1; - zc_error("zlog_record_new fail"); - goto zlog_set_record_exit; - } - - rc = zc_hashtable_put(zlog_env_records, a_record->name, a_record); - if (rc) { - zlog_record_del(a_record); - zc_error("zc_hashtable_put fail"); - goto zlog_set_record_exit; - } - - zc_arraylist_foreach(zlog_env_conf->rules, i, a_rule) { - zlog_rule_set_record(a_rule, zlog_env_records); - } - - zlog_set_record_exit: - rd = pthread_rwlock_unlock(&zlog_env_lock); - if (rd) { - zc_error("pthread_rwlock_unlock fail, rd=[%d]", rd); - return -1; - } - return rc; -} -/*******************************************************************************/ -int zlog_level_enabled(zlog_category_t *category, const int level) -{ - return category && (zlog_category_needless_level(category, level) == 0); -} - -const char *zlog_version(void) { return ZLOG_VERSION; } diff --git a/zlog/zlog.h b/zlog/zlog.h deleted file mode 100644 index d40212f..0000000 --- a/zlog/zlog.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * This file is part of the zlog Library. - * - * Copyright (C) 2011 by Hardy Simpson - * - * 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 /* for va_list */ -#include /* 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 *confpath); -int zlog_reload(const char *confpath); -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__ "" -# 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