uringmachine 0.4 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +2 -1
- data/CHANGELOG.md +16 -0
- data/README.md +44 -1
- data/TODO.md +12 -3
- data/examples/bm_snooze.rb +89 -0
- data/examples/bm_sqlite.rb +89 -0
- data/examples/bm_write.rb +56 -0
- data/examples/dns_client.rb +12 -0
- data/examples/http_server.rb +42 -43
- data/examples/pg.rb +85 -0
- data/examples/server_client.rb +64 -0
- data/examples/snooze.rb +44 -0
- data/examples/stream.rb +85 -0
- data/examples/write_dev_null.rb +16 -0
- data/ext/um/extconf.rb +81 -14
- data/ext/um/um.c +468 -414
- data/ext/um/um.h +149 -40
- data/ext/um/um_async_op.c +40 -0
- data/ext/um/um_async_op_class.c +136 -0
- data/ext/um/um_buffer.c +49 -0
- data/ext/um/um_class.c +176 -44
- data/ext/um/um_const.c +174 -9
- data/ext/um/um_ext.c +8 -0
- data/ext/um/um_mutex_class.c +47 -0
- data/ext/um/um_op.c +89 -111
- data/ext/um/um_queue_class.c +58 -0
- data/ext/um/um_ssl.c +850 -0
- data/ext/um/um_ssl.h +22 -0
- data/ext/um/um_ssl_class.c +138 -0
- data/ext/um/um_sync.c +273 -0
- data/ext/um/um_utils.c +1 -1
- data/lib/uringmachine/dns_resolver.rb +84 -0
- data/lib/uringmachine/ssl/context_builder.rb +96 -0
- data/lib/uringmachine/ssl.rb +394 -0
- data/lib/uringmachine/version.rb +1 -1
- data/lib/uringmachine.rb +27 -3
- data/supressions/ruby.supp +71 -0
- data/test/helper.rb +6 -0
- data/test/test_async_op.rb +119 -0
- data/test/test_ssl.rb +155 -0
- data/test/test_um.rb +464 -47
- data/uringmachine.gemspec +3 -2
- data/vendor/liburing/.gitignore +5 -0
- data/vendor/liburing/CHANGELOG +1 -0
- data/vendor/liburing/configure +32 -0
- data/vendor/liburing/examples/Makefile +1 -0
- data/vendor/liburing/examples/reg-wait.c +159 -0
- data/vendor/liburing/liburing.spec +1 -1
- data/vendor/liburing/src/include/liburing/io_uring.h +48 -2
- data/vendor/liburing/src/include/liburing.h +28 -2
- data/vendor/liburing/src/int_flags.h +10 -3
- data/vendor/liburing/src/liburing-ffi.map +13 -2
- data/vendor/liburing/src/liburing.map +9 -0
- data/vendor/liburing/src/queue.c +25 -16
- data/vendor/liburing/src/register.c +73 -4
- data/vendor/liburing/src/setup.c +46 -18
- data/vendor/liburing/src/setup.h +6 -0
- data/vendor/liburing/test/Makefile +7 -0
- data/vendor/liburing/test/cmd-discard.c +427 -0
- data/vendor/liburing/test/fifo-nonblock-read.c +69 -0
- data/vendor/liburing/test/file-exit-unreg.c +48 -0
- data/vendor/liburing/test/io_uring_passthrough.c +2 -0
- data/vendor/liburing/test/io_uring_register.c +13 -2
- data/vendor/liburing/test/napi-test.c +1 -1
- data/vendor/liburing/test/no-mmap-inval.c +1 -1
- data/vendor/liburing/test/read-mshot-empty.c +2 -0
- data/vendor/liburing/test/read-mshot-stdin.c +121 -0
- data/vendor/liburing/test/read-mshot.c +6 -0
- data/vendor/liburing/test/recvsend_bundle.c +2 -2
- data/vendor/liburing/test/reg-fd-only.c +1 -1
- data/vendor/liburing/test/reg-wait.c +251 -0
- data/vendor/liburing/test/regbuf-clone.c +458 -0
- data/vendor/liburing/test/resize-rings.c +643 -0
- data/vendor/liburing/test/rsrc_tags.c +1 -1
- data/vendor/liburing/test/sqpoll-sleep.c +39 -8
- data/vendor/liburing/test/sqwait.c +136 -0
- data/vendor/liburing/test/sync-cancel.c +8 -1
- data/vendor/liburing/test/timeout.c +13 -8
- metadata +52 -8
- data/examples/http_server_multishot.rb +0 -57
- data/examples/http_server_simpler.rb +0 -34
    
        data/examples/stream.rb
    ADDED
    
    | @@ -0,0 +1,85 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative '../lib/uringmachine'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            @machine = UM.new
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class UM::Stream
         | 
| 8 | 
            +
              def initialize(machine, fd)
         | 
| 9 | 
            +
                @machine, @fd, @bgid = machine, fd
         | 
| 10 | 
            +
                @buffer = +''
         | 
| 11 | 
            +
                @ofs_head = 0
         | 
| 12 | 
            +
                @ofs_tail = 0
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              def feed
         | 
| 16 | 
            +
                if (@ofs_head == @ofs_tail) && (@ofs_head >= 4096)
         | 
| 17 | 
            +
                  @buffer = +''
         | 
| 18 | 
            +
                  @ofs_head = @ofs_tail = 0
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
                ret = @machine.read(@fd, @buffer, 65536, @ofs_tail)
         | 
| 21 | 
            +
                if ret == 0
         | 
| 22 | 
            +
                  @eof = true
         | 
| 23 | 
            +
                  return false
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
                  
         | 
| 26 | 
            +
                @ofs_tail += ret
         | 
| 27 | 
            +
                true
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              def read(len)
         | 
| 31 | 
            +
                if @ofs_head + len > @ofs_tail
         | 
| 32 | 
            +
                  feed
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                str = @buffer[@ofs_head, len]
         | 
| 36 | 
            +
                @ofs_head += str.bytesize
         | 
| 37 | 
            +
                str
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
              def gets(sep = $/, _limit = nil, _chomp: nil)
         | 
| 41 | 
            +
                if sep.is_a?(Integer)
         | 
| 42 | 
            +
                  sep = $/
         | 
| 43 | 
            +
                  _limit = sep
         | 
| 44 | 
            +
                end
         | 
| 45 | 
            +
                sep_size = sep.bytesize
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                while true
         | 
| 48 | 
            +
                  idx = @buffer.index(sep, @ofs_head)
         | 
| 49 | 
            +
                  if idx
         | 
| 50 | 
            +
                    str = @buffer[@ofs_head, idx + sep_size]
         | 
| 51 | 
            +
                    @ofs_head += str.bytesize
         | 
| 52 | 
            +
                    return str
         | 
| 53 | 
            +
                  end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  return nil if !feed
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
            $machine = UringMachine.new
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            server_fd = @machine.socket(UM::AF_INET, UM::SOCK_STREAM, 0, 0)
         | 
| 63 | 
            +
            $machine.setsockopt(server_fd, UM::SOL_SOCKET, UM::SO_REUSEADDR, true)
         | 
| 64 | 
            +
            $machine.bind(server_fd, '127.0.0.1', 1234)
         | 
| 65 | 
            +
            $machine.listen(server_fd, UM::SOMAXCONN)
         | 
| 66 | 
            +
            puts 'Listening on port 1234'
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            def handle_connection(fd)
         | 
| 69 | 
            +
              stream = UM::Stream.new($machine, fd)
         | 
| 70 | 
            +
             | 
| 71 | 
            +
              while (l = stream.gets)
         | 
| 72 | 
            +
                $machine.write(fd, "You said: #{l}")
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
            rescue Exception => e
         | 
| 75 | 
            +
              puts "Got error #{e.inspect}, closing connection"
         | 
| 76 | 
            +
              $machine.close(fd) rescue nil
         | 
| 77 | 
            +
            end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            main = Fiber.current
         | 
| 80 | 
            +
            trap('SIGINT') { $machine.spin { $machine.schedule(main, SystemExit.new) } }
         | 
| 81 | 
            +
             | 
| 82 | 
            +
            $machine.accept_each(server_fd) do |fd|
         | 
| 83 | 
            +
              puts "Connection accepted fd #{fd}"
         | 
| 84 | 
            +
              $machine.spin(fd) { handle_connection(_1) }
         | 
| 85 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require_relative '../lib/uringmachine'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            ITERATIONS = 1000
         | 
| 6 | 
            +
            DEV_NULL = File.open('/dev/null', 'w')
         | 
| 7 | 
            +
            FD = DEV_NULL.fileno
         | 
| 8 | 
            +
            BUF = ('*' * 8192).freeze
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            $machine = UringMachine.new
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            def run_um_write
         | 
| 13 | 
            +
              $machine.write(FD, BUF)
         | 
| 14 | 
            +
            end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            1000.times { run_um_write }
         | 
    
        data/ext/um/extconf.rb
    CHANGED
    
    | @@ -6,10 +6,66 @@ require 'rbconfig' | |
| 6 6 |  | 
| 7 7 | 
             
            dir_config 'um_ext'
         | 
| 8 8 |  | 
| 9 | 
            +
            def config_ssl
         | 
| 10 | 
            +
              # don't use pkg_config('openssl') if '--with-openssl-dir' is used
         | 
| 11 | 
            +
              has_openssl_dir = dir_config('openssl').any? ||
         | 
| 12 | 
            +
                RbConfig::CONFIG['configure_args']&.include?('openssl')
         | 
| 13 | 
            +
             | 
| 14 | 
            +
              found_pkg_config = !has_openssl_dir && pkg_config('openssl')
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              found_ssl = if !$mingw && found_pkg_config
         | 
| 17 | 
            +
                puts '──── Using OpenSSL pkgconfig (openssl.pc) ────'
         | 
| 18 | 
            +
                true
         | 
| 19 | 
            +
              elsif have_library('libcrypto', 'BIO_read') && have_library('libssl', 'SSL_CTX_new')
         | 
| 20 | 
            +
                true
         | 
| 21 | 
            +
              elsif %w'crypto libeay32'.find {|crypto| have_library(crypto, 'BIO_read')} &&
         | 
| 22 | 
            +
                  %w'ssl ssleay32'.find {|ssl| have_library(ssl, 'SSL_CTX_new')}
         | 
| 23 | 
            +
                true
         | 
| 24 | 
            +
              else
         | 
| 25 | 
            +
                puts '** Puma will be compiled without SSL support'
         | 
| 26 | 
            +
                false
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
              if found_ssl
         | 
| 30 | 
            +
                have_header "openssl/bio.h"
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                ssl_h = "openssl/ssl.h".freeze
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                puts "\n──── Below are yes for 1.0.2 & later ────"
         | 
| 35 | 
            +
                have_func "DTLS_method"                            , ssl_h
         | 
| 36 | 
            +
                have_func "SSL_CTX_set_session_cache_mode(NULL, 0)", ssl_h
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                puts "\n──── Below are yes for 1.1.0 & later ────"
         | 
| 39 | 
            +
                have_func "TLS_server_method"                      , ssl_h
         | 
| 40 | 
            +
                have_func "SSL_CTX_set_min_proto_version(NULL, 0)" , ssl_h
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                puts "\n──── Below is yes for 1.1.0 and later, but isn't documented until 3.0.0 ────"
         | 
| 43 | 
            +
                # https://github.com/openssl/openssl/blob/OpenSSL_1_1_0/include/openssl/ssl.h#L1159
         | 
| 44 | 
            +
                have_func "SSL_CTX_set_dh_auto(NULL, 0)"           , ssl_h
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                puts "\n──── Below is yes for 1.1.1 & later ────"
         | 
| 47 | 
            +
                have_func "SSL_CTX_set_ciphersuites(NULL, \"\")"   , ssl_h
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                puts "\n──── Below is yes for 3.0.0 & later ────"
         | 
| 50 | 
            +
                have_func "SSL_get1_peer_certificate"              , ssl_h
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                puts ''
         | 
| 53 | 
            +
             | 
| 54 | 
            +
                # Random.bytes available in Ruby 2.5 and later, Random::DEFAULT deprecated in 3.0
         | 
| 55 | 
            +
                if Random.respond_to?(:bytes)
         | 
| 56 | 
            +
                  $defs.push "-DHAVE_RANDOM_BYTES"
         | 
| 57 | 
            +
                  puts "checking for Random.bytes... yes"
         | 
| 58 | 
            +
                else
         | 
| 59 | 
            +
                  puts "checking for Random.bytes... no"
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
              end
         | 
| 62 | 
            +
            end
         | 
| 63 | 
            +
             | 
| 9 64 | 
             
            KERNEL_INFO_RE = /Linux (\d)\.(\d+)(?:\.)?((?:\d+\.?)*)(?:\-)?([\w\-]+)?/
         | 
| 10 65 | 
             
            def get_config
         | 
| 11 | 
            -
               | 
| 12 | 
            -
             | 
| 66 | 
            +
              if RUBY_PLATFORM !~ /linux/
         | 
| 67 | 
            +
                raise "UringMachine only works on Linux!"
         | 
| 68 | 
            +
              end
         | 
| 13 69 |  | 
| 14 70 | 
             
              kernel_info = `uname -sr`
         | 
| 15 71 | 
             
              m = kernel_info.match(KERNEL_INFO_RE)
         | 
| @@ -20,16 +76,22 @@ def get_config | |
| 20 76 | 
             
              combined_version = version.to_i * 100 + major_revision.to_i
         | 
| 21 77 | 
             
              raise "UringMachine requires kernel version 6.4 or newer!" if combined_version < 604
         | 
| 22 78 |  | 
| 23 | 
            -
               | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 79 | 
            +
              {
         | 
| 80 | 
            +
                kernel_version:       combined_version,
         | 
| 81 | 
            +
                submit_all_flag:      combined_version >= 518,
         | 
| 82 | 
            +
                coop_taskrun_flag:    combined_version >= 519,
         | 
| 83 | 
            +
                single_issuer_flag:   combined_version >= 600,
         | 
| 84 | 
            +
                prep_bind:            combined_version >= 611,
         | 
| 85 | 
            +
                prep_listen:          combined_version >= 611,
         | 
| 86 | 
            +
                prep_cmd_sock:        combined_version >= 607,
         | 
| 87 | 
            +
                prep_futex:           combined_version >= 607,
         | 
| 88 | 
            +
                prep_waitid:          combined_version >= 607,
         | 
| 89 | 
            +
                prep_read_multishot:  combined_version >= 607
         | 
| 90 | 
            +
              }
         | 
| 31 91 | 
             
            end
         | 
| 32 92 |  | 
| 93 | 
            +
            config_ssl
         | 
| 94 | 
            +
             | 
| 33 95 | 
             
            config = get_config
         | 
| 34 96 | 
             
            puts "Building UringMachine (\n#{config.map { |(k, v)| "  #{k}: #{v}\n"}.join})"
         | 
| 35 97 |  | 
| @@ -51,10 +113,15 @@ if !find_library('uring', nil, File.join(liburing_path, 'src')) | |
| 51 113 | 
             
              raise "Couldn't find liburing.a"
         | 
| 52 114 | 
             
            end
         | 
| 53 115 |  | 
| 54 | 
            -
            $defs <<  | 
| 55 | 
            -
            $defs << '- | 
| 56 | 
            -
            $defs << '- | 
| 57 | 
            -
            $defs << '- | 
| 116 | 
            +
            $defs << "-DUM_KERNEL_VERSION=#{config[:kernel_version]}"
         | 
| 117 | 
            +
            $defs << '-DHAVE_IORING_SETUP_SUBMIT_ALL'       if config[:submit_all_flag]
         | 
| 118 | 
            +
            $defs << '-DHAVE_IORING_SETUP_COOP_TASKRUN'     if config[:coop_taskrun_flag]
         | 
| 119 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_BIND'            if config[:prep_bind]
         | 
| 120 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_LISTEN'          if config[:prep_listen]
         | 
| 121 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_CMD_SOCK'        if config[:prep_cmd_sock]
         | 
| 122 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_FUTEX'           if config[:prep_futex]
         | 
| 123 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_WAITID'          if config[:prep_waitid]
         | 
| 124 | 
            +
            $defs << '-DHAVE_IO_URING_PREP_READ_MULTISHOT'  if config[:prep_read_multishot]
         | 
| 58 125 | 
             
            $CFLAGS << ' -Wno-pointer-arith'
         | 
| 59 126 |  | 
| 60 127 | 
             
            CONFIG['optflags'] << ' -fno-strict-aliasing'
         |