00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #ifndef _OASYS_IO_H_
00040 #define _OASYS_IO_H_
00041
00042 #include <fcntl.h>
00043 #include <stdlib.h>
00044 #include <sys/poll.h>
00045 #include <sys/uio.h>
00046 #include <sys/socket.h>
00047 #include <sys/stat.h>
00048
00049 #include "../debug/DebugUtils.h"
00050 #include "../thread/Notifier.h"
00051
00052 namespace oasys {
00053
00054 class IOMonitor;
00055
00062 enum IOTimeoutReturn_t {
00063 IOEOF = 0,
00064 IOERROR = -1,
00065 IOTIMEOUT = -2,
00066 IOINTR = -3,
00067 IOAGAIN = -4,
00068 IORATELIMIT = -5,
00069 };
00070
00071
00072 struct IO {
00074 enum IO_Op_t {
00075 READV = 1,
00076 RECV,
00077 RECVFROM,
00078 RECVMSG,
00079 WRITEV,
00080 SEND,
00081 SENDTO,
00082 SENDMSG,
00083
00084 CONNECT,
00085 ACCEPT,
00086 };
00087
00091 static const char* ioerr2str(int err);
00092
00094
00095 static int open(const char* path, int flags,
00096 int* errnop = 0, const char* log = 0);
00097
00098 static int open(const char* path, int flags, mode_t mode,
00099 int* errnop = 0, const char* log = 0);
00100
00101 static int close(int fd,
00102 const char* log = 0,
00103 const char* filename = "");
00104
00105 static int unlink(const char* path,
00106 const char* log = 0);
00107
00108 static int lseek(int fd, off_t offset, int whence,
00109 const char* log = 0);
00110
00111 static int truncate(int fd, off_t length,
00112 const char* log = 0);
00113
00114 static int mkstemp(char* templ, const char* log = 0);
00115
00116 static int stat(const char* path, struct stat* buf, const char* log = 0);
00117
00118 static int lstat(const char* path, struct stat* buf, const char* log = 0);
00120
00122 static int read(int fd, char* bp, size_t len,
00123 Notifier* intr = 0, const char* log = 0);
00124
00125 static int readv(int fd, const struct iovec* iov, int iovcnt,
00126 Notifier* intr = 0, const char* log = 0);
00127
00128 static int readall(int fd, char* bp, size_t len,
00129 Notifier* intr = 0, const char* log = 0);
00130
00131 static int readvall(int fd, const struct iovec* iov, int iovcnt,
00132 Notifier* intr = 0, const char* log = 0);
00133
00134 static int timeout_read(int fd, char* bp, size_t len, int timeout_ms,
00135 Notifier* intr = 0, const char* log = 0);
00136
00137 static int timeout_readv(int fd, const struct iovec* iov, int iovcnt,
00138 int timeout_ms, Notifier* intr = 0,
00139 const char* log = 0);
00140
00141 static int timeout_readall(int fd, char* bp, size_t len, int timeout_ms,
00142 Notifier* intr = 0, const char* log = 0);
00143
00144 static int timeout_readvall(int fd, const struct iovec* iov, int iovcnt,
00145 int timeout_ms, Notifier* intr = 0,
00146 const char* log = 0);
00147
00148 static int recv(int fd, char* bp, size_t len, int flags,
00149 Notifier* intr = 0, const char* log = 0);
00150
00151 static int recvfrom(int fd, char* bp, size_t len,
00152 int flags, struct sockaddr* from, socklen_t* fromlen,
00153 Notifier* intr = 0, const char* log = 0);
00154
00155 static int recvmsg(int fd, struct msghdr* msg, int flags,
00156 Notifier* intr = 0, const char* log = 0);
00157
00158 static int write(int fd, const char* bp, size_t len,
00159 Notifier* intr = 0, const char* log = 0);
00160
00161 static int writev(int fd, const struct iovec* iov, int iovcnt,
00162 Notifier* intr = 0, const char* log = 0);
00163
00164 static int writeall(int fd, const char* bp, size_t len,
00165 Notifier* intr = 0, const char* log = 0);
00166
00167 static int writevall(int fd, const struct iovec* iov, int iovcnt,
00168 Notifier* intr = 0, const char* log = 0);
00169
00170 static int timeout_write(int fd, const char* bp, size_t len, int timeout_ms,
00171 Notifier* intr = 0, const char* log = 0);
00172
00173 static int timeout_writev(int fd, const struct iovec* iov, int iovcnt,
00174 int timeout_ms, Notifier* intr = 0,
00175 const char* log = 0);
00176
00177 static int timeout_writeall(int fd, const char* bp, size_t len,
00178 int timeout_ms,
00179 Notifier* intr = 0, const char* log = 0);
00180
00181 static int timeout_writevall(int fd, const struct iovec* iov, int iovcnt,
00182 int timeout_ms, Notifier* intr = 0,
00183 const char* log = 0);
00184
00185 static int send(int fd, const char* bp, size_t len, int flags,
00186 Notifier* intr = 0, const char* log = 0);
00187
00188 static int sendto(int fd, char* bp, size_t len,
00189 int flags, const struct sockaddr* to, socklen_t tolen,
00190 Notifier* intr = 0, const char* log = 0);
00191
00192 static int sendmsg(int fd, const struct msghdr* msg, int flags,
00193 Notifier* intr = 0, const char* log = 0);
00195
00198 static int poll_single(int fd, short events, short* revents,
00199 int timeout_ms,
00200 Notifier* intr = 0, const char* log = 0);
00201
00204 static int poll_multiple(struct pollfd* fds, int nfds, int timeout_ms,
00205 Notifier* intr = 0, const char* log = 0);
00206
00210
00212 static int get_nonblocking(int fd, bool *nonblocking,
00213 const char* log = NULL);
00214 static int set_nonblocking(int fd, bool nonblocking,
00215 const char* log = NULL);
00217
00221 static size_t iovec_size(struct iovec* iov, int num) {
00222 size_t size = 0;
00223 for (int i=0; i<num; ++i) {
00224 size += iov[i].iov_len;
00225 }
00226 return size;
00227 }
00228
00229
00231 static int poll_with_notifier(Notifier* intr,
00232 struct pollfd* fds,
00233 size_t nfds,
00234 int timeout,
00235 const struct timeval* start_time,
00236 const char* log);
00237
00239 union RwDataExtraArgs {
00240 const struct msghdr* msg_hdr;
00241
00242 struct {
00243 const struct sockaddr* to;
00244 socklen_t tolen;
00245 } sendto;
00246
00247 struct {
00248 struct sockaddr* from;
00249 socklen_t* fromlen;
00250 } recvfrom;
00251 };
00252
00255 static int rwdata(IO_Op_t op,
00256 int fd,
00257 const struct iovec* iov,
00258 int iovcnt,
00259 int flags,
00260 int timeout,
00261 RwDataExtraArgs* args,
00262 const struct timeval* start_time,
00263 Notifier* intr,
00264 bool ignore_eagain,
00265 const char* log);
00266
00268 static int rwvall(IO_Op_t op,
00269 int fd,
00270 const struct iovec* iov,
00271 int iovcnt,
00272 int timeout,
00273 const struct timeval* start,
00274 Notifier* intr,
00275 const char* fcn_name,
00276 const char* log);
00277
00279 static int adjust_timeout(int timeout, const struct timeval* start);
00280 };
00281
00283 class IOMonitor {
00284 public:
00285 struct info_t {
00286 int timeout_ms_;
00287 int err_code_;
00288
00289 };
00290
00291 virtual ~IOMonitor() {}
00292 virtual void monitor(IO::IO_Op_t op, const info_t* info) = 0;
00293 };
00294
00299 class IOHandlerBase {
00300 public:
00301 IOHandlerBase(Notifier* intr = 0)
00302 : intr_(intr), monitor_(0) {}
00303 ~IOHandlerBase() { delete_z(intr_); }
00304
00305 Notifier* get_notifier() {
00306 return intr_;
00307 }
00308
00309 void interrupt_from_io() {
00310 ASSERT(intr_ != 0);
00311 intr_->notify();
00312 }
00313
00314 void set_notifier(Notifier* intr) {
00315 ASSERT(intr_ == 0);
00316 intr_ = intr;
00317 }
00318
00319 void set_monitor(IOMonitor* monitor) {
00320 monitor_ = monitor;
00321 }
00322
00323 void monitor(IO::IO_Op_t op,
00324 const IOMonitor::info_t* info)
00325 {
00326 if (monitor_ != 0) {
00327 monitor_->monitor(op, info);
00328 }
00329 }
00330
00331 private:
00332 Notifier* intr_;
00333 IOMonitor* monitor_;
00334 };
00335
00336 }
00337
00338 #endif
00339