Add debugging stats to hashtable.
[kmemtrace-user.git] / dataset.c
blob41bce4e7545597fbcec678d1fa4358e472978f5a
1 /*
2 * Copyright (C) 2008 Eduard - Gabriel Munteanu
4 * This file is released under GPL version 2.
5 */
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <stdlib.h>
10 #include <errno.h>
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mman.h>
14 #include <fcntl.h>
15 #include <unistd.h>
17 #include <dataset.h>
18 #include <common.h>
19 #include <kmemtrace.h>
21 struct dataset *dataset_open(char *format, unsigned long cpu)
23 struct stat stat_buf;
24 struct dataset *ret;
25 int len;
27 ret = malloc(sizeof(struct dataset));
28 if (!ret)
29 return NULL;
31 len = snprintf(ret->filename, FILENAME_MAX, format, cpu);
32 if (len >= FILENAME_MAX)
33 goto fail;
35 ret->fd = open(ret->filename, O_RDONLY);
36 if (ret->fd == -1)
37 goto fail;
39 if (fstat(ret->fd, &stat_buf))
40 goto fail_close;
41 ret->size = stat_buf.st_size;
43 ret->map = mmap(NULL, ret->size, PROT_READ, MAP_PRIVATE, ret->fd, 0);
44 if (!ret->map)
45 goto fail_close;
47 return ret;
49 fail_close:
50 close(ret->fd);
51 fail:
52 free(ret);
53 return NULL;
56 void dataset_close(struct dataset *set)
58 if (!set)
59 return;
61 munmap(set->map, set->size);
62 free(set);
65 static inline struct dataset_event dataset_event_read(struct dataset *set,
66 size_t *offset)
68 struct dataset_event d_ev;
70 d_ev.event = set->map + *offset;
72 if (((void *) d_ev.event) + d_ev.event->event_size >
73 set->map + set->size) {
74 printf("dataset_event_read: Event reaches "
75 "outside mapped region, clamping dataset.\n");
76 *offset = set->size;
77 d_ev.event = NULL;
78 return d_ev;
81 if (set->size - *offset < sizeof(struct kmemtrace_event)) {
82 panic("dataset_event_read: Not enough data\n");
85 if (d_ev.event->event_size > sizeof(struct kmemtrace_event)) {
86 d_ev.extra = set->map + *offset +
87 sizeof(struct kmemtrace_event);
88 } else
89 d_ev.extra = NULL;
91 *offset += d_ev.event->event_size;
93 return d_ev;
96 int dataset_iter(struct dataset *set, int (*action)(struct kmemtrace_event *,
97 void *))
99 size_t off = 0;
100 struct dataset_event d_ev;
102 while (off < set->size) {
103 d_ev = dataset_event_read(set, &off);
104 if (!d_ev.event)
105 return 0;
106 if (action(d_ev.event, d_ev.extra))
107 return -EINTR;
110 return 0;
113 static inline unsigned long
114 dataset_group_get_earliest(struct dataset_group *group)
116 long i, min = -1;
118 for (i = 0; i < group->count; i++) {
119 if (!group->has_data[i])
120 continue;
121 if (min == -1) {
122 min = i;
123 continue;
125 if (group->ds_event[i].event->seq_num <
126 group->ds_event[min].event->seq_num)
127 min = i;
130 if (min != -1)
131 group->has_data[min] = 0;
133 return min;
136 /* Returns non-zero if interrupted / not completed. */
137 int dataset_iter_ordered(struct dataset_group *group,
138 int (*action)(struct kmemtrace_event *,
139 void *, unsigned long))
141 unsigned long i, next;
142 size_t *off, prev_off, tsize = 0;
143 int32_t expected;
144 int have_expected = 0;
146 if (!action)
147 return -EINVAL;
149 off = calloc(group->count, sizeof(size_t));
151 for (i = 0; i < group->count; i++)
152 tsize += group->dataset[i]->size;
154 while (tsize > 0) {
155 for (i = 0; i < group->count; i++)
156 if (off[i] < group->dataset[i]->size &&
157 !group->has_data[i]) {
158 prev_off = off[i];
159 group->ds_event[i] =
160 dataset_event_read(group->dataset[i],
161 &off[i]);
162 if (group->ds_event[i].event)
163 group->has_data[i] = 1;
164 tsize -= off[i] - prev_off;
167 next = dataset_group_get_earliest(group);
169 if (next == -1)
170 break;
172 if (!have_expected) {
173 have_expected = 1;
174 expected = group->ds_event[next].event->seq_num + 1;
175 } else {
176 if (expected != group->ds_event[next].event->seq_num) {
177 printf("dataset_iter_ordered: Wrong sequence "
178 "number %d, expected %d.\n",
179 group->ds_event[next].event->seq_num,
180 expected);
181 free(off);
182 return -EINVAL;
184 expected++;
187 debug("Processing packet seq_num = %d from CPU %lu...\n",
188 group->ds_event[next].event->seq_num - 1, next);
190 if (action(group->ds_event[next].event,
191 group->ds_event[next].extra, next)) {
192 free(off);
193 return -EINTR;
197 free(off);
199 return 0;
202 struct dataset_group *dataset_group_create(unsigned long count)
204 struct dataset_group *ret;
206 ret = malloc(sizeof(struct dataset_group));
207 if (!ret)
208 return NULL;
209 ret->dataset = calloc(count, sizeof(struct dataset *));
210 ret->ds_event = calloc(count, sizeof(struct dataset_event));
211 ret->has_data = calloc(count, sizeof(int));
212 ret->count = count;
214 return ret;
217 void dataset_group_destroy(struct dataset_group *group)
219 unsigned long cpu;
221 for (cpu = 0; cpu < group->count; cpu++)
222 if (group->dataset[cpu])
223 dataset_close(group->dataset[cpu]);
224 free(group->dataset);
225 free(group->ds_event);
226 free(group->has_data);
228 free(group);