detach_location(j);
}
-static int compare_order(JournalFile *af, Object *ao,
- JournalFile *bf, Object *bo) {
+static int compare_entry_order(JournalFile *af, Object *_ao,
+ JournalFile *bf, uint64_t bp) {
uint64_t a, b;
+ Object *ao, *bo;
+ int r;
assert(af);
- assert(ao);
assert(bf);
- assert(bo);
+ assert(_ao);
+
+ /* The mmap cache might invalidate the object from the first
+ * file if we look at the one from the second file. Hence
+ * temporarily copy the header of the first one, and look at
+ * that only. */
+ ao = alloca(offsetof(EntryObject, items));
+ memcpy(ao, _ao, offsetof(EntryObject, items));
+
+ r = journal_file_move_to_object(bf, OBJECT_ENTRY, bp, &bo);
+ if (r < 0)
+ return strcmp(af->path, bf->path);
/* We operate on two different files here, hence we can access
* two objects at the same time, which we normally can't.
}
static int real_journal_next(sd_journal *j, direction_t direction) {
- JournalFile *f, *new_current = NULL;
+ JournalFile *f, *new_file = NULL;
+ uint64_t new_offset = 0;
+ Object *o;
+ uint64_t p;
Iterator i;
int r;
- uint64_t new_offset = 0;
- Object *new_entry = NULL;
if (!j)
return -EINVAL;
HASHMAP_FOREACH(f, j->files, i) {
- Object *o;
- uint64_t p;
bool found;
r = next_beyond_location(j, f, direction, &o, &p);
} else if (r == 0)
continue;
- if (!new_current)
+ if (!new_file)
found = true;
else {
int k;
- k = compare_order(f, o, new_current, new_entry);
+ k = compare_entry_order(f, o, new_file, new_offset);
if (direction == DIRECTION_DOWN)
found = k < 0;
}
if (found) {
- new_current = f;
- new_entry = o;
+ new_file = f;
new_offset = p;
}
}
- if (!new_current)
+ if (!new_file)
return 0;
- set_location(j, new_current, new_entry, new_offset);
+ r = journal_file_move_to_object(new_file, OBJECT_ENTRY, new_offset, &o);
+ if (r < 0)
+ return r;
+
+ set_location(j, new_file, o, new_offset);
return 1;
}
if ((j->flags & SD_JOURNAL_SYSTEM_ONLY) &&
!(streq(filename, "system.journal") ||
- (startswith(filename, "system@") && endswith(filename, ".journal"))))
+ streq(filename, "system.journal~") ||
+ (startswith(filename, "system@") &&
+ (endswith(filename, ".journal") || endswith(filename, ".journal~")))))
return 0;
path = strjoin(prefix, "/", filename, NULL);
return 0;
}
- r = journal_file_open(path, O_RDONLY, 0, NULL, NULL, &f);
+ r = journal_file_open(path, O_RDONLY, 0, false, false, NULL, j->mmap, NULL, &f);
free(path);
if (r < 0) {
m->wd = inotify_add_watch(j->inotify_fd, m->path,
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
IN_DELETE_SELF|IN_MOVE_SELF|IN_UNMOUNT|
- IN_DONT_FOLLOW|IN_ONLYDIR);
+ IN_ONLYDIR);
if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
inotify_rm_watch(j->inotify_fd, m->wd);
}
for (;;) {
- struct dirent buf, *de;
+ struct dirent *de;
+ union dirent_storage buf;
- r = readdir_r(d, &buf, &de);
+ r = readdir_r(d, &buf.de, &de);
if (r != 0 || !de)
break;
- if (dirent_is_file_with_suffix(de, ".journal")) {
+ if (dirent_is_file_with_suffix(de, ".journal") ||
+ dirent_is_file_with_suffix(de, ".journal~")) {
r = add_file(j, m->path, de->d_name);
if (r < 0)
log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
m->wd = inotify_add_watch(j->inotify_fd, m->path,
IN_CREATE|IN_MOVED_TO|IN_MODIFY|IN_ATTRIB|IN_DELETE|
- IN_DONT_FOLLOW|IN_ONLYDIR);
+ IN_ONLYDIR);
if (m->wd > 0 && hashmap_put(j->directories_by_wd, INT_TO_PTR(m->wd), m) < 0)
inotify_rm_watch(j->inotify_fd, m->wd);
}
for (;;) {
- struct dirent buf, *de;
+ struct dirent *de;
+ union dirent_storage buf;
sd_id128_t id;
- r = readdir_r(d, &buf, &de);
+ r = readdir_r(d, &buf.de, &de);
if (r != 0 || !de)
break;
- if (dirent_is_file_with_suffix(de, ".journal")) {
+ if (dirent_is_file_with_suffix(de, ".journal") ||
+ dirent_is_file_with_suffix(de, ".journal~")) {
r = add_file(j, m->path, de->d_name);
if (r < 0)
log_debug("Failed to add file %s/%s: %s", m->path, de->d_name, strerror(-r));
- } else if ((de->d_type == DT_DIR || de->d_type == DT_UNKNOWN) &&
+ } else if ((de->d_type == DT_DIR || de->d_type == DT_LNK || de->d_type == DT_UNKNOWN) &&
sd_id128_from_string(de->d_name, &id) >= 0) {
r = add_directory(j, m->path, de->d_name);
return 0;
}
-static sd_journal *journal_new(int flags) {
+static sd_journal *journal_new(int flags, const char *path) {
sd_journal *j;
j = new0(sd_journal, 1);
j->inotify_fd = -1;
j->flags = flags;
+ if (path) {
+ j->path = strdup(path);
+ if (!j->path) {
+ free(j);
+ return NULL;
+ }
+ }
+
j->files = hashmap_new(string_hash_func, string_compare_func);
if (!j->files) {
+ free(j->path);
free(j);
return NULL;
}
j->directories_by_path = hashmap_new(string_hash_func, string_compare_func);
if (!j->directories_by_path) {
hashmap_free(j->files);
+ free(j->path);
+ free(j);
+ return NULL;
+ }
+
+ j->mmap = mmap_cache_new();
+ if (!j->mmap) {
+ hashmap_free(j->files);
+ hashmap_free(j->directories_by_path);
+ free(j->path);
free(j);
return NULL;
}
SD_JOURNAL_SYSTEM_ONLY))
return -EINVAL;
- j = journal_new(flags);
+ j = journal_new(flags, NULL);
if (!j)
return -ENOMEM;
if (flags != 0)
return -EINVAL;
- j = journal_new(flags);
+ j = journal_new(flags, path);
if (!j)
return -ENOMEM;
sd_journal_flush_matches(j);
+ if (j->mmap)
+ mmap_cache_unref(j->mmap);
+
+ free(j->path);
free(j);
}
/* Iterate through all dirs again, to add them to the
* inotify */
- r = add_search_paths(j);
+ if (j->path)
+ r = add_root_directory(j, j->path);
+ else
+ r = add_search_paths(j);
if (r < 0)
return r;
if (d) {
sd_id128_t id;
- if (!(e->mask & IN_ISDIR) && e->len > 0 && endswith(e->name, ".journal")) {
+ if (!(e->mask & IN_ISDIR) && e->len > 0 &&
+ (endswith(e->name, ".journal") ||
+ endswith(e->name, ".journal~"))) {
/* Event for a journal file */
}
}
+_public_ int sd_journal_get_usage(sd_journal *j, uint64_t *bytes) {
+ Iterator i;
+ JournalFile *f;
+ uint64_t sum = 0;
+
+ if (!j)
+ return -EINVAL;
+ if (!bytes)
+ return -EINVAL;
+
+ HASHMAP_FOREACH(f, j->files, i) {
+ struct stat st;
+
+ if (fstat(f->fd, &st) < 0)
+ return -errno;
+
+ sum += (uint64_t) st.st_blocks * 512ULL;
+ }
+
+ *bytes = sum;
+ return 0;
+}
+
/* _public_ int sd_journal_query_unique(sd_journal *j, const char *field) { */
/* if (!j) */
/* return -EINVAL; */