static gboolean _save_queue (LogQueueDisk *s, gboolean *persistent) { LogQueueDiskNonReliable *self = (LogQueueDiskNonReliable *) s; if (qdisk_save_state (s->qdisk, self->qout, self->qbacklog, self->qoverflow)) { *persistent = TRUE; qdisk_deinit (s->qdisk); return TRUE; } return FALSE; }
gboolean qdisk_start(QDisk *self, const gchar *filename, GQueue *qout, GQueue *qbacklog, GQueue *qoverflow) { gboolean new_file = FALSE; gpointer p = NULL; int openflags = 0; /* * If qdisk_start is called for already initialized qdisk file * it can cause message loosing. * We need this assert to detect programming error as soon as possible. */ g_assert(!qdisk_initialized(self)); if (self->options->disk_buf_size <= 0) return TRUE; if (self->options->read_only && !filename) return FALSE; if (!filename) { new_file = TRUE; /* NOTE: this'd be a security problem if we were not in our private directory. But we are. */ filename = _next_filename(self); } else { struct stat st; if (stat(filename,&st) == -1) { new_file = TRUE; } } self->filename = g_strdup(filename); /* assumes self is zero initialized */ openflags = self->options->read_only ? (O_RDONLY | O_LARGEFILE) : (O_RDWR | O_LARGEFILE | (new_file ? O_CREAT : 0)); self->fd = open(filename, openflags, 0600); if (self->fd < 0) { msg_error("Error opening disk-queue file", evt_tag_str("filename", self->filename), evt_tag_errno("error", errno)); return FALSE; } p = mmap(0, sizeof(QDiskFileHeader), self->options->read_only ? (PROT_READ) : (PROT_READ | PROT_WRITE), MAP_SHARED, self->fd, 0); if (p == MAP_FAILED) { msg_error("Error returned by mmap", evt_tag_errno("errno", errno), evt_tag_str("filename", self->filename)); return FALSE; } else { madvise(p, sizeof(QDiskFileHeader), MADV_RANDOM); } if (self->options->read_only) { self->hdr = g_malloc(sizeof(QDiskFileHeader)); memcpy(self->hdr, p, sizeof(QDiskFileHeader)); munmap(p, sizeof(QDiskFileHeader) ); p = NULL; } else { self->hdr = p; } /* initialize new file */ if (new_file) { QDiskFileHeader tmp; memset(&tmp, 0, sizeof(tmp)); if (!pwrite_strict(self->fd, &tmp, sizeof(tmp), 0)) { msg_error("Error occured while initalizing the new queue file",evt_tag_str("filename",self->filename),evt_tag_errno("error",errno)); munmap((void *)self->hdr, sizeof(QDiskFileHeader)); self->hdr = NULL; close(self->fd); self->fd = -1; return FALSE; } self->hdr->version = 1; self->hdr->big_endian = (G_BYTE_ORDER == G_BIG_ENDIAN); self->hdr->read_head = QDISK_RESERVED_SPACE; self->hdr->write_head = QDISK_RESERVED_SPACE; self->hdr->backlog_head = self->hdr->read_head; self->hdr->length = 0; if (!qdisk_save_state(self, qout, qbacklog, qoverflow)) { munmap((void *)self->hdr, sizeof(QDiskFileHeader)); self->hdr = NULL; close(self->fd); self->fd = -1; return FALSE; } } else { struct stat st; if (fstat(self->fd, &st) != 0 || st.st_size == 0) { msg_error("Error loading disk-queue file", evt_tag_str("filename", self->filename), evt_tag_errno("fstat error", errno), evt_tag_int("size", st.st_size)); munmap((void *)self->hdr, sizeof(QDiskFileHeader)); self->hdr = NULL; close(self->fd); self->fd = -1; return FALSE; } if (self->hdr->version == 0) { self->hdr->big_endian = TRUE; self->hdr->version = 1; self->hdr->backlog_head = self->hdr->read_head; self->hdr->backlog_len = 0; } if ((self->hdr->big_endian && G_BYTE_ORDER == G_LITTLE_ENDIAN) || (!self->hdr->big_endian && G_BYTE_ORDER == G_BIG_ENDIAN)) { self->hdr->read_head = GUINT64_SWAP_LE_BE(self->hdr->read_head); self->hdr->write_head = GUINT64_SWAP_LE_BE(self->hdr->write_head); self->hdr->length = GUINT64_SWAP_LE_BE(self->hdr->length); self->hdr->qout_ofs = GUINT64_SWAP_LE_BE(self->hdr->qout_ofs); self->hdr->qout_len = GUINT32_SWAP_LE_BE(self->hdr->qout_len); self->hdr->qout_count = GUINT32_SWAP_LE_BE(self->hdr->qout_count); self->hdr->qbacklog_ofs = GUINT64_SWAP_LE_BE(self->hdr->qbacklog_ofs); self->hdr->qbacklog_len = GUINT32_SWAP_LE_BE(self->hdr->qbacklog_len); self->hdr->qbacklog_count = GUINT32_SWAP_LE_BE(self->hdr->qbacklog_count); self->hdr->qoverflow_ofs = GUINT64_SWAP_LE_BE(self->hdr->qoverflow_ofs); self->hdr->qoverflow_len = GUINT32_SWAP_LE_BE(self->hdr->qoverflow_len); self->hdr->qoverflow_count = GUINT32_SWAP_LE_BE(self->hdr->qoverflow_count); self->hdr->backlog_head = GUINT64_SWAP_LE_BE(self->hdr->backlog_head); self->hdr->backlog_len = GUINT64_SWAP_LE_BE(self->hdr->backlog_len); self->hdr->big_endian = (G_BYTE_ORDER == G_BIG_ENDIAN); } if (!_load_state(self, qout, qbacklog, qoverflow)) { munmap((void *)self->hdr, sizeof(QDiskFileHeader)); self->hdr = NULL; close(self->fd); self->fd = -1; return FALSE; } } return TRUE; }