Skip to content

Commit ff4b734

Browse files
committed
Fail when epoll transport is requested but unavailable
Rather than silently falling back to the NIO transport, client and server constructors now throw an excpetion with info on how to fix the problem when requesting to use the native epoll transport but no implementation for the current platform is available on the classpath.
1 parent 533f00b commit ff4b734

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/aleph/http.clj

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
| `max-initial-line-length` | the maximum characters that can be in the initial line of the request, defaults to `8192`
4747
| `max-header-size` | the maximum characters that can be in a single header entry of a request, defaults to `8192`
4848
| `max-chunk-size` | the maximum characters that can be in a single chunk of a streamed request, defaults to `16384`
49-
| `epoll?` | if `true`, uses `epoll` when available, defaults to `false`
49+
| `epoll?` | if `true`, uses `epoll`, defaults to `false`.
5050
| `compression?` | when `true` enables http compression, defaults to `false`
5151
| `compression-level` | optional compression level, `1` yields the fastest compression and `9` yields the best compression, defaults to `6`. When set, enables http content compression regardless of the `compression?` flag value
5252
| `idle-timeout` | when set, forces keep-alive connections to be closed after an idle time, in milliseconds
@@ -115,7 +115,7 @@
115115
| `response-buffer-size` | the amount of the response, in bytes, that is buffered before the request returns, defaults to `65536`. This does *not* represent the maximum size response that the client can handle (which is unbounded), and is only a means of maximizing performance.
116116
| `keep-alive?` | if `true`, attempts to reuse connections for multiple requests, defaults to `true`.
117117
| `idle-timeout` | when set, forces keep-alive connections to be closed after an idle time, in milliseconds.
118-
| `epoll?` | if `true`, uses `epoll` when available, defaults to `false`
118+
| `epoll?` | if `true`, uses `epoll`, defaults to `false`
119119
| `raw-stream?` | if `true`, bodies of responses will not be buffered at all, and represented as Manifold streams of `io.netty.buffer.ByteBuf` objects rather than as an `InputStream`. This will minimize copying, but means that care must be taken with Netty's buffer reference counting. Only recommended for advanced users.
120120
| `max-initial-line-length` | the maximum length of the initial line (e.g. HTTP/1.0 200 OK), defaults to `65536`
121121
| `max-header-size` | the maximum characters that can be in a single header entry of a response, defaults to `65536`
@@ -216,7 +216,7 @@
216216
| `max-frame-payload` | maximum allowable frame payload length, in bytes, defaults to `65536`.
217217
| `max-frame-size` | maximum aggregate message size, in bytes, defaults to `1048576`.
218218
| `bootstrap-transform` | an optional function that takes an `io.netty.bootstrap.Bootstrap` object and modifies it.
219-
| `epoll?` | if `true`, uses `epoll` when available, defaults to `false`
219+
| `epoll?` | if `true`, uses `epoll`, defaults to `false`
220220
| `heartbeats` | optional configuration to send Ping frames to the server periodically (if the connection is idle), configuration keys are `:send-after-idle` (in milliseconds), `:payload` (optional, empty frame by default) and `:timeout` (optional, to close the connection if Pong is not received after specified timeout)."
221221
([url]
222222
(websocket-client url nil))

src/aleph/netty.clj

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,13 @@
798798
(defn epoll-available? []
799799
(Epoll/isAvailable))
800800

801+
(defn ensure-epoll-available! []
802+
(when-let [cause (Epoll/unavailabilityCause)]
803+
(throw (IllegalArgumentException. (str "Epoll transport requested but implementation not available. "
804+
"See https://netty.io/wiki/native-transports.html on how to add the necessary "
805+
"dependency for your platform.")
806+
cause))))
807+
801808
(defn get-default-event-loop-threads
802809
"Determines the default number of threads to use for a Netty EventLoopGroup.
803810
This mimics the default used by Netty as of version 4.1."
@@ -880,7 +887,7 @@ initialize an DnsAddressResolverGroup instance.
880887
| `decode-idn?` | set if domain / host names should be decoded to unicode when received, defaults to `true`
881888
| `recursion-desired?` | if set to `true`, the resolver sends a DNS query with the RD (recursion desired) flag set, defaults to `true`
882889
| `name-servers` | optional list of DNS server addresses, automatically discovered when not set (platform dependent)
883-
| `epoll?` | if `true`, uses `epoll` when available, defaults to `false`"
890+
| `epoll?` | if `true`, uses `epoll`, defaults to `false`"
884891
[{:keys [max-payload-size
885892
max-queries-per-resolve
886893
address-types
@@ -907,8 +914,10 @@ initialize an DnsAddressResolverGroup instance.
907914
decode-idn? true
908915
recursion-desired? true
909916
epoll? false}}]
917+
(when epoll?
918+
(ensure-epoll-available!))
910919
(let [^Class
911-
channel-type (if (and epoll? (epoll-available?))
920+
channel-type (if epoll?
912921
EpollDatagramChannel
913922
NioDatagramChannel)]
914923
(cond-> (doto (DnsNameResolverBuilder.)
@@ -965,8 +974,10 @@ initialize an DnsAddressResolverGroup instance.
965974
^SocketAddress local-address
966975
epoll?
967976
name-resolver]
977+
(when epoll?
978+
(ensure-epoll-available!))
968979
(let [^Class
969-
channel (if (and epoll? (epoll-available?))
980+
channel (if epoll?
970981
EpollSocketChannel
971982
NioSocketChannel)
972983

@@ -980,7 +991,7 @@ initialize an DnsAddressResolverGroup instance.
980991
(pipeline-builder p))
981992
pipeline-builder)]
982993
(try
983-
(let [client-group (if (and epoll? (epoll-available?))
994+
(let [client-group (if epoll?
984995
@epoll-client-group
985996
@nio-client-group)
986997
resolver' (when (some? name-resolver)
@@ -1013,25 +1024,27 @@ initialize an DnsAddressResolverGroup instance.
10131024
on-close
10141025
^SocketAddress socket-address
10151026
epoll?]
1027+
(when epoll?
1028+
(ensure-epoll-available!))
10161029
(let [num-cores (.availableProcessors (Runtime/getRuntime))
10171030
num-threads (* 2 num-cores)
10181031
thread-factory (enumerating-thread-factory "aleph-netty-server-event-pool" false)
10191032
closed? (atom false)
10201033

10211034
^EventLoopGroup group
1022-
(if (and epoll? (epoll-available?))
1035+
(if epoll?
10231036
(EpollEventLoopGroup. num-threads thread-factory)
10241037
(NioEventLoopGroup. num-threads thread-factory))
10251038

10261039
^Class channel
1027-
(if (and epoll? (epoll-available?))
1040+
(if epoll?
10281041
EpollServerSocketChannel
10291042
NioServerSocketChannel)
10301043

10311044
;; todo(kachayev): this one should be reimplemented after
10321045
;; KQueue transport is merged into master
10331046
transport
1034-
(if (and epoll? (epoll-available?)) :epoll :nio)
1047+
(if epoll? :epoll :nio)
10351048

10361049
pipeline-builder
10371050
(if ssl-context

src/aleph/udp.clj

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@
3434
| `socket-address` | a `java.net.SocketAddress` specifying both the port and interface to bind to.
3535
| `broadcast?` | if true, all UDP datagrams are broadcast.
3636
| `bootstrap-transform` | a function which takes the Netty `Bootstrap` object, and makes any desired changes before it's bound to a socket.
37-
| `raw-stream?` | if true, the `:message` within each packet will be `io.netty.buffer.ByteBuf` objects rather than byte-arrays. This will minimize copying, but means that care must be taken with Netty's buffer reference counting. Only recommended for advanced users."
37+
| `raw-stream?` | if true, the `:message` within each packet will be `io.netty.buffer.ByteBuf` objects rather than byte-arrays. This will minimize copying, but means that care must be taken with Netty's buffer reference counting. Only recommended for advanced users.
38+
| `epoll?` | if `true`, uses `epoll`, defaults to `false`"
3839
[{:keys [socket-address port broadcast? raw-stream? bootstrap-transform epoll?]
3940
:or {epoll? false
4041
broadcast? false
4142
raw-stream? false
4243
bootstrap-transform identity}}]
44+
(when epoll?
45+
(netty/ensure-epoll-available!))
4346
(let [in (atom nil)
4447
d (d/deferred)
45-
epoll? (and epoll? (netty/epoll-available?))
4648
g (if epoll?
4749
@netty/epoll-client-group
4850
@netty/nio-client-group)

0 commit comments

Comments
 (0)