[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 1/6] xenconsoled: introduce log file abstraction
It will be used to handle hypervsior log and guest console log. Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx> --- tools/console/daemon/logfile.c | 229 +++++++++++++++++++++++++++++++++++++++++ tools/console/daemon/logfile.h | 57 ++++++++++ 2 files changed, 286 insertions(+) create mode 100644 tools/console/daemon/logfile.c create mode 100644 tools/console/daemon/logfile.h diff --git a/tools/console/daemon/logfile.c b/tools/console/daemon/logfile.c new file mode 100644 index 0000000..ad73f8e --- /dev/null +++ b/tools/console/daemon/logfile.c @@ -0,0 +1,229 @@ +/* + * Copyright (C) Citrix 2016 + * Author(s): Wei Liu <wei.liu2@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see <http://www.gnu.org/licenses/>. + */ +#define _GNU_SOURCE + +#include <fcntl.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "utils.h" +#include "logfile.h" + +static void logfile_entry_free(struct logfile_entry *entry) +{ + if (!entry) return; + + if (entry->fd >= 0) close(entry->fd); + free(entry); +} + +void logfile_free(struct logfile *f) +{ + if (!f) return; + + logfile_entry_free(f->entry); + + free(f->basepath); + free(f); +} + +static struct logfile_entry *logfile_entry_new(const char *path, mode_t mode) +{ + struct logfile_entry *entry; + struct stat sb; + + entry = calloc(1, sizeof(*entry)); + if (!entry) goto err; + + entry->fd = open(path, O_CREAT|O_APPEND|O_WRONLY|O_CLOEXEC, mode); + if (entry->fd < 0) { + dolog(LOG_ERR, "Failed to open log file %s", path); + goto err; + } + + entry->pos = lseek(entry->fd, 0, SEEK_END); + if (entry->pos == (off_t)-1) { + dolog(LOG_ERR, "Unable to determine current file offset in %s", + path); + goto err; + } + + if (fstat(entry->fd, &sb) < 0) { + dolog(LOG_ERR, "Unable to fstat current file %s", path); + goto err; + } + + entry->len = sb.st_size; + return entry; + +err: + logfile_entry_free(entry); + return NULL; +} + +struct logfile *logfile_new(const char *path, mode_t mode) +{ + struct logfile *logfile; + + logfile = calloc(1, sizeof(*logfile)); + if (!logfile) goto err; + + logfile->basepath = strdup(path); + if (!logfile->basepath) { + dolog(LOG_ERR, "Failed to strdup %s", path); + goto err; + } + + logfile->mode = mode; + logfile->maxlen = LOGFILE_MAX_SIZE; + + + logfile->entry = logfile_entry_new(logfile->basepath, mode); + + if (!logfile->entry) goto err; + + return logfile; +err: + logfile_free(logfile); + return NULL; +} + +static int logfile_rollover(struct logfile *file) +{ + struct logfile_entry *old = file->entry, *new = NULL; + char *this = NULL; + char *next = NULL; + unsigned i; + + if (asprintf(&next, "%s.%u", file->basepath, + LOGFILE_MAX_BACKUP_NUM) < 0) { + dolog(LOG_ERR, "Failed to asprintf %s.%u", + file->basepath, LOGFILE_MAX_BACKUP_NUM); + goto err; + } + + for (i = LOGFILE_MAX_BACKUP_NUM; i > 0; i--) { + if (i == 1) { + this = strdup(file->basepath); + if (!this) { + dolog(LOG_ERR, "Failed to strdup %s", + file->basepath); + goto err; + } + } else { + if (asprintf(&this, "%s.%u", file->basepath, i-1) < 0) { + dolog(LOG_ERR, "Failed to asprintf %s.%u", + file->basepath, i-1); + goto err; + } + } + + if (rename(this, next) < 0 && errno != ENOENT) { + dolog(LOG_ERR, "Failed to rename %s to %s", + this, next); + goto err; + } + + free(next); + next = this; + this = NULL; + } + + new = logfile_entry_new(file->basepath, file->mode); + if (!new) goto err; + + file->entry = new; + logfile_entry_free(old); + + return 0; +err: + free(this); + free(next); + return -1; +} + +static ssize_t write_all(int fd, const char* buf, size_t len) +{ + ssize_t written = 0; + while (len) { + ssize_t r = write(fd, buf, len); + if (r < 0 && errno == EINTR) + continue; + if (r < 0) + return r; + len -= r; + buf += r; + written += r; + } + + return written; +} + +ssize_t logfile_append(struct logfile *file, const char *buf, + size_t len) +{ + ssize_t ret = 0; + + while (len) { + struct logfile_entry *entry = file->entry; + size_t towrite = len; + bool rollover = false; + + if (entry->pos > file->maxlen) { + rollover = true; + towrite = 0; + } else if (entry->pos + towrite > file->maxlen) { + towrite = file->maxlen - entry->pos; + } + + if (towrite) { + if (write_all(entry->fd, buf, towrite) != towrite) { + dolog(LOG_ERR, "Unable to write file %s", + file->basepath); + return -1; + } + + len -= towrite; + buf += towrite; + ret += towrite; + entry->pos += towrite; + entry->len += towrite; + } + + if ((entry->pos == file->maxlen && len) || rollover) { + dolog(LOG_DEBUG, "Roll over %s (maxlen %zu)", + file->basepath, file->maxlen); + if (logfile_rollover(file)) + return -1; + } + } + + return ret; +} + + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ diff --git a/tools/console/daemon/logfile.h b/tools/console/daemon/logfile.h new file mode 100644 index 0000000..87f3c51 --- /dev/null +++ b/tools/console/daemon/logfile.h @@ -0,0 +1,57 @@ +/* + * Copyright (C) Citrix 2016 + * Author(s): Wei Liu <wei.liu2@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; under version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef XENCONSOLED_LOGFILE_H +#define XENCONSOLED_LOGFILE_H + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#define LOGFILE_MAX_BACKUP_NUM 5 +#define LOGFILE_MAX_SIZE (1024*128) + +/* Append only abstraction for log file */ +struct logfile_entry { + int fd; + off_t pos; + off_t len; +}; + +struct logfile { + char *basepath; + mode_t mode; + off_t maxlen; + struct logfile_entry *entry; +}; + +struct logfile *logfile_new(const char *path, mode_t mode); +void logfile_free(struct logfile *f); +ssize_t logfile_append(struct logfile *file, const char *buf, + size_t len); + +#endif /* XENCONSOLED_LOGFILE_H */ + +/* + * Local variables: + * c-file-style: "linux" + * indent-tabs-mode: t + * c-indent-level: 8 + * c-basic-offset: 8 + * tab-width: 8 + * End: + */ -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |