#include "util-byte.h"
#include "util-conf.h"
#include "util-path.h"
+#include "util-misc.h"
#include "util-time.h"
#if defined(HAVE_SYS_UN_H) && defined(HAVE_SYS_SOCKET_H) && defined(HAVE_SYS_TYPES_H)
log_ctx->filename);
}
log_ctx->output_errors++;
- } else {
+ } else if (log_ctx->buffer_size) {
SCFflushUnlocked(log_ctx->fp);
}
}
static void SCLogFileCloseNoLock(LogFileCtx *log_ctx)
{
SCLogDebug("Closing %s", log_ctx->filename);
- if (log_ctx->fp)
+ if (log_ctx->fp) {
+ if (log_ctx->buffer_size)
+ SCFflushUnlocked(log_ctx->fp);
fclose(log_ctx->fp);
+ }
if (log_ctx->output_errors) {
SCLogError("There were %" PRIu64 " output errors to %s", log_ctx->output_errors,
* \retval FILE* on success
* \retval NULL on error
*/
-static FILE *
-SCLogOpenFileFp(const char *path, const char *append_setting, uint32_t mode)
+static FILE *SCLogOpenFileFp(
+ const char *path, const char *append_setting, uint32_t mode, const uint32_t buffer_size)
{
FILE *ret = NULL;
if (ret == NULL) {
SCLogError("Error opening file: \"%s\": %s", filename, strerror(errno));
+ goto error_exit;
} else {
if (mode != 0) {
#ifdef OS_WIN32
}
}
+ /* Set buffering behavior */
+ if (buffer_size == 0) {
+ setbuf(ret, NULL);
+ SCLogConfig("Setting output to %s non-buffered", filename);
+ } else {
+ if (setvbuf(ret, NULL, _IOFBF, buffer_size) < 0)
+ FatalError("unable to set %s to buffered: %d", filename, buffer_size);
+ SCLogConfig("Setting output to %s buffered [limit %d bytes]", filename, buffer_size);
+ }
+
+error_exit:
SCFree(filename);
+
return ret;
}
if (filetype == NULL)
filetype = DEFAULT_LOG_FILETYPE;
+ /* Determine the buffering for this output device; a value of 0 means to not buffer;
+ * any other value must be a multiple of 4096
+ */
+ uint32_t buffer_size = LOGFILE_EVE_BUFFER_SIZE;
+ const char *buffer_size_value = ConfNodeLookupChildValue(conf, "buffer-size");
+ if (buffer_size_value != NULL) {
+ uint32_t value;
+ if (ParseSizeStringU32(buffer_size_value, &value) < 0) {
+ FatalError("Error parsing "
+ "buffer-size - %s. Killing engine",
+ buffer_size_value);
+ }
+ buffer_size = value;
+ }
+
+ SCLogDebug("buffering: %s -> %d", buffer_size_value, buffer_size);
const char *filemode = ConfNodeLookupChildValue(conf, "filemode");
uint32_t mode = 0;
if (filemode != NULL && StringParseUint32(&mode, 8, (uint16_t)strlen(filemode), filemode) > 0) {
}
}
#endif
+ if (!(strcasecmp(filetype, DEFAULT_LOG_FILETYPE) == 0 || strcasecmp(filetype, "file") == 0)) {
+ SCLogConfig("buffering setting ignored for %s output types", filetype);
+ }
+
// Now, what have we been asked to open?
if (strcasecmp(filetype, "unix_stream") == 0) {
#ifdef BUILD_WITH_UNIXSOCKET
} else if (strcasecmp(filetype, DEFAULT_LOG_FILETYPE) == 0 ||
strcasecmp(filetype, "file") == 0) {
log_ctx->is_regular = 1;
+ log_ctx->buffer_size = buffer_size;
if (!log_ctx->threaded) {
- log_ctx->fp = SCLogOpenFileFp(log_path, append, log_ctx->filemode);
+ log_ctx->fp =
+ SCLogOpenFileFp(log_path, append, log_ctx->filemode, log_ctx->buffer_size);
if (log_ctx->fp == NULL)
return -1; // Error already logged by Open...Fp routine
} else {
/* Reopen the file. Append is forced in case the file was not
* moved as part of a rotation process. */
SCLogDebug("Reopening log file %s.", log_ctx->filename);
- log_ctx->fp = SCLogOpenFileFp(log_ctx->filename, "yes", log_ctx->filemode);
+ log_ctx->fp =
+ SCLogOpenFileFp(log_ctx->filename, "yes", log_ctx->filemode, log_ctx->buffer_size);
if (log_ctx->fp == NULL) {
return -1; // Already logged by Open..Fp routine.
}
}
SCLogDebug("%s: thread open -- using name %s [replaces %s] - thread %d [slot %d]",
t_thread_name, fname, log_path, entry->internal_thread_id, entry->slot_number);
- thread->fp = SCLogOpenFileFp(fname, append, thread->filemode);
+ thread->fp = SCLogOpenFileFp(fname, append, thread->filemode, parent_ctx->buffer_size);
if (thread->fp == NULL) {
goto error;
}