| 1 | #include <stdio.h> |
| 2 | #include <unistd.h> |
| 3 | #include <sys/mman.h> |
| 4 | #include <stdarg.h> |
| 5 | #include <sys/types.h> |
| 6 | #include <sys/stat.h> |
| 7 | #include <fcntl.h> |
| 8 | |
| 9 | #include "../libmarkers/marker.h" |
| 10 | #include "usterr.h" |
| 11 | #include "tracer.h" |
| 12 | #include "marker-control.h" |
| 13 | #include "relay.h" |
| 14 | |
| 15 | |
| 16 | char consumer_stack[10000]; |
| 17 | |
| 18 | #define CPRINTF(fmt, args...) safe_printf(fmt "\n", ## args) |
| 19 | |
| 20 | int safe_printf(const char *fmt, ...) |
| 21 | { |
| 22 | static char buf[500]; |
| 23 | va_list ap; |
| 24 | int n; |
| 25 | |
| 26 | va_start(ap, fmt); |
| 27 | |
| 28 | n = vsnprintf(buf, sizeof(buf), fmt, ap); |
| 29 | |
| 30 | write(STDOUT_FILENO, buf, n); |
| 31 | |
| 32 | va_end(ap); |
| 33 | } |
| 34 | |
| 35 | struct consumer_channel { |
| 36 | int fd; |
| 37 | struct ltt_channel_struct *chan; |
| 38 | }; |
| 39 | |
| 40 | int consumer(void *arg) |
| 41 | { |
| 42 | int result; |
| 43 | int fd; |
| 44 | char str[] = "Hello, this is the consumer.\n"; |
| 45 | struct ltt_trace_struct *trace; |
| 46 | struct consumer_channel *consumer_channels; |
| 47 | int i; |
| 48 | char trace_name[] = "auto"; |
| 49 | |
| 50 | ltt_lock_traces(); |
| 51 | trace = _ltt_trace_find(trace_name); |
| 52 | ltt_unlock_traces(); |
| 53 | |
| 54 | if(trace == NULL) { |
| 55 | CPRINTF("cannot find trace!"); |
| 56 | return 1; |
| 57 | } |
| 58 | |
| 59 | consumer_channels = (struct consumer_channel *) malloc(trace->nr_channels * sizeof(struct consumer_channel)); |
| 60 | if(consumer_channels == NULL) { |
| 61 | ERR("malloc returned NULL"); |
| 62 | return 1; |
| 63 | } |
| 64 | |
| 65 | CPRINTF("opening trace files"); |
| 66 | for(i=0; i<trace->nr_channels; i++) { |
| 67 | char tmp[100]; |
| 68 | struct ltt_channel_struct *chan = &trace->channels[i]; |
| 69 | |
| 70 | consumer_channels[i].chan = chan; |
| 71 | |
| 72 | snprintf(tmp, sizeof(tmp), "trace/%s", chan->channel_name); |
| 73 | result = consumer_channels[i].fd = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, 00644); |
| 74 | if(result == -1) { |
| 75 | perror("open"); |
| 76 | return -1; |
| 77 | } |
| 78 | CPRINTF("\topened trace file %s", tmp); |
| 79 | |
| 80 | } |
| 81 | CPRINTF("done opening trace files"); |
| 82 | |
| 83 | for(;;) { |
| 84 | /*wait*/ |
| 85 | |
| 86 | for(i=0; i<trace->nr_channels; i++) { |
| 87 | struct rchan *rchan = consumer_channels[i].chan->trans_channel_data; |
| 88 | struct rchan_buf *rbuf = rchan->buf; |
| 89 | struct ltt_channel_buf_struct *lttbuf = consumer_channels[i].chan->buf; |
| 90 | long consumed_old; |
| 91 | |
| 92 | result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); |
| 93 | if(result < 0) { |
| 94 | CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); |
| 95 | } |
| 96 | else { |
| 97 | CPRINTF("success!"); |
| 98 | |
| 99 | result = write(consumer_channels[i].fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); |
| 100 | ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); |
| 101 | } |
| 102 | } |
| 103 | |
| 104 | sleep(1); |
| 105 | } |
| 106 | |
| 107 | // CPRINTF("consumer: got a trace: %s with %d channels\n", trace_name, trace->nr_channels); |
| 108 | // |
| 109 | // struct ltt_channel_struct *chan = &trace->channels[0]; |
| 110 | // |
| 111 | // CPRINTF("channel 1 (%s) active=%u", chan->channel_name, chan->active & 1); |
| 112 | |
| 113 | // struct rchan *rchan = chan->trans_channel_data; |
| 114 | // struct rchan_buf *rbuf = rchan->buf; |
| 115 | // struct ltt_channel_buf_struct *lttbuf = chan->buf; |
| 116 | // long consumed_old; |
| 117 | // |
| 118 | // result = fd = open("trace.out", O_WRONLY | O_CREAT | O_TRUNC, 00644); |
| 119 | // if(result == -1) { |
| 120 | // perror("open"); |
| 121 | // return -1; |
| 122 | // } |
| 123 | |
| 124 | // for(;;) { |
| 125 | // write(STDOUT_FILENO, str, sizeof(str)); |
| 126 | // |
| 127 | // result = ltt_do_get_subbuf(rbuf, lttbuf, &consumed_old); |
| 128 | // if(result < 0) { |
| 129 | // CPRINTF("ltt_do_get_subbuf: error: %s", strerror(-result)); |
| 130 | // } |
| 131 | // else { |
| 132 | // CPRINTF("success!"); |
| 133 | // |
| 134 | // result = write(fd, rbuf->buf_data + (consumed_old & (2 * 4096-1)), 4096); |
| 135 | // ltt_do_put_subbuf(rbuf, lttbuf, consumed_old); |
| 136 | // } |
| 137 | // |
| 138 | // //CPRINTF("There seems to be %ld bytes available", SUBBUF_TRUNC(local_read(<tbuf->offset), rbuf->chan) - consumed_old); |
| 139 | // CPRINTF("Commit count %ld", local_read(<tbuf->commit_count[0])); |
| 140 | // |
| 141 | // |
| 142 | // sleep(1); |
| 143 | // } |
| 144 | } |
| 145 | |
| 146 | void start_consumer(void) |
| 147 | { |
| 148 | int result; |
| 149 | |
| 150 | result = clone(consumer, consumer_stack+sizeof(consumer_stack)-1, CLONE_FS | CLONE_FILES | CLONE_VM | CLONE_SIGHAND | CLONE_THREAD, NULL); |
| 151 | if(result == -1) { |
| 152 | perror("clone"); |
| 153 | } |
| 154 | } |
| 155 | |
| 156 | void probe(const struct marker *mdata, |
| 157 | void *probe_private, void *call_private, |
| 158 | const char *fmt, va_list *args) |
| 159 | { |
| 160 | printf("In probe\n"); |
| 161 | } |
| 162 | |
| 163 | void inthandler(int sig) |
| 164 | { |
| 165 | printf("in handler\n"); |
| 166 | exit(0); |
| 167 | } |
| 168 | |
| 169 | int init_int_handler(void) |
| 170 | { |
| 171 | int result; |
| 172 | struct sigaction act; |
| 173 | |
| 174 | result = sigemptyset(&act.sa_mask); |
| 175 | if(result == -1) { |
| 176 | PERROR("sigemptyset"); |
| 177 | return -1; |
| 178 | } |
| 179 | |
| 180 | act.sa_handler = inthandler; |
| 181 | act.sa_flags = SA_RESTART; |
| 182 | |
| 183 | /* Only defer ourselves. Also, try to restart interrupted |
| 184 | * syscalls to disturb the traced program as little as possible. |
| 185 | */ |
| 186 | result = sigaction(SIGINT, &act, NULL); |
| 187 | if(result == -1) { |
| 188 | PERROR("sigaction"); |
| 189 | return -1; |
| 190 | } |
| 191 | |
| 192 | return 0; |
| 193 | } |
| 194 | |
| 195 | int main() |
| 196 | { |
| 197 | int result; |
| 198 | int i; |
| 199 | |
| 200 | init_int_handler(); |
| 201 | |
| 202 | start_consumer(); |
| 203 | printf("Hello, World!\n"); |
| 204 | |
| 205 | sleep(1); |
| 206 | for(i=0; i<50; i++) { |
| 207 | trace_mark(foo, bar, "str %s", "FOOBAZ"); |
| 208 | trace_mark(foo, bar2, "number1 %d number2 %d", 53, 9800); |
| 209 | usleep(100000); |
| 210 | } |
| 211 | |
| 212 | scanf("%*s"); |
| 213 | |
| 214 | return 0; |
| 215 | } |
| 216 | |
| 217 | MARKER_LIB |