source: lib/ior-peek.c @ c66068d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since c66068d was c66068d, checked in by Perry Lorier <perry@…>, 13 years ago

Rewrite the libtrace io subsystem to use the new wandio abstraction layer.

  • Property mode set to 100644
File size: 3.0 KB
Line 
1#include "wandio.h"
2#include <sys/types.h>
3#include <sys/stat.h>
4#include <fcntl.h>
5#include <stdlib.h>
6#include <unistd.h>
7#include <string.h>
8
9struct peek_t {
10        io_t *child;
11        char *buffer;
12        int length;
13        int offset;
14};
15
16extern io_source_t peek_source;
17
18#define DATA(io) ((struct peek_t *)((io)->data))
19#define MIN(a,b) ((a) < (b) ? (a) : (b))
20
21io_t *peek_open(io_t *child)
22{
23        io_t *io;
24        if (!child)
25                return NULL;
26        io =  malloc(sizeof(io_t));
27        io->data = malloc(sizeof(struct peek_t));
28        io->source = &peek_source;
29
30        DATA(io)->child = child;
31        DATA(io)->buffer = NULL;
32        DATA(io)->length = 0;
33
34        return io;
35}
36
37static off_t peek_read(io_t *io, void *buffer, off_t len)
38{
39        off_t ret = 0;
40
41        /* Is some of this data in the buffer? */
42        if (DATA(io)->buffer) {
43                ret = MIN(len,DATA(io)->length - DATA(io)->offset);
44
45                memcpy(buffer, 
46                        DATA(io)->buffer + DATA(io)->offset,
47                        ret);
48                buffer += ret;
49                DATA(io)->offset += ret;
50                len -= ret;
51        }
52        /* Copy the rest of the data from the child */
53        if (len>0) {
54                off_t bytes_read = 
55                        DATA(io)->child->source->read(
56                                DATA(io)->child, buffer, len);
57                /* Error? */
58                if (bytes_read < 1) {
59                        /* Return if we have managed to get some data ok */
60                        if (ret > 0)
61                                return ret;
62                        /* Return the error upstream */
63                        return bytes_read;
64                }
65                ret += bytes_read;
66        }
67
68        /* Have we read past the end of the buffer? */
69        if (DATA(io)->buffer && DATA(io)->offset >= DATA(io)->length) {
70                /* If so, free the memory it used */
71                free(DATA(io)->buffer);
72                DATA(io)->buffer = NULL;
73                DATA(io)->offset = 0;
74                DATA(io)->length = 0;
75        }
76
77        return ret;
78}
79
80/* Round reads for peeks into the buffer up to this size */
81#define PEEK_SIZE (1024*1024)
82
83static off_t peek_peek(io_t *io, void *buffer, off_t len)
84{
85        off_t ret = 0;
86
87        /* Is there enough data in the buffer to serve this request? */
88        if (DATA(io)->length - DATA(io)->offset < len) {
89                /* No, we need to extend the buffer. */
90                off_t read_amount = len - (DATA(io)->length - DATA(io)->offset);
91                /* Round the read_amount up to the nearest MB */
92                read_amount += PEEK_SIZE - ((DATA(io)->length + read_amount) % PEEK_SIZE);
93                DATA(io)->buffer = realloc(DATA(io)->buffer, DATA(io)->length + read_amount);
94                read_amount = wandio_read(DATA(io)->child, 
95                        DATA(io)->buffer + DATA(io)->length,
96                        read_amount);
97
98                /* Pass errors up */
99                if (read_amount <1) {
100                        return read_amount;
101                }
102
103                DATA(io)->length += read_amount;
104        }
105
106        /* Right, now return data from the buffer (that now should be large enough, but might
107         * not be if we hit EOF) */
108        ret = MIN(len, DATA(io)->length - DATA(io)->offset);
109        memcpy(buffer, DATA(io)->buffer + DATA(io)->offset, ret);
110        return ret;
111}
112
113static off_t peek_tell(io_t *io)
114{
115        return wandio_tell(DATA(io)->child);
116}
117
118static off_t peek_seek(io_t *io, off_t offset, int whence)
119{
120        return wandio_seek(DATA(io)->child,offset,whence);
121}
122
123static void peek_close(io_t *io)
124{
125        wandio_destroy(DATA(io)->child);
126        if (DATA(io)->buffer)
127                free(DATA(io)->buffer);
128        free(io->data);
129        free(io);
130}
131
132io_source_t peek_source = {
133        "peek",
134        peek_read,
135        peek_peek,
136        peek_tell,
137        peek_seek,
138        peek_close
139};
140
Note: See TracBrowser for help on using the repository browser.