test_rollingfile_appender_mt.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. * test_rollingfile_appender.c
  3. *
  4. * This file demonstrates how to programatically use the rolling
  5. * file appender and tests it in a multi-threaded environment. See
  6. * also the API documentation for the appender_type_rollingfile.h file.
  7. *
  8. * It is possible to be more terse here if you accept the default values,
  9. * but we spell it out explicitly.
  10. *
  11. * See the COPYING file for the terms of usage and distribution.
  12. */
  13. #ifdef HAVE_CONFIG_H
  14. #include "config.h"
  15. #endif
  16. #include <stdio.h>
  17. #ifdef HAVE_SYS_TIME_H
  18. #include <sys/time.h>
  19. #endif
  20. #ifdef HAVE_UNISTD_H
  21. #include <unistd.h>
  22. #endif
  23. #ifdef HAVE_PTHREAD_H
  24. #include <pthread.h>
  25. #endif
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <log4c.h>
  29. #include <log4c/appender_type_rollingfile.h>
  30. #include <log4c/rollingpolicy_type_sizewin.h>
  31. /*
  32. * Include sd_xplatform to pick up handy xplatform macros.
  33. * This file is not part of the distribution of log4c so an application using the
  34. * distribution of log4c must handle it's own x-platform issues: eg. threading,
  35. * the slight differences between the c functions etc.
  36. */
  37. #include <sd/sd_xplatform.h>
  38. /*********************** Parameters **********************************
  39. *
  40. * could be taken from the command line to facilitate testing
  41. *
  42. */
  43. /*
  44. * rolling file specific params
  45. */
  46. char *param_log_dir = ROLLINGFILE_DEFAULT_LOG_DIR;
  47. char* param_log_prefix = ROLLINGFILE_DEFAULT_LOG_PREFIX"rfmt";
  48. long param_max_file_size = 10*1024; /* 0 means 'no_limit' */
  49. long param_max_num_files = 6;
  50. /*
  51. * Other Logging params
  52. */
  53. char *param_layout_to_use = "basic"; /* could also be "dated" */
  54. #define PARAM_NUM_THREADS 10
  55. int param_loops_per_thread = 100;
  56. /*******************************************************************
  57. *
  58. * Globals
  59. *
  60. */
  61. log4c_category_t* root = NULL;
  62. log4c_appender_t* file_appender = NULL;
  63. log4c_layout_t* basic_layout = NULL;
  64. /******************************************************************************
  65. *
  66. * Local functions
  67. */
  68. typedef XP_UINT64 usec_t;
  69. static usec_t now(void)
  70. {
  71. #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
  72. FILETIME tv;
  73. ULARGE_INTEGER li;
  74. #else
  75. struct timeval tv;
  76. #endif
  77. SD_GETTIMEOFDAY(&tv, NULL);
  78. #if defined(_WIN32) && !defined(__MINGW32__) && !defined(__MINGW64__)
  79. memcpy(&li, &tv, sizeof(FILETIME));
  80. li.QuadPart /= 10; /* In microseconds */
  81. /* printf("timestampstamp usec %I64u\n", li.QuadPart);*/
  82. return li.QuadPart;
  83. #else
  84. return (usec_t) (tv.tv_sec * 1000000 + tv.tv_usec);
  85. #endif
  86. }
  87. /******************************************************************************/
  88. /*
  89. * Init log4c and configure a rolling file appender
  90. *
  91. */
  92. static void init_log4c_with_rollingfile_appender(){
  93. int rc = 2;
  94. rollingfile_udata_t *rfup = NULL;
  95. log4c_rollingpolicy_t *policyp = NULL;
  96. rollingpolicy_sizewin_udata_t *sizewin_confp = NULL;
  97. printf("using the rolling file appender with multiple logging threads"
  98. "to write test log files\n"
  99. "to log directory '%s', log file prefix is '%s'"
  100. ", max file size is '%ld'\n"
  101. "max num files is '%ld'\n",
  102. param_log_dir, param_log_prefix, param_max_file_size,
  103. param_max_num_files);
  104. if ( (rc = log4c_init()) == 0 ) {
  105. printf("log4c init success\n");
  106. } else {
  107. printf("log4c init failed--error %d\n", rc);
  108. return;
  109. }
  110. /*
  111. * Get a reference to the root category
  112. */
  113. root = log4c_category_get("root");
  114. log4c_category_set_priority(root,
  115. LOG4C_PRIORITY_WARN);
  116. /*
  117. * Get a file appender and set the type to rollingfile
  118. */
  119. file_appender = log4c_appender_get("aname");
  120. log4c_appender_set_type(file_appender,
  121. log4c_appender_type_get("rollingfile"));
  122. /*
  123. * Make a rolling file conf object and set the basic parameters
  124. */
  125. rfup = rollingfile_make_udata();
  126. rollingfile_udata_set_logdir(rfup, param_log_dir);
  127. rollingfile_udata_set_files_prefix(rfup, param_log_prefix);
  128. /*
  129. * Get a new rollingpolicy
  130. * type defaults to "sizewin" but set the type explicitly here
  131. * to show how to do it.
  132. */
  133. policyp = log4c_rollingpolicy_get("a_policy_name");
  134. log4c_rollingpolicy_set_type(policyp,
  135. log4c_rollingpolicy_type_get("sizewin"));
  136. /*
  137. * Get a new sizewin policy type and configure it.
  138. * Then attach it to the policy object.
  139. */
  140. sizewin_confp = sizewin_make_udata();
  141. sizewin_udata_set_file_maxsize(sizewin_confp, param_max_file_size);
  142. sizewin_udata_set_max_num_files(sizewin_confp, param_max_num_files);
  143. log4c_rollingpolicy_set_udata(policyp,sizewin_confp);
  144. /*
  145. * Configure our rolling policy, then use that to configure
  146. * our rolling file appender.
  147. */
  148. rollingfile_udata_set_policy(rfup, policyp);
  149. log4c_appender_set_udata(file_appender, rfup);
  150. /*
  151. * Open the rollingfile appender. This will also trigger
  152. * the initialization of the rollingpolicy.
  153. * Log4c is not thread safe with respect to creation/initialization
  154. * of categories and appenders, so we must call the open
  155. * once, before all the threads kick in logging with this appender.
  156. * Calling open as a side effect of the first call to append does
  157. * not work in a MT environment.
  158. *
  159. * For info, could also call init directly on the rollingpolicy here:
  160. * log4c_rollingpolicy_init(policyp, rfup);
  161. *
  162. *
  163. */
  164. log4c_appender_open(file_appender);
  165. /*
  166. * Configure a layout for the rolling file appender
  167. * (could also have chosen "basic" here, for example)
  168. */
  169. log4c_appender_set_layout(file_appender,
  170. log4c_layout_get(param_layout_to_use) );
  171. /*
  172. * Configure the root category with our rolling file appender...
  173. * and we can then start logging to it.
  174. *
  175. */
  176. log4c_category_set_appender(root,file_appender );
  177. log4c_dump_all_instances(stderr);
  178. }
  179. /*
  180. * thread function to log messages
  181. *
  182. */
  183. #ifdef _WIN32
  184. unsigned int thread_log_messages(void *arg)
  185. #else
  186. void * thread_log_messages(void *arg)
  187. #endif
  188. {
  189. int loop;
  190. usec_t stop_time;
  191. usec_t start_time;
  192. unsigned long elapsed;
  193. int tid,j;
  194. char buf[1024];
  195. tid= *((int *)arg);
  196. loop = 0 ;
  197. while (loop < param_loops_per_thread) {
  198. /* Now start the transaction measurement. */
  199. start_time = now();
  200. /* Do a bit of work, fabricate a string containing the thread id */
  201. buf[0] = '\0';
  202. j = 0;
  203. while( j < 128) {
  204. snprintf(&buf[strlen(buf)], 1024-strlen(buf), "%d", tid);
  205. j++;
  206. }
  207. sleep(1);
  208. stop_time = now();
  209. elapsed = (unsigned long)(((usec_t)stop_time - (usec_t)start_time)/1000);
  210. /*printf("Hello world--thread(%d)! (loop %d of %d) sleeping for 1 second"
  211. "--measured time %lld--%s\n", tid, loop, param_loops_per_thread,
  212. stop_time-start_time,buf);*/
  213. log4c_category_fatal(root,
  214. "Hello world--thread(%d)! (loop %d of %d) sleeping for 1 second"
  215. "--measured tme %ld ms--%s\n", tid, loop, param_loops_per_thread,
  216. elapsed,buf);
  217. loop++;
  218. }
  219. #ifndef _WIN32
  220. return(NULL);
  221. #else
  222. return(0);
  223. #endif
  224. }
  225. int main(int argc, char *argv[])
  226. {
  227. int rc = 0;
  228. pthread_t tid[PARAM_NUM_THREADS];
  229. int i;
  230. init_log4c_with_rollingfile_appender();
  231. /* Simple start/stop example. */
  232. printf("Launching %d threads to log messages\n", PARAM_NUM_THREADS);
  233. for ( i = 0; i < PARAM_NUM_THREADS; i++){
  234. int * this_thread_arg =
  235. NULL;
  236. if ((this_thread_arg = (int *)malloc(sizeof(int))) == NULL){
  237. exit(1);
  238. }
  239. *this_thread_arg = i;
  240. rc = pthread_create(&tid[i], NULL, thread_log_messages,
  241. (void *)this_thread_arg);
  242. if ( tid[i] == 0 ) {
  243. printf("Error creating thead %d...exiting\n", i);
  244. exit(1);
  245. }
  246. }
  247. for ( i = 0; i < PARAM_NUM_THREADS; i++){
  248. pthread_join(tid[i], NULL);
  249. }
  250. /* Explicitly call the log4c cleanup routine */
  251. if ( log4c_fini()){
  252. printf("log4c_fini() failed");
  253. }
  254. return rc;
  255. }