Add a common, internal CTF serialization library; make CTF writer use it
authorPhilippe Proulx <eeppeliteloop@gmail.com>
Tue, 5 Mar 2019 20:10:17 +0000 (15:10 -0500)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Thu, 2 May 2019 20:50:15 +0000 (20:50 +0000)
This patch adds the `bt_ctfser` API and implementation, a generic,
common, and internal CTF stream file serialization library. This patch
also makes CTF writer use this library instead of its internal
serialization API (on which `bt_ctfser` is based). The purpose of this
partition is to make the `sink.ctf.fs` component class depend on
`bt_ctfser` without depending on CTF writer (as the trace IR and the CTF
writer IR objects are not compatible anymore) while still reusing code.

After initializing a `struct bt_ctfser` with bt_ctfser_init(), you need
to call bt_ctfser_open_packet() to open a packet, then call one of the
bt_ctfser_write_*() functions to write individual fields or
bt_ctfser_align_offset_in_current_packet() to align the offset within
the current packet. The serialization and alignment functions resize the
current packet as needed, which is why they can fail if resizing is not
possible. Then call bt_ctfser_close_current_packet() with the required
packet size. Repeat for each packet to append to the stream file. When
done, call bt_ctfser_fini(). bt_ctfser_fini() truncates the stream file
as needed to remove any data after the last closed packet.

It is common for the packet context to be written after writing the
last event record because this is when you know the effective content
size. For this, the bt_ctfser_get_offset_in_current_packet_bits()
and bt_ctfser_set_offset_in_current_packet_bits() functions exist to
control the current offset within the current packet. The typical
packet writing algorithm is:

1. Open the packet.
2. Write the packet header.
3. Save the current offset (packet context offset).
4. Write the packet context, potentially with wrong/incomplete fields.
5. Write each event record.
6. Get the current offset which is the packet's content size, and also
   decide on a packet's total size (greater than content size).
7. Go to the (saved) packet context offset.
8. Write the packet context with updated fields.

Fast path serialization and alignment functions are `static inline`.

There is minimal verbose logging which always indicate the stream file's
path and its numeric descriptor.

Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
19 files changed:
Makefile.am
configure.ac
ctfser/Makefile.am [new file with mode: 0644]
ctfser/ctfser.c [new file with mode: 0644]
ctfser/logging.c [new file with mode: 0644]
ctfser/logging.h [new file with mode: 0644]
include/Makefile.am
include/babeltrace/ctf-writer/event-internal.h
include/babeltrace/ctf-writer/fields-internal.h
include/babeltrace/ctf-writer/serialize-internal.h [deleted file]
include/babeltrace/ctf-writer/stream-internal.h
include/babeltrace/ctfser-internal.h [new file with mode: 0644]
lib/Makefile.am
lib/ctf-writer/Makefile.am
lib/ctf-writer/event.c
lib/ctf-writer/fields.c
lib/ctf-writer/serialize.c [deleted file]
lib/ctf-writer/stream.c
lib/ctf-writer/writer.c

index eb6831a2b16a308835d6c5fcd7a9de081c494d1f..76114749790e84f555bae56c326c35dc666d4ed4 100644 (file)
@@ -2,6 +2,7 @@ ACLOCAL_AMFLAGS = -I m4
 
 SUBDIRS = include              \
        common                  \
+       ctfser                  \
        compat                  \
        logging                 \
        lib
index ce51dbeddd8bfe57c24b363411eee24f883804f4..6426e574d1c1529f318b2dc197a950e3047d426b 100644 (file)
@@ -729,6 +729,7 @@ AC_CONFIG_FILES([
        bindings/python/bt2/setup.py
        bindings/python/bt2/bt2/__init__.py
        common/Makefile
+       ctfser/Makefile
        compat/Makefile
        cli/Makefile
        doc/Makefile
diff --git a/ctfser/Makefile.am b/ctfser/Makefile.am
new file mode 100644 (file)
index 0000000..21e605a
--- /dev/null
@@ -0,0 +1,5 @@
+AM_CPPFLAGS += -DINSTALL_LIBDIR=\"$(libdir)\"
+
+noinst_LTLIBRARIES = libbabeltrace-ctfser.la
+
+libbabeltrace_ctfser_la_SOURCES = ctfser.c logging.c logging.h
diff --git a/ctfser/ctfser.c b/ctfser/ctfser.c
new file mode 100644 (file)
index 0000000..e06972b
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2019 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_TAG "CTFSER"
+#include "logging.h"
+
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <babeltrace/assert-internal.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <stdbool.h>
+#include <babeltrace/babeltrace-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/ctfser-internal.h>
+#include <babeltrace/compat/unistd-internal.h>
+#include <babeltrace/compat/fcntl-internal.h>
+
+static inline
+uint64_t get_packet_size_increment_bytes(void)
+{
+       return bt_common_get_page_size() * 8;
+}
+
+static inline
+void mmap_align_ctfser(struct bt_ctfser *ctfser)
+{
+       ctfser->base_mma = mmap_align(ctfser->cur_packet_size_bytes, PROT_WRITE,
+               MAP_SHARED, ctfser->fd, ctfser->mmap_offset);
+}
+
+BT_HIDDEN
+int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser *ctfser)
+{
+       int ret;
+
+       BT_ASSERT(ctfser);
+       BT_LOGV("Increasing stream file's current packet size: "
+               "path=\"%s\", fd=%d, "
+               "offset-in-cur-packet-bits=%" PRIu64 ", "
+               "cur-packet-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->offset_in_cur_packet_bits,
+               ctfser->cur_packet_size_bytes);
+       ret = munmap_align(ctfser->base_mma);
+       if (ret) {
+               BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
+                       ": ret=%d", ret);
+               goto end;
+       }
+
+       ctfser->cur_packet_size_bytes += get_packet_size_increment_bytes();
+
+       do {
+               ret = bt_posix_fallocate(ctfser->fd, ctfser->mmap_offset,
+                       ctfser->cur_packet_size_bytes);
+       } while (ret == EINTR);
+
+       if (ret) {
+               BT_LOGE("Failed to preallocate memory space: ret=%d", ret);
+               goto end;
+       }
+
+       mmap_align_ctfser(ctfser);
+       if (ctfser->base_mma == MAP_FAILED) {
+               BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
+                       ": ret=%d", ret);
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Increased packet size: "
+               "path=\"%s\", fd=%d, "
+               "offset-in-cur-packet-bits=%" PRIu64 ", "
+               "new-packet-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->offset_in_cur_packet_bits,
+               ctfser->cur_packet_size_bytes);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctfser_init(struct bt_ctfser *ctfser, const char *path)
+{
+       int ret = 0;
+
+       BT_ASSERT(ctfser);
+       memset(ctfser, 0, sizeof(*ctfser));
+       ctfser->fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+       if (ctfser->fd < 0) {
+               BT_LOGW_ERRNO("Failed to open stream file for writing",
+                       ": path=\"%s\", ret=%d",
+                       path, ctfser->fd);
+               ret = -1;
+               goto end;
+       }
+
+       ctfser->path = g_string_new(path);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctfser_fini(struct bt_ctfser *ctfser)
+{
+       int ret = 0;
+
+       if (ctfser->fd == -1) {
+               goto free_path;
+       }
+
+       /*
+        * Truncate the stream file's size to the minimum required to
+        * fit the last packet as we might have grown it too much during
+        * the last memory map.
+        */
+       do {
+               ret = ftruncate(ctfser->fd, ctfser->stream_size_bytes);
+       } while (ret == -1 && errno == EINTR);
+
+       if (ret) {
+               BT_LOGE_ERRNO("Failed to truncate stream file",
+                       ": ret=%d, size-bytes=%" PRIu64,
+                       ret, ctfser->stream_size_bytes);
+               goto end;
+       }
+
+       if (ctfser->base_mma) {
+               /* Unmap old base */
+               ret = munmap_align(ctfser->base_mma);
+               if (ret) {
+                       BT_LOGE_ERRNO("Failed to unmap stream file",
+                               ": ret=%d, size-bytes=%" PRIu64,
+                               ret, ctfser->stream_size_bytes);
+                       goto end;
+               }
+
+               ctfser->base_mma = NULL;
+       }
+
+       ret = close(ctfser->fd);
+       if (ret) {
+               BT_LOGE_ERRNO("Failed to close stream file",
+                       ": ret=%d", ret);
+               goto end;
+       }
+
+       ctfser->fd = -1;
+
+free_path:
+       if (ctfser->path) {
+               g_string_free(ctfser->path, TRUE);
+               ctfser->path = NULL;
+       }
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+int bt_ctfser_open_packet(struct bt_ctfser *ctfser)
+{
+       int ret = 0;
+
+       BT_LOGV("Opening packet: path=\"%s\", fd=%d, "
+               "prev-packet-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->prev_packet_size_bytes);
+
+       if (ctfser->base_mma) {
+               /* Unmap old base (previous packet) */
+               ret = munmap_align(ctfser->base_mma);
+               if (ret) {
+                       BT_LOGE_ERRNO("Failed to unmap stream file",
+                               ": ret=%d, size-bytes=%" PRIu64,
+                               ret, ctfser->stream_size_bytes);
+                       goto end;
+               }
+
+               ctfser->base_mma = NULL;
+       }
+
+       /*
+        * Add the previous packet's size to the memory map address
+        * offset to start writing immediately after it.
+        */
+       ctfser->mmap_offset += ctfser->prev_packet_size_bytes;
+       ctfser->prev_packet_size_bytes = 0;
+
+       /* Make initial space for the current packet */
+       ctfser->cur_packet_size_bytes = get_packet_size_increment_bytes();
+
+       do {
+               ret = bt_posix_fallocate(ctfser->fd, ctfser->mmap_offset,
+                       ctfser->cur_packet_size_bytes);
+       } while (ret == EINTR);
+
+       if (ret) {
+               BT_LOGE("Failed to preallocate memory space: ret=%d", ret);
+               goto end;
+       }
+
+       /* Start writing at the beginning of the current packet */
+       ctfser->offset_in_cur_packet_bits = 0;
+
+       /* Get new base address */
+       mmap_align_ctfser(ctfser);
+       if (ctfser->base_mma == MAP_FAILED) {
+               BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
+                       ": ret=%d", ret);
+               ret = -1;
+               goto end;
+       }
+
+       BT_LOGV("Opened packet: path=\"%s\", fd=%d, "
+               "cur-packet-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->cur_packet_size_bytes);
+
+end:
+       return ret;
+}
+
+BT_HIDDEN
+void bt_ctfser_close_current_packet(struct bt_ctfser *ctfser,
+               uint64_t packet_size_bytes)
+{
+       BT_LOGV("Closing packet: path=\"%s\", fd=%d, "
+               "offset-in-cur-packet-bits=%" PRIu64
+               "cur-packet-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->offset_in_cur_packet_bits,
+               ctfser->cur_packet_size_bytes);
+
+       /*
+        * This will be used during the next call to
+        * bt_ctfser_open_packet(): we add
+        * `ctfser->prev_packet_size_bytes` to the current memory map
+        * address offset (first byte of _this_ packet), effectively
+        * making _this_ packet the required size.
+        */
+       ctfser->prev_packet_size_bytes = packet_size_bytes;
+       ctfser->stream_size_bytes += packet_size_bytes;
+       BT_LOGV("Closed packet: path=\"%s\", fd=%d, "
+               "stream-file-size-bytes=%" PRIu64,
+               ctfser->path->str, ctfser->fd,
+               ctfser->stream_size_bytes);
+}
diff --git a/ctfser/logging.c b/ctfser/logging.c
new file mode 100644 (file)
index 0000000..8ef6ed0
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_OUTPUT_LEVEL bt_ctfser_log_level
+#include <babeltrace/logging-internal.h>
+
+BT_LOG_INIT_LOG_LEVEL(bt_ctfser_log_level, "BABELTRACE_CTFSER_LOG_LEVEL");
diff --git a/ctfser/logging.h b/ctfser/logging.h
new file mode 100644 (file)
index 0000000..5892ac8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef COMMON_LOGGING_H
+#define COMMON_LOGGING_H
+
+/*
+ * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#define BT_LOG_OUTPUT_LEVEL bt_ctfser_log_level
+#include <babeltrace/logging-internal.h>
+
+BT_LOG_LEVEL_EXTERN_SYMBOL(bt_ctfser_log_level);
+
+#endif /* COMMON_LOGGING_H */
index 9e2030378d4e8aefd6fea57e7b2c6712e322d18e..b5e58d017452eee10d0113ee1fe514a9e2916198 100644 (file)
@@ -224,6 +224,7 @@ noinst_HEADERS = \
        babeltrace/compat/mman-internal.h \
        babeltrace/compat/socket-internal.h \
        babeltrace/common-internal.h \
+       babeltrace/ctfser-internal.h \
        babeltrace/bitfield-internal.h \
        babeltrace/object-internal.h \
        babeltrace/object-pool-internal.h \
@@ -243,7 +244,6 @@ noinst_HEADERS = \
        babeltrace/ctf-writer/field-wrapper-internal.h \
        babeltrace/ctf-writer/functor-internal.h \
        babeltrace/ctf-writer/resolve-internal.h \
-       babeltrace/ctf-writer/serialize-internal.h \
        babeltrace/ctf-writer/stream-class-internal.h \
        babeltrace/ctf-writer/stream-internal.h \
        babeltrace/ctf-writer/trace-internal.h \
index deecbf3163dacce96a740331f66b938318f2dc7b..7b6a5a67db85b0597bdeec68e8b7be17cefd1334 100644 (file)
@@ -43,6 +43,7 @@
 #include <babeltrace/ctf-writer/validation-internal.h>
 #include <babeltrace/ctf-writer/object-internal.h>
 #include <babeltrace/ctf-writer/values-internal.h>
+#include <babeltrace/ctfser-internal.h>
 
 struct bt_ctf_stream_class;
 struct bt_ctf_stream_pos;
@@ -254,7 +255,7 @@ int bt_ctf_event_class_serialize(struct bt_ctf_event_class *event_class,
 
 BT_HIDDEN
 int bt_ctf_event_serialize(struct bt_ctf_event *event,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *pos,
                enum bt_ctf_byte_order native_byte_order);
 
 static inline
index b4c1f224bca748967cedef8369fbfa24af273e51..e56c4f30178d6917f3c5e831e328c92fa7f96251 100644 (file)
@@ -36,9 +36,9 @@
 #include <babeltrace/common-internal.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
 #include <babeltrace/ctf-writer/fields.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
 #include <babeltrace/ctf-writer/utils-internal.h>
 #include <babeltrace/ctf-writer/object-internal.h>
+#include <babeltrace/ctfser-internal.h>
 #include <babeltrace/types.h>
 #include <glib.h>
 #include <inttypes.h>
@@ -831,7 +831,7 @@ struct bt_ctf_field_variant {
 
 BT_HIDDEN
 int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order);
 
 BT_HIDDEN
diff --git a/include/babeltrace/ctf-writer/serialize-internal.h b/include/babeltrace/ctf-writer/serialize-internal.h
deleted file mode 100644 (file)
index 85e2fec..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef BABELTRACE_CTF_WRITER_SERIALIZE_INTERNAL_H
-#define BABELTRACE_CTF_WRITER_SERIALIZE_INTERNAL_H
-
-/*
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * The Common Trace Format (CTF) Specification is available at
- * http://www.efficios.com/ctf
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <limits.h>
-#include <babeltrace/compat/mman-internal.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <babeltrace/align-internal.h>
-#include <babeltrace/endian-internal.h>
-#include <babeltrace/common-internal.h>
-#include <babeltrace/mmap-align-internal.h>
-#include <babeltrace/types.h>
-#include <babeltrace/ctf-writer/field-types.h>
-#include <babeltrace/ctf-writer/fields-internal.h>
-#include <babeltrace/ctf-writer/fields.h>
-#include <babeltrace/assert-internal.h>
-
-#define PACKET_LEN_INCREMENT   (bt_common_get_page_size() * 8 * CHAR_BIT)
-
-#if (BYTE_ORDER == BIG_ENDIAN)
-# define BT_CTF_MY_BYTE_ORDER  BT_CTF_BYTE_ORDER_BIG_ENDIAN
-#else
-# define BT_CTF_MY_BYTE_ORDER  BT_CTF_BYTE_ORDER_LITTLE_ENDIAN
-#endif
-
-struct bt_ctf_stream_pos {
-       int fd;
-       int prot;               /* mmap protection */
-       int flags;              /* mmap flags */
-
-       /* Current position */
-       off_t mmap_offset;      /* mmap offset in the file, in bytes */
-       off_t mmap_base_offset; /* offset of start of packet in mmap, in bytes */
-       uint64_t packet_size;   /* current packet size, in bits */
-       int64_t offset;         /* offset from base, in bits. EOF for end of file. */
-       struct mmap_align *base_mma;/* mmap base address */
-};
-
-BT_HIDDEN
-int bt_ctf_field_integer_write(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
-               enum bt_ctf_byte_order native_byte_order);
-
-BT_HIDDEN
-int bt_ctf_field_floating_point_write(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
-               enum bt_ctf_byte_order native_byte_order);
-
-static inline
-int bt_ctf_stream_pos_access_ok(struct bt_ctf_stream_pos *pos, uint64_t bit_len)
-{
-       uint64_t max_len;
-
-       if (unlikely(pos->offset == EOF))
-               return 0;
-
-       if (pos->prot == PROT_READ) {
-               /*
-                * Reads may only reach up to the "content_size",
-                * regardless of the packet_size.
-                */
-               max_len = pos->offset;
-       } else {
-               /* Writes may take place up to the end of the packet. */
-               max_len = pos->packet_size;
-       }
-       if (unlikely(pos->offset < 0 || bit_len > INT64_MAX - pos->offset)) {
-               return 0;
-       }
-       if (unlikely(pos->offset + bit_len > max_len))
-               return 0;
-       return 1;
-}
-
-static inline
-int bt_ctf_stream_pos_move(struct bt_ctf_stream_pos *pos, uint64_t bit_offset)
-{
-       int ret = 0;
-
-       ret = bt_ctf_stream_pos_access_ok(pos, bit_offset);
-       if (!ret) {
-               goto end;
-       }
-       pos->offset += bit_offset;
-end:
-       return ret;
-}
-
-static inline
-int bt_ctf_stream_pos_align(struct bt_ctf_stream_pos *pos, uint64_t bit_offset)
-{
-       return bt_ctf_stream_pos_move(pos,
-               offset_align(pos->offset, bit_offset));
-}
-
-static inline
-char *bt_ctf_stream_pos_get_addr(struct bt_ctf_stream_pos *pos)
-{
-       /* Only makes sense to get the address after aligning on CHAR_BIT */
-       BT_ASSERT(!(pos->offset % CHAR_BIT));
-       return ((char *) mmap_align_addr(pos->base_mma)) +
-               pos->mmap_base_offset + (pos->offset / CHAR_BIT);
-}
-
-static inline
-int bt_ctf_stream_pos_init(struct bt_ctf_stream_pos *pos,
-               int fd, int open_flags)
-{
-       pos->fd = fd;
-
-       switch (open_flags & O_ACCMODE) {
-       case O_RDONLY:
-               pos->prot = PROT_READ;
-               pos->flags = MAP_PRIVATE;
-               break;
-       case O_RDWR:
-               pos->prot = PROT_READ | PROT_WRITE;
-               pos->flags = MAP_SHARED;
-               break;
-       default:
-               abort();
-       }
-
-       return 0;
-}
-
-static inline
-int bt_ctf_stream_pos_fini(struct bt_ctf_stream_pos *pos)
-{
-       if (pos->base_mma) {
-               int ret;
-
-               /* unmap old base */
-               ret = munmap_align(pos->base_mma);
-               if (ret) {
-                       return -1;
-               }
-       }
-
-       return 0;
-}
-
-BT_HIDDEN
-void bt_ctf_stream_pos_packet_seek(struct bt_ctf_stream_pos *pos, size_t index,
-       int whence);
-
-#endif /* BABELTRACE_CTF_WRITER_SERIALIZE_INTERNAL_H */
index 7985947831734bab6094f721ce69da0f368b01e9..565d53f24438def98ea186fa9e471158e17fe150 100644 (file)
 #include <babeltrace/assert-internal.h>
 #include <babeltrace/assert-pre-internal.h>
 #include <babeltrace/babeltrace-internal.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
 #include <babeltrace/ctf-writer/stream-internal.h>
 #include <babeltrace/ctf-writer/stream.h>
 #include <babeltrace/ctf-writer/utils-internal.h>
 #include <babeltrace/ctf-writer/object-internal.h>
+#include <babeltrace/ctfser-internal.h>
 #include <stdint.h>
 
 struct bt_ctf_stream_common;
@@ -93,16 +93,12 @@ struct bt_ctf_stream {
 
        /* Array of pointers to bt_ctf_event for the current packet */
        GPtrArray *events;
-       struct bt_ctf_stream_pos pos;
+       struct bt_ctfser ctfser;
        unsigned int flushed_packet_count;
        uint64_t discarded_events;
-       uint64_t size;
        uint64_t last_ts_end;
 };
 
-BT_HIDDEN
-int bt_ctf_stream_set_fd(struct bt_ctf_stream *stream, int fd);
-
 BT_HIDDEN
 struct bt_ctf_stream *bt_ctf_stream_create_with_id(
                struct bt_ctf_stream_class *stream_class,
diff --git a/include/babeltrace/ctfser-internal.h b/include/babeltrace/ctfser-internal.h
new file mode 100644 (file)
index 0000000..5826876
--- /dev/null
@@ -0,0 +1,499 @@
+#ifndef BABELTRACE_CTFSER_INTERNAL_H
+#define BABELTRACE_CTFSER_INTERNAL_H
+
+/*
+ * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
+ * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright 2017-2019 Philippe Proulx <pproulx@efficios.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The Common Trace Format (CTF) Specification is available at
+ * http://www.efficios.com/ctf
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <limits.h>
+#include <babeltrace/compat/mman-internal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <babeltrace/align-internal.h>
+#include <babeltrace/endian-internal.h>
+#include <babeltrace/common-internal.h>
+#include <babeltrace/mmap-align-internal.h>
+#include <babeltrace/types.h>
+#include <babeltrace/assert-internal.h>
+#include <babeltrace/bitfield-internal.h>
+#include <glib.h>
+
+struct bt_ctfser {
+       /* Stream file's descriptor */
+       int fd;
+
+       /* Offset (bytes) of memory map (current packet) in the stream file */
+       off_t mmap_offset;
+
+       /* Offset (bytes) of packet's first byte in the memory map */
+       off_t mmap_base_offset;
+
+       /* Current offset (bits) within current packet */
+       uint64_t offset_in_cur_packet_bits;
+
+       /* Current packet size (bytes) */
+       uint64_t cur_packet_size_bytes;
+
+       /* Previous packet size (bytes) */
+       uint64_t prev_packet_size_bytes;
+
+       /* Current stream size (bytes) */
+       uint64_t stream_size_bytes;
+
+       /* Memory map base address */
+       struct mmap_align *base_mma;
+
+       /* Stream file's path (for debugging) */
+       GString *path;
+};
+
+union bt_ctfser_int_val {
+       int64_t i;
+       uint64_t u;
+};
+
+/*
+ * Initializes a CTF serializer.
+ *
+ * This function opens the file `path` for writing.
+ */
+BT_HIDDEN
+int bt_ctfser_init(struct bt_ctfser *ctfser, const char *path);
+
+/*
+ * Finalizes a CTF serializer.
+ *
+ * This function truncates the stream file so that there's no extra
+ * padding after the last packet, and then closes the file.
+ */
+BT_HIDDEN
+int bt_ctfser_fini(struct bt_ctfser *ctfser);
+
+/*
+ * Opens a new packet.
+ *
+ * All the next writing functions are performed within this new packet.
+ */
+BT_HIDDEN
+int bt_ctfser_open_packet(struct bt_ctfser *ctfser);
+
+/*
+ * Closes the current packet, making its size `packet_size_bytes`.
+ */
+BT_HIDDEN
+void bt_ctfser_close_current_packet(struct bt_ctfser *ctfser,
+               uint64_t packet_size_bytes);
+
+BT_HIDDEN
+int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser *ctfser);
+
+static inline
+uint64_t _bt_ctfser_cur_packet_size_bits(struct bt_ctfser *ctfser)
+{
+       return ctfser->cur_packet_size_bytes * 8;
+}
+
+static inline
+uint64_t _bt_ctfser_prev_packet_size_bits(struct bt_ctfser *ctfser)
+{
+       return ctfser->prev_packet_size_bytes * 8;
+}
+
+static inline
+uint64_t _bt_ctfser_offset_bytes(struct bt_ctfser *ctfser)
+{
+       return ctfser->offset_in_cur_packet_bits / 8;
+}
+
+static inline
+uint8_t *_bt_ctfser_get_addr(struct bt_ctfser *ctfser)
+{
+       /* Only makes sense to get the address after aligning on byte */
+       BT_ASSERT(ctfser->offset_in_cur_packet_bits % 8 == 0);
+       return ((uint8_t *) mmap_align_addr(ctfser->base_mma)) +
+               ctfser->mmap_base_offset + _bt_ctfser_offset_bytes(ctfser);
+}
+
+static inline
+bool _bt_ctfser_has_space_left(struct bt_ctfser *ctfser, uint64_t size_bits)
+{
+       bool has_space_left = true;
+
+       if (unlikely((ctfser->offset_in_cur_packet_bits + size_bits >
+                       _bt_ctfser_cur_packet_size_bits(ctfser)))) {
+               has_space_left = false;
+               goto end;
+       }
+
+       if (unlikely(ctfser->offset_in_cur_packet_bits < 0 || size_bits >
+                       UINT64_MAX - ctfser->offset_in_cur_packet_bits)) {
+               has_space_left = false;
+               goto end;
+       }
+
+end:
+       return has_space_left;
+}
+
+static inline
+void _bt_ctfser_incr_offset(struct bt_ctfser *ctfser, uint64_t size_bits)
+{
+       BT_ASSERT(_bt_ctfser_has_space_left(ctfser, size_bits));
+       ctfser->offset_in_cur_packet_bits += size_bits;
+}
+
+/*
+ * Aligns the current offset within the current packet to
+ * `alignment_bits` bits (power of two, > 0).
+ */
+static inline
+int bt_ctfser_align_offset_in_current_packet(struct bt_ctfser *ctfser,
+               uint64_t alignment_bits)
+{
+       int ret = 0;
+       uint64_t align_size_bits;
+
+       BT_ASSERT(alignment_bits > 0);
+       align_size_bits = ALIGN(ctfser->offset_in_cur_packet_bits,
+                       alignment_bits) - ctfser->offset_in_cur_packet_bits;
+
+       if (unlikely(!_bt_ctfser_has_space_left(ctfser, align_size_bits))) {
+               ret = _bt_ctfser_increase_cur_packet_size(ctfser);
+               if (unlikely(ret)) {
+                       goto end;
+               }
+       }
+
+       _bt_ctfser_incr_offset(ctfser, align_size_bits);
+
+end:
+       return ret;
+}
+
+static inline
+int _bt_ctfser_write_byte_aligned_int_no_align(struct bt_ctfser *ctfser,
+               union bt_ctfser_int_val value,
+               unsigned int size_bits, bool is_signed, int byte_order)
+{
+       int ret = 0;
+
+       /* Reverse byte order? */
+       bool rbo = byte_order != BYTE_ORDER;
+
+       BT_ASSERT(size_bits % 8 == 0);
+       BT_ASSERT(_bt_ctfser_has_space_left(ctfser, size_bits));
+
+       if (!is_signed) {
+               switch (size_bits) {
+               case 8:
+               {
+                       uint8_t v = (uint8_t) value.u;
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 16:
+               {
+                       uint16_t v = (uint16_t) value.u;
+
+                       if (rbo) {
+                               v = GUINT16_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 32:
+               {
+                       uint32_t v = (uint32_t) value.u;
+
+                       if (rbo) {
+                               v = GUINT32_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 64:
+               {
+                       uint64_t v = (uint64_t) value.u;
+
+                       if (rbo) {
+                               v = GUINT64_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               default:
+                       abort();
+               }
+       } else {
+               switch (size_bits) {
+               case 8:
+               {
+                       int8_t v = (int8_t) value.i;
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 16:
+               {
+                       int16_t v = (int16_t) value.i;
+
+                       if (rbo) {
+                               v = GUINT16_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 32:
+               {
+                       int32_t v = (int32_t) value.i;
+
+                       if (rbo) {
+                               v = GUINT32_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               case 64:
+               {
+                       int64_t v = (int64_t) value.i;
+
+                       if (rbo) {
+                               v = GUINT64_SWAP_LE_BE(v);
+                       }
+
+                       memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
+                       break;
+               }
+               default:
+                       abort();
+               }
+       }
+
+       _bt_ctfser_incr_offset(ctfser, size_bits);
+       return ret;
+}
+
+/*
+ * Writes an integer known to have an alignment that is >= 8 at the
+ * current offset within the current packet.
+ */
+static inline
+int bt_ctfser_write_byte_aligned_int(struct bt_ctfser *ctfser,
+       union bt_ctfser_int_val value, unsigned int alignment_bits,
+       unsigned int size_bits, bool is_signed, int byte_order)
+{
+       int ret;
+
+       BT_ASSERT(alignment_bits % 8 == 0);
+       ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
+       if (unlikely(ret)) {
+               goto end;
+       }
+
+       if (unlikely(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
+               ret = _bt_ctfser_increase_cur_packet_size(ctfser);
+               if (unlikely(ret)) {
+                       goto end;
+               }
+       }
+
+       ret = _bt_ctfser_write_byte_aligned_int_no_align(ctfser, value,
+               size_bits, is_signed, byte_order);
+       if (unlikely(ret)) {
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Writes an integer at the current offset within the current packet.
+ */
+static inline
+int bt_ctfser_write_int(struct bt_ctfser *ctfser, union bt_ctfser_int_val value,
+       unsigned int alignment_bits, unsigned int size_bits, bool is_signed,
+       int byte_order)
+{
+       int ret = 0;
+
+       ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
+       if (unlikely(ret)) {
+               goto end;
+       }
+
+       if (unlikely(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
+               ret = _bt_ctfser_increase_cur_packet_size(ctfser);
+               if (unlikely(ret)) {
+                       goto end;
+               }
+       }
+
+       if (alignment_bits % 8 == 0 && size_bits % 8 == 0) {
+               ret = _bt_ctfser_write_byte_aligned_int_no_align(ctfser, value,
+                       size_bits, is_signed, byte_order);
+               goto end;
+       }
+
+       if (!is_signed) {
+               if (byte_order == LITTLE_ENDIAN) {
+                       bt_bitfield_write_le(mmap_align_addr(ctfser->base_mma) +
+                               ctfser->mmap_base_offset, uint8_t,
+                               ctfser->offset_in_cur_packet_bits, size_bits,
+                               value.u);
+               } else {
+                       bt_bitfield_write_be(mmap_align_addr(ctfser->base_mma) +
+                               ctfser->mmap_base_offset, uint8_t,
+                               ctfser->offset_in_cur_packet_bits, size_bits,
+                               value.u);
+               }
+       } else {
+               if (byte_order == LITTLE_ENDIAN) {
+                       bt_bitfield_write_le(mmap_align_addr(ctfser->base_mma) +
+                               ctfser->mmap_base_offset, uint8_t,
+                               ctfser->offset_in_cur_packet_bits, size_bits,
+                               value.i);
+               } else {
+                       bt_bitfield_write_be(mmap_align_addr(ctfser->base_mma) +
+                               ctfser->mmap_base_offset, uint8_t,
+                               ctfser->offset_in_cur_packet_bits, size_bits,
+                               value.i);
+               }
+       }
+
+       _bt_ctfser_incr_offset(ctfser, size_bits);
+
+end:
+       return ret;
+}
+
+/*
+ * Writes a 32-bit floating point number at the current offset within
+ * the current packet.
+ */
+static inline
+int bt_ctfser_write_float32(struct bt_ctfser *ctfser, double value,
+       unsigned int alignment_bits, int byte_order)
+{
+       union bt_ctfser_int_val int_value;
+       union u32f {
+               uint32_t u;
+               float f;
+       } u32f;
+
+       u32f.f = (float) value;
+       int_value.u = u32f.u;
+       return bt_ctfser_write_int(ctfser, int_value, alignment_bits,
+               32, false, byte_order);
+}
+
+/*
+ * Writes a 64-bit floating point number at the current offset within
+ * the current packet.
+ */
+static inline
+int bt_ctfser_write_float64(struct bt_ctfser *ctfser, double value,
+       unsigned int alignment_bits, int byte_order)
+{
+       union bt_ctfser_int_val int_value;
+       union u64f {
+               uint64_t u;
+               float f;
+       } u64f;
+
+       u64f.f = value;
+       int_value.u = u64f.u;
+       return bt_ctfser_write_int(ctfser, int_value, alignment_bits,
+               64, false, byte_order);
+}
+
+/*
+ * Writes a C string, including the terminating null character, at the
+ * current offset within the current packet.
+ */
+static inline
+int bt_ctfser_write_string(struct bt_ctfser *ctfser, const char *value)
+{
+       int ret = 0;
+       const char *at = value;
+
+       ret = bt_ctfser_align_offset_in_current_packet(ctfser, 8);
+       if (unlikely(ret)) {
+               goto end;
+       }
+
+       while (true) {
+               if (unlikely(!_bt_ctfser_has_space_left(ctfser, 8))) {
+                       ret = _bt_ctfser_increase_cur_packet_size(ctfser);
+                       if (unlikely(ret)) {
+                               goto end;
+                       }
+               }
+
+               memcpy(_bt_ctfser_get_addr(ctfser), at, sizeof(*at));
+               _bt_ctfser_incr_offset(ctfser, 8);
+
+               if (unlikely(*at == '\0')) {
+                       break;
+               }
+
+               at++;
+       }
+
+end:
+       return ret;
+}
+
+/*
+ * Returns the current offset within the current packet (bits).
+ */
+static inline
+uint64_t bt_ctfser_get_offset_in_current_packet_bits(struct bt_ctfser *ctfser)
+{
+       return ctfser->offset_in_cur_packet_bits;
+}
+
+/*
+ * Sets the current offset within the current packet (bits).
+ */
+static inline
+void bt_ctfser_set_offset_in_current_packet_bits(struct bt_ctfser *ctfser,
+               uint64_t offset_bits)
+{
+       BT_ASSERT(offset_bits <= _bt_ctfser_cur_packet_size_bits(ctfser));
+       ctfser->offset_in_cur_packet_bits = offset_bits;
+}
+
+#endif /* BABELTRACE_CTFSER_INTERNAL_H */
index 6cafdebcdfa9520f984b26080b9c0289b97f18a5..1b4d0c119a976b3930bd4d47b754234317f888f5 100644 (file)
@@ -20,6 +20,7 @@ libbabeltrace_la_LIBADD = \
        ctf-writer/libctf-writer.la \
        $(top_builddir)/logging/libbabeltrace-logging.la \
        $(top_builddir)/common/libbabeltrace-common.la \
+       $(top_builddir)/ctfser/libbabeltrace-ctfser.la \
        $(top_builddir)/compat/libcompat.la
 
 if ENABLE_BUILT_IN_PYTHON_PLUGIN_SUPPORT
@@ -40,4 +41,5 @@ libbabeltrace_ctf_la_LIBADD = \
        ctf-writer/libctf-writer.la \
        $(top_builddir)/logging/libbabeltrace-logging.la \
        $(top_builddir)/common/libbabeltrace-common.la \
+       $(top_builddir)/ctfser/libbabeltrace-ctfser.la \
        $(top_builddir)/compat/libcompat.la
index 4ed7b1f4701f471e7938cee2ad5949744d08b475..bee4b394d070c8a4661965fa18f35f2b65f90d08 100644 (file)
@@ -14,7 +14,6 @@ libctf_writer_la_SOURCES = \
        object.c \
        object-pool.c \
        resolve.c \
-       serialize.c \
        stream.c \
        stream-class.c \
        trace.c \
index e5ed458efc1e0b583d164ee6a96b4534d4df9d9c..a6c1213c953e5759ebf8938a12d33e95fb104983 100644 (file)
@@ -708,18 +708,18 @@ struct bt_ctf_field *bt_ctf_event_get_stream_event_context(
 
 BT_HIDDEN
 int bt_ctf_event_serialize(struct bt_ctf_event *event,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        int ret = 0;
 
        BT_ASSERT(event);
-       BT_ASSERT(pos);
+       BT_ASSERT(ctfser);
 
        BT_LOGV_STR("Serializing event's context field.");
        if (event->common.context_field) {
                ret = bt_ctf_field_serialize_recursive(
-                       (void *) event->common.context_field, pos,
+                       (void *) event->common.context_field, ctfser,
                        native_byte_order);
                if (ret) {
                        BT_LOGW("Cannot serialize event's context field: "
@@ -735,7 +735,7 @@ int bt_ctf_event_serialize(struct bt_ctf_event *event,
        BT_LOGV_STR("Serializing event's payload field.");
        if (event->common.payload_field) {
                ret = bt_ctf_field_serialize_recursive(
-                       (void *) event->common.payload_field, pos,
+                       (void *) event->common.payload_field, ctfser,
                        native_byte_order);
                if (ret) {
                        BT_LOGW("Cannot serialize event's payload field: "
index e8c124981150b53d6b0b3c8c519b925eec780a7e..13b1cb66da9c6144b21efbaad57002a91285745d 100644 (file)
 #include <babeltrace/compiler-internal.h>
 #include <babeltrace/ctf-writer/field-types-internal.h>
 #include <babeltrace/ctf-writer/fields-internal.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
 #include <babeltrace/endian-internal.h>
 #include <babeltrace/ctf-writer/object-internal.h>
 #include <babeltrace/ctf-writer/object.h>
+#include <babeltrace/ctfser-internal.h>
 #include <float.h>
 #include <inttypes.h>
 #include <inttypes.h>
@@ -778,7 +778,7 @@ struct bt_ctf_field *(* const field_create_funcs[])(struct bt_ctf_field_type *)
 };
 
 typedef int (*bt_ctf_field_serialize_recursive_func)(
-               struct bt_ctf_field_common *, struct bt_ctf_stream_pos *,
+               struct bt_ctf_field_common *, struct bt_ctfser *,
                enum bt_ctf_byte_order);
 
 static
@@ -857,138 +857,110 @@ void bt_ctf_field_string_destroy(struct bt_ctf_field *field)
 
 BT_HIDDEN
 int bt_ctf_field_serialize_recursive(struct bt_ctf_field *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        struct bt_ctf_field_common *field_common = (void *) field;
        bt_ctf_field_serialize_recursive_func serialize_func;
 
-       BT_ASSERT(pos);
+       BT_ASSERT(ctfser);
        BT_ASSERT_PRE_NON_NULL(field, "Field");
        BT_ASSERT(field_common->spec.writer.serialize_func);
        serialize_func = field_common->spec.writer.serialize_func;
-       return serialize_func(field_common, pos,
+       return serialize_func(field_common, ctfser,
                native_byte_order);
 }
 
 static
-int increase_packet_size(struct bt_ctf_stream_pos *pos)
+int bt_ctf_field_integer_serialize(struct bt_ctf_field_common *field,
+               struct bt_ctfser *ctfser,
+               enum bt_ctf_byte_order native_byte_order)
 {
        int ret;
+       struct bt_ctf_field_type_common_integer *int_type =
+               BT_CTF_FROM_COMMON(field->type);
+       struct bt_ctf_field_common_integer *int_field =
+               BT_CTF_FROM_COMMON(field);
+       enum bt_ctf_byte_order byte_order;
+       union bt_ctfser_int_val value;
 
-       BT_ASSERT(pos);
-       BT_LOGV("Increasing packet size: pos-offset=%" PRId64 ", "
-               "cur-packet-size=%" PRIu64,
-               pos->offset, pos->packet_size);
-       ret = munmap_align(pos->base_mma);
-       if (ret) {
-               BT_LOGE_ERRNO("Failed to perform an aligned memory unmapping",
-                       ": ret=%d", ret);
-               goto end;
+       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Integer field");
+       BT_LOGV("Serializing CTF writer integer field: addr=%p, native-bo=%s",
+               field,
+               bt_ctf_byte_order_string(native_byte_order));
+       byte_order = int_type->user_byte_order;
+       if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+               byte_order = native_byte_order;
        }
 
-       pos->packet_size += PACKET_LEN_INCREMENT;
-       do {
-               ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
-                       pos->packet_size / CHAR_BIT);
-       } while (ret == EINTR);
-       if (ret) {
-               BT_LOGE_ERRNO("Failed to preallocate memory space",
-                       ": ret=%d", ret);
-               errno = EINTR;
-               ret = -1;
+       value.i = int_field->payload.signd;
+       value.u = int_field->payload.unsignd;
+       ret = bt_ctfser_write_int(ctfser, value, int_type->common.alignment,
+               int_type->size, int_type->is_signed,
+               byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+                       LITTLE_ENDIAN : BIG_ENDIAN);
+       if (unlikely(ret)) {
+               BT_LOGE("Cannot serialize integer field: ret=%d", ret);
                goto end;
        }
 
-       pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
-               pos->flags, pos->fd, pos->mmap_offset);
-       if (pos->base_mma == MAP_FAILED) {
-               BT_LOGE_ERRNO("Failed to perform an aligned memory mapping",
-                       ": ret=%d", ret);
-               ret = -1;
-       }
-
-       BT_LOGV("Increased packet size: pos-offset=%" PRId64 ", "
-               "new-packet-size=%" PRIu64,
-               pos->offset, pos->packet_size);
-       BT_ASSERT(pos->packet_size % 8 == 0);
-
-end:
-       return ret;
-}
-
-static
-int bt_ctf_field_integer_serialize(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
-               enum bt_ctf_byte_order native_byte_order)
-{
-       int ret = 0;
-
-       BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Integer field");
-       BT_LOGV("Serializing CTF writer integer field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
-
-retry:
-       ret = bt_ctf_field_integer_write(field, pos, native_byte_order);
-       if (ret == -EFAULT) {
-               /*
-                * The field is too large to fit in the current packet's
-                * remaining space. Bump the packet size and retry.
-                */
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-               goto retry;
-       }
-
 end:
        return ret;
 }
 
 static
-int bt_ctf_field_enumeration_serialize_recursive(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+int bt_ctf_field_enumeration_serialize_recursive(
+               struct bt_ctf_field_common *field, struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        struct bt_ctf_field_enumeration *enumeration = (void *) field;
 
-       BT_LOGV("Serializing enumeration field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
+       BT_LOGV("Serializing enumeration field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string(native_byte_order));
        BT_LOGV_STR("Serializing enumeration field's payload field.");
        return bt_ctf_field_serialize_recursive(
-               (void *) enumeration->container, pos, native_byte_order);
+               (void *) enumeration->container, ctfser, native_byte_order);
 }
 
 static
 int bt_ctf_field_floating_point_serialize(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
-       int ret = 0;
+       int ret = -1;
+       struct bt_ctf_field_type_common_floating_point *flt_type =
+               BT_CTF_FROM_COMMON(field->type);
+       struct bt_ctf_field_common_floating_point *flt_field = BT_CTF_FROM_COMMON(field);
+       enum bt_ctf_byte_order byte_order;
 
        BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "Floating point number field");
-       BT_LOGV("Serializing floating point number field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
+       BT_LOGV("Serializing floating point number field: "
+               "addr=%p, native-bo=%s", field,
+               bt_ctf_byte_order_string(native_byte_order));
 
-retry:
-       ret = bt_ctf_field_floating_point_write(field, pos,
-               native_byte_order);
-       if (ret == -EFAULT) {
-               /*
-                * The field is too large to fit in the current packet's
-                * remaining space. Bump the packet size and retry.
-                */
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-               goto retry;
+       byte_order = flt_type->user_byte_order;
+       if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
+               byte_order = native_byte_order;
+       }
+
+       if (flt_type->mant_dig == FLT_MANT_DIG) {
+               ret = bt_ctfser_write_float32(ctfser, flt_field->payload,
+                       flt_type->common.alignment,
+                       byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+                               LITTLE_ENDIAN : BIG_ENDIAN);
+       } else if (flt_type->mant_dig == DBL_MANT_DIG) {
+               ret = bt_ctfser_write_float64(ctfser, flt_field->payload,
+                       flt_type->common.alignment,
+                       byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN ?
+                               LITTLE_ENDIAN : BIG_ENDIAN);
+       } else {
+               abort();
+       }
+
+       if (unlikely(ret)) {
+               BT_LOGE("Cannot serialize floating point number field: "
+                       "ret=%d", ret);
+               goto end;
        }
 
 end:
@@ -997,30 +969,20 @@ end:
 
 static
 int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        int64_t i;
-       int ret = 0;
+       int ret;
        struct bt_ctf_field_common_structure *structure = BT_CTF_FROM_COMMON(field);
 
-       BT_LOGV("Serializing structure field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
-
-       while (!bt_ctf_stream_pos_access_ok(pos,
-               offset_align(pos->offset, field->type->alignment))) {
-               ret = increase_packet_size(pos);
-               if (ret) {
-                       BT_LOGE("Cannot increase packet size: ret=%d", ret);
-                       goto end;
-               }
-       }
-
-       if (!bt_ctf_stream_pos_align(pos, field->type->alignment)) {
-               BT_LOGE("Cannot align packet's position: pos-offset=%" PRId64 ", "
-                       "align=%u", pos->offset, field->type->alignment);
-               ret = -1;
+       BT_LOGV("Serializing structure field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string(native_byte_order));
+       ret = bt_ctfser_align_offset_in_current_packet(ctfser,
+               field->type->alignment);
+       if (unlikely(ret)) {
+               BT_LOGE("Cannot align offset before serializing structure field: "
+                       "ret=%d", ret);
                goto end;
        }
 
@@ -1029,11 +991,12 @@ int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_field_common *field
                        structure->fields, i);
                const char *field_name = NULL;
 
-               BT_LOGV("Serializing structure field's field: pos-offset=%" PRId64 ", "
-                       "field-addr=%p, index=%" PRId64,
-                       pos->offset, member, i);
+               BT_LOGV("Serializing structure field's field: ser-offset=%" PRIu64 ", "
+                       "field-addr=%p, index=%" PRIu64,
+                       bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+                       member, i);
 
-               if (!member) {
+               if (unlikely(!member)) {
                        ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
                                field->type, &field_name, NULL, i);
                        BT_ASSERT(ret == 0);
@@ -1045,9 +1008,9 @@ int bt_ctf_field_structure_serialize_recursive(struct bt_ctf_field_common *field
                        goto end;
                }
 
-               ret = bt_ctf_field_serialize_recursive((void *) member, pos,
+               ret = bt_ctf_field_serialize_recursive((void *) member, ctfser,
                        native_byte_order);
-               if (ret) {
+               if (unlikely(ret)) {
                        ret = bt_ctf_field_type_common_structure_borrow_field_by_index(
                                field->type, &field_name, NULL, i);
                        BT_ASSERT(ret == 0);
@@ -1065,42 +1028,41 @@ end:
 
 static
 int bt_ctf_field_variant_serialize_recursive(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        struct bt_ctf_field_common_variant *variant = BT_CTF_FROM_COMMON(field);
 
-       BT_LOGV("Serializing variant field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
+       BT_LOGV("Serializing variant field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string(native_byte_order));
        BT_LOGV_STR("Serializing variant field's payload field.");
        return bt_ctf_field_serialize_recursive(
-               (void *) variant->current_field, pos, native_byte_order);
+               (void *) variant->current_field, ctfser, native_byte_order);
 }
 
 static
 int bt_ctf_field_array_serialize_recursive(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        int64_t i;
        int ret = 0;
        struct bt_ctf_field_common_array *array = BT_CTF_FROM_COMMON(field);
 
-       BT_LOGV("Serializing array field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
+       BT_LOGV("Serializing array field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string(native_byte_order));
 
        for (i = 0; i < array->elements->len; i++) {
                struct bt_ctf_field_common *elem_field =
                        g_ptr_array_index(array->elements, i);
 
                BT_LOGV("Serializing array field's element field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
-                       pos->offset, elem_field, i);
+                       "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
+                       bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+                       elem_field, i);
                ret = bt_ctf_field_serialize_recursive(
-                       (void *) elem_field, pos, native_byte_order);
-               if (ret) {
+                       (void *) elem_field, ctfser, native_byte_order);
+               if (unlikely(ret)) {
                        BT_LOGW("Cannot serialize array field's element field: "
                                "array-field-addr=%p, field-addr=%p, "
                                "index=%" PRId64, field, elem_field, i);
@@ -1114,27 +1076,27 @@ end:
 
 static
 int bt_ctf_field_sequence_serialize_recursive(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
        int64_t i;
        int ret = 0;
        struct bt_ctf_field_common_sequence *sequence = BT_CTF_FROM_COMMON(field);
 
-       BT_LOGV("Serializing sequence field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
+       BT_LOGV("Serializing sequence field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string(native_byte_order));
 
        for (i = 0; i < sequence->elements->len; i++) {
                struct bt_ctf_field_common *elem_field =
                        g_ptr_array_index(sequence->elements, i);
 
                BT_LOGV("Serializing sequence field's element field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, index=%" PRId64,
-                       pos->offset, elem_field, i);
+                       "ser-offset=%" PRIu64 ", field-addr=%p, index=%" PRId64,
+                       bt_ctfser_get_offset_in_current_packet_bits(ctfser),
+                       elem_field, i);
                ret = bt_ctf_field_serialize_recursive(
-                       (void *) elem_field, pos, native_byte_order);
-               if (ret) {
+                       (void *) elem_field, ctfser, native_byte_order);
+               if (unlikely(ret)) {
                        BT_LOGW("Cannot serialize sequence field's element field: "
                                "sequence-field-addr=%p, field-addr=%p, "
                                "index=%" PRId64, field, elem_field, i);
@@ -1148,44 +1110,22 @@ end:
 
 static
 int bt_ctf_field_string_serialize(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
+               struct bt_ctfser *ctfser,
                enum bt_ctf_byte_order native_byte_order)
 {
-       int64_t i;
-       int ret = 0;
+       int ret;
        struct bt_ctf_field_common_string *string = BT_CTF_FROM_COMMON(field);
-       struct bt_ctf_field_type *character_type =
-               get_field_type(FIELD_TYPE_ALIAS_UINT8_T);
-       struct bt_ctf_field *character;
 
        BT_ASSERT_PRE_CTF_FIELD_COMMON_IS_SET(field, "String field");
-       BT_LOGV("Serializing string field: addr=%p, pos-offset=%" PRId64 ", "
-               "native-bo=%s", field, pos->offset,
-               bt_ctf_byte_order_string((int) native_byte_order));
-
-       BT_LOGV_STR("Creating character field from string field's character field type.");
-       character = bt_ctf_field_create(character_type);
-
-       for (i = 0; i < string->size + 1; i++) {
-               const uint64_t chr = (uint64_t) ((char *) string->buf->data)[i];
-
-               ret = bt_ctf_field_integer_unsigned_set_value(character, chr);
-               BT_ASSERT(ret == 0);
-               BT_LOGV("Serializing string field's character field: "
-                       "pos-offset=%" PRId64 ", field-addr=%p, "
-                       "index=%" PRId64 ", char-int=%" PRIu64,
-                       pos->offset, character, i, chr);
-               ret = bt_ctf_field_integer_serialize(
-                       (void *) character, pos, native_byte_order);
-               if (ret) {
-                       BT_LOGW_STR("Cannot serialize character field.");
-                       goto end;
-               }
+       BT_LOGV("Serializing string field: addr=%p, native-bo=%s",
+               field, bt_ctf_byte_order_string((int) native_byte_order));
+       ret = bt_ctfser_write_string(ctfser, (const char *) string->buf->data);
+       if (unlikely(ret)) {
+               BT_LOGE("Cannot serialize string field: ret=%d", ret);
+               goto end;
        }
 
 end:
-       bt_ctf_object_put_ref(character);
-       bt_ctf_object_put_ref(character_type);
        return ret;
 }
 
diff --git a/lib/ctf-writer/serialize.c b/lib/ctf-writer/serialize.c
deleted file mode 100644 (file)
index 46ec8af..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
- * serialize.c
- *
- * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
- * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
- * Copyright 2017 Philippe Proulx <pproulx@efficios.com>
- *
- * The original author of the serialization functions for Babeltrace 1
- * is Mathieu Desnoyers. Philippe Proulx modified the functions in 2017
- * to use Babeltrace 2 objects.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#define BT_LOG_TAG "CTF-WRITER-SERIALIZE"
-#include <babeltrace/lib-logging-internal.h>
-
-#include <babeltrace/align-internal.h>
-#include <babeltrace/bitfield-internal.h>
-#include <babeltrace/common-internal.h>
-#include <babeltrace/compat/fcntl-internal.h>
-#include <babeltrace/ctf-writer/field-types-internal.h>
-#include <babeltrace/ctf-writer/field-types.h>
-#include <babeltrace/ctf-writer/fields-internal.h>
-#include <babeltrace/ctf-writer/fields.h>
-#include <babeltrace/ctf-writer/serialize-internal.h>
-#include <babeltrace/ctf-writer/utils-internal.h>
-#include <babeltrace/endian-internal.h>
-#include <babeltrace/mmap-align-internal.h>
-#include <babeltrace/types.h>
-#include <glib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if (FLT_RADIX != 2)
-# error "Unsupported floating point radix"
-#endif
-
-union intval {
-       int64_t signd;
-       uint64_t unsignd;
-};
-
-/*
- * The aligned read/write functions are expected to be faster than the
- * bitfield variants. They will be enabled eventually as an
- * optimisation.
- */
-static
-int aligned_integer_write(struct bt_ctf_stream_pos *pos, union intval value,
-               unsigned int alignment, unsigned int size, bt_bool is_signed,
-               enum bt_ctf_byte_order byte_order)
-{
-       /* reverse byte order */
-       bt_bool rbo = (byte_order != BT_CTF_MY_BYTE_ORDER);
-
-       if (!bt_ctf_stream_pos_align(pos, alignment))
-               return -EFAULT;
-
-       if (!bt_ctf_stream_pos_access_ok(pos, size))
-               return -EFAULT;
-
-       BT_ASSERT(!(pos->offset % CHAR_BIT));
-       if (!is_signed) {
-               switch (size) {
-               case 8:
-               {
-                       uint8_t v = value.unsignd;
-
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 16:
-               {
-                       uint16_t v = value.unsignd;
-
-                       if (rbo)
-                               v = GUINT16_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 32:
-               {
-                       uint32_t v = value.unsignd;
-
-                       if (rbo)
-                               v = GUINT32_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 64:
-               {
-                       uint64_t v = value.unsignd;
-
-                       if (rbo)
-                               v = GUINT64_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               default:
-                       abort();
-               }
-       } else {
-               switch (size) {
-               case 8:
-               {
-                       uint8_t v = value.signd;
-
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 16:
-               {
-                       int16_t v = value.signd;
-
-                       if (rbo)
-                               v = GUINT16_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 32:
-               {
-                       int32_t v = value.signd;
-
-                       if (rbo)
-                               v = GUINT32_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               case 64:
-               {
-                       int64_t v = value.signd;
-
-                       if (rbo)
-                               v = GUINT64_SWAP_LE_BE(v);
-                       memcpy(bt_ctf_stream_pos_get_addr(pos), &v, sizeof(v));
-                       break;
-               }
-               default:
-                       abort();
-               }
-       }
-
-       if (!bt_ctf_stream_pos_move(pos, size))
-               return -EFAULT;
-       return 0;
-}
-
-static
-int integer_write(struct bt_ctf_stream_pos *pos, union intval value,
-       unsigned int alignment, unsigned int size, bt_bool is_signed,
-       enum bt_ctf_byte_order byte_order)
-{
-       if (!(alignment % CHAR_BIT)
-           && !(size % CHAR_BIT)) {
-               return aligned_integer_write(pos, value, alignment,
-                       size, is_signed, byte_order);
-       }
-
-       if (!bt_ctf_stream_pos_align(pos, alignment))
-               return -EFAULT;
-
-       if (!bt_ctf_stream_pos_access_ok(pos, size))
-               return -EFAULT;
-
-       if (!is_signed) {
-               if (byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN)
-                       bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
-                               pos->mmap_base_offset, unsigned char,
-                               pos->offset, size, value.unsignd);
-               else
-                       bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
-                               pos->mmap_base_offset, unsigned char,
-                               pos->offset, size, value.unsignd);
-       } else {
-               if (byte_order == BT_CTF_BYTE_ORDER_LITTLE_ENDIAN)
-                       bt_bitfield_write_le(mmap_align_addr(pos->base_mma) +
-                               pos->mmap_base_offset, unsigned char,
-                               pos->offset, size, value.signd);
-               else
-                       bt_bitfield_write_be(mmap_align_addr(pos->base_mma) +
-                               pos->mmap_base_offset, unsigned char,
-                               pos->offset, size, value.signd);
-       }
-
-       if (!bt_ctf_stream_pos_move(pos, size))
-               return -EFAULT;
-       return 0;
-}
-
-BT_HIDDEN
-int bt_ctf_field_integer_write(struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
-               enum bt_ctf_byte_order native_byte_order)
-{
-       struct bt_ctf_field_type_common_integer *int_type =
-               BT_CTF_FROM_COMMON(field->type);
-       struct bt_ctf_field_common_integer *int_field = BT_CTF_FROM_COMMON(field);
-       enum bt_ctf_byte_order byte_order;
-       union intval value;
-
-       byte_order = (int) int_type->user_byte_order;
-       if ((int) byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
-               byte_order = native_byte_order;
-       }
-
-       value.signd = int_field->payload.signd;
-       value.unsignd = int_field->payload.unsignd;
-       return integer_write(pos, value, int_type->common.alignment,
-               int_type->size, int_type->is_signed,
-               byte_order);
-}
-
-BT_HIDDEN
-int bt_ctf_field_floating_point_write(
-               struct bt_ctf_field_common *field,
-               struct bt_ctf_stream_pos *pos,
-               enum bt_ctf_byte_order native_byte_order)
-{
-       struct bt_ctf_field_type_common_floating_point *flt_type =
-               BT_CTF_FROM_COMMON(field->type);
-       struct bt_ctf_field_common_floating_point *flt_field = BT_CTF_FROM_COMMON(field);
-       enum bt_ctf_byte_order byte_order;
-       union intval value;
-       unsigned int size;
-
-       byte_order = (int) flt_type->user_byte_order;
-       if ((int) byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
-               byte_order = native_byte_order;
-       }
-
-       if (flt_type->mant_dig == FLT_MANT_DIG) {
-               union u32f {
-                       uint32_t u;
-                       float f;
-               } u32f;
-
-               u32f.f = (float) flt_field->payload;
-               value.unsignd = u32f.u;
-               size = 32;
-       } else if (flt_type->mant_dig == DBL_MANT_DIG) {
-               union u64d {
-                       uint64_t u;
-                       double d;
-               } u64d;
-
-               u64d.d = flt_field->payload;
-               value.unsignd = u64d.u;
-               size = 64;
-       } else {
-               return -EINVAL;
-       }
-
-       return integer_write(pos, value, flt_type->common.alignment,
-               size, BT_FALSE, byte_order);
-}
-
-BT_HIDDEN
-void bt_ctf_stream_pos_packet_seek(struct bt_ctf_stream_pos *pos, size_t index,
-       int whence)
-{
-       int ret;
-
-       BT_ASSERT(whence == SEEK_CUR && index == 0);
-
-       if (pos->base_mma) {
-               /* unmap old base */
-               ret = munmap_align(pos->base_mma);
-               if (ret) {
-                       // FIXME: this can legitimately fail?
-                       abort();
-               }
-               pos->base_mma = NULL;
-       }
-
-       /* The writer will add padding */
-       pos->mmap_offset += pos->packet_size / CHAR_BIT;
-       pos->packet_size = PACKET_LEN_INCREMENT;
-       do {
-               ret = bt_posix_fallocate(pos->fd, pos->mmap_offset,
-                       pos->packet_size / CHAR_BIT);
-       } while (ret == EINTR);
-       BT_ASSERT(ret == 0);
-       pos->offset = 0;
-
-       /* map new base. Need mapping length from header. */
-       pos->base_mma = mmap_align(pos->packet_size / CHAR_BIT, pos->prot,
-               pos->flags, pos->fd, pos->mmap_offset);
-       if (pos->base_mma == MAP_FAILED) {
-               // FIXME: this can legitimately fail?
-               abort();
-       }
-}
index 503bee374d1b772ae1ae10df00882d83adb13236..3546facd0bf42a7dd1b155ea5516c5265387934e 100644 (file)
@@ -40,6 +40,7 @@
 #include <babeltrace/ctf-writer/trace.h>
 #include <babeltrace/ctf-writer/writer-internal.h>
 #include <babeltrace/ctf-writer/object.h>
+#include <babeltrace/ctfser-internal.h>
 #include <inttypes.h>
 #include <stdint.h>
 #include <unistd.h>
@@ -359,43 +360,33 @@ end:
 }
 
 static
-int set_packet_context_packet_size(struct bt_ctf_stream *stream)
+int set_packet_context_packet_size(struct bt_ctf_stream *stream,
+               uint64_t packet_size_bits)
 {
        int ret = 0;
        struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
                stream->packet_context, "packet_size");
 
-       BT_ASSERT(stream);
-
-       if (!field) {
-               /* No packet size field found. Not an error, skip. */
-               BT_LOGV("No field named `packet_size` in packet context: skipping: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_ctf_stream_get_name(stream));
-               goto end;
-       }
-
-       ret = bt_ctf_field_integer_unsigned_set_value(field,
-               stream->pos.packet_size);
+       ret = bt_ctf_field_integer_unsigned_set_value(field, packet_size_bits);
        if (ret) {
                BT_LOGW("Cannot set packet context field's `packet_size` integer field's value: "
                        "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
                        stream, bt_ctf_stream_get_name(stream),
-                       field, stream->pos.packet_size);
+                       field, packet_size_bits);
        } else {
                BT_LOGV("Set packet context field's `packet_size` field's value: "
                        "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
                        stream, bt_ctf_stream_get_name(stream),
-                       field, stream->pos.packet_size);
+                       field, packet_size_bits);
        }
 
-end:
        bt_ctf_object_put_ref(field);
        return ret;
 }
 
 static
-int set_packet_context_content_size(struct bt_ctf_stream *stream)
+int set_packet_context_content_size(struct bt_ctf_stream *stream,
+               uint64_t content_size_bits)
 {
        int ret = 0;
        struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
@@ -411,18 +402,17 @@ int set_packet_context_content_size(struct bt_ctf_stream *stream)
                goto end;
        }
 
-       ret = bt_ctf_field_integer_unsigned_set_value(field,
-               stream->pos.offset);
+       ret = bt_ctf_field_integer_unsigned_set_value(field, content_size_bits);
        if (ret) {
                BT_LOGW("Cannot set packet context field's `content_size` integer field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
                        stream, bt_ctf_stream_get_name(stream),
-                       field, stream->pos.offset);
+                       field, content_size_bits);
        } else {
                BT_LOGV("Set packet context field's `content_size` field's value: "
-                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRId64,
+                       "stream-addr=%p, stream-name=\"%s\", field-addr=%p, value=%" PRIu64,
                        stream, bt_ctf_stream_get_name(stream),
-                       field, stream->pos.offset);
+                       field, content_size_bits);
        }
 
 end:
@@ -900,7 +890,8 @@ end:
 }
 
 static
-int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts)
+int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts,
+               uint64_t packet_size_bits, uint64_t content_size_bits)
 {
        int ret = 0;
 
@@ -908,7 +899,7 @@ int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts)
                goto end;
        }
 
-       ret = set_packet_context_packet_size(stream);
+       ret = set_packet_context_packet_size(stream, packet_size_bits);
        if (ret) {
                BT_LOGW("Cannot set packet context's packet size field: "
                        "stream-addr=%p, stream-name=\"%s\"",
@@ -916,7 +907,7 @@ int auto_populate_packet_context(struct bt_ctf_stream *stream, bool set_ts)
                goto end;
        }
 
-       ret = set_packet_context_content_size(stream);
+       ret = set_packet_context_content_size(stream, content_size_bits);
        if (ret) {
                BT_LOGW("Cannot set packet context's content size field: "
                        "stream-addr=%p, stream-name=\"%s\"",
@@ -970,7 +961,7 @@ static
 int create_stream_file(struct bt_ctf_writer *writer,
                struct bt_ctf_stream *stream)
 {
-       int fd;
+       int ret = 0;
        GString *filename = g_string_new(NULL);
        int64_t stream_class_id;
        char *file_path = NULL;
@@ -1028,36 +1019,25 @@ append_ids:
 
        file_path = g_build_filename(writer->path->str, filename->str, NULL);
        if (file_path == NULL) {
-               fd = -1;
+               ret = -1;
                goto end;
        }
 
-       fd = open(file_path,
-               O_RDWR | O_CREAT | O_TRUNC,
-               S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+       ret = bt_ctfser_init(&stream->ctfser, file_path);
        g_free(file_path);
-       if (fd < 0) {
-               BT_LOGW_ERRNO("Failed to open stream file for writing",
-                       ": file_path=\"%s\", filename=\"%s\", ret=%d",
-                       file_path, filename->str, fd);
+       if (ret) {
+               /* bt_ctfser_init() logs errors */
                goto end;
        }
 
        BT_LOGD("Created stream file for writing: "
                "stream-addr=%p, stream-name=\"%s\", "
-               "filename=\"%s\", fd=%d", stream, bt_ctf_stream_get_name(stream),
-               filename->str, fd);
+               "filename=\"%s\"", stream, bt_ctf_stream_get_name(stream),
+               filename->str);
 
 end:
        g_string_free(filename, TRUE);
-       return fd;
-}
-
-static
-void set_stream_fd(struct bt_ctf_stream *stream, int fd)
-{
-       (void) bt_ctf_stream_pos_init(&stream->pos, fd, O_RDWR);
-       stream->pos.fd = fd;
+       return ret;
 }
 
 BT_HIDDEN
@@ -1104,7 +1084,6 @@ struct bt_ctf_stream *bt_ctf_stream_create_with_id(
                goto error;
        }
 
-       stream->pos.fd = -1;
        writer = (struct bt_ctf_writer *)
                bt_ctf_object_get_parent(&trace->common.base);
        stream->last_ts_end = -1ULL;
@@ -1174,8 +1153,6 @@ struct bt_ctf_stream *bt_ctf_stream_create_with_id(
                goto error;
        }
 
-       set_stream_fd(stream, fd);
-
        /* Freeze the writer */
        BT_LOGD_STR("Freezing stream's CTF writer.");
        bt_ctf_writer_freeze(writer);
@@ -1219,14 +1196,6 @@ int bt_ctf_stream_get_discarded_events_count(
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"",
-                       stream, bt_ctf_stream_get_name(stream));
-               ret = -1;
-               goto end;
-       }
-
        *count = (uint64_t) stream->discarded_events;
 
 end:
@@ -1285,11 +1254,6 @@ void bt_ctf_stream_append_discarded_events(struct bt_ctf_stream *stream,
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               goto end;
-       }
-
        events_discarded_field = bt_ctf_field_structure_get_field_by_name(
                stream->packet_context, "events_discarded");
        if (!events_discarded_field) {
@@ -1427,12 +1391,6 @@ int bt_ctf_stream_append_event(struct bt_ctf_stream *stream,
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
        BT_LOGV("Appending event to stream: "
                "stream-addr=%p, stream-name=\"%s\", event-addr=%p, "
                "event-class-name=\"%s\", event-class-id=%" PRId64,
@@ -1511,13 +1469,6 @@ struct bt_ctf_field *bt_ctf_stream_get_packet_context(struct bt_ctf_stream *stre
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"", stream,
-                       bt_ctf_stream_get_name(stream));
-               goto end;
-       }
-
        packet_context = stream->packet_context;
        if (packet_context) {
                bt_ctf_object_get_ref(packet_context);
@@ -1538,12 +1489,6 @@ int bt_ctf_stream_set_packet_context(struct bt_ctf_stream *stream,
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
        field_type = bt_ctf_field_get_type(field);
        if (bt_ctf_field_type_common_compare((void *) field_type,
                        stream->common.stream_class->packet_context_field_type)) {
@@ -1577,13 +1522,6 @@ struct bt_ctf_field *bt_ctf_stream_get_packet_header(struct bt_ctf_stream *strea
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW("Invalid parameter: stream is not a CTF writer stream: "
-                       "stream-addr=%p, stream-name=\"%s\"", stream,
-                       bt_ctf_stream_get_name(stream));
-               goto end;
-       }
-
        packet_header = stream->packet_header;
        if (packet_header) {
                bt_ctf_object_get_ref(packet_header);
@@ -1605,12 +1543,6 @@ int bt_ctf_stream_set_packet_header(struct bt_ctf_stream *stream,
                goto end;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
        trace = (struct bt_ctf_trace *)
                bt_ctf_object_get_parent(&stream->common.base);
 
@@ -1673,10 +1605,12 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
 {
        int ret = 0;
        size_t i;
-       struct bt_ctf_stream_pos packet_context_pos;
+       uint64_t packet_context_offset_bits;
        struct bt_ctf_trace *trace;
        enum bt_ctf_byte_order native_byte_order;
        bool has_packet_size = false;
+       uint64_t packet_size_bits = 0;
+       uint64_t content_size_bits = 0;
 
        if (!stream) {
                BT_LOGW_STR("Invalid parameter: stream is NULL.");
@@ -1684,12 +1618,6 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                goto end_no_stream;
        }
 
-       if (stream->pos.fd < 0) {
-               BT_LOGW_STR("Invalid parameter: stream is not a CTF writer stream.");
-               ret = -1;
-               goto end;
-       }
-
        if (stream->packet_context) {
                struct bt_ctf_field *packet_size_field;
 
@@ -1728,23 +1656,25 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                goto end;
        }
 
-       ret = auto_populate_packet_context(stream, true);
+       /* Initialize packet/content sizes to `0`; we will overwrite later */
+       ret = auto_populate_packet_context(stream, true, 0, 0);
        if (ret) {
                BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
                ret = -1;
                goto end;
        }
 
-       /* mmap the next packet */
-       BT_LOGV("Seeking to the next packet: pos-offset=%" PRId64,
-               stream->pos.offset);
-       bt_ctf_stream_pos_packet_seek(&stream->pos, 0, SEEK_CUR);
-       BT_ASSERT(stream->pos.packet_size % 8 == 0);
+       ret = bt_ctfser_open_packet(&stream->ctfser);
+       if (ret) {
+               /* bt_ctfser_open_packet() logs errors */
+               ret = -1;
+               goto end;
+       }
 
        if (stream->packet_header) {
-               BT_LOGV_STR("Serializing packet header field.");
+               BT_LOGV_STR("Serializing packet header field (initial).");
                ret = bt_ctf_field_serialize_recursive(stream->packet_header,
-                       &stream->pos, native_byte_order);
+                       &stream->ctfser, native_byte_order);
                if (ret) {
                        BT_LOGW("Cannot serialize stream's packet header field: "
                                "field-addr=%p", stream->packet_header);
@@ -1753,12 +1683,15 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
        }
 
        if (stream->packet_context) {
+               /* Save packet context's position to overwrite it later */
+               packet_context_offset_bits =
+                       bt_ctfser_get_offset_in_current_packet_bits(
+                               &stream->ctfser);
+
                /* Write packet context */
-               memcpy(&packet_context_pos, &stream->pos,
-                       sizeof(packet_context_pos));
-               BT_LOGV_STR("Serializing packet context field.");
+               BT_LOGV_STR("Serializing packet context field (initial).");
                ret = bt_ctf_field_serialize_recursive(stream->packet_context,
-                       &stream->pos, native_byte_order);
+                       &stream->ctfser, native_byte_order);
                if (ret) {
                        BT_LOGW("Cannot serialize stream's packet context field: "
                                "field-addr=%p", stream->packet_context);
@@ -1777,17 +1710,18 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
 
                BT_LOGV("Serializing event: index=%zu, event-addr=%p, "
                        "event-class-name=\"%s\", event-class-id=%" PRId64 ", "
-                       "pos-offset=%" PRId64 ", packet-size=%" PRIu64,
+                       "ser-offset=%" PRIu64,
                        i, event, bt_ctf_event_class_get_name(event_class),
                        bt_ctf_event_class_get_id(event_class),
-                       stream->pos.offset, stream->pos.packet_size);
+                       bt_ctfser_get_offset_in_current_packet_bits(
+                               &stream->ctfser));
 
                /* Write event header */
                if (event->common.header_field) {
                        BT_LOGV_STR("Serializing event's header field.");
                        ret = bt_ctf_field_serialize_recursive(
                                (void *) event->common.header_field->field,
-                               &stream->pos, native_byte_order);
+                               &stream->ctfser, native_byte_order);
                        if (ret) {
                                BT_LOGW("Cannot serialize event's header field: "
                                        "field-addr=%p",
@@ -1801,7 +1735,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                        BT_LOGV_STR("Serializing event's stream event context field.");
                        ret = bt_ctf_field_serialize_recursive(
                                (void *) event->common.stream_event_context_field,
-                               &stream->pos, native_byte_order);
+                               &stream->ctfser, native_byte_order);
                        if (ret) {
                                BT_LOGW("Cannot serialize event's stream event context field: "
                                        "field-addr=%p",
@@ -1811,50 +1745,50 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                }
 
                /* Write event content */
-               ret = bt_ctf_event_serialize(event,
-                       &stream->pos, native_byte_order);
+               ret = bt_ctf_event_serialize(event, &stream->ctfser,
+                       native_byte_order);
                if (ret) {
                        /* bt_ctf_event_serialize() logs errors */
                        goto end;
                }
        }
 
-       if (!has_packet_size && stream->pos.offset % 8 != 0) {
+       content_size_bits = bt_ctfser_get_offset_in_current_packet_bits(
+               &stream->ctfser);
+
+       if (!has_packet_size && content_size_bits % 8 != 0) {
                BT_LOGW("Stream's packet context field type has no `packet_size` field, "
                        "but current content size is not a multiple of 8 bits: "
-                       "content-size=%" PRId64 ", "
+                       "content-size=%" PRIu64 ", "
                        "packet-size=%" PRIu64,
-                       stream->pos.offset,
-                       stream->pos.packet_size);
+                       content_size_bits,
+                       packet_size_bits);
                ret = -1;
                goto end;
        }
 
-       BT_ASSERT(stream->pos.packet_size % 8 == 0);
-
-       /*
-        * Remove extra padding bytes.
-        */
-       stream->pos.packet_size = (stream->pos.offset + 7) & ~7;
+       /* Set packet size; make it a multiple of 8 */
+       packet_size_bits = (content_size_bits + 7) & ~UINT64_C(7);
 
        if (stream->packet_context) {
                /*
-                * The whole packet is serialized at this point. Make sure that,
-                * if `packet_size` is missing, the current content size is
-                * equal to the current packet size.
+                * The whole packet is serialized at this point. Make
+                * sure that, if `packet_size` is missing, the current
+                * content size is equal to the current packet size.
                 */
-               struct bt_ctf_field *field = bt_ctf_field_structure_get_field_by_name(
-                       stream->packet_context, "content_size");
+               struct bt_ctf_field *field =
+                       bt_ctf_field_structure_get_field_by_name(
+                               stream->packet_context, "content_size");
 
                bt_ctf_object_put_ref(field);
                if (!field) {
-                       if (stream->pos.offset != stream->pos.packet_size) {
+                       if (content_size_bits != packet_size_bits) {
                                BT_LOGW("Stream's packet context's `content_size` field is missing, "
                                        "but current packet's content size is not equal to its packet size: "
-                                       "content-size=%" PRId64 ", "
+                                       "content-size=%" PRIu64 ", "
                                        "packet-size=%" PRIu64,
-                                       stream->pos.offset,
-                                       stream->pos.packet_size);
+                                       bt_ctfser_get_offset_in_current_packet_bits(&stream->ctfser),
+                                       packet_size_bits);
                                ret = -1;
                                goto end;
                        }
@@ -1864,12 +1798,11 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
                 * Overwrite the packet context now that the stream
                 * position's packet and content sizes have the correct
                 * values.
-                *
-                * Copy base_mma as the packet may have been remapped
-                * (e.g. when a packet is resized).
                 */
-               packet_context_pos.base_mma = stream->pos.base_mma;
-               ret = auto_populate_packet_context(stream, false);
+               bt_ctfser_set_offset_in_current_packet_bits(&stream->ctfser,
+                       packet_context_offset_bits);
+               ret = auto_populate_packet_context(stream, false,
+                       packet_size_bits, content_size_bits);
                if (ret) {
                        BT_LOGW_STR("Cannot automatically populate the stream's packet context field.");
                        ret = -1;
@@ -1878,7 +1811,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
 
                BT_LOGV("Rewriting (serializing) packet context field.");
                ret = bt_ctf_field_serialize_recursive(stream->packet_context,
-                       &packet_context_pos, native_byte_order);
+                       &stream->ctfser, native_byte_order);
                if (ret) {
                        BT_LOGW("Cannot serialize stream's packet context field: "
                                "field-addr=%p", stream->packet_context);
@@ -1888,7 +1821,7 @@ int bt_ctf_stream_flush(struct bt_ctf_stream *stream)
 
        g_ptr_array_set_size(stream->events, 0);
        stream->flushed_packet_count++;
-       stream->size += stream->pos.packet_size / CHAR_BIT;
+       bt_ctfser_close_current_packet(&stream->ctfser, packet_size_bits / 8);
 
 end:
        /* Reset automatically-set fields. */
@@ -1900,18 +1833,10 @@ end:
                reset_structure_field(stream->packet_context, "events_discarded");
        }
 
-       if (ret < 0) {
-               /*
-                * We failed to write the packet. Its size is therefore set to 0
-                * to ensure the next mapping is done in the same place rather
-                * than advancing by "stream->pos.packet_size", which would
-                * leave a corrupted packet in the trace.
-                */
-               stream->pos.packet_size = 0;
-       } else {
-               BT_LOGV("Flushed stream's current packet: content-size=%" PRId64 ", "
-                       "packet-size=%" PRIu64,
-                       stream->pos.offset, stream->pos.packet_size);
+       if (ret == 0) {
+               BT_LOGV("Flushed stream's current packet: "
+                       "content-size=%" PRIu64 ", packet-size=%" PRIu64,
+                       content_size_bits, packet_size_bits);
        }
 
 end_no_stream:
@@ -1927,30 +1852,7 @@ void bt_ctf_stream_destroy(struct bt_ctf_object *obj)
                stream, bt_ctf_stream_get_name(stream));
 
        bt_ctf_stream_common_finalize(BT_CTF_TO_COMMON(stream));
-       (void) bt_ctf_stream_pos_fini(&stream->pos);
-
-       if (stream->pos.fd >= 0) {
-               int ret;
-
-               /*
-                * Truncate the file's size to the minimum required to fit the
-                * last packet as we might have grown it too much on the last
-                * mmap.
-                */
-               do {
-                       ret = ftruncate(stream->pos.fd, stream->size);
-               } while (ret == -1 && errno == EINTR);
-               if (ret) {
-                       BT_LOGE_ERRNO("Failed to truncate stream file",
-                               ": ret=%d, size=%" PRIu64,
-                               ret, (uint64_t) stream->size);
-               }
-
-               if (close(stream->pos.fd)) {
-                       BT_LOGE_ERRNO("Failed to close stream file",
-                               ": ret=%d", ret);
-               }
-       }
+       bt_ctfser_fini(&stream->ctfser);
 
        if (stream->events) {
                BT_LOGD_STR("Putting events.");
index b0e3dc45ad276c8689bafcb71e22b5c8d36afd68..a69b1d695ff5d34e250856dbe8b9d529a26065dc 100644 (file)
@@ -373,7 +373,11 @@ int bt_ctf_writer_set_byte_order(struct bt_ctf_writer *writer,
        }
 
        if (byte_order == BT_CTF_BYTE_ORDER_NATIVE) {
-               byte_order = BT_CTF_MY_BYTE_ORDER;
+               if (BYTE_ORDER == LITTLE_ENDIAN) {
+                       byte_order = BT_CTF_BYTE_ORDER_LITTLE_ENDIAN;
+               } else {
+                       byte_order = BT_CTF_BYTE_ORDER_BIG_ENDIAN;
+               }
        }
 
        ret = bt_ctf_trace_set_native_byte_order(writer->trace,
This page took 0.057043 seconds and 4 git commands to generate.