chiark / gitweb /
journal: abstract the resetting of JournalFile's location
[elogind.git] / src / journal / journal-file.c
index 6679ea46d6702514e55be367168f6e2cbf6aa522..8cbdbb9f9634557119011ec7c4ba1057c094ad43 100644 (file)
@@ -136,7 +136,7 @@ void journal_file_close(JournalFile *f) {
         if (f->mmap)
                 mmap_cache_unref(f->mmap);
 
-        hashmap_free_free(f->chain_cache);
+        ordered_hashmap_free_free(f->chain_cache);
 
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
         free(f->compress_buffer);
@@ -374,7 +374,13 @@ static int journal_file_allocate(JournalFile *f, uint64_t offset, uint64_t size)
         return 0;
 }
 
-static int journal_file_move_to(JournalFile *f, int context, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
+static unsigned type_to_context(ObjectType type) {
+        /* One context for each type, plus one catch-all for the rest */
+        assert_cc(_OBJECT_TYPE_MAX <= MMAP_CACHE_MAX_CONTEXTS);
+        return type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX ? type : 0;
+}
+
+static int journal_file_move_to(JournalFile *f, ObjectType type, bool keep_always, uint64_t offset, uint64_t size, void **ret) {
         assert(f);
         assert(ret);
 
@@ -391,7 +397,7 @@ static int journal_file_move_to(JournalFile *f, int context, bool keep_always, u
                         return -EADDRNOTAVAIL;
         }
 
-        return mmap_cache_get(f->mmap, f->fd, f->prot, context, keep_always, offset, size, &f->last_stat, ret);
+        return mmap_cache_get(f->mmap, f->fd, f->prot, type_to_context(type), keep_always, offset, size, &f->last_stat, ret);
 }
 
 static uint64_t minimum_header_size(Object *o) {
@@ -412,7 +418,7 @@ static uint64_t minimum_header_size(Object *o) {
         return table[o->object.type];
 }
 
-int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Object **ret) {
+int journal_file_move_to_object(JournalFile *f, ObjectType type, uint64_t offset, Object **ret) {
         int r;
         void *t;
         Object *o;
@@ -425,8 +431,7 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
         if (!VALID64(offset))
                 return -EFAULT;
 
-
-        r = journal_file_move_to(f, type_to_context(type), false, offset, sizeof(ObjectHeader), &t);
+        r = journal_file_move_to(f, type, false, offset, sizeof(ObjectHeader), &t);
         if (r < 0)
                 return r;
 
@@ -442,11 +447,11 @@ int journal_file_move_to_object(JournalFile *f, int type, uint64_t offset, Objec
         if (s < minimum_header_size(o))
                 return -EBADMSG;
 
-        if (type > 0 && o->object.type != type)
+        if (type > OBJECT_UNUSED && o->object.type != type)
                 return -EBADMSG;
 
         if (s > sizeof(ObjectHeader)) {
-                r = journal_file_move_to(f, o->object.type, false, offset, s, &t);
+                r = journal_file_move_to(f, type, false, offset, s, &t);
                 if (r < 0)
                         return r;
 
@@ -483,14 +488,14 @@ static uint64_t journal_file_entry_seqnum(JournalFile *f, uint64_t *seqnum) {
         return r;
 }
 
-int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object **ret, uint64_t *offset) {
+int journal_file_append_object(JournalFile *f, ObjectType type, uint64_t size, Object **ret, uint64_t *offset) {
         int r;
         uint64_t p;
         Object *tail, *o;
         void *t;
 
         assert(f);
-        assert(type > 0 && type < _OBJECT_TYPE_MAX);
+        assert(type > OBJECT_UNUSED && type < _OBJECT_TYPE_MAX);
         assert(size >= sizeof(ObjectHeader));
         assert(offset);
         assert(ret);
@@ -503,7 +508,7 @@ int journal_file_append_object(JournalFile *f, int type, uint64_t size, Object *
         if (p == 0)
                 p = le64toh(f->header->header_size);
         else {
-                r = journal_file_move_to_object(f, -1, p, &tail);
+                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &tail);
                 if (r < 0)
                         return r;
 
@@ -814,7 +819,8 @@ int journal_file_find_data_object_with_hash(
 
                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
-                        uint64_t l, rsize;
+                        uint64_t l;
+                        size_t rsize;
 
                         l = le64toh(o->object.size);
                         if (l <= offsetof(Object, data.payload))
@@ -979,7 +985,7 @@ static int journal_file_append_data(
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
         if (f->compress_xz &&
             size >= COMPRESSION_SIZE_THRESHOLD) {
-                uint64_t rsize;
+                size_t rsize;
 
                 compression = compress_blob(data, size, o->data.payload, &rsize);
 
@@ -987,7 +993,7 @@ static int journal_file_append_data(
                         o->object.size = htole64(offsetof(Object, data.payload) + rsize);
                         o->object.flags |= compression;
 
-                        log_debug("Compressed data object %"PRIu64" -> %"PRIu64" using %s",
+                        log_debug("Compressed data object %"PRIu64" -> %zu using %s",
                                   size, rsize, object_compressed_to_string(compression));
                 }
         }
@@ -1292,7 +1298,7 @@ void journal_file_post_change(JournalFile *f) {
         __sync_synchronize();
 
         if (ftruncate(f->fd, f->last_stat.st_size) < 0)
-                log_error("Failed to truncate file to its own size: %m");
+                log_error_errno(errno, "Failed to truncate file to its own size: %m");
 }
 
 static int entry_item_cmp(const void *_a, const void *_b) {
@@ -1366,7 +1372,7 @@ typedef struct ChainCacheItem {
 } ChainCacheItem;
 
 static void chain_cache_put(
-                Hashmap *h,
+                OrderedHashmap *h,
                 ChainCacheItem *ci,
                 uint64_t first,
                 uint64_t array,
@@ -1380,9 +1386,10 @@ static void chain_cache_put(
                 if (array == first)
                         return;
 
-                if (hashmap_size(h) >= CHAIN_CACHE_MAX)
-                        ci = hashmap_steal_first(h);
-                else {
+                if (ordered_hashmap_size(h) >= CHAIN_CACHE_MAX) {
+                        ci = ordered_hashmap_steal_first(h);
+                        assert(ci);
+                } else {
                         ci = new(ChainCacheItem, 1);
                         if (!ci)
                                 return;
@@ -1390,7 +1397,7 @@ static void chain_cache_put(
 
                 ci->first = first;
 
-                if (hashmap_put(h, &ci->first, ci) < 0) {
+                if (ordered_hashmap_put(h, &ci->first, ci) < 0) {
                         free(ci);
                         return;
                 }
@@ -1419,7 +1426,7 @@ static int generic_array_get(
         a = first;
 
         /* Try the chain cache first */
-        ci = hashmap_get(f->chain_cache, &first);
+        ci = ordered_hashmap_get(f->chain_cache, &first);
         if (ci && i > ci->total) {
                 a = ci->array;
                 i -= ci->total;
@@ -1522,7 +1529,7 @@ static int generic_array_bisect(
         /* Start with the first array in the chain */
         a = first;
 
-        ci = hashmap_get(f->chain_cache, &first);
+        ci = ordered_hashmap_get(f->chain_cache, &first);
         if (ci && n > ci->total) {
                 /* Ah, we have iterated this bisection array chain
                  * previously! Let's see if we can skip ahead in the
@@ -1656,7 +1663,7 @@ static int generic_array_bisect(
                         }
                 }
 
-                if (k > n) {
+                if (k >= n) {
                         if (direction == DIRECTION_UP) {
                                 i = n;
                                 subtract_one = true;
@@ -1792,23 +1799,6 @@ _pure_ static int test_object_offset(JournalFile *f, uint64_t p, uint64_t needle
                 return TEST_RIGHT;
 }
 
-int journal_file_move_to_entry_by_offset(
-                JournalFile *f,
-                uint64_t p,
-                direction_t direction,
-                Object **ret,
-                uint64_t *offset) {
-
-        return generic_array_bisect(f,
-                                    le64toh(f->header->entry_array_offset),
-                                    le64toh(f->header->n_entries),
-                                    p,
-                                    test_object_offset,
-                                    direction,
-                                    ret, offset, NULL);
-}
-
-
 static int test_object_seqnum(JournalFile *f, uint64_t p, uint64_t needle) {
         Object *o;
         int r;
@@ -1938,6 +1928,10 @@ int journal_file_move_to_entry_by_monotonic(
                                              ret, offset, NULL);
 }
 
+void journal_file_reset_location(JournalFile *f) {
+        f->current_offset = 0;
+}
+
 int journal_file_next_entry(
                 JournalFile *f,
                 Object *o, uint64_t p,
@@ -2005,55 +1999,6 @@ int journal_file_next_entry(
         return 1;
 }
 
-int journal_file_skip_entry(
-                JournalFile *f,
-                Object *o, uint64_t p,
-                int64_t skip,
-                Object **ret, uint64_t *offset) {
-
-        uint64_t i, n;
-        int r;
-
-        assert(f);
-        assert(o);
-        assert(p > 0);
-
-        if (o->object.type != OBJECT_ENTRY)
-                return -EINVAL;
-
-        r = generic_array_bisect(f,
-                                 le64toh(f->header->entry_array_offset),
-                                 le64toh(f->header->n_entries),
-                                 p,
-                                 test_object_offset,
-                                 DIRECTION_DOWN,
-                                 NULL, NULL,
-                                 &i);
-        if (r <= 0)
-                return r;
-
-        /* Calculate new index */
-        if (skip < 0) {
-                if ((uint64_t) -skip >= i)
-                        i = 0;
-                else
-                        i = i - (uint64_t) -skip;
-        } else
-                i  += (uint64_t) skip;
-
-        n = le64toh(f->header->n_entries);
-        if (n <= 0)
-                return -EBADMSG;
-
-        if (i >= n)
-                i = n-1;
-
-        return generic_array_get(f,
-                                 le64toh(f->header->entry_array_offset),
-                                 i,
-                                 ret, offset);
-}
-
 int journal_file_next_entry_for_data(
                 JournalFile *f,
                 Object *o, uint64_t p,
@@ -2288,7 +2233,7 @@ void journal_file_dump(JournalFile *f) {
 
         p = le64toh(f->header->header_size);
         while (p != 0) {
-                r = journal_file_move_to_object(f, -1, p, &o);
+                r = journal_file_move_to_object(f, OBJECT_UNUSED, p, &o);
                 if (r < 0)
                         goto fail;
 
@@ -2498,7 +2443,7 @@ int journal_file_open(
                 goto fail;
         }
 
-        f->chain_cache = hashmap_new(uint64_hash_func, uint64_compare_func);
+        f->chain_cache = ordered_hashmap_new(&uint64_hash_ops);
         if (!f->chain_cache) {
                 r = -ENOMEM;
                 goto fail;
@@ -2526,7 +2471,7 @@ int journal_file_open(
                  * currently no usable API to query this, hence let's
                  * emulate this via extended attributes. If extended
                  * attributes are not supported we'll just skip this,
-                 * and rely solely on mtime/atime/ctime of the file.*/
+                 * and rely solely on mtime/atime/ctime of the file. */
 
                 crtime = htole64((uint64_t) now(CLOCK_REALTIME));
                 fsetxattr(f->fd, "user.crtime_usec", &crtime, sizeof(crtime), XATTR_CREATE);
@@ -2770,7 +2715,7 @@ int journal_file_copy_entry(JournalFile *from, JournalFile *to, Object *o, uint6
 
                 if (o->object.flags & OBJECT_COMPRESSION_MASK) {
 #if defined(HAVE_XZ) || defined(HAVE_LZ4)
-                        uint64_t rsize;
+                        size_t rsize;
 
                         r = decompress_blob(o->object.flags & OBJECT_COMPRESSION_MASK,
                                             o->data.payload, l, &from->compress_buffer, &from->compress_buffer_size, &rsize, 0);