@@ -25,6 +25,7 @@ ifeq ($(VSOCK_DEFINED), 1)
OBJS += trace-timesync-ptp.o
OBJS += trace-timesync-kvm.o
endif
+OBJS += trace-compress.o
# Additional util objects
OBJS += trace-blk-hack.o
@@ -471,6 +471,28 @@ void tracecmd_tsync_free(struct tracecmd_time_sync *tsync);
int tracecmd_write_guest_time_shift(struct tracecmd_output *handle,
struct tracecmd_time_sync *tsync);
+/* --- Compression --- */
+struct tracecmd_compress_proto;
+struct tracecmd_compress_proto *tracecmd_compress_proto_get(const char *name, const char *version);
+struct tracecmd_compress_proto *tracecmd_compress_proto_select(void);
+int tracecmd_compress_proto_register(const char *name, const char *version, int weight,
+ int (*compress)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes),
+ int (*uncompress)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes),
+ unsigned int (*comress_size)(unsigned int bytes),
+ bool (*is_supported)(const char *name, const char *version));
+int tracecmd_compress_protos_get(char ***names, char ***versions);
+int tracecmd_compress_proto_get_name(struct tracecmd_compress_proto *proto,
+ const char **name, const char **version);
+int tracecmd_compress_data(struct tracecmd_compress_proto *proto,
+ char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes);
+int tracecmd_uncompress_data(struct tracecmd_compress_proto *proto,
+ char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes);
+unsigned int tracecmd_get_compress_size(struct tracecmd_compress_proto *proto, unsigned int bytes);
+
/* --- Plugin handling --- */
extern struct tep_plugin_option trace_ftrace_options[];
@@ -30,5 +30,7 @@ void tracecmd_fatal(const char *fmt, ...);
#endif
#endif
+int tracecmd_compress_init(void);
+void tracecmd_compress_free(void);
#endif /* _TRACE_CMD_LOCAL_H */
new file mode 100644
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: LGPL-2.1
+/*
+ * Copyright (C) 2021, VMware, Tzvetomir Stoyanov tz.stoyanov@gmail.com>
+ *
+ */
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "trace-cmd-private.h"
+#include "trace-cmd-local.h"
+
+struct tracecmd_compress_proto {
+ struct tracecmd_compress_proto *next;
+ char *proto_name;
+ char *proto_version;
+ int weight;
+
+ int (*comress_block)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes);
+ int (*uncompress_block)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes);
+ unsigned int (*comress_size)(unsigned int bytes);
+ bool (*is_supported)(const char *name, const char *version);
+};
+
+static struct tracecmd_compress_proto *proto_list;
+
+/**
+ * tracecmd_compress_init - initialize the library with available compression algorithms
+ *
+ * Returns 0. If no compression algorithms are available, a warning is printed.
+ */
+int tracecmd_compress_init(void)
+{
+ struct timeval time;
+ int count = 0;
+
+ gettimeofday(&time, NULL);
+ srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
+
+/* toDo: add here initialization of compression protocols */
+
+ if (!count)
+ tracecmd_warning("No compression support available");
+
+ return 0;
+}
+
+/**
+ * tracecmd_compress_proto_get - get handler to compression algorithm from name and version
+ * @name: name of the compression algorithm.
+ * @version: version of the compression algorithm.
+ *
+ * Returns a handler to compression algorithm, or NULL if algorithm with given name and version is
+ * not found.
+ */
+struct tracecmd_compress_proto *tracecmd_compress_proto_get(const char *name, const char *version)
+{
+ struct tracecmd_compress_proto *proto = proto_list;
+
+ if (!name)
+ return NULL;
+
+ while (proto) {
+ if (proto->is_supported && proto->is_supported(name, version))
+ return proto;
+ proto = proto->next;
+ }
+ return NULL;
+}
+
+/**
+ * tracecmd_compress_proto_select - select compression algorithm
+ *
+ * The algorithm with the lowest weight is selected.
+ * Returns a handler to compression algorithm, or NULL if no algorithms are available.
+ */
+struct tracecmd_compress_proto *tracecmd_compress_proto_select(void)
+{
+ struct tracecmd_compress_proto *proto = proto_list;
+ struct tracecmd_compress_proto *selected = NULL;
+
+ while (proto) {
+ if (!selected || selected->weight > proto->weight)
+ selected = proto;
+ proto = proto->next;
+ }
+
+ return selected;
+}
+
+/**
+ * tracecmd_compress_proto_get_name - get name and version of compression algorithm
+ * @proto: handler to compression algorithm.
+ * @name: return, name of the compression algorithm.
+ * @version: return, version of the compression algorithm.
+ *
+ * Returns 0 on success, or -1 in case of an error. If 0 is returned, the name and version of the
+ * algorithm are stored in @name and @version. The returned strings must *not* be freed.
+ */
+int tracecmd_compress_proto_get_name(struct tracecmd_compress_proto *proto,
+ const char **name, const char **version)
+{
+ if (!proto)
+ return -1;
+ if (name)
+ *name = proto->proto_name;
+ if (version)
+ *version = proto->proto_version;
+ return 0;
+}
+
+/**
+ * tracecmd_compress_proto_register - register a new compression algorithm
+ * @name: name of the compression algorithm.
+ * @version: version of the compression algorithm.
+ * @weight: weight of the compression algorithm, lower is better.
+ * @compress: compression hook, called to compress a memory block.
+ * @uncompress: uncompression hook, called to uncompress a memory block.
+ * @comress_size: hook, called to get the required minimum size of the buffer for compression
+ * given number of bytes.
+ * @is_supported: check hook, called to check if compression with given name and version is
+ * supported by this plugin.
+ *
+ * Returns 0 on success, or -1 in case of an error. If algorithm with given name and version is
+ * already registered, -1 is returned.
+ */
+int tracecmd_compress_proto_register(const char *name, const char *version, int weight,
+ int (*compress)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes),
+ int (*uncompress)(char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes),
+ unsigned int (*comress_size)(unsigned int bytes),
+ bool (*is_supported)(const char *name, const char *version))
+{
+ struct tracecmd_compress_proto *new;
+
+ if (!name || !compress || !uncompress)
+ return -1;
+ if (tracecmd_compress_proto_get(name, version))
+ return -1;
+
+ new = calloc(1, sizeof(*new));
+ if (!new)
+ return -1;
+
+ new->proto_name = strdup(name);
+ if (!new->proto_name)
+ goto error;
+ new->proto_version = strdup(version);
+ if (!new->proto_version)
+ goto error;
+ new->comress_block = compress;
+ new->uncompress_block = uncompress;
+ new->comress_size = comress_size;
+ new->is_supported = is_supported;
+ new->weight = weight;
+ new->next = proto_list;
+ proto_list = new;
+ return 0;
+
+error:
+ free(new->proto_name);
+ free(new->proto_version);
+ free(new);
+ return -1;
+}
+
+/**
+ * tracecmd_compress_free - free the library resources, related to available compression algorithms
+ *
+ */
+void tracecmd_compress_free(void)
+{
+ struct tracecmd_compress_proto *proto = proto_list;
+ struct tracecmd_compress_proto *del;
+
+ while (proto) {
+ del = proto;
+ proto = proto->next;
+ free(del->proto_name);
+ free(del->proto_version);
+ free(del);
+ }
+ proto_list = NULL;
+}
+
+/**
+ * tracecmd_compress_data - compress a memory block
+ * @proto: handle to compression algorithm that will be used to compress the data.
+ * @in: pointer to the data that will be compressed.
+ * @in_bytes: number of bytes in @in.
+ * @out: pre-allocated memory to store the compressed data. It must be at least the size returned
+ * by tracecmd_get_compress_size().
+ * @out_bytes: size of the allocated memory in @out. On successful return, @out_bytes is updated
+ * with the size of the compressed data.
+ *
+ * Returns 0 on success, or -1 in case of an error.
+ */
+int tracecmd_compress_data(struct tracecmd_compress_proto *proto,
+ char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes)
+{
+ if (proto && proto->comress_block)
+ return proto->comress_block(in, in_bytes, out, out_bytes);
+ return -1;
+}
+
+/**
+ * tracecmd_uncompress_data - uncompress a memory block
+ * @proto: handle to compression algorithm that will be used to uncompress the data.
+ * @in: pointer to the data that will be uncompressed.
+ * @in_bytes: number of bytes in @in.
+ * @out: pre-allocated memory to store the uncompressed data.
+ * @out_bytes: size of the allocated memory in @out. On successful return, @out_bytes is updated
+ * with the size of the uncompressed data.
+ *
+ * Returns 0 on success, or -1 in case of an error.
+ */
+int tracecmd_uncompress_data(struct tracecmd_compress_proto *proto,
+ char *in, unsigned int in_bytes,
+ char *out, unsigned int *out_bytes)
+{
+ if (proto && proto->uncompress_block)
+ return proto->uncompress_block(in, in_bytes, out, out_bytes);
+ return -1;
+}
+
+/**
+ * tracecmd_get_compress_size - get the buffer size, required to compress given data
+ * @proto: handle to compression algorithm that will be used to compress the data.
+ * @bytes: number of bytes that will be compressed.
+ *
+ * Returns the required size of the buffer for compression of @bytes, or 0 in case of an error
+ */
+unsigned int tracecmd_get_compress_size(struct tracecmd_compress_proto *proto, unsigned int bytes)
+{
+ if (proto && proto->comress_size)
+ return proto->comress_size(bytes);
+ return -1;
+}
+
+
+/**
+ * tracecmd_compress_protos_get - get a list of all supported compression algorithms and versions
+ * @names: return, array with names of all supported compression algorithms
+ * @versions: return, array with versions of all supported compression algorithms
+ *
+ * On success, the size of @names and @versions arrays is returned. Those arrays are allocated by
+ * the API and must be freed with free() by the caller. Both arrays are with same size, each name
+ * from @names corresponds to a version from @versions.
+ * On error -1 is returned and @names and @versions arrays are not allocated.
+ */
+int tracecmd_compress_protos_get(char ***names, char ***versions)
+{
+ struct tracecmd_compress_proto *proto = proto_list;
+ char **n = NULL;
+ char **v = NULL;
+ int c, i;
+
+ for (c = 0; proto; proto = proto->next)
+ ;
+
+ if (c < 1)
+ return c;
+
+ n = calloc(c, sizeof(char *));
+ if (!n)
+ goto error;
+ v = calloc(c, sizeof(char *));
+ if (!n)
+ goto error;
+
+ for (i = 0; proto; proto = proto->next) {
+ n[i] = proto->proto_name;
+ v[i] = proto->proto_version;
+ }
+
+ names = &n;
+ versions = &v;
+ return c;
+
+error:
+ free(n);
+ free(v);
+ return -1;
+}
@@ -592,9 +592,12 @@ bool tracecmd_is_version_supported(unsigned int version)
int tracecmd_lib_init(void)
{
+
+ tracecmd_compress_init();
return 0;
}
void tracecmd_lib_free(void)
{
+ tracecmd_compress_free();
}
Added infrastructure to trace-cmd library for compression. Introduced various new APIs to work with this new functionality: tracecmd_compress_proto_get() tracecmd_compress_protos_get() tracecmd_compress_proto_get_name() tracecmd_compress_proto_select() tracecmd_compress_proto_register() tracecmd_compress_data() tracecmd_uncompress_data() tracecmd_get_compress_size() The compression algorithms are not part of this patch. Signed-off-by: Tzvetomir Stoyanov (VMware) <tz.stoyanov@gmail.com> --- lib/trace-cmd/Makefile | 1 + .../include/private/trace-cmd-private.h | 22 ++ lib/trace-cmd/include/trace-cmd-local.h | 2 + lib/trace-cmd/trace-compress.c | 287 ++++++++++++++++++ lib/trace-cmd/trace-util.c | 3 + 5 files changed, 315 insertions(+) create mode 100644 lib/trace-cmd/trace-compress.c