ret_t cherokee_logger_writer_flush (cherokee_logger_writer_t *writer, cherokee_boolean_t locked) { int re; ret_t ret = ret_ok; /* The internal buffer might be empty */ if (cherokee_buffer_is_empty (&writer->buffer)) { return ret_ok; } if (!locked) { CHEROKEE_MUTEX_LOCK (&PRIV(writer)->mutex); } /* If not, do the proper thing */ switch (writer->type) { case cherokee_logger_writer_stderr: /* In this case we ignore errors. */ re = fwrite (writer->buffer.buf, 1, writer->buffer.len, stderr); if (re != (size_t) writer->buffer.len) { ret = ret_error; } /* Cleanup the log buffer even if there is an error, * because it's safer to go on anyway. */ cherokee_buffer_clean (&writer->buffer); break; case cherokee_logger_writer_pipe: case cherokee_logger_writer_file: { ssize_t nwr = 0; size_t buflen = writer->buffer.len; /* If there is at least 1 page to write then round * down the length to speed up write(s). */ if (buflen > LOGGER_BUF_PAGESIZE) { buflen &= ~LOGGER_BUF_PAGESIZE; } do { nwr = write (writer->fd, writer->buffer.buf, buflen); } while (nwr == -1 && errno == EINTR); if (nwr <= 0) { /* If an error occured in blocking write, then * cleanup the log buffer now because we don't * want to let it grow too much. */ cherokee_buffer_clean (&writer->buffer); ret = ret_error; goto out; } /* OK, something has been written. */ cherokee_buffer_move_to_begin (&writer->buffer, nwr); if (! cherokee_buffer_is_empty (&writer->buffer)) { ret = ret_eagain; } break; } case cherokee_logger_writer_syslog: /* Write to syslog the whole log buffer, then cleanup * it in any case. */ ret = cherokee_syslog (LOG_INFO, &writer->buffer); cherokee_buffer_clean (&writer->buffer); break; default: SHOULDNT_HAPPEN; ret = ret_error; } out: if (! locked) { CHEROKEE_MUTEX_UNLOCK (&PRIV(writer)->mutex); } return ret; }
void cherokee_trace_do_trace (const char *entry, const char *file, int line, const char *func, const char *fmt, ...) { ret_t ret; char *p; char *lentry; char *lentry_end; va_list args; cherokee_connection_t *conn; cherokee_buffer_t *trace_modules = &trace.modules; cherokee_boolean_t do_log = false; cherokee_buffer_t entries = CHEROKEE_BUF_INIT; /* Prevents loops */ if (disabled) { return; } disabled = true; /* Return ASAP if nothing is being traced */ if (cherokee_buffer_is_empty (&trace.modules)) { goto out; } /* Check the connection source, if possible */ if (trace.from_filter != NULL) { conn = CONN (CHEROKEE_THREAD_PROP_GET (thread_connection_ptr)); /* No conn, no trace entry */ if (conn == NULL) { goto out; } if (conn->socket.socket < 0) { goto out; } /* Skip the trace if the conn doesn't match */ ret = cherokee_access_ip_match (trace.from_filter, &conn->socket); if (ret != ret_ok) { goto out; } } /* Also, check for 'all' */ p = strstr (trace_modules->buf, "all"); if (p == NULL) { /* Parse the In-code module string */ cherokee_buffer_add (&entries, entry, strlen(entry)); for (lentry = entries.buf;;) { lentry_end = strchr (lentry, ','); if (lentry_end) *lentry_end = '\0'; /* Check the type */ p = strstr (trace_modules->buf, lentry); if (p) { char *tmp = p + strlen(lentry); if ((*tmp == '\0') || (*tmp == ',') || (*tmp == ' ')) do_log = true; } if ((lentry_end == NULL) || (do_log)) break; lentry = lentry_end + 1; } /* Return if trace entry didn't match with the configured list */ if (! do_log) { goto out; } } /* Format the message and log it: * 'entries' is not needed at this stage, reuse it */ cherokee_buffer_clean (&entries); if (trace.print_thread) { int len; char tmp[32+1]; static int longest_len = 0; len = snprintf (tmp, 32+1, "%llX", (unsigned long long) CHEROKEE_THREAD_SELF); longest_len = MAX (longest_len, len); cherokee_buffer_add_str (&entries, "{0x"); cherokee_buffer_add_char_n (&entries, '0', longest_len - len); cherokee_buffer_add (&entries, tmp, len); cherokee_buffer_add_str (&entries, "} "); } if (trace.print_time) { cherokee_buffer_add_char (&entries, '['); cherokee_buf_add_bogonow (&entries, true); cherokee_buffer_add_str (&entries, "] "); } cherokee_buffer_add_va (&entries, "%18s:%04d (%30s): ", file, line, func); va_start (args, fmt); cherokee_buffer_add_va_list (&entries, (char *)fmt, args); va_end (args); if (trace.use_syslog) { cherokee_syslog (LOG_DEBUG, &entries); } else { #ifdef HAVE_FLOCKFILE flockfile (stdout); #endif fprintf (stdout, "%s", entries.buf); #ifdef HAVE_FUNLOCKFILE funlockfile (stdout); #endif } out: cherokee_buffer_mrproper (&entries); disabled = false; }