]> git.ipfire.org Git - telemetry.git/commitdiff
buffer: Add a buffer implementation to write larger data to
authorMichael Tremer <michael.tremer@ipfire.org>
Wed, 8 Oct 2025 15:42:55 +0000 (15:42 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Wed, 8 Oct 2025 15:42:55 +0000 (15:42 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
Makefile.am
src/daemon/buffer.c [new file with mode: 0644]
src/daemon/buffer.h [new file with mode: 0644]

index f3b17e316fdce8778472315f46f3e8803ca5138f..5ad4d4c30d65ee1806c424d82f9507d58bcfe0cd 100644 (file)
@@ -92,6 +92,8 @@ bin_PROGRAMS += \
 dist_collectyd_SOURCES = \
        src/daemon/args.c \
        src/daemon/args.h \
+       src/daemon/buffer.c \
+       src/daemon/buffer.h \
        src/daemon/bus.c \
        src/daemon/bus.h \
        src/daemon/colors.h \
diff --git a/src/daemon/buffer.c b/src/daemon/buffer.c
new file mode 100644 (file)
index 0000000..4fb187b
--- /dev/null
@@ -0,0 +1,222 @@
+/*#############################################################################
+#                                                                             #
+# collecty - A system statistics collection daemon for IPFire                 #
+# Copyright (C) 2025 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ctx.h"
+#include "buffer.h"
+
+struct collecty_buffer {
+       collecty_ctx* ctx;
+       int nrefs;
+
+       // File Handle
+       FILE* f;
+
+       // Flags
+       enum {
+               COLLECTY_BUFFER_LOCKED = (1 << 0),
+       } flags;
+
+       // Data & Length
+       char* data;
+       size_t length;
+
+       // Pointer
+       off_t p;
+};
+
+static void collecty_buffer_free(collecty_buffer* self) {
+       if (self->f)
+               fclose(self->f);
+       if (self->data)
+               free(self->data);
+       if (self->ctx)
+               collecty_ctx_unref(self->ctx);
+       free(self);
+}
+
+int collecty_buffer_create(collecty_buffer** buffer, collecty_ctx* ctx) {
+       collecty_buffer* self = NULL;
+
+       // Allocate some memory
+       self = calloc(1, sizeof(*self));
+       if (!self)
+               return -errno;
+
+       // Initialize the reference counter
+       self->nrefs = 1;
+
+       // Store a reference to the context
+       self->ctx = collecty_ctx_ref(ctx);
+
+       // Return pointer
+       *buffer = self;
+       return 0;
+}
+
+collecty_buffer* collecty_buffer_ref(collecty_buffer* self) {
+       ++self->nrefs;
+       return self;
+}
+
+collecty_buffer* collecty_buffer_unref(collecty_buffer* self) {
+       if (--self->nrefs > 0)
+               return self;
+
+       collecty_buffer_free(self);
+       return NULL;
+}
+
+static int collecty_buffer_has_flag(collecty_buffer* self, int flag) {
+       return self->flags & flag;
+}
+
+static void collecty_buffer_lock(collecty_buffer* self) {
+       self->flags |= COLLECTY_BUFFER_LOCKED;
+}
+
+static ssize_t __collecty_buffer_read(void* cookie, char* buffer, size_t length) {
+       collecty_buffer* self = cookie;
+
+       // Determine how much data is left
+       size_t bytes_left = self->length - self->p;
+
+       // Cap reading beyond the end
+       if (length > bytes_left)
+               length = bytes_left;
+
+       // We have reached the end already
+       if (!length)
+               return 0;
+
+       // Check if p is in range
+       if (self->p < 0 || self->p > (off_t)self->length) {
+               errno = -ERANGE;
+               return -1;
+       }
+
+       // Copy the data to the buffer
+       memcpy(buffer, self->data + self->p, length);
+
+       // Advance p
+       self->p += length;
+
+       return length;
+}
+
+static int __collecty_buffer_seek(void* cookie, off_t* offset, int whence) {
+       collecty_buffer* self = cookie;
+
+       // Update p
+       switch (whence) {
+               case SEEK_SET:
+                       self->p = *offset;
+                       break;
+
+               case SEEK_CUR:
+                       self->p += *offset;
+                       break;
+
+               case SEEK_END:
+                       self->p = self->length + *offset;
+       }
+
+       // Update offset
+       *offset = self->p;
+
+       return 0;
+}
+
+static int __collecty_buffer_close(void* cookie) {
+       collecty_buffer* self = cookie;
+
+       // Drop the reference to the buffer
+       collecty_buffer_unref(self);
+
+       return 0;
+}
+
+cookie_io_functions_t collecty_buffer_io_funcs = {
+       .read  = __collecty_buffer_read,
+       .seek  = __collecty_buffer_seek,
+       .close = __collecty_buffer_close,
+};
+
+FILE* collecty_buffer_fopen(collecty_buffer* self, const char* mode) {
+       // Check if mode was passed
+       if (!mode) {
+               errno = EINVAL;
+               return NULL;
+       }
+
+       // We only support read mode
+       if (!(*mode == 'r')) {
+               errno = -ENOTSUP;
+               return NULL;
+       }
+
+       // Lock the buffer
+       collecty_buffer_lock(self);
+
+       // Reset p
+       self->p = 0;
+
+       // Return a file handle
+       return fopencookie(collecty_buffer_ref(self), mode, collecty_buffer_io_funcs);
+}
+
+int collecty_buffer_write(collecty_buffer* self, const char* chunk, size_t length) {
+       char* data = NULL;
+       int r;
+
+       // Cannot write if the buffer is locked
+       if (collecty_buffer_has_flag(self, COLLECTY_BUFFER_LOCKED))
+               return -ENOTSUP;
+
+       // Increase the size of the buffer
+       data = realloc(self->data, self->length + length);
+       if (!data) {
+               ERROR(self->ctx, "Failed to increase the buffer size: %m\n");
+               r = -errno;
+               goto ERROR;
+       }
+
+       // Copy the chunk
+       memcpy(data + self->length, chunk, length);
+
+       // Update the data pointer
+       self->data = data;
+
+       // Increase the size of the buffer
+       self->length += length;
+
+       // Done
+       return 0;
+
+ERROR:
+       if (data)
+               free(data);
+
+       return r;
+}
diff --git a/src/daemon/buffer.h b/src/daemon/buffer.h
new file mode 100644 (file)
index 0000000..bc6939e
--- /dev/null
@@ -0,0 +1,39 @@
+/*#############################################################################
+#                                                                             #
+# collecty - A system statistics collection daemon for IPFire                 #
+# Copyright (C) 2025 IPFire Development Team                                  #
+#                                                                             #
+# This program is free software: you can redistribute it and/or modify        #
+# it under the terms of the GNU General Public License as published by        #
+# the Free Software Foundation, either version 3 of the License, or           #
+# (at your option) any later version.                                         #
+#                                                                             #
+# This program is distributed in the hope that it will be useful,             #
+# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
+# GNU General Public License for more details.                                #
+#                                                                             #
+# You should have received a copy of the GNU General Public License           #
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
+#                                                                             #
+#############################################################################*/
+
+#ifndef COLLECTY_BUFFER_H
+#define COLLECTY_BUFFER_H
+
+#include <stdio.h>
+
+typedef struct collecty_buffer collecty_buffer;
+
+#include "ctx.h"
+
+int collecty_buffer_create(collecty_buffer** buffer, collecty_ctx* ctx);
+
+collecty_buffer* collecty_buffer_ref(collecty_buffer* self);
+collecty_buffer* collecty_buffer_unref(collecty_buffer* self);
+
+FILE* collecty_buffer_fopen(collecty_buffer* self, const char* mode);
+
+int collecty_buffer_write(collecty_buffer* self, const char* chunk, size_t length);
+
+#endif /* COLLECTY_BUFFER_H */