CTRL_SRCS-y += xc_mem_event.c
CTRL_SRCS-y += xc_mem_paging.c
CTRL_SRCS-y += xc_memshr.c
+CTRL_SRCS-y += xtl_core.c
+CTRL_SRCS-y += xtl_logger_stdio.c
CTRL_SRCS-$(CONFIG_X86) += xc_pagetab.c
CTRL_SRCS-$(CONFIG_Linux) += xc_linux.c
CTRL_SRCS-$(CONFIG_SunOS) += xc_solaris.c
$(INSTALL_DATA) libxenctrl.a $(DESTDIR)$(LIBDIR)
ln -sf libxenctrl.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so.$(MAJOR)
ln -sf libxenctrl.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libxenctrl.so
- $(INSTALL_DATA) xenctrl.h $(DESTDIR)$(INCLUDEDIR)
-
+ $(INSTALL_DATA) xenctrl.h xentoollog.h $(DESTDIR)$(INCLUDEDIR)
$(INSTALL_PROG) libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)
$(INSTALL_DATA) libxenguest.a $(DESTDIR)$(LIBDIR)
ln -sf libxenguest.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libxenguest.so.$(MAJOR)
--- /dev/null
+/*
+ * xentoollog.h
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ */
+
+#ifndef XENTOOLLOG_H
+#define XENTOOLLOG_H
+
+#include <stdio.h>
+#include <stdarg.h>
+
+
+/*---------- common declarations and types ----------*/
+
+typedef enum xentoollog_level {
+ XTL_NONE, /* sentinel etc, never used for logging */
+ XTL_DEBUG,
+ XTL_VERBOSE,
+ XTL_DETAIL,
+ XTL_PROGRESS, /* also used for "progress" messages */
+ XTL_INFO,
+ XTL_NOTICE,
+ XTL_WARN,
+ XTL_ERROR,
+ XTL_CRITICAL,
+ XTL_NUM_LEVELS
+} xentoollog_level;
+
+typedef struct xentoollog_logger xentoollog_logger;
+struct xentoollog_logger {
+ void (*vmessage)(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xl", may be 0 */,
+ const char *format /* without level, context, \n */,
+ va_list al)
+ __attribute__((format(printf,5,0)));
+ void (*progress)(struct xentoollog_logger *logger,
+ const char *context /* see above */,
+ const char *doing_what /* no \r,\n */,
+ int percent, unsigned long done, unsigned long total)
+ /* null function pointer is ok.
+ * will always be called with done==0 for each new
+ * context/doing_what */;
+ void (*destroy)(struct xentoollog_logger *logger);
+ /* each logger can put its necessary data here */
+};
+
+
+/*---------- facilities for consuming log messages ----------*/
+
+#define XTL_STDIOSTREAM_SHOW_PID 01u
+#define XTL_STDIOSTREAM_SHOW_DATE 02u
+
+typedef struct xentoollog_logger_stdiostream xentoollog_logger_stdiostream;
+
+xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
+ (FILE *f, xentoollog_level min_level, unsigned flags);
+ /* may return 0 if malloc fails, in which case error was logged */
+ /* destroy on this logger does not close the file */
+
+void xtl_logger_destroy(struct xentoollog_logger *logger /* 0 is ok */);
+
+
+/*---------- facilities for generating log messages ----------*/
+
+void xtl_logv(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl", may be 0 */,
+ const char *format /* does not contain \n */,
+ va_list) __attribute__((format(printf,5,0)));
+
+void xtl_log(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl" */,
+ const char *format /* does not contain \n */,
+ ...) __attribute__((format(printf,5,6)));
+
+void xtl_progress(struct xentoollog_logger *logger,
+ const char *context /* see above, may be 0 */,
+ const char *doing_what,
+ unsigned long done, unsigned long total);
+
+
+/*---------- facilities for defining log message consumers ----------*/
+
+const char *xtl_level_to_string(xentoollog_level); /* never fails */
+
+
+#define XTL_NEW_LOGGER(LOGGER,buffer) ({ \
+ xentoollog_logger_##LOGGER *new_consumer; \
+ \
+ (buffer).vtable.vmessage = LOGGER##_vmessage; \
+ (buffer).vtable.progress = LOGGER##_progress; \
+ (buffer).vtable.destroy = LOGGER##_destroy; \
+ \
+ new_consumer = malloc(sizeof(*new_consumer)); \
+ if (!new_consumer) { \
+ xtl_log((xentoollog_logger*)&buffer, \
+ XTL_CRITICAL, errno, "xtl", \
+ "failed to allocate memory for new message logger"); \
+ } else { \
+ *new_consumer = buffer; \
+ } \
+ \
+ new_consumer; \
+});
+
+
+#endif /* XENTOOLLOG_H */
--- /dev/null
+/*
+ * xtl_core.c
+ *
+ * core code including functions for generating log messages
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ */
+
+#include "xentoollog.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+
+static const char *level_strings[XTL_NUM_LEVELS]= {
+ "[BUG:XTL_NONE]",
+ "debug", "verbose", "detail", /* normally off by default */
+ "progress", "info", "notice", /* not a problem */
+ "warning", "error", "critical" /* problems and errors */
+};
+
+const char *xtl_level_to_string(xentoollog_level level) {
+ assert(level >= 0 && level < XTL_NUM_LEVELS);
+ return level_strings[level];
+}
+
+void xtl_logv(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl" */,
+ const char *format /* does not contain \n */,
+ va_list al) {
+ int errno_save = errno;
+ assert(level > XTL_NONE && level < XTL_NUM_LEVELS);
+ logger->vmessage(logger,level,errnoval,context,format,al);
+ errno = errno_save;
+}
+
+void xtl_log(struct xentoollog_logger *logger,
+ xentoollog_level level,
+ int errnoval /* or -1 */,
+ const char *context /* eg "xc", "xenstore", "xl" */,
+ const char *format /* does not contain \n */,
+ ...) {
+ va_list al;
+ va_start(al,format);
+ xtl_logv(logger,level,errnoval,context,format,al);
+ va_end(al);
+}
+
+void xtl_progress(struct xentoollog_logger *logger,
+ const char *context, const char *doing_what,
+ unsigned long done, unsigned long total) {
+ int percent;
+
+ if (!logger->progress) return;
+
+ percent = (total < LONG_MAX/100)
+ ? (done * 100) / total
+ : done / ((total + 99) / 100);
+
+ logger->progress(logger, context, doing_what, percent, done, total);
+}
+
+void xtl_logger_destroy(struct xentoollog_logger *logger) {
+ if (!logger) return;
+ logger->destroy(logger);
+}
--- /dev/null
+/*
+ * xtl_logger_stdio.c
+ *
+ * log message consumer that writes to stdio
+ *
+ * Copyright (c) 2010 Citrix
+ * Part of a generic logging interface used by various dom0 userland libraries.
+ */
+
+#include "xentoollog.h"
+
+#include <time.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+struct xentoollog_logger_stdiostream {
+ xentoollog_logger vtable;
+ FILE *f;
+ xentoollog_level min_level;
+ unsigned flags;
+ int progress_erase_len, progress_last_percent;
+};
+
+static void progress_erase(xentoollog_logger_stdiostream *lg) {
+ if (lg->progress_erase_len)
+ fprintf(lg->f, "\r%*s\r", lg->progress_erase_len, "");
+}
+
+static void stdiostream_vmessage(xentoollog_logger *logger_in,
+ xentoollog_level level,
+ int errnoval,
+ const char *context,
+ const char *format,
+ va_list al) {
+ xentoollog_logger_stdiostream *lg = (void*)logger_in;
+
+ progress_erase(lg);
+
+ if (lg->flags & XTL_STDIOSTREAM_SHOW_DATE) {
+ struct tm lt_buf;
+ time_t now = time(0);
+ struct tm *lt= localtime_r(&now, <_buf);
+ fprintf(lg->f, "%04d-%02d-%02d %02d:%02d:%02d %s ",
+ lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
+ lt->tm_hour, lt->tm_min, lt->tm_sec,
+ tzname[daylight ? !!lt->tm_isdst : 0]);
+ }
+ if (lg->flags & XTL_STDIOSTREAM_SHOW_PID)
+ fprintf(lg->f, "[%lu] ", (unsigned long)getpid());
+
+ if (context)
+ fprintf(lg->f, "%s: ", context);
+
+ fprintf(lg->f, "%s: ", xtl_level_to_string(level));
+
+ vfprintf(lg->f, format, al);
+
+ if (errnoval >= 0)
+ vfprintf(lg->f, ": %s", strerror(errnoval));
+
+ putc('\n', lg->f);
+ fflush(lg->f);
+}
+
+static void stdiostream_progress(struct xentoollog_logger *logger_in,
+ const char *context,
+ const char *doing_what, int percent,
+ unsigned long done, unsigned long total) {
+ xentoollog_logger_stdiostream *lg = (void*)logger_in;
+ int newpel, extra_erase;
+ xentoollog_level this_level;
+
+ if (percent < lg->progress_last_percent) {
+ this_level = XTL_PROGRESS;
+ } else if (percent == lg->progress_last_percent) {
+ return;
+ } else if (percent < lg->progress_last_percent + 5) {
+ this_level = XTL_DETAIL;
+ } else {
+ this_level = XTL_PROGRESS;
+ }
+
+ if (lg->min_level < this_level)
+ return;
+
+ if (lg->progress_erase_len)
+ putc('\r', lg->f);
+
+ newpel = fprintf(lg->f, "%s%s" "%s: %lu/%lu %3d%%",
+ context?context:"", context?": ":"",
+ doing_what, done, total, percent);
+
+ extra_erase = lg->progress_erase_len - newpel;
+ if (extra_erase > 0)
+ fprintf(lg->f, "%*s\r", extra_erase, "");
+
+ lg->progress_erase_len = newpel;
+}
+
+static void stdiostream_destroy(struct xentoollog_logger *logger_in) {
+ xentoollog_logger_stdiostream *lg = (void*)logger_in;
+ progress_erase(lg);
+ free(lg);
+}
+
+
+xentoollog_logger_stdiostream *xtl_createlogger_stdiostream
+ (FILE *f, xentoollog_level min_level, unsigned flags) {
+ xentoollog_logger_stdiostream newlogger;
+
+ newlogger.f = f;
+ newlogger.min_level = min_level;
+ newlogger.flags = flags;
+
+ if (newlogger.flags & XTL_STDIOSTREAM_SHOW_DATE) tzset();
+
+ newlogger.progress_erase_len = 0;
+
+ return XTL_NEW_LOGGER(stdiostream, newlogger);
+}