summary refs log tree commit diff
path: root/mico-store.c
diff options
context:
space:
mode:
Diffstat (limited to 'mico-store.c')
-rw-r--r--mico-store.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/mico-store.c b/mico-store.c
new file mode 100644
index 0000000..1083928
--- /dev/null
+++ b/mico-store.c
@@ -0,0 +1,237 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include <zip.h>
+
+#define STB_DS_IMPLEMENTATION
+#include "stb_ds.h"
+
+struct event {
+	int64_t t;
+	double v;
+};
+
+struct metric {
+	char *key;
+	struct event *value;  // array
+};
+
+struct metric *metrics;
+
+int
+timecmp(const void *a, const void *b)
+{
+        struct event *ea = (struct event *)a;
+        struct event *eb = (struct event *)b;
+
+	if (ea->t < eb->t)
+		return -1;
+	else if (ea->t > eb->t)
+		return 1;
+	else
+		return 0;  // needed?
+}
+
+struct bitfile {
+        FILE *output;
+	char *mem;
+	size_t memlen;
+
+        uint64_t bitbuf;        // value of bits in write buffer
+        int bitcount;   // number of bits in write buffer
+};
+
+static void
+putbits1_msb(struct bitfile *bf, int count, uint32_t bits)
+{
+        assert(count >= 1 && count <= 57);
+
+        bf->bitbuf <<= count;
+        bf->bitcount += count;
+
+        bf->bitbuf |= bits;   /* mask? */
+
+        while (bf->bitcount > 8) {
+                bf->bitcount -= 8;
+                putc_unlocked((bf->bitbuf >> bf->bitcount) & 0xff, bf->output);
+        }
+}
+
+static void
+putbits1_flush(struct bitfile *bf)
+{
+        printf("flush: %d\n", bf->bitcount);
+        for (int i = bf->bitcount; i >= 0; i--)
+                putbits1_msb(bf, 1, 0);
+        fflush(bf->output);
+}
+
+static void
+putsigned(struct bitfile *bf, int count, int v)
+{
+        if (v < 0)
+                putbits1_msb(bf, count, (1 << (count - 1)) - (v + 1));
+        else
+                putbits1_msb(bf, count, v);
+}
+
+void
+put1(struct bitfile *bf, int v)
+{
+        if (v == 0) {
+                putbits1_msb(bf, 1, 0x0);
+                return;
+        }
+        if (v >= -64 && v <= 63) {
+                putbits1_msb(bf, 2, 0x2);
+                putsigned(bf, 7, v);
+                return;
+        }
+        if (v >= -256 && v <= 255) {
+                putbits1_msb(bf, 3, 0x6);
+                putsigned(bf, 9, v);
+                return;
+        }
+        if (v >= -2048 && v <= 2047) {
+                putbits1_msb(bf, 4, 0xe);
+                putsigned(bf, 12, v);
+                return;
+        }
+
+        putbits1_msb(bf, 4, 0xf);
+        putsigned(bf, 32, v);
+}
+
+
+int
+main()
+{
+	sh_new_arena(metrics);
+
+	char name[255];
+	char lastname[255];
+
+	char *line = 0;
+	size_t linebuflen = 0;
+	ssize_t linelen = 0;
+	int i = 0;
+
+	while ((linelen = getdelim(&line, &linebuflen, '\n', stdin)) >= 0) {
+		char *start = strchr(line, ' ');
+		if (!start) break;
+		char *start2 = strchr(start+1, ' ');
+		if (!start2) break;
+
+		struct event ev;
+		char *eend;
+		ev.v = strtod(start, &eend);
+		ev.t = strtoll(eend+1, 0, 10);
+
+		if (start - line > (ssize_t)sizeof name) {
+			fprintf(stderr, "metric too long: %s\n", line);
+			continue;
+		}
+		memcpy(name, line, start-line);
+		name[start-line] = 0;
+
+		// XXX normalize name;
+
+		// ts = ts / 1000;  // XXX
+
+		if (strcmp(name, lastname) == 0) {
+			// same name, skip hash lookup, use old i
+		} else {
+			if (shgeti(metrics, name) < 0)
+				shput(metrics, name, 0);
+			i = shgeti(metrics, name);
+		}
+
+		arrput(metrics[i].value, ev);
+
+		strcpy(lastname, name);
+	}
+
+	printf("metrics: %ld\n", shlen(metrics));
+	for (int i = 0; i < shlen(metrics); i++) {
+		printf("%s %ld\n",
+		    metrics[i].key,
+		    arrlen(metrics[i].value));
+	}
+
+        zip_t *zip = zip_open("out.zip", ZIP_CREATE | ZIP_TRUNCATE, 0);
+        if (!zip)
+                exit(-1);
+
+	for (int m = 0; m < shlen(metrics); m++) {
+		// ensure events are ordered by size
+		qsort(metrics[m].value, arrlen(metrics[m].value),
+		    sizeof (struct event), timecmp);
+
+		struct bitfile ts = { 0 };
+		struct bitfile vs = { 0 };
+		ts.output = open_memstream(&ts.mem, &ts.memlen);
+		vs.output = open_memstream(&vs.mem, &vs.memlen);
+
+		int64_t t, pt = 0, ppt = 0;
+		double v, pv = 0.0;
+
+		for (ssize_t i = 0; i < arrlen(metrics[m].value); i++) {
+			t = metrics[m].value[i].t;
+			v = metrics[m].value[i].v;
+
+			put1(&ts, (t - pt) - (pt - ppt));
+			put1(&vs, (int32_t)((v - pv) * 10));
+
+			ppt = pt;
+			pt = t;
+			pv = v;
+		}
+
+		putbits1_flush(&ts);
+		putbits1_flush(&vs);
+
+		printf("%s: %ld + %ld\n", metrics[m].key,
+		    ts.memlen, vs.memlen);
+
+		char prefix[255];
+		char path[255];
+		strcpy(prefix, metrics[m].key);
+		char *s = strchr(prefix, '{');
+		if (!s) {
+			abort();
+		}
+		*s = '/';
+		s = strrchr(prefix, '}');
+		if (s)
+			*s = 0;
+
+		time_t mtime = metrics[m].value[0].t / 1000;
+		snprintf(path, sizeof path, "%s/time.dd", prefix);
+
+		zip_source_t *buft = zip_source_buffer(zip,
+		    ts.mem, ts.memlen, 0);
+		int jj= zip_file_add(zip, path, buft, ZIP_FL_ENC_UTF_8);
+		printf("index of %s = %d\n", path, jj);
+		if (jj < 0) {
+			printf("error adding file: %s\n", zip_strerror(zip));
+		}
+		zip_file_set_mtime(zip, jj, mtime, 0);
+
+		snprintf(path, sizeof path, "%s/data.d", prefix);
+
+		zip_source_t *bufv = zip_source_buffer(zip,
+		    vs.mem, vs.memlen, 0);
+		jj= zip_file_add(zip, path, bufv, ZIP_FL_ENC_UTF_8);
+		printf("index of %s = %d\n", path, jj);
+		if (jj < 0) {
+			printf("error adding file: %s\n", zip_strerror(zip));
+		}
+		zip_file_set_mtime(zip, jj, mtime, 0);
+
+		// note that data must be kept in memory until zip_close
+		// actually writes the archive.
+		arrfree(metrics[m].value);
+	}
+
+	zip_close(zip);
+}