aboutsummaryrefslogtreecommitdiffstats
path: root/src/ftsort.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftsort.c')
-rw-r--r--src/ftsort.c206
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
34static unsigned int holes = 0;
35static unsigned int reordered = 0;
36
37#define LOOK_AHEAD 1000
38
39/* wall-clock time in seconds */
40double wctime(void)
41{
42 struct timeval tv;
43 gettimeofday(&tv, NULL);
44 return (tv.tv_sec + 1E-6 * tv.tv_usec);
45}
46
47
48static 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
64static 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
80static 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
104static inline uint64_t bget(int x, uint64_t quad)
105
106{
107 return (((0xffll << 8 * x) & quad) >> 8 * x);
108}
109
110static inline uint64_t bput(uint64_t b, int pos)
111{
112 return (b << 8 * pos);
113}
114
115static 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
123static 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
139static 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
150int 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}