eio 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/COPYING +502 -0
- data/LICENSE +16 -0
- data/README.rdoc +201 -0
- data/Rakefile +48 -0
- data/bench/eventmachine.rb +134 -0
- data/eio.gemspec +17 -0
- data/ext/eio/eio_ext.c +1447 -0
- data/ext/eio/extconf.rb +11 -0
- data/ext/libeio/CVS/Entries +13 -0
- data/ext/libeio/CVS/Repository +1 -0
- data/ext/libeio/CVS/Root +1 -0
- data/ext/libeio/Changes +40 -0
- data/ext/libeio/LICENSE +36 -0
- data/ext/libeio/Makefile +692 -0
- data/ext/libeio/Makefile.am +15 -0
- data/ext/libeio/Makefile.in +692 -0
- data/ext/libeio/aclocal.m4 +8937 -0
- data/ext/libeio/autogen.sh +3 -0
- data/ext/libeio/autom4te.cache/output.0 +13871 -0
- data/ext/libeio/autom4te.cache/output.1 +13867 -0
- data/ext/libeio/autom4te.cache/requests +275 -0
- data/ext/libeio/autom4te.cache/traces.0 +2384 -0
- data/ext/libeio/autom4te.cache/traces.1 +621 -0
- data/ext/libeio/config.guess +1501 -0
- data/ext/libeio/config.h +122 -0
- data/ext/libeio/config.h.in +121 -0
- data/ext/libeio/config.status +2035 -0
- data/ext/libeio/config.sub +1705 -0
- data/ext/libeio/configure +13867 -0
- data/ext/libeio/configure.ac +22 -0
- data/ext/libeio/demo.c +194 -0
- data/ext/libeio/eio.3 +3428 -0
- data/ext/libeio/eio.c +2075 -0
- data/ext/libeio/eio.h +336 -0
- data/ext/libeio/eio.pod +303 -0
- data/ext/libeio/install-sh +520 -0
- data/ext/libeio/libeio.m4 +156 -0
- data/ext/libeio/libtool +8890 -0
- data/ext/libeio/ltmain.sh +8406 -0
- data/ext/libeio/missing +376 -0
- data/ext/libeio/stamp-h1 +1 -0
- data/ext/libeio/xthread.h +168 -0
- data/lib/eio.rb +9 -0
- data/lib/eio/eventmachine.rb +24 -0
- data/lib/eio/middleware.rb +21 -0
- data/test/test_eio.rb +1161 -0
- data/test/test_eventmachine.rb +23 -0
- data/test/test_middleware.rb +20 -0
- metadata +148 -0
data/ext/libeio/eio.h
ADDED
@@ -0,0 +1,336 @@
|
|
1
|
+
/*
|
2
|
+
* libeio API header
|
3
|
+
*
|
4
|
+
* Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libeio@schmorp.de>
|
5
|
+
* All rights reserved.
|
6
|
+
*
|
7
|
+
* Redistribution and use in source and binary forms, with or without modifica-
|
8
|
+
* tion, are permitted provided that the following conditions are met:
|
9
|
+
*
|
10
|
+
* 1. Redistributions of source code must retain the above copyright notice,
|
11
|
+
* this list of conditions and the following disclaimer.
|
12
|
+
*
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
16
|
+
*
|
17
|
+
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
18
|
+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
19
|
+
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
20
|
+
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
21
|
+
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
22
|
+
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
23
|
+
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
24
|
+
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
25
|
+
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
26
|
+
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
27
|
+
*
|
28
|
+
* Alternatively, the contents of this file may be used under the terms of
|
29
|
+
* the GNU General Public License ("GPL") version 2 or any later version,
|
30
|
+
* in which case the provisions of the GPL are applicable instead of
|
31
|
+
* the above. If you wish to allow the use of your version of this file
|
32
|
+
* only under the terms of the GPL and not to allow others to use your
|
33
|
+
* version of this file under the BSD license, indicate your decision
|
34
|
+
* by deleting the provisions above and replace them with the notice
|
35
|
+
* and other provisions required by the GPL. If you do not delete the
|
36
|
+
* provisions above, a recipient may use your version of this file under
|
37
|
+
* either the BSD or the GPL.
|
38
|
+
*/
|
39
|
+
|
40
|
+
#ifndef EIO_H_
|
41
|
+
#define EIO_H_
|
42
|
+
|
43
|
+
#ifdef __cplusplus
|
44
|
+
extern "C" {
|
45
|
+
#endif
|
46
|
+
|
47
|
+
#include <stddef.h>
|
48
|
+
#include <sys/types.h>
|
49
|
+
|
50
|
+
typedef struct eio_req eio_req;
|
51
|
+
typedef struct eio_dirent eio_dirent;
|
52
|
+
|
53
|
+
typedef int (*eio_cb)(eio_req *req);
|
54
|
+
|
55
|
+
#ifndef EIO_REQ_MEMBERS
|
56
|
+
# define EIO_REQ_MEMBERS
|
57
|
+
#endif
|
58
|
+
|
59
|
+
#ifndef EIO_STRUCT_STAT
|
60
|
+
# define EIO_STRUCT_STAT struct stat
|
61
|
+
#endif
|
62
|
+
|
63
|
+
#ifndef EIO_STRUCT_STATVFS
|
64
|
+
# define EIO_STRUCT_STATVFS struct statvfs
|
65
|
+
#endif
|
66
|
+
|
67
|
+
/* for readdir */
|
68
|
+
|
69
|
+
/* eio_readdir flags */
|
70
|
+
enum
|
71
|
+
{
|
72
|
+
EIO_READDIR_DENTS = 0x01, /* ptr2 contains eio_dirents, not just the (unsorted) names */
|
73
|
+
EIO_READDIR_DIRS_FIRST = 0x02, /* dirents gets sorted into a good stat() ing order to find directories first */
|
74
|
+
EIO_READDIR_STAT_ORDER = 0x04, /* dirents gets sorted into a good stat() ing order to quickly stat all files */
|
75
|
+
EIO_READDIR_FOUND_UNKNOWN = 0x80, /* set by eio_readdir when *_ARRAY was set and any TYPE=UNKNOWN's were found */
|
76
|
+
|
77
|
+
EIO_READDIR_CUSTOM1 = 0x100, /* for use by apps */
|
78
|
+
EIO_READDIR_CUSTOM2 = 0x200 /* for use by apps */
|
79
|
+
};
|
80
|
+
|
81
|
+
/* using "typical" values in the hope that the compiler will do something sensible */
|
82
|
+
enum eio_dtype
|
83
|
+
{
|
84
|
+
EIO_DT_UNKNOWN = 0,
|
85
|
+
EIO_DT_FIFO = 1,
|
86
|
+
EIO_DT_CHR = 2,
|
87
|
+
EIO_DT_MPC = 3, /* multiplexed char device (v7+coherent) */
|
88
|
+
EIO_DT_DIR = 4,
|
89
|
+
EIO_DT_NAM = 5, /* xenix special named file */
|
90
|
+
EIO_DT_BLK = 6,
|
91
|
+
EIO_DT_MPB = 7, /* multiplexed block device (v7+coherent) */
|
92
|
+
EIO_DT_REG = 8,
|
93
|
+
EIO_DT_NWK = 9, /* HP-UX network special */
|
94
|
+
EIO_DT_CMP = 9, /* VxFS compressed */
|
95
|
+
EIO_DT_LNK = 10,
|
96
|
+
/* DT_SHAD = 11,*/
|
97
|
+
EIO_DT_SOCK = 12,
|
98
|
+
EIO_DT_DOOR = 13, /* solaris door */
|
99
|
+
EIO_DT_WHT = 14,
|
100
|
+
EIO_DT_MAX = 15 /* highest DT_VALUE ever, hopefully */
|
101
|
+
};
|
102
|
+
|
103
|
+
struct eio_dirent
|
104
|
+
{
|
105
|
+
int nameofs; /* offset of null-terminated name string in (char *)req->ptr2 */
|
106
|
+
unsigned short namelen; /* size of filename without trailing 0 */
|
107
|
+
unsigned char type; /* one of EIO_DT_* */
|
108
|
+
signed char score; /* internal use */
|
109
|
+
ino_t inode; /* the inode number, if available, otherwise unspecified */
|
110
|
+
};
|
111
|
+
|
112
|
+
/* eio_msync flags */
|
113
|
+
enum
|
114
|
+
{
|
115
|
+
EIO_MS_ASYNC = 1,
|
116
|
+
EIO_MS_INVALIDATE = 2,
|
117
|
+
EIO_MS_SYNC = 4
|
118
|
+
};
|
119
|
+
|
120
|
+
/* eio_mtouch flags */
|
121
|
+
|
122
|
+
enum
|
123
|
+
{
|
124
|
+
EIO_MT_MODIFY = 1
|
125
|
+
};
|
126
|
+
|
127
|
+
/* eio_sync_file_range flags */
|
128
|
+
|
129
|
+
enum
|
130
|
+
{
|
131
|
+
EIO_SYNC_FILE_RANGE_WAIT_BEFORE = 1,
|
132
|
+
EIO_SYNC_FILE_RANGE_WRITE = 2,
|
133
|
+
EIO_SYNC_FILE_RANGE_WAIT_AFTER = 4
|
134
|
+
};
|
135
|
+
|
136
|
+
typedef double eio_tstamp; /* feel free to use double in your code directly */
|
137
|
+
|
138
|
+
/* the eio request structure */
|
139
|
+
|
140
|
+
enum
|
141
|
+
{
|
142
|
+
EIO_CUSTOM,
|
143
|
+
EIO_OPEN, EIO_CLOSE, EIO_DUP2,
|
144
|
+
EIO_READ, EIO_WRITE,
|
145
|
+
EIO_READAHEAD, EIO_SENDFILE,
|
146
|
+
EIO_STAT, EIO_LSTAT, EIO_FSTAT,
|
147
|
+
EIO_STATVFS, EIO_FSTATVFS,
|
148
|
+
EIO_TRUNCATE, EIO_FTRUNCATE,
|
149
|
+
EIO_UTIME, EIO_FUTIME,
|
150
|
+
EIO_CHMOD, EIO_FCHMOD,
|
151
|
+
EIO_CHOWN, EIO_FCHOWN,
|
152
|
+
EIO_SYNC, EIO_FSYNC, EIO_FDATASYNC,
|
153
|
+
EIO_MSYNC, EIO_MTOUCH, EIO_SYNC_FILE_RANGE,
|
154
|
+
EIO_MLOCK, EIO_MLOCKALL,
|
155
|
+
EIO_UNLINK, EIO_RMDIR, EIO_MKDIR, EIO_RENAME,
|
156
|
+
EIO_MKNOD, EIO_READDIR,
|
157
|
+
EIO_LINK, EIO_SYMLINK, EIO_READLINK,
|
158
|
+
EIO_GROUP, EIO_NOP,
|
159
|
+
EIO_BUSY
|
160
|
+
};
|
161
|
+
|
162
|
+
/* mlockall constants */
|
163
|
+
enum
|
164
|
+
{
|
165
|
+
EIO_MCL_CURRENT = 1,
|
166
|
+
EIO_MCL_FUTURE = 2,
|
167
|
+
};
|
168
|
+
|
169
|
+
/* request priorities */
|
170
|
+
|
171
|
+
enum {
|
172
|
+
EIO_PRI_MIN = -4,
|
173
|
+
EIO_PRI_MAX = 4,
|
174
|
+
EIO_PRI_DEFAULT = 0,
|
175
|
+
};
|
176
|
+
|
177
|
+
/* eio request structure */
|
178
|
+
/* this structure is mostly read-only */
|
179
|
+
/* when initialising it, all members must be zero-initialised */
|
180
|
+
struct eio_req
|
181
|
+
{
|
182
|
+
eio_req volatile *next; /* private ETP */
|
183
|
+
|
184
|
+
ssize_t result; /* result of syscall, e.g. result = read (... */
|
185
|
+
off_t offs; /* read, write, truncate, readahead, sync_file_range: file offset, mknod: dev_t */
|
186
|
+
size_t size; /* read, write, readahead, sendfile, msync, mlock, sync_file_range: length */
|
187
|
+
void *ptr1; /* all applicable requests: pathname, old name; readdir: optional eio_dirents */
|
188
|
+
void *ptr2; /* all applicable requests: new name or memory buffer; readdir: name strings */
|
189
|
+
eio_tstamp nv1; /* utime, futime: atime; busy: sleep time */
|
190
|
+
eio_tstamp nv2; /* utime, futime: mtime */
|
191
|
+
|
192
|
+
int type; /* EIO_xxx constant ETP */
|
193
|
+
int int1; /* all applicable requests: file descriptor; sendfile: output fd; open, msync, mlockall, readdir: flags */
|
194
|
+
long int2; /* chown, fchown: uid; sendfile: input fd; open, chmod, mkdir, mknod: file mode, sync_file_range: flags */
|
195
|
+
long int3; /* chown, fchown: gid */
|
196
|
+
int errorno; /* errno value on syscall return */
|
197
|
+
|
198
|
+
unsigned char flags; /* private */
|
199
|
+
signed char pri; /* the priority */
|
200
|
+
|
201
|
+
void *data;
|
202
|
+
eio_cb finish;
|
203
|
+
void (*destroy)(eio_req *req); /* called when requets no longer needed */
|
204
|
+
void (*feed)(eio_req *req); /* only used for group requests */
|
205
|
+
|
206
|
+
EIO_REQ_MEMBERS
|
207
|
+
|
208
|
+
eio_req *grp, *grp_prev, *grp_next, *grp_first; /* private */
|
209
|
+
};
|
210
|
+
|
211
|
+
/* _private_ request flags */
|
212
|
+
enum {
|
213
|
+
EIO_FLAG_CANCELLED = 0x01, /* request was cancelled */
|
214
|
+
EIO_FLAG_PTR1_FREE = 0x02, /* need to free(ptr1) */
|
215
|
+
EIO_FLAG_PTR2_FREE = 0x04, /* need to free(ptr2) */
|
216
|
+
EIO_FLAG_GROUPADD = 0x08 /* some request was added to the group */
|
217
|
+
};
|
218
|
+
|
219
|
+
/* undocumented/unsupported/private helper */
|
220
|
+
/*void eio_page_align (void **addr, size_t *length);*/
|
221
|
+
|
222
|
+
/* returns < 0 on error, errno set
|
223
|
+
* need_poll, if non-zero, will be called when results are available
|
224
|
+
* and eio_poll_cb needs to be invoked (it MUST NOT call eio_poll_cb itself).
|
225
|
+
* done_poll is called when the need to poll is gone.
|
226
|
+
*/
|
227
|
+
int eio_init (void (*want_poll)(void), void (*done_poll)(void));
|
228
|
+
|
229
|
+
/* must be called regularly to handle pending requests */
|
230
|
+
/* returns 0 if all requests were handled, -1 if not, or the value of EIO_FINISH if != 0 */
|
231
|
+
int eio_poll (void);
|
232
|
+
|
233
|
+
/* stop polling if poll took longer than duration seconds */
|
234
|
+
void eio_set_max_poll_time (eio_tstamp nseconds);
|
235
|
+
/* do not handle more then count requests in one call to eio_poll_cb */
|
236
|
+
void eio_set_max_poll_reqs (unsigned int nreqs);
|
237
|
+
|
238
|
+
/* set minimum required number
|
239
|
+
* maximum wanted number
|
240
|
+
* or maximum idle number of threads */
|
241
|
+
void eio_set_min_parallel (unsigned int nthreads);
|
242
|
+
void eio_set_max_parallel (unsigned int nthreads);
|
243
|
+
void eio_set_max_idle (unsigned int nthreads);
|
244
|
+
void eio_set_idle_timeout (unsigned int seconds);
|
245
|
+
|
246
|
+
unsigned int eio_nreqs (void); /* number of requests in-flight */
|
247
|
+
unsigned int eio_nready (void); /* number of not-yet handled requests */
|
248
|
+
unsigned int eio_npending (void); /* numbe rof finished but unhandled requests */
|
249
|
+
unsigned int eio_nthreads (void); /* number of worker threads in use currently */
|
250
|
+
|
251
|
+
/*****************************************************************************/
|
252
|
+
/* convinience wrappers */
|
253
|
+
|
254
|
+
#ifndef EIO_NO_WRAPPERS
|
255
|
+
eio_req *eio_nop (int pri, eio_cb cb, void *data); /* does nothing except go through the whole process */
|
256
|
+
eio_req *eio_busy (eio_tstamp delay, int pri, eio_cb cb, void *data); /* ties a thread for this long, simulating busyness */
|
257
|
+
eio_req *eio_sync (int pri, eio_cb cb, void *data);
|
258
|
+
eio_req *eio_fsync (int fd, int pri, eio_cb cb, void *data);
|
259
|
+
eio_req *eio_fdatasync (int fd, int pri, eio_cb cb, void *data);
|
260
|
+
eio_req *eio_msync (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
|
261
|
+
eio_req *eio_mtouch (void *addr, size_t length, int flags, int pri, eio_cb cb, void *data);
|
262
|
+
eio_req *eio_mlock (void *addr, size_t length, int pri, eio_cb cb, void *data);
|
263
|
+
eio_req *eio_mlockall (int flags, int pri, eio_cb cb, void *data);
|
264
|
+
eio_req *eio_sync_file_range (int fd, off_t offset, size_t nbytes, unsigned int flags, int pri, eio_cb cb, void *data);
|
265
|
+
eio_req *eio_close (int fd, int pri, eio_cb cb, void *data);
|
266
|
+
eio_req *eio_readahead (int fd, off_t offset, size_t length, int pri, eio_cb cb, void *data);
|
267
|
+
eio_req *eio_read (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
|
268
|
+
eio_req *eio_write (int fd, void *buf, size_t length, off_t offset, int pri, eio_cb cb, void *data);
|
269
|
+
eio_req *eio_fstat (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
270
|
+
eio_req *eio_fstatvfs (int fd, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
271
|
+
eio_req *eio_futime (int fd, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
|
272
|
+
eio_req *eio_ftruncate (int fd, off_t offset, int pri, eio_cb cb, void *data);
|
273
|
+
eio_req *eio_fchmod (int fd, mode_t mode, int pri, eio_cb cb, void *data);
|
274
|
+
eio_req *eio_fchown (int fd, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data);
|
275
|
+
eio_req *eio_dup2 (int fd, int fd2, int pri, eio_cb cb, void *data);
|
276
|
+
eio_req *eio_sendfile (int out_fd, int in_fd, off_t in_offset, size_t length, int pri, eio_cb cb, void *data);
|
277
|
+
eio_req *eio_open (const char *path, int flags, mode_t mode, int pri, eio_cb cb, void *data);
|
278
|
+
eio_req *eio_utime (const char *path, eio_tstamp atime, eio_tstamp mtime, int pri, eio_cb cb, void *data);
|
279
|
+
eio_req *eio_truncate (const char *path, off_t offset, int pri, eio_cb cb, void *data);
|
280
|
+
eio_req *eio_chown (const char *path, uid_t uid, gid_t gid, int pri, eio_cb cb, void *data);
|
281
|
+
eio_req *eio_chmod (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
|
282
|
+
eio_req *eio_mkdir (const char *path, mode_t mode, int pri, eio_cb cb, void *data);
|
283
|
+
eio_req *eio_readdir (const char *path, int flags, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
|
284
|
+
eio_req *eio_rmdir (const char *path, int pri, eio_cb cb, void *data);
|
285
|
+
eio_req *eio_unlink (const char *path, int pri, eio_cb cb, void *data);
|
286
|
+
eio_req *eio_readlink (const char *path, int pri, eio_cb cb, void *data); /* result=ptr2 allocated dynamically */
|
287
|
+
eio_req *eio_stat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
288
|
+
eio_req *eio_lstat (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
289
|
+
eio_req *eio_statvfs (const char *path, int pri, eio_cb cb, void *data); /* stat buffer=ptr2 allocated dynamically */
|
290
|
+
eio_req *eio_mknod (const char *path, mode_t mode, dev_t dev, int pri, eio_cb cb, void *data);
|
291
|
+
eio_req *eio_link (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
292
|
+
eio_req *eio_symlink (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
293
|
+
eio_req *eio_rename (const char *path, const char *new_path, int pri, eio_cb cb, void *data);
|
294
|
+
eio_req *eio_custom (eio_cb execute, int pri, eio_cb cb, void *data);
|
295
|
+
#endif
|
296
|
+
|
297
|
+
/*****************************************************************************/
|
298
|
+
/* groups */
|
299
|
+
|
300
|
+
eio_req *eio_grp (eio_cb cb, void *data);
|
301
|
+
void eio_grp_feed (eio_req *grp, void (*feed)(eio_req *req), int limit);
|
302
|
+
void eio_grp_limit (eio_req *grp, int limit);
|
303
|
+
void eio_grp_add (eio_req *grp, eio_req *req);
|
304
|
+
void eio_grp_cancel (eio_req *grp); /* cancels all sub requests but not the group */
|
305
|
+
|
306
|
+
/*****************************************************************************/
|
307
|
+
/* request api */
|
308
|
+
|
309
|
+
/* true if the request was cancelled, useful in the invoke callback */
|
310
|
+
#define EIO_CANCELLED(req) ((req)->flags & EIO_FLAG_CANCELLED)
|
311
|
+
|
312
|
+
#define EIO_RESULT(req) ((req)->result)
|
313
|
+
/* returns a pointer to the result buffer allocated by eio */
|
314
|
+
#define EIO_BUF(req) ((req)->ptr2)
|
315
|
+
#define EIO_STAT_BUF(req) ((EIO_STRUCT_STAT *)EIO_BUF(req))
|
316
|
+
#define EIO_STATVFS_BUF(req) ((EIO_STRUCT_STATVFS *)EIO_BUF(req))
|
317
|
+
#define EIO_PATH(req) ((char *)(req)->ptr1)
|
318
|
+
|
319
|
+
/* submit a request for execution */
|
320
|
+
void eio_submit (eio_req *req);
|
321
|
+
/* cancel a request as soon fast as possible, if possible */
|
322
|
+
void eio_cancel (eio_req *req);
|
323
|
+
/* destroy a request that has never been submitted */
|
324
|
+
void eio_destroy (eio_req *req);
|
325
|
+
|
326
|
+
/*****************************************************************************/
|
327
|
+
/* convinience functions */
|
328
|
+
|
329
|
+
ssize_t eio_sendfile_sync (int ofd, int ifd, off_t offset, size_t count);
|
330
|
+
|
331
|
+
#ifdef __cplusplus
|
332
|
+
}
|
333
|
+
#endif
|
334
|
+
|
335
|
+
#endif
|
336
|
+
|
data/ext/libeio/eio.pod
ADDED
@@ -0,0 +1,303 @@
|
|
1
|
+
=head1 NAME
|
2
|
+
|
3
|
+
libeio - truly asynchronous POSIX I/O
|
4
|
+
|
5
|
+
=head1 SYNOPSIS
|
6
|
+
|
7
|
+
#include <eio.h>
|
8
|
+
|
9
|
+
=head1 DESCRIPTION
|
10
|
+
|
11
|
+
The newest version of this document is also available as an html-formatted
|
12
|
+
web page you might find easier to navigate when reading it for the first
|
13
|
+
time: L<http://pod.tst.eu/http://cvs.schmorp.de/libeio/eio.pod>.
|
14
|
+
|
15
|
+
Note that this library is a by-product of the C<IO::AIO> perl
|
16
|
+
module, and many of the subtler points regarding requests lifetime
|
17
|
+
and so on are only documented in its documentation at the
|
18
|
+
moment: L<http://pod.tst.eu/http://cvs.schmorp.de/IO-AIO/AIO.pm>.
|
19
|
+
|
20
|
+
=head2 FEATURES
|
21
|
+
|
22
|
+
This library provides fully asynchronous versions of most POSIX functions
|
23
|
+
dealing with I/O. Unlike most asynchronous libraries, this not only
|
24
|
+
includes C<read> and C<write>, but also C<open>, C<stat>, C<unlink> and
|
25
|
+
similar functions, as well as less rarely ones such as C<mknod>, C<futime>
|
26
|
+
or C<readlink>.
|
27
|
+
|
28
|
+
It also offers wrappers around C<sendfile> (Solaris, Linux, HP-UX and
|
29
|
+
FreeBSD, with emulation on other platforms) and C<readahead> (Linux, with
|
30
|
+
emulation elsewhere>).
|
31
|
+
|
32
|
+
The goal is to enable you to write fully non-blocking programs. For
|
33
|
+
example, in a game server, you would not want to freeze for a few seconds
|
34
|
+
just because the server is running a backup and you happen to call
|
35
|
+
C<readdir>.
|
36
|
+
|
37
|
+
=head2 TIME REPRESENTATION
|
38
|
+
|
39
|
+
Libeio represents time as a single floating point number, representing the
|
40
|
+
(fractional) number of seconds since the (POSIX) epoch (somewhere near
|
41
|
+
the beginning of 1970, details are complicated, don't ask). This type is
|
42
|
+
called C<eio_tstamp>, but it is guaranteed to be of type C<double> (or
|
43
|
+
better), so you can freely use C<double> yourself.
|
44
|
+
|
45
|
+
Unlike the name component C<stamp> might indicate, it is also used for
|
46
|
+
time differences throughout libeio.
|
47
|
+
|
48
|
+
=head2 FORK SUPPORT
|
49
|
+
|
50
|
+
Calling C<fork ()> is fully supported by this module. It is implemented in these steps:
|
51
|
+
|
52
|
+
1. wait till all requests in "execute" state have been handled
|
53
|
+
(basically requests that are already handed over to the kernel).
|
54
|
+
2. fork
|
55
|
+
3. in the parent, continue business as usual, done
|
56
|
+
4. in the child, destroy all ready and pending requests and free the
|
57
|
+
memory used by the worker threads. This gives you a fully empty
|
58
|
+
libeio queue.
|
59
|
+
|
60
|
+
=head1 INITIALISATION/INTEGRATION
|
61
|
+
|
62
|
+
Before you can call any eio functions you first have to initialise the
|
63
|
+
library. The library integrates into any event loop, but can also be used
|
64
|
+
without one, including in polling mode.
|
65
|
+
|
66
|
+
You have to provide the necessary glue yourself, however.
|
67
|
+
|
68
|
+
=over 4
|
69
|
+
|
70
|
+
=item int eio_init (void (*want_poll)(void), void (*done_poll)(void))
|
71
|
+
|
72
|
+
This function initialises the library. On success it returns C<0>, on
|
73
|
+
failure it returns C<-1> and sets C<errno> appropriately.
|
74
|
+
|
75
|
+
It accepts two function pointers specifying callbacks as argument, both of
|
76
|
+
which can be C<0>, in which case the callback isn't called.
|
77
|
+
|
78
|
+
=item want_poll callback
|
79
|
+
|
80
|
+
The C<want_poll> callback is invoked whenever libeio wants attention (i.e.
|
81
|
+
it wants to be polled by calling C<eio_poll>). It is "edge-triggered",
|
82
|
+
that is, it will only be called once when eio wants attention, until all
|
83
|
+
pending requests have been handled.
|
84
|
+
|
85
|
+
This callback is called while locks are being held, so I<you must
|
86
|
+
not call any libeio functions inside this callback>. That includes
|
87
|
+
C<eio_poll>. What you should do is notify some other thread, or wake up
|
88
|
+
your event loop, and then call C<eio_poll>.
|
89
|
+
|
90
|
+
=item done_poll callback
|
91
|
+
|
92
|
+
This callback is invoked when libeio detects that all pending requests
|
93
|
+
have been handled. It is "edge-triggered", that is, it will only be
|
94
|
+
called once after C<want_poll>. To put it differently, C<want_poll> and
|
95
|
+
C<done_poll> are invoked in pairs: after C<want_poll> you have to call
|
96
|
+
C<eio_poll ()> until either C<eio_poll> indicates that everything has been
|
97
|
+
handled or C<done_poll> has been called, which signals the same.
|
98
|
+
|
99
|
+
Note that C<eio_poll> might return after C<done_poll> and C<want_poll>
|
100
|
+
have been called again, so watch out for races in your code.
|
101
|
+
|
102
|
+
As with C<want_poll>, this callback is called while locks are being held,
|
103
|
+
so you I<must not call any libeio functions form within this callback>.
|
104
|
+
|
105
|
+
=item int eio_poll ()
|
106
|
+
|
107
|
+
This function has to be called whenever there are pending requests that
|
108
|
+
need finishing. You usually call this after C<want_poll> has indicated
|
109
|
+
that you should do so, but you can also call this function regularly to
|
110
|
+
poll for new results.
|
111
|
+
|
112
|
+
If any request invocation returns a non-zero value, then C<eio_poll ()>
|
113
|
+
immediately returns with that value as return value.
|
114
|
+
|
115
|
+
Otherwise, if all requests could be handled, it returns C<0>. If for some
|
116
|
+
reason not all requests have been handled, i.e. some are still pending, it
|
117
|
+
returns C<-1>.
|
118
|
+
|
119
|
+
=back
|
120
|
+
|
121
|
+
For libev, you would typically use an C<ev_async> watcher: the
|
122
|
+
C<want_poll> callback would invoke C<ev_async_send> to wake up the event
|
123
|
+
loop. Inside the callback set for the watcher, one would call C<eio_poll
|
124
|
+
()> (followed by C<ev_async_send> again if C<eio_poll> indicates that not
|
125
|
+
all requests have been handled yet). The race is taken care of because
|
126
|
+
libev resets/rearms the async watcher before calling your callback,
|
127
|
+
and therefore, before calling C<eio_poll>. This might result in (some)
|
128
|
+
spurious wake-ups, but is generally harmless.
|
129
|
+
|
130
|
+
For most other event loops, you would typically use a pipe - the event
|
131
|
+
loop should be told to wait for read readiness on the read end. In
|
132
|
+
C<want_poll> you would write a single byte, in C<done_poll> you would try
|
133
|
+
to read that byte, and in the callback for the read end, you would call
|
134
|
+
C<eio_poll>. The race is avoided here because the event loop should invoke
|
135
|
+
your callback again and again until the byte has been read (as the pipe
|
136
|
+
read callback does not read it, only C<done_poll>).
|
137
|
+
|
138
|
+
=head2 CONFIGURATION
|
139
|
+
|
140
|
+
The functions in this section can sometimes be useful, but the default
|
141
|
+
configuration will do in most case, so you should skip this section on
|
142
|
+
first reading.
|
143
|
+
|
144
|
+
=over 4
|
145
|
+
|
146
|
+
=item eio_set_max_poll_time (eio_tstamp nseconds)
|
147
|
+
|
148
|
+
This causes C<eio_poll ()> to return after it has detected that it was
|
149
|
+
running for C<nsecond> seconds or longer (this number can be fractional).
|
150
|
+
|
151
|
+
This can be used to limit the amount of time spent handling eio requests,
|
152
|
+
for example, in interactive programs, you might want to limit this time to
|
153
|
+
C<0.01> seconds or so.
|
154
|
+
|
155
|
+
Note that:
|
156
|
+
|
157
|
+
a) libeio doesn't know how long your request callbacks take, so the time
|
158
|
+
spent in C<eio_poll> is up to one callback invocation longer then this
|
159
|
+
interval.
|
160
|
+
|
161
|
+
b) this is implemented by calling C<gettimeofday> after each request,
|
162
|
+
which can be costly.
|
163
|
+
|
164
|
+
c) at least one request will be handled.
|
165
|
+
|
166
|
+
=item eio_set_max_poll_reqs (unsigned int nreqs)
|
167
|
+
|
168
|
+
When C<nreqs> is non-zero, then C<eio_poll> will not handle more than
|
169
|
+
C<nreqs> requests per invocation. This is a less costly way to limit the
|
170
|
+
amount of work done by C<eio_poll> then setting a time limit.
|
171
|
+
|
172
|
+
If you know your callbacks are generally fast, you could use this to
|
173
|
+
encourage interactiveness in your programs by setting it to C<10>, C<100>
|
174
|
+
or even C<1000>.
|
175
|
+
|
176
|
+
=item eio_set_min_parallel (unsigned int nthreads)
|
177
|
+
|
178
|
+
Make sure libeio can handle at least this many requests in parallel. It
|
179
|
+
might be able handle more.
|
180
|
+
|
181
|
+
=item eio_set_max_parallel (unsigned int nthreads)
|
182
|
+
|
183
|
+
Set the maximum number of threads that libeio will spawn.
|
184
|
+
|
185
|
+
=item eio_set_max_idle (unsigned int nthreads)
|
186
|
+
|
187
|
+
Libeio uses threads internally to handle most requests, and will start and stop threads on demand.
|
188
|
+
|
189
|
+
This call can be used to limit the number of idle threads (threads without
|
190
|
+
work to do): libeio will keep some threads idle in preparation for more
|
191
|
+
requests, but never longer than C<nthreads> threads.
|
192
|
+
|
193
|
+
In addition to this, libeio will also stop threads when they are idle for
|
194
|
+
a few seconds, regardless of this setting.
|
195
|
+
|
196
|
+
=item unsigned int eio_nthreads ()
|
197
|
+
|
198
|
+
Return the number of worker threads currently running.
|
199
|
+
|
200
|
+
=item unsigned int eio_nreqs ()
|
201
|
+
|
202
|
+
Return the number of requests currently handled by libeio. This is the
|
203
|
+
total number of requests that have been submitted to libeio, but not yet
|
204
|
+
destroyed.
|
205
|
+
|
206
|
+
=item unsigned int eio_nready ()
|
207
|
+
|
208
|
+
Returns the number of ready requests, i.e. requests that have been
|
209
|
+
submitted but have not yet entered the execution phase.
|
210
|
+
|
211
|
+
=item unsigned int eio_npending ()
|
212
|
+
|
213
|
+
Returns the number of pending requests, i.e. requests that have been
|
214
|
+
executed and have results, but have not been finished yet by a call to
|
215
|
+
C<eio_poll>).
|
216
|
+
|
217
|
+
=back
|
218
|
+
|
219
|
+
|
220
|
+
=head1 ANATOMY OF AN EIO REQUEST
|
221
|
+
|
222
|
+
#TODO
|
223
|
+
|
224
|
+
|
225
|
+
=head1 HIGH LEVEL REQUEST API
|
226
|
+
|
227
|
+
#TODO
|
228
|
+
|
229
|
+
=back
|
230
|
+
|
231
|
+
|
232
|
+
=head1 LOW LEVEL REQUEST API
|
233
|
+
|
234
|
+
#TODO
|
235
|
+
|
236
|
+
=head1 EMBEDDING
|
237
|
+
|
238
|
+
Libeio can be embedded directly into programs. This functionality is not
|
239
|
+
documented and not (yet) officially supported.
|
240
|
+
|
241
|
+
Note that, when including C<libeio.m4>, you are responsible for defining
|
242
|
+
the compilation environment (C<_LARGEFILE_SOURCE>, C<_GNU_SOURCE> etc.).
|
243
|
+
|
244
|
+
If you need to know how, check the C<IO::AIO> perl module, which does
|
245
|
+
exactly that.
|
246
|
+
|
247
|
+
|
248
|
+
=head1 COMPILETIME CONFIGURATION
|
249
|
+
|
250
|
+
These symbols, if used, must be defined when compiling F<eio.c>.
|
251
|
+
|
252
|
+
=over 4
|
253
|
+
|
254
|
+
=item EIO_STACKSIZE
|
255
|
+
|
256
|
+
This symbol governs the stack size for each eio thread. Libeio itself
|
257
|
+
was written to use very little stackspace, but when using C<EIO_CUSTOM>
|
258
|
+
requests, you might want to increase this.
|
259
|
+
|
260
|
+
If this symbol is undefined (the default) then libeio will use its default
|
261
|
+
stack size (C<sizeof (long) * 4096> currently). If it is defined, but
|
262
|
+
C<0>, then the default operating system stack size will be used. In all
|
263
|
+
other cases, the value must be an expression that evaluates to the desired
|
264
|
+
stack size.
|
265
|
+
|
266
|
+
=back
|
267
|
+
|
268
|
+
|
269
|
+
=head1 PORTABILITY REQUIREMENTS
|
270
|
+
|
271
|
+
In addition to a working ISO-C implementation, libeio relies on a few
|
272
|
+
additional extensions:
|
273
|
+
|
274
|
+
=over 4
|
275
|
+
|
276
|
+
=item POSIX threads
|
277
|
+
|
278
|
+
To be portable, this module uses threads, specifically, the POSIX threads
|
279
|
+
library must be available (and working, which partially excludes many xBSD
|
280
|
+
systems, where C<fork ()> is buggy).
|
281
|
+
|
282
|
+
=item POSIX-compatible filesystem API
|
283
|
+
|
284
|
+
This is actually a harder portability requirement: The libeio API is quite
|
285
|
+
demanding regarding POSIX API calls (symlinks, user/group management
|
286
|
+
etc.).
|
287
|
+
|
288
|
+
=item C<double> must hold a time value in seconds with enough accuracy
|
289
|
+
|
290
|
+
The type C<double> is used to represent timestamps. It is required to
|
291
|
+
have at least 51 bits of mantissa (and 9 bits of exponent), which is good
|
292
|
+
enough for at least into the year 4000. This requirement is fulfilled by
|
293
|
+
implementations implementing IEEE 754 (basically all existing ones).
|
294
|
+
|
295
|
+
=back
|
296
|
+
|
297
|
+
If you know of other additional requirements drop me a note.
|
298
|
+
|
299
|
+
|
300
|
+
=head1 AUTHOR
|
301
|
+
|
302
|
+
Marc Lehmann <libeio@schmorp.de>.
|
303
|
+
|