Esempio n. 1
0
size_t my_fread(FILE *stream, uchar *Buffer, size_t Count, myf MyFlags)
{
    size_t readbytes;
    DBUG_ENTER("my_fread");
    DBUG_PRINT("my",("stream: 0x%lx  Buffer: 0x%lx  Count: %u  MyFlags: %d",
                     (long) stream, (long) Buffer, (uint) Count, MyFlags));

    if ((readbytes= fread(Buffer, sizeof(char), Count, stream)) != Count)
    {
        DBUG_PRINT("error",("Read only %d bytes", (int) readbytes));
        if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
        {
            if (ferror(stream))
                my_error(EE_READ, MYF(ME_BELL+ME_WAITTANG),
                         my_filename(my_fileno(stream)),errno);
            else if (MyFlags & (MY_NABP | MY_FNABP))
                my_error(EE_EOFERR, MYF(ME_BELL+ME_WAITTANG),
                         my_filename(my_fileno(stream)),errno);
        }
        my_errno=errno ? errno : -1;
        if (ferror(stream) || MyFlags & (MY_NABP | MY_FNABP))
            DBUG_RETURN((size_t) -1);			/* Return with error */
    }
    if (MyFlags & (MY_NABP | MY_FNABP))
        DBUG_RETURN(0);				/* Read ok */
    DBUG_RETURN(readbytes);
} /* my_fread */
Esempio n. 2
0
static VALUE
my_accept(struct accept_args *a, int force_nonblock)
{
	int client_fd;
	VALUE client_io;
	int retried = 0;

retry:
	client_fd = thread_accept(a, force_nonblock);
	if (client_fd == -1) {
		switch (errno) {
		case EAGAIN:
			if (force_nonblock)
				return Qnil;
			a->fd = my_fileno(a->accept_io);
			set_blocking_or_block(a->fd);
#ifdef ECONNABORTED
		case ECONNABORTED:
#endif /* ECONNABORTED */
#ifdef EPROTO
		case EPROTO:
#endif /* EPROTO */
		case EINTR:
			a->fd = my_fileno(a->accept_io);
			goto retry;
		case ENOMEM:
		case EMFILE:
		case ENFILE:
#ifdef ENOBUFS
		case ENOBUFS:
#endif /* ENOBUFS */
			if (!retried) {
				retried = 1;
				errno = 0;
				rb_gc();
				goto retry;
			}
		default:
			rb_sys_fail("accept");
		}
	}
	client_io = sock_for_fd(a->accepted_class, client_fd);
	post_accept(a->accept_io, client_io);

	if (a->addr)
		in_addr_set(client_io,
		            (struct sockaddr_storage *)a->addr, *a->addrlen);
	else
		rb_ivar_set(client_io, iv_kgio_addr, localhost);
	return client_io;
}
Esempio n. 3
0
static int read_check(struct io_args *a, long n, const char *msg, int io_wait)
{
	if (n == -1) {
		if (errno == EINTR) {
			a->fd = my_fileno(a->io);
			return -1;
		}
		rb_str_set_len(a->buf, 0);
		if (errno == EAGAIN) {
			if (io_wait) {
				(void)kgio_call_wait_readable(a->io);

				/* buf may be modified in other thread/fiber */
				rb_str_modify(a->buf);
				rb_str_resize(a->buf, a->len);
				a->ptr = RSTRING_PTR(a->buf);
				return -1;
			} else {
				a->buf = sym_wait_readable;
				return 0;
			}
		}
		rd_sys_fail(msg);
	}
	rb_str_set_len(a->buf, n);
	if (n == 0)
		a->buf = Qnil;
	return 0;
}
Esempio n. 4
0
FILE *my_fopen(const char *filename, int flags, myf MyFlags)
{
  FILE *fd;
  char type[5];
  char *dup_filename= NULL;
  DBUG_ENTER("my_fopen");
  DBUG_PRINT("my",("Name: '%s'  flags: %d  MyFlags: %d",
		   filename, flags, MyFlags));

  make_ftype(type,flags);

#ifdef _WIN32
  fd= my_win_fopen(filename, type);
#else
  fd= fopen(filename, type);
#endif
  if (fd != 0)
  {
    /*
      The test works if MY_NFILE < 128. The problem is that fileno() is char
      on some OS (SUNOS). Actually the filename save isn't that important
      so we can ignore if this doesn't work.
    */

    int filedesc= my_fileno(fd);
    if ((uint)filedesc >= my_file_limit)
    {
      mysql_mutex_lock(&THR_LOCK_open);
      my_stream_opened++;
      mysql_mutex_unlock(&THR_LOCK_open);
      DBUG_RETURN(fd);				/* safeguard */
    }
    dup_filename= my_strdup(key_memory_my_file_info, filename, MyFlags);
    if (dup_filename != NULL)
    {
      mysql_mutex_lock(&THR_LOCK_open);
      my_file_info[filedesc].name= dup_filename;
      my_stream_opened++;
      my_file_total_opened++;
      my_file_info[filedesc].type= STREAM_BY_FOPEN;
      mysql_mutex_unlock(&THR_LOCK_open);
      DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
      DBUG_RETURN(fd);
    }
    (void) my_fclose(fd,MyFlags);
    set_my_errno(ENOMEM);
  }
  else
    set_my_errno(errno);
  DBUG_PRINT("error",("Got error %d on open",my_errno()));
  if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
  {
    char errbuf[MYSYS_STRERROR_SIZE];
    my_error((flags & O_RDONLY) || (flags == O_RDONLY ) ? EE_FILENOTFOUND :
             EE_CANTCREATEFILE,
             MYF(0), filename,
             my_errno(), my_strerror(errbuf, sizeof(errbuf), my_errno()));
  }
  DBUG_RETURN((FILE*) 0);
} /* my_fopen */
Esempio n. 5
0
/* Close a stream */
int my_fclose(FILE *fd, myf MyFlags)
{
  int err,file;
  DBUG_ENTER("my_fclose");
  DBUG_PRINT("my",("stream: 0x%lx  MyFlags: %d", (long) fd, MyFlags));

  mysql_mutex_lock(&THR_LOCK_open);
  file= my_fileno(fd);
#ifndef _WIN32
  err= fclose(fd);
#else
  err= my_win_fclose(fd);
#endif
  if(err < 0)
  {
    set_my_errno(errno);
    if (MyFlags & (MY_FAE | MY_WME))
    {
      char errbuf[MYSYS_STRERROR_SIZE];
      my_error(EE_BADCLOSE, MYF(0), my_filename(file),
               my_errno(), my_strerror(errbuf, sizeof(errbuf), my_errno()));
    }
  }
  else
    my_stream_opened--;
  if ((uint) file < my_file_limit && my_file_info[file].type != UNOPEN)
  {
    my_file_info[file].type = UNOPEN;
    my_free(my_file_info[file].name);
  }
  mysql_mutex_unlock(&THR_LOCK_open);
  DBUG_RETURN(err);
} /* my_fclose */
Esempio n. 6
0
File: wait.c Progetto: 7kaji/try
static int kgio_timedwait(VALUE self, VALUE timeout, int write_p)
{
	struct timeval tv = rb_time_interval(timeout);
	int events = write_p ? RB_WAITFD_OUT : RB_WAITFD_IN;

	return rb_wait_for_single_fd(my_fileno(self), events, &tv);
}
Esempio n. 7
0
static void prepare_write(struct io_args *a, VALUE io, VALUE str)
{
	a->buf = (TYPE(str) == T_STRING) ? str : rb_obj_as_string(str);
	a->ptr = RSTRING_PTR(a->buf);
	a->len = RSTRING_LEN(a->buf);
	a->io = io;
	a->fd = my_fileno(io);
}
Esempio n. 8
0
static VALUE FORCE_CLOEXEC(VALUE io)
{
	int fd = my_fileno(io);
	int flags = fcntl(fd, F_SETFD, FD_CLOEXEC);
	if (flags == -1)
		rb_sys_fail("fcntl(F_SETFD, FD_CLOEXEC)");
	return io;
}
Esempio n. 9
0
/*
 * Blocks the running Thread indefinitely until +self+ IO object is writable.
 * This method is automatically called whenever kgio_write needs to
 * block on output.
 *
 * Users of alternative threading/fiber libraries are
 * encouraged to override this method in their subclasses or modules to
 * work with their threading/blocking methods.
 */
static VALUE kgio_wait_writable(VALUE self)
{
	int fd = my_fileno(self);

	errno = EAGAIN;
	if (!rb_io_wait_writable(fd))
		rb_sys_fail("kgio_wait_writable");

	return self;
}
Esempio n. 10
0
FILE *my_fopen(const char *filename, int flags, myf MyFlags)
{
  FILE *fd;
  char type[5];
  DBUG_ENTER("my_fopen");
  DBUG_PRINT("my",("Name: '%s'  flags: %d  MyFlags: %d",
		   filename, flags, MyFlags));

  make_ftype(type,flags);

#ifdef _WIN32
  fd= my_win_fopen(filename, type);
#else
  fd= fopen(filename, type);
#endif
  if (fd != 0)
  {
    /*
      The test works if MY_NFILE < 128. The problem is that fileno() is char
      on some OS (SUNOS). Actually the filename save isn't that important
      so we can ignore if this doesn't work.
    */

    int filedesc= my_fileno(fd);
    if ((uint)filedesc >= my_file_limit)
    {
      thread_safe_increment(my_stream_opened,&THR_LOCK_open);
      DBUG_RETURN(fd);				/* safeguard */
    }
    mysql_mutex_lock(&THR_LOCK_open);
    if ((my_file_info[filedesc].name= (char*)
	 my_strdup(filename,MyFlags)))
    {
      my_stream_opened++;
      my_file_total_opened++;
      my_file_info[filedesc].type= STREAM_BY_FOPEN;
      mysql_mutex_unlock(&THR_LOCK_open);
      DBUG_PRINT("exit",("stream: 0x%lx", (long) fd));
      DBUG_RETURN(fd);
    }
    mysql_mutex_unlock(&THR_LOCK_open);
    (void) my_fclose(fd,MyFlags);
    my_errno=ENOMEM;
  }
  else
    my_errno=errno;
  DBUG_PRINT("error",("Got error %d on open",my_errno));
  if (MyFlags & (MY_FFNF | MY_FAE | MY_WME))
    my_error((flags & O_RDONLY) || (flags == O_RDONLY ) ? EE_FILENOTFOUND :
	     EE_CANTCREATEFILE,
	     MYF(ME_BELL+ME_WAITTANG), filename, my_errno);
  DBUG_RETURN((FILE*) 0);
} /* my_fopen */
Esempio n. 11
0
/*
 * call-seq:
 *
 *	Raindrops::TCP_Info.new(tcp_socket)	-> TCP_Info object
 *
 * Reads a TCP_Info object from any given +tcp_socket+.  See the tcp(7)
 * manpage and /usr/include/linux/tcp.h for more details.
 */
static VALUE init(VALUE self, VALUE io)
{
	int fd = my_fileno(io);
	struct tcp_info *info = DATA_PTR(self);
	socklen_t len = (socklen_t)sizeof(struct tcp_info);
	int rc = getsockopt(fd, IPPROTO_TCP, TCP_INFO, info, &len);

	if (rc != 0)
		rb_sys_fail("getsockopt");

	return self;
}
Esempio n. 12
0
/*
 * checks to see if we've written anything since the last recv()
 * If we have, uncork the socket and immediately recork it.
 */
static void push_pending_data(VALUE io)
{
	int optval = 0;
	const socklen_t optlen = sizeof(int);
	const int fd = my_fileno(io);

	if (setsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &optval, optlen) != 0)
		rb_sys_fail("setsockopt(TCP_CORK/TCP_NOPUSH, 0)");
	/* immediately recork */
	optval = 1;
	if (setsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &optval, optlen) != 0)
		rb_sys_fail("setsockopt(TCP_CORK/TCP_NOPUSH, 1)");
}
Esempio n. 13
0
File: wait.c Progetto: 7kaji/try
static int kgio_wait(int argc, VALUE *argv, VALUE self, int write_p)
{
	int fd;
	VALUE timeout;

	if (rb_scan_args(argc, argv, "01", &timeout) == 1 && !NIL_P(timeout))
		return kgio_timedwait(self, timeout, write_p);

	fd = my_fileno(self);
	errno = EAGAIN;
	write_p ? rb_io_wait_writable(fd) : rb_io_wait_readable(fd);
	return 1;
}
Esempio n. 14
0
int my_win_fclose(FILE *file)
{
  File fd;

  DBUG_ENTER("my_win_close");
  fd= my_fileno(file);
  if(fd < 0)
    DBUG_RETURN(-1);
  if(fclose(file) < 0)
    DBUG_RETURN(-1);
  invalidate_fd(fd);
  DBUG_RETURN(0);
}
Esempio n. 15
0
/*
 * call-seq:
 *
 *	io.kgio_addr! => refreshes the given sock address
 */
static VALUE addr_bang(VALUE io)
{
	int fd = my_fileno(io);
	struct sockaddr_storage addr;
	socklen_t len = sizeof(struct sockaddr_storage);

	if (getpeername(fd, (struct sockaddr *)&addr, &len) != 0)
		rb_sys_fail("getpeername");

	if (addr.ss_family == AF_UNIX)
		return rb_ivar_set(io, iv_kgio_addr, localhost);

	return in_addr_set(io, &addr, len);
}
Esempio n. 16
0
static void prepare_writev(struct wrv_args *a, VALUE io, VALUE ary)
{
	a->io = io;
	a->fd = my_fileno(io);
	a->something_written = 0;

	if (TYPE(ary) == T_ARRAY)
		/* rb_ary_subseq will not copy array unless it modified */
		a->buf = MY_ARY_SUBSEQ(ary, 0, RARRAY_LEN(ary));
	else
		a->buf = rb_Array(ary);

	a->vec_buf = rb_str_new(0, 0);
	a->vec = NULL;
}
Esempio n. 17
0
static void prepare_read(struct io_args *a, int argc, VALUE *argv, VALUE io)
{
	VALUE length;

	a->io = io;
	a->fd = my_fileno(io);
	rb_scan_args(argc, argv, "11", &length, &a->buf);
	a->len = NUM2LONG(length);
	if (NIL_P(a->buf)) {
		a->buf = rb_str_new(NULL, a->len);
	} else {
		StringValue(a->buf);
		rb_str_modify(a->buf);
		rb_str_resize(a->buf, a->len);
	}
	a->ptr = RSTRING_PTR(a->buf);
}
Esempio n. 18
0
/*
 * call-seq:
 *
 *	s = Kgio::Socket.new(:INET, :STREAM)
 *	addr = Socket.pack_sockaddr_in(80, "example.com")
 *	s.kgio_fastopen("hello world", addr) -> nil
 *
 * Starts a TCP connection using TCP Fast Open.  This uses a blocking
 * sendto() syscall and is only available on Ruby 1.9 or later.
 * This raises exceptions (including Errno::EINPROGRESS/Errno::EAGAIN)
 * on errors.  Using this is only recommended for blocking sockets.
 *
 * Timeouts may be set with setsockopt:
 *
 *	s.setsockopt(:SOCKET, :SNDTIMEO, [1,0].pack("l_l_"))
 */
static VALUE fastopen(VALUE sock, VALUE buf, VALUE addr)
{
	struct tfo_args a;
	VALUE str = (TYPE(buf) == T_STRING) ? buf : rb_obj_as_string(buf);
	ssize_t w;

	a.fd = my_fileno(sock);
	a.buf = RSTRING_PTR(str);
	a.buflen = (size_t)RSTRING_LEN(str);
	a.addr = sockaddr_from(&a.addrlen, addr);

	/* n.b. rb_thread_blocking_region preserves errno */
	w = (ssize_t)rb_thread_io_blocking_region(tfo_sendto, &a, a.fd);
	if (w < 0)
		rb_sys_fail("sendto");
	if ((size_t)w == a.buflen)
		return Qnil;

	return rb_str_subseq(str, w, a.buflen - w);
}
Esempio n. 19
0
static enum autopush_state detect_acceptor_state(VALUE io)
{
	int corked = 0;
	int fd = my_fileno(io);
	socklen_t optlen = sizeof(int);
	enum autopush_state state;

	if (getsockopt(fd, IPPROTO_TCP, KGIO_NOPUSH, &corked, &optlen) != 0) {
		if (errno != EOPNOTSUPP)
			rb_sys_fail("getsockopt(TCP_CORK/TCP_NOPUSH)");
		errno = 0;
		state = AUTOPUSH_STATE_ACCEPTOR_IGNORE;
	} else if (corked) {
		state = AUTOPUSH_STATE_ACCEPTOR;
	} else {
		state = AUTOPUSH_STATE_ACCEPTOR_IGNORE;
	}
	state_set(io, state);

	return state;
}
Esempio n. 20
0
static int write_check(struct io_args *a, long n, const char *msg, int io_wait)
{
	if (a->len == n) {
done:
		a->buf = Qnil;
	} else if (n == -1) {
		if (errno == EINTR) {
			a->fd = my_fileno(a->io);
			return -1;
		}
		if (errno == EAGAIN) {
			long written = RSTRING_LEN(a->buf) - a->len;

			if (io_wait) {
				(void)kgio_call_wait_writable(a->io);

				/* buf may be modified in other thread/fiber */
				a->len = RSTRING_LEN(a->buf) - written;
				if (a->len <= 0)
					goto done;
				a->ptr = RSTRING_PTR(a->buf) + written;
				return -1;
			} else if (written > 0) {
				a->buf = rb_str_new(a->ptr, a->len);
			} else {
				a->buf = sym_wait_writable;
			}
			return 0;
		}
		wr_sys_fail(msg);
	} else {
		assert(n >= 0 && n < a->len && "write/send syscall broken?");
		a->ptr += n;
		a->len -= n;
		return -1;
	}
	return 0;
}
Esempio n. 21
0
static void
prepare_accept(struct accept_args *a, VALUE self, int argc, const VALUE *argv)
{
	a->fd = my_fileno(self);
	a->accept_io = self;

	switch (argc) {
	case 2:
		a->flags = NUM2INT(argv[1]);
		a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
		return;
	case 0: /* default, legacy behavior */
		a->flags = accept4_flags;
		a->accepted_class = cClientSocket;
		return;
	case 1:
		a->flags = accept4_flags;
		a->accepted_class = NIL_P(argv[0]) ? cClientSocket : argv[0];
		return;
	}

	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
Esempio n. 22
0
static long
writev_check(struct wrv_args *a, ssize_t n, const char *msg, int io_wait)
{
	if (n >= 0) {
		if (n > 0) a->something_written = 1;
		return trim_writev_buffer(a, n);
	} else if (n < 0) {
		if (errno == EINTR) {
			a->fd = my_fileno(a->io);
			return -1;
		}
		if (errno == EAGAIN) {
			if (io_wait) {
				(void)kgio_call_wait_writable(a->io);
				return -1;
			} else if (!a->something_written) {
				a->buf = sym_wait_writable;
			}
			return 0;
		}
		kgio_wr_sys_fail(msg);
	}
	return 0;
}
Esempio n. 23
0
/*
 * call-seq:
 *      Raindrops::Linux.tcp_listener_stats([addrs[, sock]]) => hash
 *
 * If specified, +addr+ may be a string or array of strings representing
 * listen addresses to filter for. Returns a hash with given addresses as
 * keys and ListenStats objects as the values or a hash of all addresses.
 *
 *      addrs = %w(0.0.0.0:80 127.0.0.1:8080)
 *
 * If +addr+ is nil or not specified, all (IPv4) addresses are returned.
 * If +sock+ is specified, it should be a Raindrops::InetDiagSock object.
 */
static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self)
{
	VALUE rv = rb_hash_new();
	struct nogvl_args args;
	VALUE addrs, sock;

	rb_scan_args(argc, argv, "02", &addrs, &sock);

	/*
	 * allocating page_size instead of OP_LEN since we'll reuse the
	 * buffer for recvmsg() later, we already checked for
	 * OPLEN <= page_size at initialization
	 */
	args.iov[2].iov_len = OPLEN;
	args.iov[2].iov_base = alloca(page_size);
	args.table = NULL;
	if (NIL_P(sock))
		sock = rb_funcall(cIDSock, id_new, 0);
	args.fd = my_fileno(sock);

	switch (TYPE(addrs)) {
	case T_STRING:
		rb_hash_aset(rv, addrs, tcp_stats(&args, addrs));
		return rv;
	case T_ARRAY: {
		long i;
		long len = RARRAY_LEN(addrs);
		VALUE cur;

		if (len == 1) {
			cur = rb_ary_entry(addrs, 0);

			rb_hash_aset(rv, cur, tcp_stats(&args, cur));
			return rv;
		}
		for (i = 0; i < len; i++) {
			union any_addr check;
			VALUE cur = rb_ary_entry(addrs, i);

			parse_addr(&check, cur);
			rb_hash_aset(rv, cur, Qtrue);
		}
		/* fall through */
	}
	case T_NIL:
		args.table = st_init_strtable();
		gen_bytecode_all(&args.iov[2]);
		break;
	default:
		rb_raise(rb_eArgError,
		         "addr must be an array of strings, a string, or nil");
	}

	nl_errcheck(rb_thread_io_blocking_region(diag, &args, args.fd));

	st_foreach(args.table, NIL_P(addrs) ? st_to_hash : st_AND_hash, rv);
	st_free_table(args.table);

	/* let GC deal with corner cases */
	if (argc < 2) rb_io_close(sock);
	return rv;
}
Esempio n. 24
0
size_t my_fwrite(FILE *stream, const uchar *Buffer, size_t Count, myf MyFlags)
{
    size_t writtenbytes =0;
    my_off_t seekptr;
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
    uint errors;
#endif
    DBUG_ENTER("my_fwrite");
    DBUG_PRINT("my",("stream: 0x%lx  Buffer: 0x%lx  Count: %u  MyFlags: %d",
                     (long) stream, (long) Buffer, (uint) Count, MyFlags));

#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
    errors=0;
#endif
    seekptr= ftell(stream);
    for (;;)
    {
        size_t written;
        if ((written = (size_t) fwrite((char*) Buffer,sizeof(char),
                                       Count, stream)) != Count)
        {
            DBUG_PRINT("error",("Write only %d bytes", (int) writtenbytes));
            my_errno=errno;
            if (written != (size_t) -1)
            {
                seekptr+=written;
                Buffer+=written;
                writtenbytes+=written;
                Count-=written;
            }
#ifdef EINTR
            if (errno == EINTR)
            {
                (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0));
                continue;
            }
#endif
#if !defined(NO_BACKGROUND) && defined(USE_MY_STREAM)
            if (my_thread_var->abort)
                MyFlags&= ~ MY_WAIT_IF_FULL;		/* End if aborted by user */

            if ((errno == ENOSPC || errno == EDQUOT) &&
                    (MyFlags & MY_WAIT_IF_FULL))
            {
                wait_for_free_space("[stream]", errors);
                errors++;
                (void) my_fseek(stream,seekptr,MY_SEEK_SET,MYF(0));
                continue;
            }
#endif
            if (ferror(stream) || (MyFlags & (MY_NABP | MY_FNABP)))
            {
                if (MyFlags & (MY_WME | MY_FAE | MY_FNABP))
                {
                    my_error(EE_WRITE, MYF(ME_BELL+ME_WAITTANG),
                             my_filename(my_fileno(stream)),errno);
                }
                writtenbytes= (size_t) -1;        /* Return that we got error */
                break;
            }
        }
        if (MyFlags & (MY_NABP | MY_FNABP))
            writtenbytes= 0;				/* Everything OK */
        else
            writtenbytes+= written;
        break;
    }
    DBUG_RETURN(writtenbytes);
} /* my_fwrite */