logsys.c 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575
  1. /*
  2. * Copyright (c) 2002-2004 MontaVista Software, Inc.
  3. * Copyright (c) 2006-2009 Red Hat, Inc.
  4. *
  5. * Author: Steven Dake (sdake@redhat.com)
  6. * Author: Lon Hohberger (lhh@redhat.com)
  7. * Author: Fabio M. Di Nitto (fdinitto@redhat.com)
  8. *
  9. * All rights reserved.
  10. *
  11. * This software licensed under BSD license, the text of which follows:
  12. *
  13. * Redistribution and use in source and binary forms, with or without
  14. * modification, are permitted provided that the following conditions are met:
  15. *
  16. * - Redistributions of source code must retain the above copyright notice,
  17. * this list of conditions and the following disclaimer.
  18. * - Redistributions in binary form must reproduce the above copyright notice,
  19. * this list of conditions and the following disclaimer in the documentation
  20. * and/or other materials provided with the distribution.
  21. * - Neither the name of the MontaVista Software, Inc. nor the names of its
  22. * contributors may be used to endorse or promote products derived from this
  23. * software without specific prior written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  26. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  29. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  30. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  31. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  32. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  33. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  34. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  35. * THE POSSIBILITY OF SUCH DAMAGE.
  36. */
  37. #include <config.h>
  38. #include <stdio.h>
  39. #include <ctype.h>
  40. #include <string.h>
  41. #include <stdarg.h>
  42. #include <sys/time.h>
  43. #include <sys/stat.h>
  44. #include <fcntl.h>
  45. #include <time.h>
  46. #include <errno.h>
  47. #include <sys/types.h>
  48. #include <sys/socket.h>
  49. #include <unistd.h>
  50. #if defined(COROSYNC_LINUX)
  51. #include <linux/un.h>
  52. #endif
  53. #if defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
  54. #include <sys/un.h>
  55. #endif
  56. #define SYSLOG_NAMES
  57. #include <syslog.h>
  58. #include <stdlib.h>
  59. #include <pthread.h>
  60. #include <limits.h>
  61. #include <corosync/engine/logsys.h>
  62. #define YIELD_AFTER_LOG_OPS 10
  63. /*
  64. * similar to syslog facilities/priorities tables,
  65. * make a tag table for internal use
  66. */
  67. #ifdef SYSLOG_NAMES
  68. struct syslog_names {
  69. const char *c_name;
  70. int c_val;
  71. };
  72. struct syslog_names tagnames[] =
  73. {
  74. { "log", LOGSYS_TAG_LOG },
  75. { "enter", LOGSYS_TAG_ENTER },
  76. { "leave", LOGSYS_TAG_LEAVE },
  77. { "trace1", LOGSYS_TAG_TRACE1 },
  78. { "trace2", LOGSYS_TAG_TRACE2 },
  79. { "trace3", LOGSYS_TAG_TRACE3 },
  80. { "trace4", LOGSYS_TAG_TRACE4 },
  81. { "trace5", LOGSYS_TAG_TRACE5 },
  82. { "trace6", LOGSYS_TAG_TRACE6 },
  83. { "trace7", LOGSYS_TAG_TRACE7 },
  84. { "trace8", LOGSYS_TAG_TRACE8 },
  85. { NULL, -1 }
  86. };
  87. #endif
  88. /*
  89. * These are not static so they can be read from the core file
  90. */
  91. int *flt_data;
  92. int flt_data_size;
  93. #define COMBINE_BUFFER_SIZE 2048
  94. /* values for logsys_logger init_status */
  95. #define LOGSYS_LOGGER_INIT_DONE 0
  96. #define LOGSYS_LOGGER_NEEDS_INIT 1
  97. static int logsys_system_needs_init = LOGSYS_LOGGER_NEEDS_INIT;
  98. static int logsys_after_log_ops_yield = 10;
  99. /*
  100. * need unlogical order to preserve 64bit alignment
  101. */
  102. struct logsys_logger {
  103. char subsys[LOGSYS_MAX_SUBSYS_NAMELEN]; /* subsystem name */
  104. char *logfile; /* log to file */
  105. FILE *logfile_fp; /* track file descriptor */
  106. unsigned int mode; /* subsystem mode */
  107. unsigned int debug; /* debug on|off */
  108. unsigned int tags; /* trace tags */
  109. int syslog_facility; /* facility */
  110. int syslog_priority; /* priority */
  111. int logfile_priority; /* priority to file */
  112. int init_status; /* internal field to handle init queues
  113. for subsystems */
  114. };
  115. /*
  116. * operating global variables
  117. */
  118. static struct logsys_logger logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT + 1];
  119. static int wthread_active = 0;
  120. static int wthread_should_exit = 0;
  121. static pthread_mutex_t logsys_config_mutex = PTHREAD_MUTEX_INITIALIZER;
  122. static unsigned int records_written = 1;
  123. static pthread_t logsys_thread_id;
  124. static pthread_cond_t logsys_cond;
  125. static pthread_mutex_t logsys_cond_mutex;
  126. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  127. static pthread_spinlock_t logsys_idx_spinlock;
  128. #else
  129. static pthread_mutex_t logsys_idx_mutex = PTHREAD_MUTEX_INITIALIZER;
  130. #endif
  131. static unsigned int log_rec_idx;
  132. static int logsys_buffer_full = 0;
  133. static char *format_buffer=NULL;
  134. static int log_requests_pending = 0;
  135. static int log_requests_lost = 0;
  136. void *logsys_rec_end;
  137. #define FDHEAD_INDEX (flt_data_size)
  138. #define FDTAIL_INDEX (flt_data_size + 1)
  139. /* forward declarations */
  140. static void logsys_close_logfile(int subsysid);
  141. /*
  142. * Helpers for _logsys_log_rec functionality
  143. */
  144. static inline void my_memcpy_32bit (int *dest, const int *src, unsigned int words)
  145. {
  146. unsigned int word_idx;
  147. for (word_idx = 0; word_idx < words; word_idx++) {
  148. dest[word_idx] = src[word_idx];
  149. }
  150. }
  151. static inline void my_memcpy_8bit (char *dest, const char *src,
  152. unsigned int bytes)
  153. {
  154. unsigned int byte_idx;
  155. for (byte_idx = 0; byte_idx < bytes; byte_idx++) {
  156. dest[byte_idx] = src[byte_idx];
  157. }
  158. }
  159. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  160. static void logsys_lock (void)
  161. {
  162. pthread_spin_lock (&logsys_idx_spinlock);
  163. }
  164. static void logsys_unlock (void)
  165. {
  166. pthread_spin_unlock (&logsys_idx_spinlock);
  167. }
  168. #else
  169. static void logsys_lock (void)
  170. {
  171. pthread_mutex_lock (&logsys_idx_mutex);
  172. }
  173. static void logsys_unlock (void)
  174. {
  175. pthread_mutex_unlock (&logsys_idx_mutex);
  176. }
  177. #endif
  178. /*
  179. * Before any write operation, a reclaim on the buffer area must be executed
  180. */
  181. static inline void records_reclaim (unsigned int idx, unsigned int words)
  182. {
  183. unsigned int should_reclaim;
  184. should_reclaim = 0;
  185. if ((idx + words) >= flt_data_size) {
  186. logsys_buffer_full = 1;
  187. }
  188. if (logsys_buffer_full == 0) {
  189. return;
  190. }
  191. logsys_lock();
  192. if (flt_data[FDTAIL_INDEX] > flt_data[FDHEAD_INDEX]) {
  193. if (idx + words >= flt_data[FDTAIL_INDEX]) {
  194. should_reclaim = 1;
  195. }
  196. } else {
  197. if ((idx + words) >= (flt_data[FDTAIL_INDEX] + flt_data_size)) {
  198. should_reclaim = 1;
  199. }
  200. }
  201. if (should_reclaim) {
  202. int words_needed = 0;
  203. words_needed = words + 1;
  204. do {
  205. unsigned int old_tail;
  206. words_needed -= flt_data[flt_data[FDTAIL_INDEX]];
  207. old_tail = flt_data[FDTAIL_INDEX];
  208. flt_data[FDTAIL_INDEX] =
  209. (flt_data[FDTAIL_INDEX] +
  210. flt_data[flt_data[FDTAIL_INDEX]]) % (flt_data_size);
  211. if (log_rec_idx == old_tail) {
  212. log_requests_lost += 1;
  213. log_rec_idx = flt_data[FDTAIL_INDEX];
  214. }
  215. } while (words_needed > 0);
  216. }
  217. logsys_unlock();
  218. }
  219. #define idx_word_step(idx) \
  220. do { \
  221. if (idx > (flt_data_size - 1)) { \
  222. idx = 0; \
  223. } \
  224. } while (0);
  225. #define idx_buffer_step(idx) \
  226. do { \
  227. if (idx > (flt_data_size - 1)) { \
  228. idx = ((idx) % (flt_data_size)); \
  229. } \
  230. } while (0);
  231. /*
  232. * Internal threaded logging implementation
  233. */
  234. static inline int strcpy_cutoff (char *dest, const char *src, int cutoff)
  235. {
  236. if (cutoff <= 0) {
  237. size_t len = strlen (src);
  238. memcpy (dest, src, len + 1);
  239. return (len);
  240. } else {
  241. size_t len;
  242. strncpy (dest, src, cutoff);
  243. dest[cutoff] = '\0';
  244. len = strlen (dest);
  245. if (len != cutoff) {
  246. memset (&dest[len], ' ', cutoff - len);
  247. }
  248. }
  249. return (cutoff);
  250. }
  251. /*
  252. * %s SUBSYSTEM
  253. * %n FUNCTION NAME
  254. * %f FILENAME
  255. * %l FILELINE
  256. * %p PRIORITY
  257. * %t TIMESTAMP
  258. * %b BUFFER
  259. *
  260. * any number between % and character specify field length to pad or chop
  261. */
  262. static void log_printf_to_logs (
  263. const char *subsys,
  264. const char *file_name,
  265. const char *function_name,
  266. int file_line,
  267. unsigned int level,
  268. const char *buffer)
  269. {
  270. char output_buffer[COMBINE_BUFFER_SIZE];
  271. char char_time[128];
  272. char line_no[30];
  273. unsigned int format_buffer_idx = 0;
  274. unsigned int output_buffer_idx = 0;
  275. struct timeval tv;
  276. int cutoff;
  277. unsigned int len;
  278. int subsysid;
  279. subsysid = _logsys_config_subsys_get(subsys);
  280. if (subsysid <= - 1) {
  281. return;
  282. }
  283. while (format_buffer[format_buffer_idx]) {
  284. cutoff = -1;
  285. if (format_buffer[format_buffer_idx] == '%') {
  286. format_buffer_idx += 1;
  287. if (isdigit (format_buffer[format_buffer_idx])) {
  288. cutoff = atoi (&format_buffer[format_buffer_idx]);
  289. }
  290. while (isdigit (format_buffer[format_buffer_idx])) {
  291. format_buffer_idx += 1;
  292. }
  293. switch (format_buffer[format_buffer_idx]) {
  294. case 's':
  295. len = strcpy_cutoff (&output_buffer[output_buffer_idx], subsys, cutoff);
  296. output_buffer_idx += len;
  297. break;
  298. case 'n':
  299. len = strcpy_cutoff (&output_buffer[output_buffer_idx], function_name, cutoff);
  300. output_buffer_idx += len;
  301. break;
  302. case 'f':
  303. len = strcpy_cutoff (&output_buffer[output_buffer_idx], file_name, cutoff);
  304. output_buffer_idx += len;
  305. break;
  306. case 'l':
  307. sprintf (line_no, "%d", file_line);
  308. len = strcpy_cutoff (&output_buffer[output_buffer_idx], line_no, cutoff);
  309. output_buffer_idx += len;
  310. break;
  311. case 'p':
  312. break;
  313. case 't':
  314. gettimeofday (&tv, NULL);
  315. (void)strftime (char_time, sizeof (char_time), "%b %e %k:%M:%S", localtime ((time_t *)&tv.tv_sec));
  316. len = strcpy_cutoff (&output_buffer[output_buffer_idx], char_time, cutoff);
  317. output_buffer_idx += len;
  318. break;
  319. case 'b':
  320. len = strcpy_cutoff (&output_buffer[output_buffer_idx], buffer, cutoff);
  321. output_buffer_idx += len;
  322. break;
  323. }
  324. format_buffer_idx += 1;
  325. } else {
  326. output_buffer[output_buffer_idx++] = format_buffer[format_buffer_idx++];
  327. }
  328. }
  329. output_buffer[output_buffer_idx] = '\0';
  330. /*
  331. * Output to syslog
  332. */
  333. if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_SYSLOG) &&
  334. ((level <= logsys_loggers[subsysid].syslog_priority) ||
  335. (logsys_loggers[subsysid].debug != 0))) {
  336. syslog (level | logsys_loggers[subsysid].syslog_facility, "%s", output_buffer);
  337. }
  338. /*
  339. * Terminate string with \n \0
  340. */
  341. output_buffer[output_buffer_idx++] = '\n';
  342. output_buffer[output_buffer_idx] = '\0';
  343. /*
  344. * Output to configured file
  345. */
  346. if (((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_FILE) &&
  347. (logsys_loggers[subsysid].logfile_fp != NULL)) &&
  348. ((level <= logsys_loggers[subsysid].logfile_priority) ||
  349. (logsys_loggers[subsysid].debug != 0))) {
  350. /*
  351. * Output to a file
  352. */
  353. if ((fwrite (output_buffer, strlen (output_buffer), 1,
  354. logsys_loggers[subsysid].logfile_fp) < 1) ||
  355. (fflush (logsys_loggers[subsysid].logfile_fp) == EOF)) {
  356. char tmpbuffer[1024];
  357. /*
  358. * if we are here, it's bad.. it's really really bad.
  359. * Best thing would be to light a candle in a church
  360. * and pray.
  361. */
  362. snprintf(tmpbuffer, sizeof(tmpbuffer),
  363. "LOGSYS EMERGENCY: %s Unable to write to %s.",
  364. logsys_loggers[subsysid].subsys,
  365. logsys_loggers[subsysid].logfile);
  366. pthread_mutex_lock (&logsys_config_mutex);
  367. logsys_close_logfile(subsysid);
  368. logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_FILE;
  369. pthread_mutex_unlock (&logsys_config_mutex);
  370. log_printf_to_logs(logsys_loggers[subsysid].subsys,
  371. __FILE__, __FUNCTION__, __LINE__,
  372. LOGSYS_LEVEL_EMERG, tmpbuffer);
  373. }
  374. }
  375. /*
  376. * Output to stderr
  377. */
  378. if ((logsys_loggers[subsysid].mode & LOGSYS_MODE_OUTPUT_STDERR) &&
  379. ((level <= logsys_loggers[subsysid].logfile_priority) ||
  380. (logsys_loggers[subsysid].debug != 0))) {
  381. if (write (STDERR_FILENO, output_buffer, strlen (output_buffer)) < 0) {
  382. char tmpbuffer[1024];
  383. /*
  384. * if we are here, it's bad.. it's really really bad.
  385. * Best thing would be to light 20 candles for each saint
  386. * in the calendar and pray a lot...
  387. */
  388. pthread_mutex_lock (&logsys_config_mutex);
  389. logsys_loggers[subsysid].mode &= ~LOGSYS_MODE_OUTPUT_STDERR;
  390. pthread_mutex_unlock (&logsys_config_mutex);
  391. snprintf(tmpbuffer, sizeof(tmpbuffer),
  392. "LOGSYS EMERGENCY: %s Unable to write to STDERR.",
  393. logsys_loggers[subsysid].subsys);
  394. log_printf_to_logs(logsys_loggers[subsysid].subsys,
  395. __FILE__, __FUNCTION__, __LINE__,
  396. LOGSYS_LEVEL_EMERG, tmpbuffer);
  397. }
  398. }
  399. }
  400. static void record_print (const char *buf)
  401. {
  402. const int *buf_uint32t = (const int *)buf;
  403. unsigned int rec_size = buf_uint32t[0];
  404. unsigned int rec_ident = buf_uint32t[1];
  405. unsigned int file_line = buf_uint32t[2];
  406. unsigned int level = rec_ident >> 28;
  407. unsigned int i;
  408. unsigned int words_processed;
  409. unsigned int arg_size_idx;
  410. const void *arguments[64];
  411. unsigned int arg_count;
  412. arg_size_idx = 4;
  413. words_processed = 4;
  414. arg_count = 0;
  415. for (i = 0; words_processed < rec_size; i++) {
  416. arguments[arg_count++] = &buf_uint32t[arg_size_idx + 1];
  417. arg_size_idx += buf_uint32t[arg_size_idx] + 1;
  418. words_processed += buf_uint32t[arg_size_idx] + 1;
  419. }
  420. /*
  421. * (char *)arguments[0] -> subsystem
  422. * (char *)arguments[1] -> file_name
  423. * (char *)arguments[2] -> function_name
  424. * (char *)arguments[3] -> message
  425. */
  426. log_printf_to_logs (
  427. (char *)arguments[0],
  428. (char *)arguments[1],
  429. (char *)arguments[2],
  430. file_line,
  431. (level-1),
  432. (char *)arguments[3]);
  433. }
  434. static int record_read (char *buf, int rec_idx, int *log_msg) {
  435. unsigned int rec_size;
  436. unsigned int rec_ident;
  437. int firstcopy, secondcopy;
  438. rec_size = flt_data[rec_idx];
  439. rec_ident = flt_data[(rec_idx + 1) % flt_data_size];
  440. /*
  441. * Not a log record
  442. */
  443. if ((rec_ident & LOGSYS_TAG_LOG) == 0) {
  444. *log_msg = 0;
  445. return ((rec_idx + rec_size) % flt_data_size);
  446. }
  447. /*
  448. * A log record
  449. */
  450. *log_msg = 1;
  451. firstcopy = rec_size;
  452. secondcopy = 0;
  453. if (firstcopy + rec_idx > flt_data_size) {
  454. firstcopy = flt_data_size - rec_idx;
  455. secondcopy -= firstcopy - rec_size;
  456. }
  457. memcpy (&buf[0], &flt_data[rec_idx], firstcopy << 2);
  458. if (secondcopy) {
  459. memcpy (&buf[(firstcopy << 2)], &flt_data[0], secondcopy << 2);
  460. }
  461. return ((rec_idx + rec_size) % flt_data_size);
  462. }
  463. static inline void wthread_signal (void)
  464. {
  465. if (wthread_active == 0) {
  466. return;
  467. }
  468. pthread_mutex_lock (&logsys_cond_mutex);
  469. pthread_cond_signal (&logsys_cond);
  470. pthread_mutex_unlock (&logsys_cond_mutex);
  471. }
  472. static inline void wthread_wait (void)
  473. {
  474. pthread_mutex_lock (&logsys_cond_mutex);
  475. pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
  476. pthread_mutex_unlock (&logsys_cond_mutex);
  477. }
  478. static inline void wthread_wait_locked (void)
  479. {
  480. pthread_cond_wait (&logsys_cond, &logsys_cond_mutex);
  481. pthread_mutex_unlock (&logsys_cond_mutex);
  482. }
  483. static void *logsys_worker_thread (void *data) __attribute__((__noreturn__));
  484. static void *logsys_worker_thread (void *data)
  485. {
  486. int log_msg;
  487. char buf[COMBINE_BUFFER_SIZE];
  488. /*
  489. * Signal wthread_create that the initialization process may continue
  490. */
  491. wthread_signal ();
  492. logsys_lock();
  493. log_rec_idx = flt_data[FDTAIL_INDEX];
  494. logsys_unlock();
  495. for (;;) {
  496. wthread_wait ();
  497. /*
  498. * Read and copy the logging record index position
  499. * It may have been updated by records_reclaim if
  500. * messages were lost or or log_rec on the first new
  501. * logging record available
  502. */
  503. /*
  504. * Process any pending log messages here
  505. */
  506. for (;;) {
  507. int yield_counter = 1;
  508. logsys_lock();
  509. if (log_requests_lost > 0) {
  510. printf ("lost %d log requests\n", log_requests_lost);
  511. log_requests_pending -= log_requests_lost;
  512. log_requests_lost = 0;
  513. }
  514. if (log_requests_pending == 0) {
  515. logsys_unlock();
  516. break;
  517. }
  518. log_rec_idx = record_read (buf, log_rec_idx, &log_msg);
  519. if (log_msg) {
  520. log_requests_pending -= 1;
  521. }
  522. logsys_unlock();
  523. /*
  524. * print the stored buffer
  525. */
  526. if (log_msg) {
  527. record_print (buf);
  528. if (yield_counter++ > logsys_after_log_ops_yield) {
  529. yield_counter = 0;
  530. sched_yield ();
  531. }
  532. }
  533. }
  534. if (wthread_should_exit) {
  535. pthread_exit (NULL);
  536. }
  537. }
  538. }
  539. static void wthread_create (void)
  540. {
  541. int res;
  542. if (wthread_active) {
  543. return;
  544. }
  545. wthread_active = 1;
  546. pthread_mutex_init (&logsys_cond_mutex, NULL);
  547. pthread_cond_init (&logsys_cond, NULL);
  548. pthread_mutex_lock (&logsys_cond_mutex);
  549. res = pthread_create (&logsys_thread_id, NULL,
  550. logsys_worker_thread, NULL);
  551. /*
  552. * Wait for thread to be started
  553. */
  554. wthread_wait_locked ();
  555. }
  556. static int _logsys_config_subsys_get_unlocked (const char *subsys)
  557. {
  558. unsigned int i;
  559. if (!subsys) {
  560. return LOGSYS_MAX_SUBSYS_COUNT;
  561. }
  562. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  563. if (strcmp (logsys_loggers[i].subsys, subsys) == 0) {
  564. pthread_mutex_unlock (&logsys_config_mutex);
  565. return i;
  566. }
  567. }
  568. return (-1);
  569. }
  570. static void syslog_facility_reconf (void)
  571. {
  572. closelog();
  573. openlog(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].subsys,
  574. LOG_CONS|LOG_PID,
  575. logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].syslog_facility);
  576. }
  577. /*
  578. * this is always invoked within the mutex, so it's safe to parse the
  579. * whole thing as we need.
  580. */
  581. static void logsys_close_logfile (
  582. int subsysid)
  583. {
  584. int i;
  585. if ((logsys_loggers[subsysid].logfile_fp == NULL) &&
  586. (logsys_loggers[subsysid].logfile == NULL)) {
  587. return;
  588. }
  589. /*
  590. * if there is another subsystem or system using the same fp,
  591. * then we clean our own structs, but we can't close the file
  592. * as it is in use by somebody else.
  593. * Only the last users will be allowed to perform the fclose.
  594. */
  595. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  596. if ((logsys_loggers[i].logfile_fp == logsys_loggers[subsysid].logfile_fp) &&
  597. (i != subsysid)) {
  598. logsys_loggers[subsysid].logfile = NULL;
  599. logsys_loggers[subsysid].logfile_fp = NULL;
  600. return;
  601. }
  602. }
  603. /*
  604. * if we are here, we are the last users of that fp, so we can safely
  605. * close it.
  606. */
  607. fclose (logsys_loggers[subsysid].logfile_fp);
  608. logsys_loggers[subsysid].logfile_fp = NULL;
  609. free (logsys_loggers[subsysid].logfile);
  610. logsys_loggers[subsysid].logfile = NULL;
  611. }
  612. /*
  613. * we need a version that can work when somebody else is already
  614. * holding a config mutex lock or we will never get out of here
  615. */
  616. static int logsys_config_file_set_unlocked (
  617. int subsysid,
  618. const char **error_string,
  619. const char *file)
  620. {
  621. static char error_string_response[512];
  622. int i;
  623. logsys_close_logfile(subsysid);
  624. if ((file == NULL) ||
  625. (strcmp(logsys_loggers[subsysid].subsys, "") == 0)) {
  626. return (0);
  627. }
  628. if (strlen(file) >= PATH_MAX) {
  629. snprintf (error_string_response,
  630. sizeof(error_string_response),
  631. "%s: logfile name exceed maximum system filename lenght\n",
  632. logsys_loggers[subsysid].subsys);
  633. *error_string = error_string_response;
  634. return (-1);
  635. }
  636. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  637. if ((logsys_loggers[i].logfile != NULL) &&
  638. (strcmp (logsys_loggers[i].logfile, file) == 0) &&
  639. (i != subsysid)) {
  640. logsys_loggers[subsysid].logfile =
  641. logsys_loggers[i].logfile;
  642. logsys_loggers[subsysid].logfile_fp =
  643. logsys_loggers[i].logfile_fp;
  644. return (0);
  645. }
  646. }
  647. logsys_loggers[subsysid].logfile = strdup(file);
  648. if (logsys_loggers[subsysid].logfile == NULL) {
  649. snprintf (error_string_response,
  650. sizeof(error_string_response),
  651. "Unable to allocate memory for logfile '%s'\n",
  652. file);
  653. *error_string = error_string_response;
  654. return (-1);
  655. }
  656. logsys_loggers[subsysid].logfile_fp = fopen (file, "a+");
  657. if (logsys_loggers[subsysid].logfile_fp == NULL) {
  658. free(logsys_loggers[subsysid].logfile);
  659. logsys_loggers[subsysid].logfile = NULL;
  660. snprintf (error_string_response,
  661. sizeof(error_string_response),
  662. "Can't open logfile '%s' for reason (%s).\n",
  663. file, strerror (errno));
  664. *error_string = error_string_response;
  665. return (-1);
  666. }
  667. return (0);
  668. }
  669. static void logsys_subsys_init (
  670. const char *subsys,
  671. int subsysid)
  672. {
  673. if (logsys_system_needs_init == LOGSYS_LOGGER_NEEDS_INIT) {
  674. logsys_loggers[subsysid].init_status =
  675. LOGSYS_LOGGER_NEEDS_INIT;
  676. } else {
  677. memcpy(&logsys_loggers[subsysid],
  678. &logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT],
  679. sizeof(logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT]));
  680. logsys_loggers[subsysid].tags = LOGSYS_TAG_LOG;
  681. logsys_loggers[subsysid].init_status =
  682. LOGSYS_LOGGER_INIT_DONE;
  683. }
  684. strncpy (logsys_loggers[subsysid].subsys, subsys,
  685. LOGSYS_MAX_SUBSYS_NAMELEN);
  686. }
  687. /*
  688. * Internal API - exported
  689. */
  690. int _logsys_system_setup(
  691. const char *mainsystem,
  692. unsigned int mode,
  693. unsigned int debug,
  694. const char *logfile,
  695. int logfile_priority,
  696. int syslog_facility,
  697. int syslog_priority,
  698. unsigned int tags)
  699. {
  700. int i;
  701. const char *errstr;
  702. char tempsubsys[LOGSYS_MAX_SUBSYS_NAMELEN];
  703. if ((mainsystem == NULL) ||
  704. (strlen(mainsystem) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
  705. return -1;
  706. }
  707. i = LOGSYS_MAX_SUBSYS_COUNT;
  708. pthread_mutex_lock (&logsys_config_mutex);
  709. snprintf(logsys_loggers[i].subsys,
  710. LOGSYS_MAX_SUBSYS_NAMELEN,
  711. "%s", mainsystem);
  712. logsys_loggers[i].mode = mode;
  713. logsys_loggers[i].debug = debug;
  714. if (logsys_config_file_set_unlocked (i, &errstr, logfile) < 0) {
  715. pthread_mutex_unlock (&logsys_config_mutex);
  716. return (-1);
  717. }
  718. logsys_loggers[i].logfile_priority = logfile_priority;
  719. logsys_loggers[i].syslog_facility = syslog_facility;
  720. logsys_loggers[i].syslog_priority = syslog_priority;
  721. syslog_facility_reconf();
  722. logsys_loggers[i].tags = tags;
  723. logsys_loggers[i].init_status = LOGSYS_LOGGER_INIT_DONE;
  724. logsys_system_needs_init = LOGSYS_LOGGER_INIT_DONE;
  725. for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
  726. if ((strcmp (logsys_loggers[i].subsys, "") != 0) &&
  727. (logsys_loggers[i].init_status ==
  728. LOGSYS_LOGGER_NEEDS_INIT)) {
  729. strncpy (tempsubsys, logsys_loggers[i].subsys,
  730. LOGSYS_MAX_SUBSYS_NAMELEN);
  731. logsys_subsys_init(tempsubsys, i);
  732. }
  733. }
  734. pthread_mutex_unlock (&logsys_config_mutex);
  735. return (0);
  736. }
  737. unsigned int _logsys_subsys_create (const char *subsys)
  738. {
  739. int i;
  740. if ((subsys == NULL) ||
  741. (strlen(subsys) >= LOGSYS_MAX_SUBSYS_NAMELEN)) {
  742. return -1;
  743. }
  744. pthread_mutex_lock (&logsys_config_mutex);
  745. i = _logsys_config_subsys_get_unlocked (subsys);
  746. if ((i > -1) && (i < LOGSYS_MAX_SUBSYS_COUNT)) {
  747. pthread_mutex_unlock (&logsys_config_mutex);
  748. return i;
  749. }
  750. for (i = 0; i < LOGSYS_MAX_SUBSYS_COUNT; i++) {
  751. if (strcmp (logsys_loggers[i].subsys, "") == 0) {
  752. logsys_subsys_init(subsys, i);
  753. break;
  754. }
  755. }
  756. if (i >= LOGSYS_MAX_SUBSYS_COUNT) {
  757. i = -1;
  758. }
  759. pthread_mutex_unlock (&logsys_config_mutex);
  760. return i;
  761. }
  762. int _logsys_wthread_create (void)
  763. {
  764. if (((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_FORK) == 0) &&
  765. ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) != 0)) {
  766. wthread_create();
  767. atexit (logsys_atexit);
  768. }
  769. return (0);
  770. }
  771. int _logsys_rec_init (unsigned int size)
  772. {
  773. /*
  774. * First record starts at zero
  775. * Last record ends at zero
  776. */
  777. flt_data = malloc ((size + 2) * sizeof (unsigned int));
  778. if (flt_data == NULL) {
  779. return (-1);
  780. }
  781. flt_data_size = size;
  782. flt_data[FDHEAD_INDEX] = 0;
  783. flt_data[FDTAIL_INDEX] = 0;
  784. #if defined(HAVE_PTHREAD_SPIN_LOCK)
  785. pthread_spin_init (&logsys_idx_spinlock, 0);
  786. #endif
  787. return (0);
  788. }
  789. /*
  790. * u32 RECORD SIZE
  791. * u32 record ident
  792. * u32 arg count
  793. * u32 file line
  794. * u32 subsys length
  795. * buffer null terminated subsys
  796. * u32 filename length
  797. * buffer null terminated filename
  798. * u32 filename length
  799. * buffer null terminated function
  800. * u32 arg1 length
  801. * buffer arg1
  802. * ... repeats length & arg
  803. */
  804. void _logsys_log_rec (
  805. int subsysid,
  806. const char *function_name,
  807. const char *file_name,
  808. int file_line,
  809. unsigned int rec_ident,
  810. ...)
  811. {
  812. va_list ap;
  813. const void *buf_args[64];
  814. unsigned int buf_len[64];
  815. unsigned int i;
  816. unsigned int idx;
  817. unsigned int arguments = 0;
  818. unsigned int record_reclaim_size;
  819. unsigned int index_start;
  820. int words_written;
  821. record_reclaim_size = 0;
  822. /*
  823. * Decode VA Args
  824. */
  825. va_start (ap, rec_ident);
  826. arguments = 3;
  827. for (;;) {
  828. buf_args[arguments] = va_arg (ap, void *);
  829. if (buf_args[arguments] == LOGSYS_REC_END) {
  830. break;
  831. }
  832. buf_len[arguments] = va_arg (ap, int);
  833. record_reclaim_size += ((buf_len[arguments] + 3) >> 2) + 1;
  834. arguments++;
  835. if (arguments >= 64) {
  836. break;
  837. }
  838. }
  839. va_end (ap);
  840. /*
  841. * Encode logsys subsystem identity, filename, and function
  842. */
  843. buf_args[0] = logsys_loggers[subsysid].subsys;
  844. buf_len[0] = strlen (logsys_loggers[subsysid].subsys) + 1;
  845. buf_args[1] = file_name;
  846. buf_len[1] = strlen (file_name) + 1;
  847. buf_args[2] = function_name;
  848. buf_len[2] = strlen (function_name) + 1;
  849. for (i = 0; i < 3; i++) {
  850. record_reclaim_size += ((buf_len[i] + 3) >> 2) + 1;
  851. }
  852. idx = flt_data[FDHEAD_INDEX];
  853. index_start = idx;
  854. /*
  855. * Reclaim data needed for record including 4 words for the header
  856. */
  857. records_reclaim (idx, record_reclaim_size + 4);
  858. /*
  859. * Write record size of zero and rest of header information
  860. */
  861. flt_data[idx++] = 0;
  862. idx_word_step(idx);
  863. flt_data[idx++] = rec_ident;
  864. idx_word_step(idx);
  865. flt_data[idx++] = file_line;
  866. idx_word_step(idx);
  867. flt_data[idx++] = records_written;
  868. idx_word_step(idx);
  869. /*
  870. * Encode all of the arguments into the log message
  871. */
  872. for (i = 0; i < arguments; i++) {
  873. unsigned int bytes;
  874. unsigned int full_words;
  875. unsigned int total_words;
  876. bytes = buf_len[i];
  877. full_words = bytes >> 2;
  878. total_words = (bytes + 3) >> 2;
  879. flt_data[idx++] = total_words;
  880. idx_word_step(idx);
  881. /*
  882. * determine if this is a wrapped write or normal write
  883. */
  884. if (idx + total_words < flt_data_size) {
  885. /*
  886. * dont need to wrap buffer
  887. */
  888. my_memcpy_32bit (&flt_data[idx], buf_args[i], full_words);
  889. if (bytes % 4) {
  890. my_memcpy_8bit ((char *)&flt_data[idx + full_words],
  891. ((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
  892. }
  893. } else {
  894. /*
  895. * need to wrap buffer
  896. */
  897. unsigned int first;
  898. unsigned int second;
  899. first = flt_data_size - idx;
  900. if (first > full_words) {
  901. first = full_words;
  902. }
  903. second = full_words - first;
  904. my_memcpy_32bit (&flt_data[idx],
  905. (const int *)buf_args[i], first);
  906. my_memcpy_32bit (&flt_data[0],
  907. (const int *)(((const unsigned char *)buf_args[i]) + (first << 2)),
  908. second);
  909. if (bytes % 4) {
  910. my_memcpy_8bit ((char *)&flt_data[0 + second],
  911. ((const char *)buf_args[i]) + (full_words << 2), bytes % 4);
  912. }
  913. }
  914. idx += total_words;
  915. idx_buffer_step (idx);
  916. }
  917. words_written = idx - index_start;
  918. if (words_written < 0) {
  919. words_written += flt_data_size;
  920. }
  921. /*
  922. * Commit the write of the record size now that the full record
  923. * is in the memory buffer
  924. */
  925. flt_data[index_start] = words_written;
  926. /*
  927. * If the index of the current head equals the current log_rec_idx,
  928. * and this is not a log_printf operation, set the log_rec_idx to
  929. * the new head position and commit the new head.
  930. */
  931. logsys_lock();
  932. if (rec_ident & LOGSYS_TAG_LOG) {
  933. log_requests_pending += 1;
  934. }
  935. if (log_requests_pending == 0) {
  936. log_rec_idx = idx;
  937. }
  938. flt_data[FDHEAD_INDEX] = idx;
  939. logsys_unlock();
  940. records_written++;
  941. }
  942. void _logsys_log_vprintf (
  943. int subsysid,
  944. const char *function_name,
  945. const char *file_name,
  946. int file_line,
  947. unsigned int level,
  948. const char *format,
  949. va_list ap)
  950. {
  951. char logsys_print_buffer[COMBINE_BUFFER_SIZE];
  952. unsigned int len;
  953. if (subsysid <= -1) {
  954. subsysid = LOGSYS_MAX_SUBSYS_COUNT;
  955. }
  956. if ((level > logsys_loggers[subsysid].syslog_priority) &&
  957. (level > logsys_loggers[subsysid].logfile_priority) &&
  958. (logsys_loggers[subsysid].debug == 0)) {
  959. return;
  960. }
  961. len = vsprintf (logsys_print_buffer, format, ap);
  962. if (logsys_print_buffer[len - 1] == '\n') {
  963. logsys_print_buffer[len - 1] = '\0';
  964. len -= 1;
  965. }
  966. /*
  967. * Create a log record
  968. */
  969. _logsys_log_rec (subsysid,
  970. function_name,
  971. file_name,
  972. file_line,
  973. (level+1) << 28,
  974. logsys_print_buffer, len + 1,
  975. LOGSYS_REC_END);
  976. if ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) == 0) {
  977. /*
  978. * Output (and block) if the log mode is not threaded otherwise
  979. * expect the worker thread to output the log data once signaled
  980. */
  981. log_printf_to_logs (logsys_loggers[subsysid].subsys,
  982. file_name, function_name, file_line, level,
  983. logsys_print_buffer);
  984. } else {
  985. /*
  986. * Signal worker thread to display logging output
  987. */
  988. wthread_signal ();
  989. }
  990. }
  991. void _logsys_log_printf (
  992. int subsysid,
  993. const char *function_name,
  994. const char *file_name,
  995. int file_line,
  996. unsigned int level,
  997. const char *format,
  998. ...)
  999. {
  1000. char logsys_print_buffer[COMBINE_BUFFER_SIZE];
  1001. unsigned int len;
  1002. va_list ap;
  1003. if (subsysid <= -1) {
  1004. subsysid = LOGSYS_MAX_SUBSYS_COUNT;
  1005. }
  1006. if ((level > logsys_loggers[subsysid].syslog_priority) &&
  1007. (level > logsys_loggers[subsysid].logfile_priority) &&
  1008. (logsys_loggers[subsysid].debug == 0)) {
  1009. return;
  1010. }
  1011. va_start (ap, format);
  1012. len = vsprintf (logsys_print_buffer, format, ap);
  1013. va_end (ap);
  1014. if (logsys_print_buffer[len - 1] == '\n') {
  1015. logsys_print_buffer[len - 1] = '\0';
  1016. len -= 1;
  1017. }
  1018. /*
  1019. * Create a log record
  1020. */
  1021. _logsys_log_rec (subsysid,
  1022. function_name,
  1023. file_name,
  1024. file_line,
  1025. (level+1) << 28,
  1026. logsys_print_buffer, len + 1,
  1027. LOGSYS_REC_END);
  1028. if ((logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode & LOGSYS_MODE_THREADED) == 0) {
  1029. /*
  1030. * Output (and block) if the log mode is not threaded otherwise
  1031. * expect the worker thread to output the log data once signaled
  1032. */
  1033. log_printf_to_logs (logsys_loggers[subsysid].subsys,
  1034. file_name, function_name, file_line, level,
  1035. logsys_print_buffer);
  1036. } else {
  1037. /*
  1038. * Signal worker thread to display logging output
  1039. */
  1040. wthread_signal ();
  1041. }
  1042. }
  1043. int _logsys_config_subsys_get (const char *subsys)
  1044. {
  1045. unsigned int i;
  1046. pthread_mutex_lock (&logsys_config_mutex);
  1047. i = _logsys_config_subsys_get_unlocked (subsys);
  1048. pthread_mutex_unlock (&logsys_config_mutex);
  1049. return i;
  1050. }
  1051. /*
  1052. * External Configuration and Initialization API
  1053. */
  1054. void logsys_fork_completed (void)
  1055. {
  1056. logsys_loggers[LOGSYS_MAX_SUBSYS_COUNT].mode &= ~LOGSYS_MODE_FORK;
  1057. _logsys_wthread_create ();
  1058. }
  1059. unsigned int logsys_config_mode_set (const char *subsys, unsigned int mode)
  1060. {
  1061. int i;
  1062. pthread_mutex_lock (&logsys_config_mutex);
  1063. if (subsys != NULL) {
  1064. i = _logsys_config_subsys_get_unlocked (subsys);
  1065. if (i >= 0) {
  1066. logsys_loggers[i].mode = mode;
  1067. i = 0;
  1068. }
  1069. } else {
  1070. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1071. logsys_loggers[i].mode = mode;
  1072. }
  1073. i = 0;
  1074. }
  1075. pthread_mutex_unlock (&logsys_config_mutex);
  1076. return i;
  1077. }
  1078. unsigned int logsys_config_mode_get (const char *subsys)
  1079. {
  1080. int i;
  1081. i = _logsys_config_subsys_get (subsys);
  1082. if (i < 0) {
  1083. return i;
  1084. }
  1085. return logsys_loggers[i].mode;
  1086. }
  1087. unsigned int logsys_config_tags_set (const char *subsys, unsigned int tags)
  1088. {
  1089. int i;
  1090. pthread_mutex_lock (&logsys_config_mutex);
  1091. if (subsys != NULL) {
  1092. i = _logsys_config_subsys_get_unlocked (subsys);
  1093. if (i >= 0) {
  1094. logsys_loggers[i].tags = tags;
  1095. i = 0;
  1096. }
  1097. } else {
  1098. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1099. logsys_loggers[i].tags = tags;
  1100. }
  1101. i = 0;
  1102. }
  1103. pthread_mutex_unlock (&logsys_config_mutex);
  1104. return i;
  1105. }
  1106. unsigned int logsys_config_tags_get (const char *subsys)
  1107. {
  1108. int i;
  1109. i = _logsys_config_subsys_get (subsys);
  1110. if (i < 0) {
  1111. return i;
  1112. }
  1113. return logsys_loggers[i].tags;
  1114. }
  1115. int logsys_config_file_set (
  1116. const char *subsys,
  1117. const char **error_string,
  1118. const char *file)
  1119. {
  1120. int i;
  1121. int res;
  1122. pthread_mutex_lock (&logsys_config_mutex);
  1123. if (subsys != NULL) {
  1124. i = _logsys_config_subsys_get_unlocked (subsys);
  1125. if (i < 0) {
  1126. res = i;
  1127. } else {
  1128. res = logsys_config_file_set_unlocked(i, error_string, file);
  1129. }
  1130. } else {
  1131. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1132. res = logsys_config_file_set_unlocked(i, error_string, file);
  1133. if (res < 0) {
  1134. break;
  1135. }
  1136. }
  1137. }
  1138. pthread_mutex_unlock (&logsys_config_mutex);
  1139. return res;
  1140. }
  1141. int logsys_format_set (const char *format)
  1142. {
  1143. int ret = 0;
  1144. pthread_mutex_lock (&logsys_config_mutex);
  1145. if (format_buffer) {
  1146. free(format_buffer);
  1147. format_buffer = NULL;
  1148. }
  1149. format_buffer = strdup(format ? format : "[%6s] %b");
  1150. if (format_buffer == NULL) {
  1151. ret = -1;
  1152. }
  1153. pthread_mutex_unlock (&logsys_config_mutex);
  1154. return ret;
  1155. }
  1156. char *logsys_format_get (void)
  1157. {
  1158. return format_buffer;
  1159. }
  1160. unsigned int logsys_config_syslog_facility_set (
  1161. const char *subsys,
  1162. unsigned int facility)
  1163. {
  1164. int i;
  1165. pthread_mutex_lock (&logsys_config_mutex);
  1166. if (subsys != NULL) {
  1167. i = _logsys_config_subsys_get_unlocked (subsys);
  1168. if (i >= 0) {
  1169. logsys_loggers[i].syslog_facility = facility;
  1170. if (i == LOGSYS_MAX_SUBSYS_COUNT) {
  1171. syslog_facility_reconf();
  1172. }
  1173. i = 0;
  1174. }
  1175. } else {
  1176. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1177. logsys_loggers[i].syslog_facility = facility;
  1178. }
  1179. syslog_facility_reconf();
  1180. i = 0;
  1181. }
  1182. pthread_mutex_unlock (&logsys_config_mutex);
  1183. return i;
  1184. }
  1185. unsigned int logsys_config_syslog_priority_set (
  1186. const char *subsys,
  1187. unsigned int priority)
  1188. {
  1189. int i;
  1190. pthread_mutex_lock (&logsys_config_mutex);
  1191. if (subsys != NULL) {
  1192. i = _logsys_config_subsys_get_unlocked (subsys);
  1193. if (i >= 0) {
  1194. logsys_loggers[i].syslog_priority = priority;
  1195. i = 0;
  1196. }
  1197. } else {
  1198. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1199. logsys_loggers[i].syslog_priority = priority;
  1200. }
  1201. i = 0;
  1202. }
  1203. pthread_mutex_unlock (&logsys_config_mutex);
  1204. return i;
  1205. }
  1206. unsigned int logsys_config_logfile_priority_set (
  1207. const char *subsys,
  1208. unsigned int priority)
  1209. {
  1210. int i;
  1211. pthread_mutex_lock (&logsys_config_mutex);
  1212. if (subsys != NULL) {
  1213. i = _logsys_config_subsys_get_unlocked (subsys);
  1214. if (i >= 0) {
  1215. logsys_loggers[i].logfile_priority = priority;
  1216. i = 0;
  1217. }
  1218. } else {
  1219. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1220. logsys_loggers[i].logfile_priority = priority;
  1221. }
  1222. i = 0;
  1223. }
  1224. pthread_mutex_unlock (&logsys_config_mutex);
  1225. return i;
  1226. }
  1227. unsigned int logsys_config_debug_set (
  1228. const char *subsys,
  1229. unsigned int debug)
  1230. {
  1231. int i;
  1232. pthread_mutex_lock (&logsys_config_mutex);
  1233. if (subsys != NULL) {
  1234. i = _logsys_config_subsys_get_unlocked (subsys);
  1235. if (i >= 0) {
  1236. logsys_loggers[i].debug = debug;
  1237. i = 0;
  1238. }
  1239. } else {
  1240. for (i = 0; i <= LOGSYS_MAX_SUBSYS_COUNT; i++) {
  1241. logsys_loggers[i].debug = debug;
  1242. }
  1243. i = 0;
  1244. }
  1245. pthread_mutex_unlock (&logsys_config_mutex);
  1246. return i;
  1247. }
  1248. int logsys_facility_id_get (const char *name)
  1249. {
  1250. unsigned int i;
  1251. for (i = 0; facilitynames[i].c_name != NULL; i++) {
  1252. if (strcasecmp(name, facilitynames[i].c_name) == 0) {
  1253. return (facilitynames[i].c_val);
  1254. }
  1255. }
  1256. return (-1);
  1257. }
  1258. const char *logsys_facility_name_get (unsigned int facility)
  1259. {
  1260. unsigned int i;
  1261. for (i = 0; facilitynames[i].c_name != NULL; i++) {
  1262. if (facility == facilitynames[i].c_val) {
  1263. return (facilitynames[i].c_name);
  1264. }
  1265. }
  1266. return (NULL);
  1267. }
  1268. int logsys_priority_id_get (const char *name)
  1269. {
  1270. unsigned int i;
  1271. for (i = 0; prioritynames[i].c_name != NULL; i++) {
  1272. if (strcasecmp(name, prioritynames[i].c_name) == 0) {
  1273. return (prioritynames[i].c_val);
  1274. }
  1275. }
  1276. return (-1);
  1277. }
  1278. const char *logsys_priority_name_get (unsigned int priority)
  1279. {
  1280. unsigned int i;
  1281. for (i = 0; prioritynames[i].c_name != NULL; i++) {
  1282. if (priority == prioritynames[i].c_val) {
  1283. return (prioritynames[i].c_name);
  1284. }
  1285. }
  1286. return (NULL);
  1287. }
  1288. int logsys_tag_id_get (const char *name)
  1289. {
  1290. unsigned int i;
  1291. for (i = 0; tagnames[i].c_name != NULL; i++) {
  1292. if (strcasecmp(name, tagnames[i].c_name) == 0) {
  1293. return (tagnames[i].c_val);
  1294. }
  1295. }
  1296. return (-1);
  1297. }
  1298. const char *logsys_tag_name_get (unsigned int tag)
  1299. {
  1300. unsigned int i;
  1301. for (i = 0; tagnames[i].c_name != NULL; i++) {
  1302. if (tag == tagnames[i].c_val) {
  1303. return (tagnames[i].c_name);
  1304. }
  1305. }
  1306. return (NULL);
  1307. }
  1308. int logsys_thread_priority_set (
  1309. int policy,
  1310. const struct sched_param *param,
  1311. unsigned int after_log_ops_yield)
  1312. {
  1313. int res = 0;
  1314. if (policy != SCHED_OTHER) {
  1315. res = pthread_setschedparam (logsys_thread_id, policy, param);
  1316. }
  1317. if (after_log_ops_yield > 0) {
  1318. logsys_after_log_ops_yield = after_log_ops_yield;
  1319. }
  1320. return (res);
  1321. }
  1322. int logsys_log_rec_store (const char *filename)
  1323. {
  1324. int fd;
  1325. ssize_t written_size;
  1326. size_t size_to_write = (flt_data_size + 2) * sizeof (unsigned int);
  1327. fd = open (filename, O_CREAT|O_RDWR, 0700);
  1328. if (fd < 0) {
  1329. return (-1);
  1330. }
  1331. written_size = write (fd, flt_data, size_to_write);
  1332. if (close (fd) != 0)
  1333. return (-1);
  1334. if (written_size < 0) {
  1335. return (-1);
  1336. } else if ((size_t)written_size != size_to_write) {
  1337. return (-1);
  1338. }
  1339. return (0);
  1340. }
  1341. void logsys_atexit (void)
  1342. {
  1343. if (wthread_active) {
  1344. wthread_should_exit = 1;
  1345. wthread_signal ();
  1346. pthread_join (logsys_thread_id, NULL);
  1347. }
  1348. }
  1349. void logsys_flush (void)
  1350. {
  1351. wthread_signal ();
  1352. }