GlusterFS源代码解析 —— GlusterFS 日志
Logging.c:
/*
Copyright (c) 2008-2012 Red Hat, Inc. <http://www.redhat.com>
This file is part of GlusterFS. This file is licensed to you under your choice of the GNU Lesser
General Public License, version 3 or any later version (LGPLv3 or
later), or the GNU General Public License, version 2 (GPLv2), in all
cases as published by the Free Software Foundation.
*/ #ifndef _CONFIG_H
#define _CONFIG_H
#include "config.h"
#endif #include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <locale.h>
#include <string.h>
#include <stdlib.h> #include "xlator.h"
#include "logging.h"
#include "defaults.h"
#include "glusterfs.h" #ifdef GF_LINUX_HOST_OS
#include <syslog.h>
#endif #ifdef HAVE_BACKTRACE
#include <execinfo.h>
#endif /* Ideally this should get moved to logging.h */
struct _msg_queue {
struct list_head msgs;
}; struct _log_msg {
const char *msg;
struct list_head queue;
}; void
gf_log_logrotate (int signum)
{
THIS->ctx->log.logrotate = 1;
} void
gf_log_enable_syslog (void)
{
THIS->ctx->log.gf_log_syslog = 1;
} void
gf_log_disable_syslog (void)
{
THIS->ctx->log.gf_log_syslog = 0;
} gf_loglevel_t
gf_log_get_loglevel (void)
{
return THIS->ctx->log.loglevel;
} void
gf_log_set_loglevel (gf_loglevel_t level)
{
THIS->ctx->log.loglevel = level;
} gf_loglevel_t
gf_log_get_xl_loglevel (void *this)
{
xlator_t *xl = this;
if (!xl)
return 0;
return xl->loglevel;
} void
gf_log_set_xl_loglevel (void *this, gf_loglevel_t level)
{
xlator_t *xl = this;
if (!xl)
return;
xl->ctx->log.gf_log_xl_log_set = 1;
xl->loglevel = level;
} void
gf_log_fini (void)
{
pthread_mutex_destroy (&THIS->ctx->log.logfile_mutex);
} void
gf_log_globals_init (void *data)
{
glusterfs_ctx_t *ctx = data; pthread_mutex_init (&ctx->log.logfile_mutex, NULL); ctx->log.loglevel = GF_LOG_INFO;
ctx->log.gf_log_syslog = 1;
ctx->log.sys_log_level = GF_LOG_CRITICAL; #ifdef GF_LINUX_HOST_OS
/* For the 'syslog' output. one can grep 'GlusterFS' in syslog
for serious logs */
openlog ("GlusterFS", LOG_PID, LOG_DAEMON);
#endif
} int
gf_log_init (void *data, const char *file)
{
glusterfs_ctx_t *ctx = NULL;
int fd = -1; ctx = data; if (!file){
fprintf (stderr, "ERROR: no filename specified\n");
return -1;
} if (strcmp (file, "-") == 0) {
ctx->log.gf_log_logfile = stderr; return 0;
} ctx->log.filename = gf_strdup (file);
if (!ctx->log.filename) {
fprintf (stderr, "ERROR: updating log-filename failed: %s\n",
strerror (errno));
return -1;
} fd = open (file, O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
fprintf (stderr, "ERROR: failed to create logfile \"%s\" (%s)\n",
file, strerror (errno));
return -1;
}
close (fd); ctx->log.logfile = fopen (file, "a");
if (!ctx->log.logfile){
fprintf (stderr, "ERROR: failed to open logfile \"%s\" (%s)\n",
file, strerror (errno));
return -1;
} ctx->log.gf_log_logfile = ctx->log.logfile; return 0;
} void
set_sys_log_level (gf_loglevel_t level)
{
THIS->ctx->log.sys_log_level = level;
} /*
* 内存申请失败日志打印.假设日志级别较高,打印到系统日志中"/var/log/message"
* 不支持变參
*
* 若定义了HAVE_BACKTRACE,则打出函数调用栈
*
* @domain 模块名
*
* 假设日志文件不存在,则打印到标准错误输出
*/
int
_gf_log_nomem (const char *domain, const char *file,
const char *function, int line, gf_loglevel_t level,
size_t size)
{
const char *basename = NULL;
xlator_t *this = NULL;
struct timeval tv = {0,};
int ret = 0;
char msg[8092] = {0,};
char timestr[256] = {0,};
char callstr[4096] = {0,};
glusterfs_ctx_t *ctx = NULL; this = THIS;
ctx = this->ctx; if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out; static char *level_strings[] = {"", /* NONE */
"M", /* EMERGENCY */
"A", /* ALERT */
"C", /* CRITICAL */
"E", /* ERROR */
"W", /* WARNING */
"N", /* NOTICE */
"I", /* INFO */
"D", /* DEBUG */
"T", /* TRACE */
""}; if (!domain || !file || !function) {
fprintf (stderr,
"logging: %s:%s():%d: invalid argument\n",
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
} #if HAVE_BACKTRACE
/* Print 'calling function' */
do {
void *array[5];
char **callingfn = NULL;
size_t bt_size = 0; bt_size = backtrace (array, 5);
if (bt_size)
callingfn = backtrace_symbols (&array[2], bt_size-2);
if (!callingfn)
break; if (bt_size == 5)
snprintf (callstr, 4096, "(-->%s (-->%s (-->%s)))",
callingfn[2], callingfn[1], callingfn[0]);
if (bt_size == 4)
snprintf (callstr, 4096, "(-->%s (-->%s))",
callingfn[1], callingfn[0]);
if (bt_size == 3)
snprintf (callstr, 4096, "(-->%s)", callingfn[0]); free (callingfn);
} while (0);
#endif /* HAVE_BACKTRACE */ ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec); basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file; ret = sprintf (msg, "[%s] %s [%s:%d:%s] %s %s: no memory "
"available for size (%"GF_PRI_SIZET")",
timestr, level_strings[level],
basename, line, function, callstr,
domain, size);
if (-1 == ret) {
goto out;
} pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile) {
fprintf (ctx->log.logfile, "%s\n", msg);
} else {
fprintf (stderr, "%s\n", msg);
} #ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), "%s\n", msg);
#endif
} pthread_mutex_unlock (&ctx->log.logfile_mutex);
out:
return ret;
} /*
* 函数调用參数无效日志打印.假设日志级别较高,打印到系统日志中"/var/log/message"
* 支持变參
*
* 若定义了HAVE_BACKTRACE,则打出函数调用栈
*
* @domain 模块名
*
* 假设日志文件不存在,则打印到标准输出
*/
int
_gf_log_callingfn (const char *domain, const char *file, const char *function,
int line, gf_loglevel_t level, const char *fmt, ...)
{
const char *basename = NULL;
xlator_t *this = NULL;
char *str1 = NULL;
char *str2 = NULL;
char *msg = NULL;
char timestr[256] = {0,};
char callstr[4096] = {0,};
struct timeval tv = {0,};
size_t len = 0;
int ret = 0;
va_list ap;
glusterfs_ctx_t *ctx = NULL; this = THIS;
ctx = this->ctx; if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out; static char *level_strings[] = {"", /* NONE */
"M", /* EMERGENCY */
"A", /* ALERT */
"C", /* CRITICAL */
"E", /* ERROR */
"W", /* WARNING */
"N", /* NOTICE */
"I", /* INFO */
"D", /* DEBUG */
"T", /* TRACE */
""}; if (!domain || !file || !function || !fmt) {
fprintf (stderr,
"logging: %s:%s():%d: invalid argument\n",
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
} #if HAVE_BACKTRACE
/* Print 'calling function' */
do {
void *array[5];
char **callingfn = NULL;
size_t size = 0; size = backtrace (array, 5);
if (size)
callingfn = backtrace_symbols (&array[2], size-2);
if (!callingfn)
break; if (size == 5)
snprintf (callstr, 4096, "(-->%s (-->%s (-->%s)))",
callingfn[2], callingfn[1], callingfn[0]);
if (size == 4)
snprintf (callstr, 4096, "(-->%s (-->%s))",
callingfn[1], callingfn[0]);
if (size == 3)
snprintf (callstr, 4096, "(-->%s)", callingfn[0]); free (callingfn);
} while (0);
#endif /* HAVE_BACKTRACE */ ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec); basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file; ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %s %d-%s: ",
timestr, level_strings[level],
basename, line, function, callstr,
((this->graph) ? this->graph->id:0), domain);
if (-1 == ret) {
goto out;
} ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto out;
} va_end (ap); len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); strcpy (msg, str1);
strcpy (msg + len, str2); pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile) {
fprintf (ctx->log.logfile, "%s\n", msg);
} else {
fprintf (stderr, "%s\n", msg);
} #ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), "%s\n", msg);
#endif
} pthread_mutex_unlock (&ctx->log.logfile_mutex); out:
GF_FREE (msg); GF_FREE (str1); FREE (str2); return ret;
} /*
* 记录系统执行日志到文件
*
* 假设日志文件不存在,则打印到标准输出
*/
int
_gf_log (const char *domain, const char *file, const char *function, int line,
gf_loglevel_t level, const char *fmt, ...)
{
const char *basename = NULL;
FILE *new_logfile = NULL;
va_list ap;
char timestr[256] = {0,};
struct timeval tv = {0,};
char *str1 = NULL;
char *str2 = NULL;
char *msg = NULL;
size_t len = 0;
int ret = 0;
int fd = -1;
xlator_t *this = NULL;
glusterfs_ctx_t *ctx = NULL; this = THIS;
ctx = this->ctx; if (ctx->log.gf_log_xl_log_set) {
if (this->loglevel && (level > this->loglevel))
goto out;
}
if (level > ctx->log.loglevel)
goto out; static char *level_strings[] = {"", /* NONE */
"M", /* EMERGENCY */
"A", /* ALERT */
"C", /* CRITICAL */
"E", /* ERROR */
"W", /* WARNING */
"N", /* NOTICE */
"I", /* INFO */
"D", /* DEBUG */
"T", /* TRACE */
""}; if (!domain || !file || !function || !fmt) {
fprintf (stderr,
"logging: %s:%s():%d: invalid argument\n",
__FILE__, __PRETTY_FUNCTION__, __LINE__);
return -1;
} if (ctx->log.logrotate) {
ctx->log.logrotate = 0; fd = open (ctx->log.filename,
O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
gf_log ("logrotate", GF_LOG_ERROR,
"%s", strerror (errno));
return -1;
}
close (fd); new_logfile = fopen (ctx->log.filename, "a");
if (!new_logfile) {
gf_log ("logrotate", GF_LOG_CRITICAL,
"failed to open logfile %s (%s)",
ctx->log.filename, strerror (errno));
goto log;
} pthread_mutex_lock (&ctx->log.logfile_mutex);
{
if (ctx->log.logfile)
fclose (ctx->log.logfile); ctx->log.gf_log_logfile = ctx->log.logfile = new_logfile;
}
pthread_mutex_unlock (&ctx->log.logfile_mutex); } log:
ret = gettimeofday (&tv, NULL);
if (-1 == ret)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), sizeof timestr - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec); basename = strrchr (file, '/');
if (basename)
basename++;
else
basename = file; ret = gf_asprintf (&str1, "[%s] %s [%s:%d:%s] %d-%s: ",
timestr, level_strings[level],
basename, line, function,
((this->graph)?this->graph->id:0), domain);
if (-1 == ret) {
goto err;
} ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto err;
} va_end (ap); len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); strcpy (msg, str1);
strcpy (msg + len, str2); pthread_mutex_lock (&ctx->log.logfile_mutex);
{ if (ctx->log.logfile) {
fprintf (ctx->log.logfile, "%s\n", msg);
fflush (ctx->log.logfile);
} else {
fprintf (stderr, "%s\n", msg);
fflush (stderr);
} #ifdef GF_LINUX_HOST_OS
/* We want only serious log in 'syslog', not our debug
and trace logs */
if (ctx->log.gf_log_syslog && level &&
(level <= ctx->log.sys_log_level))
syslog ((level-1), "%s\n", msg);
#endif
} pthread_mutex_unlock (&ctx->log.logfile_mutex); err:
GF_FREE (msg); GF_FREE (str1); FREE (str2); out:
return (0);
} int
_gf_log_eh (const char *function, const char *fmt, ...)
{
int ret = -1;
va_list ap;
char *str1 = NULL;
char *str2 = NULL;
char *msg = NULL;
xlator_t *this = NULL; this = THIS; ret = gf_asprintf (&str1, "[%d] %s: ",
((this->graph)?this->graph->id:0),
function);
if (-1 == ret) {
goto out;
} va_start (ap, fmt); ret = vasprintf (&str2, fmt, ap);
if (-1 == ret) {
goto out;
} va_end (ap); msg = GF_MALLOC (strlen (str1) + strlen (str2) + 1, gf_common_mt_char);
if (!msg) {
ret = -1;
goto out;
} strcpy (msg, str1);
strcat (msg, str2); ret = eh_save_history (this->history, msg); out:
GF_FREE (str1); /* Use FREE instead of GF_FREE since str2 was allocated by vasprintf */
if (str2)
FREE (str2); return ret;
} /*
* 初始化"命令记录"日志
*/
int
gf_cmd_log_init (const char *filename)
{
int fd = -1;
xlator_t *this = NULL;
glusterfs_ctx_t *ctx = NULL; this = THIS;
ctx = this->ctx; if (!filename){
gf_log (this->name, GF_LOG_CRITICAL, "gf_cmd_log_init: no "
"filename specified\n");
return -1;
} ctx->log.cmd_log_filename = gf_strdup (filename);
if (!ctx->log.cmd_log_filename) {
gf_log (this->name, GF_LOG_CRITICAL,
"gf_cmd_log_init: strdup error\n");
return -1;
}
/* close and reopen cmdlogfile for log rotate*/
if (ctx->log.cmdlogfile) {
fclose (ctx->log.cmdlogfile);
ctx->log.cmdlogfile = NULL;
} fd = open (ctx->log.cmd_log_filename,
O_CREAT | O_RDONLY, S_IRUSR | S_IWUSR);
if (fd < 0) {
gf_log (this->name, GF_LOG_CRITICAL,
"%s", strerror (errno));
return -1;
}
close (fd); ctx->log.cmdlogfile = fopen (ctx->log.cmd_log_filename, "a");
if (!ctx->log.cmdlogfile){
gf_log (this->name, GF_LOG_CRITICAL,
"gf_cmd_log_init: failed to open logfile \"%s\" "
"(%s)\n", ctx->log.cmd_log_filename, strerror (errno));
return -1;
}
return 0;
} /*
* 记录命令日志到文件
*/
int
gf_cmd_log (const char *domain, const char *fmt, ...)
{
va_list ap;
char timestr[64];
struct timeval tv = {0,};
char *str1 = NULL;
char *str2 = NULL;
char *msg = NULL;
size_t len = 0;
int ret = 0;
glusterfs_ctx_t *ctx = NULL; ctx = THIS->ctx;
if (!ctx->log.cmdlogfile)
return -1; if (!domain || !fmt) {
gf_log ("glusterd", GF_LOG_TRACE,
"logging: invalid argument\n");
return -1;
} ret = gettimeofday (&tv, NULL);
if (ret == -1)
goto out;
va_start (ap, fmt);
gf_time_fmt (timestr, sizeof timestr, tv.tv_sec, gf_timefmt_FT);
snprintf (timestr + strlen (timestr), 256 - strlen (timestr),
".%"GF_PRI_SUSECONDS, tv.tv_usec); ret = gf_asprintf (&str1, "[%s] %s : ",
timestr, domain);
if (ret == -1) {
goto out;
} ret = vasprintf (&str2, fmt, ap);
if (ret == -1) {
goto out;
} va_end (ap); len = strlen (str1);
msg = GF_MALLOC (len + strlen (str2) + 1, gf_common_mt_char); strcpy (msg, str1);
strcpy (msg + len, str2); fprintf (ctx->log.cmdlogfile, "%s\n", msg);
fflush (ctx->log.cmdlogfile); out:
GF_FREE (msg); GF_FREE (str1); FREE (str2); return (0);
}
GlusterFS源代码解析 —— GlusterFS 日志的更多相关文章
- GlusterFS源代码解析 —— GlusterFS 简单介绍
原文地址:http://blog.csdn.net/wangyuling1234567890/article/details/24564185 -- -- 本系列博客源代码是基于GlusterFS 3 ...
- GlusterFS源代码解析 —— GlusterFS 内存分配方式
原文地址:http://blog.csdn.net/wangyuling1234567890/article/details/24564891 GlusterFS 的内存分配主要有两种方式,一种是内存 ...
- Android源代码解析之(六)-->Log日志
转载请标明出处:一片枫叶的专栏 首先说点题外话,对于想学android framework源代码的同学,事实上能够在github中fork一份,详细地址:platform_frameworks_bas ...
- Spring源代码解析
Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的启动:http://www.itey ...
- Arrays.sort源代码解析
Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...
- Spring源代码解析(收藏)
Spring源代码解析(收藏) Spring源代码解析(一):IOC容器:http://www.iteye.com/topic/86339 Spring源代码解析(二):IoC容器在Web容器中的 ...
- volley源代码解析(七)--终于目的之Response<T>
在上篇文章中,我们终于通过网络,获取到了HttpResponse对象 HttpResponse是android包里面的一个类.然后为了更高的扩展性,我们在BasicNetwork类里面看到.Volle ...
- Cocos2d-x源代码解析(1)——地图模块(3)
接上一章<Cocos2d-x源代码解析(1)--地图模块(2)> 通过前面两章的分析,我们能够知道cocos将tmx的信息结构化到 CCTMXMapInfo.CCTMXTilesetInf ...
- Android EventBus源代码解析 带你深入理解EventBus
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/40920453,本文出自:[张鸿洋的博客] 上一篇带大家初步了解了EventBus ...
随机推荐
- PhoneGap 3 在 Mac 上安装使用
1.下载安装 NodeJS . 2.安装 PhoneGap.打开终端执行: 1 $ sudo npm install -g phonegap 3.PhoneGap 3 不需要在Xcode中创建,而是在 ...
- 简谈Comparable和Comparator区别
对于Comparable和Comparator这连个相似的接口,还是做一下比较比较好: Comparable Comparator (1)只包含一个compareTo()方法,此方法可以给两个对象排序 ...
- ACdream训练赛系列のJava专场
/* * this code is made by mhy12345 * Problem: 1669 * Verdict: Accepted * Submission Date: 2015-04-21 ...
- 关于多域名EXCHANGE如何设置PTR的问题
找了很多网页, 有效的是MX可以设置不同的域名,但PTR只设置一个即可... 如果设置为一个IP为两个PTR,则在进行测试时,会发生DNS ROBBINS,即一次找这个,一次找那个. 切记. .... ...
- [转贴]watin的一些例子
Some WatiN ExamplesBelow are some examples of WatiN codes for testing:// find div by idvar div = bro ...
- JavaScript用JQuery呼叫Server端方法
准备好Server端的方法 [System.Web.Services.WebMethod] public static string VeryUserName(string name) { strin ...
- [DP] LCS小结
额..失误.. LCS是Longest Common Subsequence的缩写,即最长公共子序列.一个序列,如果是两个或多个已知序列的子序列,且是所有子序列中最长的,则为最长公共子序列. DP.O ...
- ActionBar 中setDisplayHomeAsUpEnabled和setHomeButtonEnabled和setDisplayShowHomeEnabled方法的理解
setHomeButtonEnabled这个小于4.0版本的默认值为true的.但是在4.0及其以上是false,该方法的作用:决定左上角的图标是否可以点击.没有向左的小图标. true 图标可以点击 ...
- 【Android 复习】:第02期:引导界面(二)使用ViewPager实现欢迎引导页面
一.实现的效果图 也许是养成了这样一个习惯,每次看别人的代码前,必须要先看实现的效果图达到了一个什么样的效果,是不是跟自己想要实现的效果类似,有图才有真相嘛,呵呵. 二.编码前的准 ...
- Asp.Net 前后台交互小结
转自:http://blog.csdn.net/wlccomeon/article/details/17270427 一.前台调用后台 前台调用后台的方法一共可分为两大类:使用Ht ...