log.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  2. *
  3. * Gearmand client and server library.
  4. *
  5. * Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
  6. * Copyright (C) 2008 Brian Aker, Eric Day
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted provided that the following conditions are
  11. * met:
  12. *
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above
  17. * copyright notice, this list of conditions and the following disclaimer
  18. * in the documentation and/or other materials provided with the
  19. * distribution.
  20. *
  21. * * The names of its contributors may not be used to endorse or
  22. * promote products derived from this software without specific prior
  23. * written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  26. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  27. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  28. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  29. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  30. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  31. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  32. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  33. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  34. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  35. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  36. *
  37. */
  38. /**
  39. * @file
  40. * @brief Gearman State Definitions
  41. */
  42. #include "gear_config.h"
  43. #include "libgearman-server/common.h"
  44. #include "libgearman-server/timer.h"
  45. #include <algorithm>
  46. #include <cerrno>
  47. #include <cstddef>
  48. #include <cstdlib>
  49. #include <cstring>
  50. #include <ctime>
  51. #include <pthread.h>
  52. #ifdef _WIN32
  53. # include <malloc.h>
  54. #else
  55. # include <alloca.h>
  56. #endif
  57. #pragma GCC diagnostic push
  58. #ifndef __INTEL_COMPILER
  59. # pragma GCC diagnostic ignored "-Wold-style-cast"
  60. # pragma GCC diagnostic ignored "-Wformat-nonliteral"
  61. # pragma GCC diagnostic ignored "-Wformat-security"
  62. #endif
  63. static pthread_key_t logging_key;
  64. static pthread_once_t intitialize_log_once= PTHREAD_ONCE_INIT;
  65. static void delete_log(void * ptr)
  66. {
  67. if (ptr)
  68. {
  69. free(ptr);
  70. }
  71. }
  72. static void create_log(void)
  73. {
  74. int pthread_error;
  75. if ((pthread_error= pthread_key_create(&logging_key, delete_log)))
  76. {
  77. gearmand_log_fatal_perror(GEARMAND_AT, "pthread_key_create", pthread_error, "pthread_key_create");
  78. abort();
  79. }
  80. }
  81. gearmand_error_t gearmand_initialize_thread_logging(const char *identity)
  82. {
  83. if (identity)
  84. {
  85. int pthread_error;
  86. if ((pthread_error= pthread_once(&intitialize_log_once, create_log)))
  87. {
  88. return gearmand_log_fatal_perror(GEARMAND_AT, "pthread_once", pthread_error, "identity: %s", identity);
  89. }
  90. if (pthread_getspecific(logging_key) == NULL)
  91. {
  92. const char *key_to_use= strdup(identity);
  93. if ((pthread_error= pthread_setspecific(logging_key, key_to_use)))
  94. {
  95. return gearmand_log_fatal_perror(GEARMAND_AT, "pthread_setspecific", pthread_error, "identity: %s", identity);
  96. }
  97. }
  98. return GEARMAND_SUCCESS;
  99. }
  100. gearmand_fatal("identity was NULL");
  101. return GEARMAND_INVALID_ARGUMENT;
  102. }
  103. #if __GNUC__ >= 7
  104. #pragma GCC diagnostic warning "-Wimplicit-fallthrough"
  105. #endif
  106. static gearmand_error_t __errno_to_gearmand_error_t(int local_errno)
  107. {
  108. gearmand_error_t error_to_report= GEARMAND_ERRNO;
  109. switch (local_errno)
  110. {
  111. case ENOMEM:
  112. error_to_report= GEARMAND_MEMORY_ALLOCATION_FAILURE;
  113. break;
  114. case ECONNRESET:
  115. case EHOSTDOWN:
  116. error_to_report= GEARMAND_LOST_CONNECTION;
  117. break;
  118. default:
  119. break;
  120. }
  121. return error_to_report;
  122. }
  123. /**
  124. * Log a message.
  125. *
  126. * @param[in] gearman Structure previously initialized with gearman_create() or
  127. * gearman_clone().
  128. * @param[in] verbose Logging level of the message.
  129. * @param[in] format Format and variable argument list of message.
  130. * @param[in] args Variable argument list that has been initialized.
  131. */
  132. static void gearmand_log(const char *position, const char *func /* func */,
  133. gearmand_verbose_t verbose,
  134. const gearmand_error_t error_arg,
  135. const char *format, va_list args)
  136. {
  137. struct timeval current_epoch;
  138. if (Gearmand() and Gearmand()->verbose < GEARMAND_VERBOSE_DEBUG)
  139. {
  140. current_epoch= libgearman::server::Epoch::current();
  141. current_epoch.tv_usec= 0;
  142. }
  143. else
  144. {
  145. (void)gettimeofday(&current_epoch, NULL);
  146. }
  147. struct tm current_tm;
  148. if (current_epoch.tv_sec == 0)
  149. {
  150. (void)gettimeofday(&current_epoch, NULL);
  151. }
  152. if ((localtime_r(&current_epoch.tv_sec, &current_tm) == NULL))
  153. {
  154. memset(&current_epoch, 0, sizeof(current_epoch));
  155. }
  156. (void) pthread_once(&intitialize_log_once, create_log);
  157. const char *identity= (const char *)pthread_getspecific(logging_key);
  158. if (identity == NULL)
  159. {
  160. identity= "[ main ]";
  161. }
  162. char log_buffer[GEARMAN_MAX_ERROR_SIZE*2] = { 0 };
  163. if (Gearmand() && Gearmand()->log_fn)
  164. {
  165. char *log_buffer_ptr= log_buffer;
  166. size_t remaining_size= sizeof(log_buffer);
  167. {
  168. int length= snprintf(log_buffer, sizeof(log_buffer), "%04d-%02d-%02d %02d:%02d:%02d.%06d %s ",
  169. int(1900 +current_tm.tm_year), current_tm.tm_mon +1, current_tm.tm_mday, current_tm.tm_hour,
  170. current_tm.tm_min, current_tm.tm_sec, int(current_epoch.tv_usec),
  171. identity);
  172. // We just return whatever we have if this occurs
  173. if (length <= 0 or (size_t)length >= sizeof(log_buffer))
  174. {
  175. remaining_size= 0;
  176. }
  177. else
  178. {
  179. remaining_size-= size_t(length);
  180. log_buffer_ptr+= length;
  181. }
  182. }
  183. if (remaining_size)
  184. {
  185. int length= vsnprintf(log_buffer_ptr, remaining_size, format, args);
  186. if (length <= 0 or size_t(length) >= remaining_size)
  187. {
  188. remaining_size= 0;
  189. }
  190. else
  191. {
  192. remaining_size-= size_t(length);
  193. log_buffer_ptr+= length;
  194. }
  195. }
  196. if (remaining_size and error_arg != GEARMAND_SUCCESS)
  197. {
  198. int length= snprintf(log_buffer_ptr, remaining_size, " %s(%s)", func, gearmand_strerror(error_arg));
  199. if (length <= 0 or size_t(length) >= remaining_size)
  200. {
  201. remaining_size= 0;
  202. }
  203. else
  204. {
  205. remaining_size-= size_t(length);
  206. log_buffer_ptr+= length;
  207. }
  208. }
  209. if (remaining_size and position and verbose != GEARMAND_VERBOSE_INFO)
  210. {
  211. int length= snprintf(log_buffer_ptr, remaining_size, " -> %s", position);
  212. if (length <= 0 or size_t(length) >= remaining_size)
  213. {
  214. remaining_size= 0;
  215. }
  216. }
  217. // Make sure this is null terminated
  218. log_buffer[sizeof(log_buffer) -1]= 0;
  219. }
  220. if (Gearmand() and Gearmand()->log_fn)
  221. {
  222. Gearmand()->log_fn(log_buffer, verbose, (void *)Gearmand()->log_context);
  223. }
  224. else
  225. {
  226. fprintf(stderr, "%s -> %s",
  227. log_buffer, gearmand_verbose_name(verbose));
  228. vfprintf(stderr, format, args);
  229. fprintf(stderr, "\n");
  230. }
  231. }
  232. gearmand_error_t gearmand_log_fatal(const char *position, const char *func, const char *format, ...)
  233. {
  234. if (Gearmand() and Gearmand()->verbose < GEARMAND_VERBOSE_FATAL)
  235. {
  236. return GEARMAND_ERRNO;
  237. }
  238. {
  239. va_list args;
  240. va_start(args, format);
  241. gearmand_log(position, func, GEARMAND_VERBOSE_FATAL, GEARMAND_SUCCESS, format, args);
  242. va_end(args);
  243. }
  244. gearmand_wakeup(Gearmand(), GEARMAND_WAKEUP_SHUTDOWN_GRACEFUL);
  245. return GEARMAND_ERRNO;
  246. }
  247. gearmand_error_t gearmand_log_fatal_perror(const char *position, const char *function, const int local_errno, const char *format, ...)
  248. {
  249. if (Gearmand() and Gearmand()->verbose < GEARMAND_VERBOSE_FATAL)
  250. {
  251. return GEARMAND_ERRNO;
  252. }
  253. char* message_buffer= NULL;
  254. {
  255. va_list args;
  256. va_start(args, format);
  257. size_t ask= snprintf(0, 0, format);
  258. ask++; // for null
  259. message_buffer= (char*)alloca(sizeof(char) * ask);
  260. if (message_buffer)
  261. {
  262. vsnprintf(message_buffer, ask, format, args);
  263. }
  264. va_end(args);
  265. }
  266. {
  267. const char *errmsg_ptr;
  268. char errmsg[GEARMAN_MAX_ERROR_SIZE];
  269. errmsg[0]= 0;
  270. #ifdef STRERROR_R_CHAR_P
  271. errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
  272. #else
  273. strerror_r(local_errno, errmsg, sizeof(errmsg));
  274. errmsg_ptr= errmsg;
  275. #endif
  276. if (message_buffer)
  277. {
  278. gearmand_log_fatal(position, function, "%s(%s)", message_buffer, errmsg_ptr);
  279. }
  280. else
  281. {
  282. gearmand_log_fatal(position, function, "%s", errmsg_ptr);
  283. }
  284. }
  285. return __errno_to_gearmand_error_t(local_errno);
  286. }
  287. gearmand_error_t gearmand_log_error(const char *position, const char *function, const char *format, ...)
  288. {
  289. if (not Gearmand() or Gearmand()->verbose >= GEARMAND_VERBOSE_ERROR)
  290. {
  291. va_list args;
  292. va_start(args, format);
  293. gearmand_log(position, function, GEARMAND_VERBOSE_ERROR, GEARMAND_SUCCESS, format, args);
  294. va_end(args);
  295. }
  296. return GEARMAND_UNKNOWN_OPTION;
  297. }
  298. void gearmand_log_warning(const char *position, const char *function, const char *format, ...)
  299. {
  300. if (not Gearmand() or Gearmand()->verbose >= GEARMAND_VERBOSE_WARN)
  301. {
  302. va_list args;
  303. va_start(args, format);
  304. gearmand_log(position, function, GEARMAND_VERBOSE_WARN, GEARMAND_SUCCESS, format, args);
  305. va_end(args);
  306. }
  307. }
  308. // LOG_NOTICE is only used for reporting job status.
  309. void gearmand_log_notice(const char *position, const char *function, const char *format, ...)
  310. {
  311. if (not Gearmand() or Gearmand()->verbose >= GEARMAND_VERBOSE_NOTICE)
  312. {
  313. va_list args;
  314. va_start(args, format);
  315. gearmand_log(position, function, GEARMAND_VERBOSE_NOTICE, GEARMAND_SUCCESS, format, args);
  316. va_end(args);
  317. }
  318. }
  319. void gearmand_log_info(const char *position, const char *function, const char *format, ...)
  320. {
  321. if (not Gearmand() or Gearmand()->verbose >= GEARMAND_VERBOSE_INFO)
  322. {
  323. va_list args;
  324. va_start(args, format);
  325. gearmand_log(position, function, GEARMAND_VERBOSE_INFO, GEARMAND_SUCCESS, format, args);
  326. va_end(args);
  327. }
  328. }
  329. void gearmand_log_debug(const char *position, const char *function, const char *format, ...)
  330. {
  331. va_list args;
  332. if (not Gearmand() || Gearmand()->verbose >= GEARMAND_VERBOSE_DEBUG)
  333. {
  334. va_start(args, format);
  335. gearmand_log(position, function, GEARMAND_VERBOSE_DEBUG, GEARMAND_SUCCESS, format, args);
  336. va_end(args);
  337. }
  338. }
  339. gearmand_error_t gearmand_log_perror(const char *position, const char *function, const int local_errno, const char *format, ...)
  340. {
  341. if (not Gearmand() or (Gearmand()->verbose >= GEARMAND_VERBOSE_ERROR))
  342. {
  343. char* message_buffer= NULL;
  344. {
  345. va_list args;
  346. va_start(args, format);
  347. size_t ask= snprintf(0, 0, format);
  348. ask++; // for null
  349. message_buffer= (char*)alloca(sizeof(char) * ask);
  350. vsnprintf(message_buffer, ask, format, args);
  351. va_end(args);
  352. }
  353. const char *errmsg_ptr;
  354. char errmsg[GEARMAN_MAX_ERROR_SIZE];
  355. errmsg[0]= 0;
  356. #ifdef STRERROR_R_CHAR_P
  357. errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
  358. #else
  359. strerror_r(local_errno, errmsg, sizeof(errmsg));
  360. errmsg_ptr= errmsg;
  361. #endif
  362. if (message_buffer)
  363. {
  364. gearmand_log_error(position, function, "%s(%s)", message_buffer, errmsg_ptr);
  365. }
  366. else
  367. {
  368. gearmand_log_error(position, function, "%s", errmsg_ptr);
  369. }
  370. }
  371. return __errno_to_gearmand_error_t(local_errno);
  372. }
  373. void gearmand_log_perror_warn(const char *position, const char *function, const int local_errno, const char *format, ...)
  374. {
  375. if (not Gearmand() or (Gearmand()->verbose >= GEARMAND_VERBOSE_WARN))
  376. {
  377. char* message_buffer= NULL;
  378. {
  379. va_list args;
  380. va_start(args, format);
  381. size_t ask= snprintf(0, 0, format);
  382. ask++; // for null
  383. message_buffer= (char*)alloca(sizeof(char) * ask);
  384. vsnprintf(message_buffer, ask, format, args);
  385. va_end(args);
  386. }
  387. const char *errmsg_ptr;
  388. char errmsg[GEARMAN_MAX_ERROR_SIZE];
  389. errmsg[0]= 0;
  390. #ifdef STRERROR_R_CHAR_P
  391. errmsg_ptr= strerror_r(local_errno, errmsg, sizeof(errmsg));
  392. #else
  393. strerror_r(local_errno, errmsg, sizeof(errmsg));
  394. errmsg_ptr= errmsg;
  395. #endif
  396. if (message_buffer)
  397. {
  398. gearmand_log_warning(position, function, "%s(%s)", message_buffer, errmsg_ptr);
  399. }
  400. else
  401. {
  402. gearmand_log_warning(position, function, "%s", errmsg_ptr);
  403. }
  404. }
  405. }
  406. gearmand_error_t gearmand_log_gerror(const char *position, const char *function, const gearmand_error_t rc, const char *format, ...)
  407. {
  408. if (gearmand_failed(rc) and rc != GEARMAND_IO_WAIT)
  409. {
  410. va_list args;
  411. if (Gearmand() == NULL or Gearmand()->verbose >= GEARMAND_VERBOSE_ERROR)
  412. {
  413. va_start(args, format);
  414. gearmand_log(position, function, GEARMAND_VERBOSE_ERROR, rc, format, args);
  415. va_end(args);
  416. }
  417. }
  418. else if (rc == GEARMAND_IO_WAIT)
  419. { }
  420. return rc;
  421. }
  422. void gearmand_log_gerror_warn(const char *position, const char *function, const gearmand_error_t rc, const char *format, ...)
  423. {
  424. if (gearmand_failed(rc) and rc != GEARMAND_IO_WAIT)
  425. {
  426. va_list args;
  427. if (Gearmand() == NULL or Gearmand()->verbose >= GEARMAND_VERBOSE_WARN)
  428. {
  429. va_start(args, format);
  430. gearmand_log(position, function, GEARMAND_VERBOSE_WARN, rc, format, args);
  431. va_end(args);
  432. }
  433. }
  434. }
  435. gearmand_error_t gearmand_log_gai_error(const char *position, const char *function, const int rc, const char *message)
  436. {
  437. if (rc == EAI_SYSTEM)
  438. {
  439. return gearmand_log_perror(position, function, errno, message);
  440. }
  441. gearmand_log_error(position, function, "%s getaddrinfo(%s)", message, gai_strerror(rc));
  442. return GEARMAND_GETADDRINFO;
  443. }
  444. gearmand_error_t gearmand_log_memory_error(const char *position, const char *function, const char *allocator, const char *object_type, size_t count, size_t size)
  445. {
  446. if (count > 1)
  447. {
  448. gearmand_log_error(position, function, "%s(%s, count: %lu size: %lu)", allocator, object_type, static_cast<unsigned long>(count), static_cast<unsigned long>(size));
  449. }
  450. else
  451. {
  452. gearmand_log_error(position, function, "%s(%s, size: %lu)", allocator, object_type, static_cast<unsigned long>(count), static_cast<unsigned long>(size));
  453. }
  454. return GEARMAND_MEMORY_ALLOCATION_FAILURE;
  455. }
  456. #pragma GCC diagnostic pop