struct byteq byteq;
};
-static bool async_append_enabled;
-
-void
-async_append_enable(void)
-{
- assert_single_threaded();
- forbid_forking("async i/o enabled");
- async_append_enabled = true;
-}
-
struct async_append *
async_append_create(int fd)
{
{
const uint8_t *data = data_;
- if (!async_append_enabled) {
- ignore(write(ap->fd, data, size));
- return;
- }
-
while (size > 0) {
struct aiocb *aiocb;
size_t chunk_size;
#include <config.h>
-/* This implementation of the async-append.h interface uses ordinary
- * synchronous I/O, so it should be portable everywhere. */
+/* This is a null implementation of the asynchronous I/O interface for systems
+ * that don't have a form of asynchronous I/O. */
#include "async-append.h"
#include "util.h"
-struct async_append {
- int fd;
-};
-
-void
-async_append_enable(void)
-{
- /* Nothing to do. */
-}
-
struct async_append *
-async_append_create(int fd)
+async_append_create(int fd OVS_UNUSED)
{
- struct async_append *ap = xmalloc(sizeof *ap);
- ap->fd = fd;
- return ap;
+ return NULL;
}
void
async_append_destroy(struct async_append *ap)
{
- free(ap);
+ ovs_assert(ap == NULL);
}
void
-async_append_write(struct async_append *ap, const void *data, size_t size)
+async_append_write(struct async_append *ap OVS_UNUSED,
+ const void *data OVS_UNUSED, size_t size OVS_UNUSED)
{
- ignore(write(ap->fd, data, size));
+ NOT_REACHED();
}
void
async_append_flush(struct async_append *ap OVS_UNUSED)
{
- /* Nothing to do. */
+ NOT_REACHED();
}
* Only a single thread may use a given 'struct async_append' at one time.
*/
-/* Enables using asynchronous I/O. Some implementations may treat this as a
- * no-op.
- *
- * Before this function is called, the POSIX aio implementation uses ordinary
- * synchronous I/O because some POSIX aio libraries actually use threads
- * internally, which has enough cost and robustness implications that it's
- * better to use asynchronous I/O only when it has real expected benefits.
- *
- * Must be called while the process is still single-threaded. May forbid the
- * process from subsequently forking. */
-void async_append_enable(void);
-
/* Creates and returns a new asynchronous appender for file descriptor 'fd',
- * which the caller must have opened in append mode (O_APPEND).
- *
- * This function must always succeed. If the system is for some reason unable
- * to support asynchronous I/O on 'fd' then the library must fall back to
- * syncrhonous I/O. */
+ * which the caller must have opened in append mode (O_APPEND). If the system
+ * is for some reason unable to support asynchronous I/O on 'fd' this function
+ * may return NULL. */
struct async_append *async_append_create(int fd);
/* Destroys 'ap', without closing its underlying file descriptor. */
if HAVE_POSIX_AIO
lib_libopenvswitch_a_SOURCES += lib/async-append-aio.c
else
-lib_libopenvswitch_a_SOURCES += lib/async-append-sync.c
+lib_libopenvswitch_a_SOURCES += lib/async-append-null.c
endif
if ESX
static char *log_file_name OVS_GUARDED_BY(log_file_mutex);
static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
+static bool log_async OVS_GUARDED_BY(log_file_mutex);
static void format_log_message(const struct vlog_module *, enum vlog_level,
enum vlog_facility,
log_file_name = xstrdup(new_log_file_name);
log_fd = new_log_fd;
- log_writer = async_append_create(new_log_fd);
+ if (log_async) {
+ log_writer = async_append_create(new_log_fd);
+ }
for (mp = vlog_modules; mp < &vlog_modules[n_vlog_modules]; mp++) {
update_min_level(*mp);
pthread_once(&once, vlog_init__);
}
+/* Enables VLF_FILE log output to be written asynchronously to disk.
+ * Asynchronous file writes avoid blocking the process in the case of a busy
+ * disk, but on the other hand they are less robust: there is a chance that the
+ * write will not make it to the log file if the process crashes soon after the
+ * log call. */
+void
+vlog_enable_async(void)
+{
+ ovs_mutex_lock(&log_file_mutex);
+ log_async = true;
+ if (log_fd >= 0 && !log_writer) {
+ log_writer = async_append_create(log_fd);
+ }
+ ovs_mutex_unlock(&log_file_mutex);
+}
+
/* Print the current logging level for each module. */
char *
vlog_get_levels(void)
ovs_mutex_lock(&log_file_mutex);
if (log_fd >= 0) {
- async_append_write(log_writer, s.string, s.length);
- if (level == VLL_EMER) {
- async_append_flush(log_writer);
+ if (log_writer) {
+ async_append_write(log_writer, s.string, s.length);
+ if (level == VLL_EMER) {
+ async_append_flush(log_writer);
+ }
+ } else {
+ ignore(write(log_fd, s.string, s.length));
}
}
ovs_mutex_unlock(&log_file_mutex);
/* Initialization. */
void vlog_init(void);
+void vlog_enable_async(void);
/* Functions for actual logging. */
void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...)
* process that forked us to exit successfully. */
daemonize_complete();
- async_append_enable();
+ vlog_enable_async();
VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION);
}