summaryrefslogtreecommitdiff
path: root/qa/src/mmv_noinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'qa/src/mmv_noinit.c')
-rw-r--r--qa/src/mmv_noinit.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/qa/src/mmv_noinit.c b/qa/src/mmv_noinit.c
new file mode 100644
index 0000000..7a8fa3e
--- /dev/null
+++ b/qa/src/mmv_noinit.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010 Aconex. All Rights Reserved.
+ *
+ * This test emulates a client which directly overwrites the
+ * MMV data file without unlinking and recreating it (Parfait
+ * does this) - we're relying on the generation number change
+ * as the mechanism available to pmdammv to detect this.
+ *
+ * We use this test program in conjunction with a traditional
+ * (C) MMV API client (like mmv_genstats.c) to do this test.
+ */
+
+#include <pcp/pmapi.h>
+#include <pcp/mmv_stats.h>
+#include <pcp/mmv_dev.h>
+#include <pcp/impl.h>
+
+static mmv_disk_header_t hdr = {
+ .magic = "MMV",
+ .version = MMV_VERSION,
+ .tocs = 2,
+};
+
+static mmv_disk_toc_t toc[] = {
+ { .type = MMV_TOC_METRICS, .count = 1, },
+ { .type = MMV_TOC_VALUES, .count = 1, },
+};
+
+static mmv_disk_metric_t metric = {
+ .name = "noinit",
+ .item = 1,
+ .type = MMV_TYPE_U32,
+ .semantics = MMV_SEM_COUNTER,
+ .dimension = MMV_UNITS(0,0,1,0,0,PM_COUNT_ONE),
+};
+
+static mmv_disk_value_t values;
+
+static size_t
+mmv_filesize(void)
+{
+ return sizeof(mmv_disk_header_t) +
+ sizeof(mmv_disk_toc_t) * 2 +
+ sizeof(mmv_disk_metric_t) +
+ sizeof(mmv_disk_value_t);
+}
+
+static void *
+mmv_noinit(const char *filename)
+{
+ char path[MAXPATHLEN];
+ size_t size = mmv_filesize();
+ int fd, sep = __pmPathSeparator();
+ void *addr = NULL;
+ int sts;
+
+ snprintf(path, sizeof(path), "%s%c" "mmv" "%c%s",
+ pmGetConfig("PCP_TMP_DIR"), sep, sep, filename);
+
+ fd = open(path, O_RDWR, 0644);
+ if (fd < 0) {
+ fprintf(stderr, "noinit: failed to open %s: %s\n",
+ path, strerror(errno));
+ return NULL;
+ }
+ sts = ftruncate(fd, size);
+ if (sts != 0) {
+ fprintf(stderr, "Error: ftruncate() returns %d\n", sts);
+ exit(1);
+ }
+ addr = __pmMemoryMap(fd, size, 1);
+
+ close(fd);
+ return addr;
+}
+
+static __uint64_t
+mmv_generation(void)
+{
+ struct timeval now;
+ __uint32_t gen1, gen2;
+
+ gettimeofday(&now, NULL);
+ gen1 = now.tv_sec;
+ gen2 = now.tv_usec;
+ return (((__uint64_t)gen1 << 32) | (__uint64_t)gen2);
+}
+
+int
+main(int ac, char * av[])
+{
+ char * file = (ac > 1) ? av[1] : "test";
+ void * addr = mmv_noinit(file);
+ char * data = addr;
+ __uint64_t gennum = mmv_generation();
+
+ if (!addr) {
+ perror("noinit");
+ return 1;
+ }
+
+ /*
+ * Write ondisk structures directly into file.
+ * fixing up offsets, etc, as we go.
+ */
+ hdr.g1 = gennum;
+ hdr.process = getpid();
+ memcpy(data, &hdr, sizeof(hdr));
+
+ data += sizeof(hdr);
+ toc[0].offset = sizeof(hdr) + sizeof(toc);
+ toc[1].offset = sizeof(hdr) + sizeof(toc) + sizeof(metric);
+ memcpy(data, &toc, sizeof(toc));
+
+ data += sizeof(toc);
+ memcpy(data, &metric, sizeof(metric));
+
+ values.value.ul = 42;
+ values.metric = sizeof(hdr) + sizeof(toc);
+ data += sizeof(metric);
+ memcpy(data, &values, sizeof(values));
+
+ /* "unlock" the file and bail out */
+ hdr.g2 = (__uint64_t) gennum;
+ memcpy(addr, &hdr, sizeof(hdr));
+ __pmMemoryUnmap(addr, mmv_filesize());
+ return 0;
+}