diff options
Diffstat (limited to 'src/ftsort.c')
-rw-r--r-- | src/ftsort.c | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/src/ftsort.c b/src/ftsort.c new file mode 100644 index 0000000..5ddb48f --- /dev/null +++ b/src/ftsort.c | |||
@@ -0,0 +1,206 @@ | |||
1 | /* ft2sort -- Sort Feather-Trace events in a binary file by sequence number. | ||
2 | * Copyright (C) 2011 B. Brandenburg. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along | ||
15 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | */ | ||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <string.h> | ||
21 | |||
22 | #include <time.h> | ||
23 | #include <sys/time.h> | ||
24 | |||
25 | #include <errno.h> | ||
26 | #include <unistd.h> | ||
27 | #include <arpa/inet.h> | ||
28 | #include <sys/mman.h> | ||
29 | |||
30 | #include "mapping.h" | ||
31 | |||
32 | #include "timestamp.h" | ||
33 | |||
34 | static unsigned int holes = 0; | ||
35 | static unsigned int reordered = 0; | ||
36 | |||
37 | #define LOOK_AHEAD 1000 | ||
38 | |||
39 | /* wall-clock time in seconds */ | ||
40 | double wctime(void) | ||
41 | { | ||
42 | struct timeval tv; | ||
43 | gettimeofday(&tv, NULL); | ||
44 | return (tv.tv_sec + 1E-6 * tv.tv_usec); | ||
45 | } | ||
46 | |||
47 | |||
48 | static struct timestamp* find_lowest_seq_no(struct timestamp* start, | ||
49 | struct timestamp* end, | ||
50 | unsigned int seqno) | ||
51 | { | ||
52 | struct timestamp *pos, *min = start; | ||
53 | |||
54 | if (end > start + LOOK_AHEAD) | ||
55 | end = start + LOOK_AHEAD; | ||
56 | |||
57 | for (pos = start; pos != end && min->seq_no != seqno; pos++) | ||
58 | if (pos->seq_no < min->seq_no) | ||
59 | min = pos; | ||
60 | return min; | ||
61 | } | ||
62 | |||
63 | |||
64 | static void move_record(struct timestamp* target, struct timestamp* pos) | ||
65 | { | ||
66 | struct timestamp tmp, *prev; | ||
67 | |||
68 | while (pos > target) { | ||
69 | /* shift backwards */ | ||
70 | tmp = *pos; | ||
71 | prev = pos - 1; | ||
72 | |||
73 | *pos = *prev; | ||
74 | *prev = tmp; | ||
75 | |||
76 | pos = prev; | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static void reorder(struct timestamp* start, struct timestamp* end) | ||
81 | { | ||
82 | struct timestamp* pos, *tmp; | ||
83 | unsigned int last_seqno = 0; | ||
84 | |||
85 | for (pos = start; pos != end; pos++) { | ||
86 | /* check for for holes in the sequence number */ | ||
87 | if (last_seqno && last_seqno + 1 != pos->seq_no) { | ||
88 | tmp = find_lowest_seq_no(pos, end, last_seqno + 1); | ||
89 | if (tmp->seq_no == last_seqno + 1) | ||
90 | /* Good, we found it. */ | ||
91 | /* Move it to the right place. */ | ||
92 | reordered++; | ||
93 | else { | ||
94 | /* bad, there's a hole here */ | ||
95 | holes++; | ||
96 | fprintf(stderr, "HOLE: %u instead of %u\n", tmp->seq_no, last_seqno + 1); | ||
97 | } | ||
98 | move_record(pos, tmp); | ||
99 | } | ||
100 | last_seqno = pos->seq_no; | ||
101 | } | ||
102 | } | ||
103 | |||
104 | static inline uint64_t bget(int x, uint64_t quad) | ||
105 | |||
106 | { | ||
107 | return (((0xffll << 8 * x) & quad) >> 8 * x); | ||
108 | } | ||
109 | |||
110 | static inline uint64_t bput(uint64_t b, int pos) | ||
111 | { | ||
112 | return (b << 8 * pos); | ||
113 | } | ||
114 | |||
115 | static inline uint64_t ntohx(uint64_t q) | ||
116 | { | ||
117 | return (bput(bget(0, q), 7) | bput(bget(1, q), 6) | | ||
118 | bput(bget(2, q), 5) | bput(bget(3, q), 4) | | ||
119 | bput(bget(4, q), 3) | bput(bget(5, q), 2) | | ||
120 | bput(bget(6, q), 1) | bput(bget(7, q), 0)); | ||
121 | } | ||
122 | |||
123 | static void restore_byte_order(struct timestamp* start, struct timestamp* end) | ||
124 | { | ||
125 | struct timestamp* pos = start; | ||
126 | while (pos !=end) { | ||
127 | pos->timestamp = ntohx(pos->timestamp); | ||
128 | pos->seq_no = ntohl(pos->seq_no); | ||
129 | pos++; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | #define USAGE \ | ||
134 | "Usage: ftsort [-e] <logfile> \n" \ | ||
135 | " -e: endianess swap -- restores byte order \n" \ | ||
136 | "\n" \ | ||
137 | "WARNING: Changes are permanent.\n" | ||
138 | |||
139 | static void die(char* msg) | ||
140 | { | ||
141 | if (errno) | ||
142 | perror("error: "); | ||
143 | fprintf(stderr, "%s\n", msg); | ||
144 | fprintf(stderr, "%s", USAGE); | ||
145 | exit(1); | ||
146 | } | ||
147 | |||
148 | #define OPTS "e" | ||
149 | |||
150 | int main(int argc, char** argv) | ||
151 | { | ||
152 | void* mapped; | ||
153 | size_t size, count; | ||
154 | struct timestamp *ts, *end; | ||
155 | int swap_byte_order = 0; | ||
156 | int opt; | ||
157 | double start, stop; | ||
158 | |||
159 | while ((opt = getopt(argc, argv, OPTS)) != -1) { | ||
160 | switch (opt) { | ||
161 | case 'e': | ||
162 | swap_byte_order = 1; | ||
163 | break; | ||
164 | default: | ||
165 | die("Unknown option."); | ||
166 | break; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | if (argc - optind != 1) | ||
171 | die("arguments missing"); | ||
172 | |||
173 | start = wctime(); | ||
174 | |||
175 | if (map_file_rw(argv[optind], &mapped, &size)) | ||
176 | die("could not map file"); | ||
177 | |||
178 | ts = (struct timestamp*) mapped; | ||
179 | count = size / sizeof(struct timestamp); | ||
180 | end = ts + count; | ||
181 | |||
182 | if (swap_byte_order) | ||
183 | restore_byte_order(ts, end); | ||
184 | |||
185 | reorder(ts, end); | ||
186 | |||
187 | /* write back */ | ||
188 | msync(ts, size, MS_SYNC | MS_INVALIDATE); | ||
189 | |||
190 | stop = wctime(); | ||
191 | |||
192 | fprintf(stderr, | ||
193 | "Total : %10d\n" | ||
194 | "Holes : %10d\n" | ||
195 | "Reordered : %10d\n" | ||
196 | "Size : %10.2f Mb\n" | ||
197 | "Time : %10.2f s\n" | ||
198 | "Throughput : %10.2f Mb/s\n", | ||
199 | (int) count, | ||
200 | holes, reordered, | ||
201 | ((double) size) / 1024.0 / 1024.0, | ||
202 | (stop - start), | ||
203 | ((double) size) / 1024.0 / 1024.0 / (stop - start)); | ||
204 | |||
205 | return 0; | ||
206 | } | ||