init.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. static const char version[] = "$Id$";
  2. /*
  3. * init.c
  4. *
  5. * Copyright 2001-2003, Meiosys (www.meiosys.com). All rights reserved.
  6. *
  7. * See the COPYING file for the terms of usage and distribution.
  8. */
  9. #ifdef HAVE_CONFIG_H
  10. #endif
  11. #include "log4c/config.h"
  12. #include <log4c/init.h>
  13. #include <log4c/category.h>
  14. #include <log4c/appender.h>
  15. #include <log4c/layout.h>
  16. #include <log4c/rollingpolicy.h>
  17. #include <log4c/rc.h>
  18. #include <sd/error.h>
  19. #include <sd/sprintf.h>
  20. #include <sd/factory.h>
  21. #include <sd/sd_xplatform.h>
  22. #include <stdlib.h>
  23. #include <log4c/appender_type_stream.h>
  24. #include <log4c/appender_type_stream2.h>
  25. #include <log4c/appender_type_syslog.h>
  26. #include <log4c/appender_type_mmap.h>
  27. #include <log4c/appender_type_rollingfile.h>
  28. #include <log4c/rollingpolicy_type_sizewin.h>
  29. #include <log4c/layout_type_basic.h>
  30. #include <log4c/layout_type_dated.h>
  31. #include <log4c/layout_type_basic_r.h>
  32. #include <log4c/layout_type_dated_r.h>
  33. #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
  34. #include <mcheck.h>
  35. #endif
  36. static const log4c_layout_type_t * const layout_types[] = {
  37. &log4c_layout_type_basic,
  38. &log4c_layout_type_dated,
  39. /* These appenders are not yet ported with msvc */
  40. #ifndef _WIN32
  41. &log4c_layout_type_basic_r,
  42. &log4c_layout_type_dated_r
  43. #endif
  44. };
  45. static size_t nlayout_types = sizeof(layout_types) / sizeof(layout_types[0]);
  46. static const log4c_appender_type_t * const appender_types[] = {
  47. &log4c_appender_type_stream,
  48. &log4c_appender_type_stream2,
  49. #ifdef HAVE_MMAP
  50. &log4c_appender_type_mmap,
  51. #endif
  52. #ifdef HAVE_SYSLOG_H
  53. &log4c_appender_type_syslog,
  54. #endif
  55. #ifdef WITH_ROLLINGFILE
  56. &log4c_appender_type_rollingfile
  57. #endif
  58. };
  59. static size_t nappender_types = sizeof(appender_types) / sizeof(appender_types[0]);
  60. #ifdef WITH_ROLLINGFILE
  61. static const log4c_rollingpolicy_type_t * const rollingpolicy_types[] = {
  62. &log4c_rollingpolicy_type_sizewin
  63. };
  64. static size_t nrollingpolicy_types =
  65. sizeof(rollingpolicy_types) / sizeof(rollingpolicy_types[0]);
  66. #endif
  67. static int log4c_is_init = 0;
  68. typedef struct rcfile
  69. {
  70. char name[256];
  71. time_t ctime;
  72. int exists;
  73. } rcfile_t;
  74. static rcfile_t rcfiles[] = {
  75. { "$LOG4C_RCPATH/log4crc" },
  76. { "$HOME/.log4crc" },
  77. { "./log4crc" }
  78. };
  79. static const int nrcfiles = sizeof(rcfiles) / sizeof(rcfiles[0]);
  80. /******************************************************************************/
  81. extern int log4c_init(void)
  82. {
  83. size_t i;
  84. int ret = 0;
  85. sd_debug("log4c_init[");
  86. /* activate GLIBC allocation debugging */
  87. #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
  88. mtrace();
  89. #endif
  90. if (log4c_is_init){
  91. sd_debug("log4c already initialized ]");
  92. return 0;
  93. }
  94. log4c_is_init++;
  95. /* Initialize default types: layouts, appenders, rollingpolicies */
  96. sd_debug("intializing default types: appenders, layouts, rollingpolicies");
  97. for (i = 0; i < nlayout_types; i++)
  98. log4c_layout_type_set(layout_types[i]);
  99. for (i = 0; i < nappender_types; i++)
  100. log4c_appender_type_set(appender_types[i]);
  101. #ifdef WITH_ROLLINGFILE
  102. for (i = 0; i < nrollingpolicy_types; i++)
  103. log4c_rollingpolicy_type_set(rollingpolicy_types[i]);
  104. #endif
  105. /* load configuration files */
  106. {
  107. int i;
  108. sd_debug("looking for conf files...");
  109. snprintf(rcfiles[0].name, sizeof(rcfiles[0].name) - 1, "%s/log4crc",
  110. getenv("LOG4C_RCPATH") ? getenv("LOG4C_RCPATH") : LOG4C_RCPATH);
  111. snprintf(rcfiles[1].name, sizeof(rcfiles[1].name) - 1, "%s/.log4crc",
  112. getenv("HOME") ? getenv("HOME") : "");
  113. for (i = 0; i < nrcfiles; i++) {
  114. sd_debug("checking for conf file at '%s'", rcfiles[i].name);
  115. if (SD_ACCESS_READ(rcfiles[i].name)) continue;
  116. if (SD_STAT_CTIME(rcfiles[i].name,&rcfiles[i].ctime) != 0)
  117. sd_error("sd_stat_ctime %s failed", rcfiles[i].name);
  118. rcfiles[i].exists=1;
  119. if (log4c_load(rcfiles[i].name) == -1) {
  120. sd_error("loading %s failed", rcfiles[i].name);
  121. ret = -1;
  122. }
  123. else
  124. sd_debug("loading %s succeeded", rcfiles[i].name);
  125. }
  126. }
  127. /* override configuration with environment variables */
  128. {
  129. const char* priority;
  130. const char* appender;
  131. sd_debug("checking environment variables...");
  132. if ( (priority = getenv("LOG4C_PRIORITY")) != NULL){
  133. sd_debug("setting priority of root category to '%s'",
  134. priority);
  135. log4c_category_set_priority(log4c_category_get("root"),
  136. log4c_priority_to_int(priority));
  137. }
  138. if ( (appender = getenv("LOG4C_APPENDER")) != NULL){
  139. sd_debug("setting appender of root category to '%s'",
  140. appender);
  141. log4c_category_set_appender(log4c_category_get("root"),
  142. log4c_appender_get(appender));
  143. }
  144. }
  145. /*
  146. * For debug dump current types and instances:
  147. * this allows the caller of log4c_init() to see:
  148. * 1. all types currently registered, including perhaps his own.
  149. * 2. all instances instantiated via the configuration file.
  150. *
  151. * If the caller goes on to programmatically create instaces then he
  152. * can call log4c_dump_all_instances() later himself to
  153. * verify that they were created as expected.
  154. *
  155. */
  156. #ifdef __SD_DEBUG__
  157. if( getenv("SD_DEBUG")){
  158. log4c_dump_all_types(stderr);
  159. log4c_dump_all_instances(stderr);
  160. }
  161. #endif
  162. sd_debug("]");
  163. return ret;
  164. }
  165. /******************************************************************************/
  166. void __log4c_reread(void)
  167. {
  168. time_t file_ctime;
  169. int i;
  170. for (i = 0; i < nrcfiles; i++){
  171. /* only reread files that existed when we first initialized */
  172. if (rcfiles[i].exists && SD_STAT_CTIME(rcfiles[i].name,&file_ctime) == 0){
  173. /* time_t is number of second since epoch, just compare for == */
  174. if (file_ctime != rcfiles[i].ctime){
  175. sd_debug("Need reread on file %s\n",rcfiles[i].name);
  176. SD_STAT_CTIME(rcfiles[i].name,&rcfiles[i].ctime);
  177. if (log4c_rc_load(log4c_rc, rcfiles[i].name) == -1){
  178. sd_error("re-loading config file %s failed", rcfiles[i].name);
  179. }
  180. }
  181. }
  182. }
  183. }
  184. /******************************************************************************/
  185. /*
  186. * Rereads any log4crc files that have changed
  187. */
  188. void log4c_reread(void)
  189. {
  190. #ifdef __ENABLE_REREAD__
  191. if (0 != log4c_rc->config.reread){
  192. __log4c_reread();
  193. }
  194. #endif
  195. }
  196. /******************************************************************************/
  197. extern int log4c_fini(void)
  198. {
  199. int rc = 0;
  200. /* Some acceptable use of goto here to avoid lots of nested ifs
  201. * when we need a quick exit
  202. */
  203. sd_debug("log4c_fini[");
  204. if (log4c_rc->config.nocleanup){
  205. sd_debug("not cleaning up--nocleanup specified in conf");
  206. rc = -1;
  207. goto log4c_fini_exit;
  208. }
  209. if (!log4c_is_init){
  210. rc = 0;
  211. sd_debug("not cleaning up--log4c not initialized");
  212. goto log4c_fini_exit;
  213. }
  214. log4c_is_init--;
  215. sd_debug("cleaning up category, appender, layout and"
  216. "rollingpolicy instances");
  217. if (log4c_category_factory) {
  218. sd_factory_delete(log4c_category_factory);
  219. log4c_category_factory = NULL;
  220. }
  221. if (log4c_appender_factory) {
  222. sd_factory_delete(log4c_appender_factory);
  223. log4c_appender_factory = NULL;
  224. }
  225. if (log4c_layout_factory) {
  226. sd_factory_delete(log4c_layout_factory);
  227. log4c_layout_factory = NULL;
  228. }
  229. if (log4c_rollingpolicy_factory) {
  230. sd_factory_delete(log4c_rollingpolicy_factory);
  231. log4c_rollingpolicy_factory = NULL;
  232. }
  233. ///////////////////////////////////////////////////////////////////////////
  234. // 检测出来需要额外释放的内存 [7/23/2010 jesse]
  235. log4c_layout_delete_global();
  236. log4c_appender_delete_global();
  237. log4c_rollingpolicy_delete_global();
  238. #ifdef __SD_DEBUG__
  239. if( getenv("SD_DEBUG")){
  240. sd_debug("Instance dump after cleanup:");
  241. log4c_dump_all_instances(stderr);
  242. }
  243. #endif
  244. #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
  245. muntrace();
  246. #endif
  247. log4c_fini_exit:
  248. sd_debug("]");
  249. return 0;
  250. }
  251. /******************************************************************************/
  252. #ifdef __GNUC__
  253. extern void __attribute__ ((constructor)) __log4c_init(void)
  254. {
  255. #ifdef WITH_CONSTRUCTORS
  256. log4c_init();
  257. #endif
  258. }
  259. extern void __attribute__ ((destructor)) __log4c_fini(void)
  260. {
  261. #ifdef WITH_CONSTRUCTORS
  262. log4c_fini();
  263. #endif
  264. }
  265. #endif
  266. /******************************************************************************/
  267. extern void log4c_dump_all_types(FILE *fp){
  268. /*
  269. *
  270. * For debug, dump all the types that have been registered during init. We just
  271. * display the name of the the type for the moment--the rest of the type info
  272. * right now consists of functions to call, so not really printable.
  273. */
  274. log4c_appender_types_print(fp);
  275. log4c_layout_types_print(fp);
  276. #ifdef WITH_ROLLINGFILE
  277. log4c_rollingpolicy_types_print(fp);
  278. #endif
  279. }
  280. extern void log4c_dump_all_instances(FILE *fp){
  281. /*
  282. * Also dump any instances that were created during init by
  283. * reading the conf file.
  284. *
  285. * An instances of a type consists of the base
  286. * type information (name plus function table) and an instance name and
  287. * configuration. For example one can have an instance of the rollingfile
  288. * appender which logs to /var/tmp and another instance which logs to
  289. * /usr/tmp. They are both of type rollingfile, but are distinct instances of
  290. * it
  291. */
  292. fprintf(fp, "instance dump follows (may be empty):\n");
  293. sd_factory_print(log4c_category_factory, fp);
  294. sd_factory_print(log4c_appender_factory, fp);
  295. sd_factory_print(log4c_layout_factory, fp);
  296. #ifdef WITH_ROLLINGFILE
  297. sd_factory_print(log4c_rollingpolicy_factory, fp);
  298. #endif
  299. }
  300. //////////////////////////////////////////////////////////////////////////
  301. ///下面函数为自己写的一些函数,为使用log4c起来方便而设置的
  302. /** 带有配置文件名的初始化函数
  303. 完成功能和log4c_init完全一致,只是这里的配置文件名以参数形式传入的
  304. @returns 0 for success .
  305. 作者:jesse 日期:2008-9-6
  306. */
  307. extern int log4c_init_with_cfg_file(const char *strCfgFileName)
  308. {
  309. size_t i;
  310. int ret = 0;
  311. sd_debug("log4c_init[");
  312. /* activate GLIBC allocation debugging */
  313. #if defined(__LOG4C_DEBUG__) && defined(__GLIBC__)
  314. mtrace();
  315. #endif
  316. if (log4c_is_init)
  317. {
  318. sd_debug("log4c already initialized ]");
  319. return 0;
  320. }
  321. log4c_is_init++;
  322. /* Initialize default types: layouts, appenders, rollingpolicies */
  323. sd_debug("intializing default types: appenders, layouts, rollingpolicies");
  324. for (i = 0; i < nlayout_types; i++)
  325. {
  326. log4c_layout_type_set(layout_types[i]);
  327. }
  328. for (i = 0; i < nappender_types; i++)
  329. {
  330. log4c_appender_type_set(appender_types[i]);
  331. }
  332. #ifdef WITH_ROLLINGFILE
  333. for (i = 0; i < nrollingpolicy_types; i++)
  334. {
  335. log4c_rollingpolicy_type_set(rollingpolicy_types[i]);
  336. }
  337. #endif
  338. /* load configuration files */
  339. {
  340. ///int i;
  341. sd_debug("looking for conf files...");
  342. if(NULL == strCfgFileName)
  343. {
  344. sd_debug("log4c_init[ERROR:strCfgFileName==NULL");
  345. ret = -1;
  346. }
  347. else
  348. {
  349. time_t timeFile;
  350. sd_debug("checking for conf file at '%s'", strCfgFileName);
  351. if (SD_ACCESS_READ(strCfgFileName))
  352. {
  353. sd_error("loading %s failed", strCfgFileName);
  354. ret = -1;
  355. }
  356. else
  357. {
  358. if (SD_STAT_CTIME(strCfgFileName, &timeFile) != 0)
  359. {
  360. sd_error("sd_stat_ctime %s failed", strCfgFileName);
  361. }
  362. ///rcfiles[i].exists=1;
  363. if (log4c_load(strCfgFileName) == -1)
  364. {
  365. sd_error("loading %s failed", strCfgFileName);
  366. ret = -1;
  367. }
  368. else
  369. {
  370. sd_debug("loading %s succeeded", strCfgFileName);
  371. }
  372. }
  373. }
  374. }
  375. /* override configuration with environment variables */
  376. {
  377. const char* priority;
  378. const char* appender;
  379. sd_debug("checking environment variables...");
  380. if ( (priority = getenv("LOG4C_PRIORITY")) != NULL){
  381. sd_debug("setting priority of root category to '%s'",
  382. priority);
  383. log4c_category_set_priority(log4c_category_get("root"),
  384. log4c_priority_to_int(priority));
  385. }
  386. if ( (appender = getenv("LOG4C_APPENDER")) != NULL){
  387. sd_debug("setting appender of root category to '%s'",
  388. appender);
  389. log4c_category_set_appender(log4c_category_get("root"),
  390. log4c_appender_get(appender));
  391. }
  392. }
  393. /*
  394. * For debug dump current types and instances:
  395. * ptrThis allows the caller of log4c_init() to see:
  396. * 1. all types currently registered, including perhaps his own.
  397. * 2. all instances instantiated via the configuration file.
  398. *
  399. * If the caller goes on to programmatically create instaces then he
  400. * can call log4c_dump_all_instances() later himself to
  401. * verify that they were created as expected.
  402. *
  403. */
  404. #ifdef __SD_DEBUG__
  405. if( getenv("SD_DEBUG")){
  406. log4c_dump_all_types(stderr);
  407. log4c_dump_all_instances(stderr);
  408. }
  409. #endif
  410. sd_debug("]");
  411. return ret;
  412. }