1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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;
}
|