Skip to content

Commit

Permalink
iiod-client: Add support for ZSTD-compressed metadata
Browse files Browse the repository at this point in the history
If compiled WITH_ZSTD, use the ZPRINT command to receive a
ZSTD-compressed payload that can be decompressed into the original XML
string of the remote context. If the remote IIOD does not support
ZPRINT, it will simply revert to using PRINT instead.

This can dramatically speed up context creation when using a slow
transport (e.g. serial), as the XML strings can be really big.

For instance, the XML string of the ADALM-Pluto is close to 25 KiB.
On a standard 57600 bps UART connection, this would take about ~3.4
seconds to transfer. The compressed payload amounts to only about
3.7 KiB, which would take about ~0.5 seconds to transfer.

Signed-off-by: Paul Cercueil <[email protected]>
  • Loading branch information
pcercuei committed Apr 15, 2021
1 parent fbc2f1a commit c188d75
Showing 1 changed file with 59 additions and 4 deletions.
63 changes: 59 additions & 4 deletions iiod-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@

#include "debug.h"
#include "iiod-client.h"
#include "iio-config.h"
#include "iio-lock.h"
#include "iio-private.h"

#include <errno.h>
#include <inttypes.h>
#include <string.h>
#include <stdio.h>
#if WITH_ZSTD
#include <zstd.h>
#endif

struct iiod_client {
struct iio_context_pdata *pdata;
Expand Down Expand Up @@ -504,18 +508,29 @@ ssize_t iiod_client_write_attr(struct iiod_client *client, void *desc,
return ret;
}

struct iio_context * iiod_client_create_context(
struct iiod_client *client, void *desc)
static struct iio_context *
iiod_client_create_context_private(struct iiod_client *client,
void *desc, bool zstd)
{
const char *cmd = zstd ? "ZPRINT\r\n" : "PRINT\r\n";
struct iio_context *ctx = NULL;
size_t xml_len;
char *xml;
int ret;

iio_mutex_lock(client->lock);
ret = iiod_client_exec_command(client, desc, "PRINT\r\n");
if (ret < 0)
ret = iiod_client_exec_command(client, desc, cmd);
if (ret < 0) {
if (ret == -EINVAL && zstd) {
/* If the ZPRINT command does not exist, try again
* with the regular PRINT command. */
iio_mutex_unlock(client->lock);

return iiod_client_create_context_private(client, desc, false);
}

goto out_unlock;
}

xml_len = (size_t) ret;
xml = malloc(xml_len + 1);
Expand All @@ -529,6 +544,41 @@ struct iio_context * iiod_client_create_context(
if (ret < 0)
goto out_free_xml;

#if WITH_ZSTD
if (zstd) {
unsigned long long len;
char *xml_zstd;

IIO_DEBUG("Received ZSTD-compressed XML string.\n");

len = ZSTD_getFrameContentSize(xml, xml_len);
if (len == ZSTD_CONTENTSIZE_UNKNOWN ||
len == ZSTD_CONTENTSIZE_ERROR) {
ret = -EIO;
goto out_free_xml;
}

xml_zstd = malloc(len);
if (!xml_zstd) {
ret = -ENOMEM;
goto out_free_xml;
}

xml_len = ZSTD_decompress(xml_zstd, len, xml, xml_len);
if (ZSTD_isError(xml_len)) {
IIO_ERROR("Unable to decompress ZSTD data: %s\n",
ZSTD_getErrorName(xml_len));
ret = -EIO;
free(xml_zstd);
goto out_free_xml;
}

/* Free compressed data, make "xml" point to uncompressed data */
free(xml);
xml = xml_zstd;
}
#endif

ctx = iio_create_xml_context_mem(xml, xml_len);
if (!ctx)
ret = -errno;
Expand All @@ -542,6 +592,11 @@ struct iio_context * iiod_client_create_context(
return ctx;
}

struct iio_context * iiod_client_create_context(struct iiod_client *client, void *desc)
{
return iiod_client_create_context_private(client, desc, WITH_ZSTD);
}

int iiod_client_open_unlocked(struct iiod_client *client, void *desc,
const struct iio_device *dev, size_t samples_count, bool cyclic)
{
Expand Down

0 comments on commit c188d75

Please sign in to comment.