22
33import java .io .IOException ;
44import java .net .InetAddress ;
5+ import java .net .SocketAddress ;
56import java .net .InetSocketAddress ;
67import java .net .UnknownHostException ;
78import java .nio .ByteBuffer ;
1920import java .util .concurrent .ThreadFactory ;
2021import java .util .concurrent .ThreadLocalRandom ;
2122import java .util .concurrent .TimeUnit ;
22-
23+ import jnr .unixsocket .UnixSocketAddress ;
24+ import jnr .unixsocket .UnixDatagramChannel ;
25+ import jnr .unixsocket .UnixSocketOptions ;
2326
2427
2528/**
@@ -305,7 +308,7 @@ public NonBlockingStatsDClient(final String prefix, final String hostname, final
305308 * if the client could not be started
306309 */
307310 public NonBlockingStatsDClient (final String prefix , final int queueSize , String [] constantTags , final StatsDClientErrorHandler errorHandler ,
308- final Callable <InetSocketAddress > addressLookup ) throws StatsDClientException {
311+ final Callable <SocketAddress > addressLookup ) throws StatsDClientException {
309312 if ((prefix != null ) && (!prefix .isEmpty ())) {
310313 this .prefix = new StringBuilder (prefix ).append ("." ).toString ();
311314 } else {
@@ -330,7 +333,15 @@ public NonBlockingStatsDClient(final String prefix, final int queueSize, String
330333 }
331334
332335 try {
333- clientChannel = DatagramChannel .open ();
336+ final SocketAddress address = addressLookup .call ();
337+ if (address instanceof UnixSocketAddress ) {
338+ clientChannel = UnixDatagramChannel .open ();
339+ // Set send timeout to 100ms, to handle the case where the transmission buffer is full
340+ // If no timeout is set, the send becomes blocking
341+ clientChannel .setOption (UnixSocketOptions .SO_SNDTIMEO , Integer .valueOf (100 ));
342+ } else {
343+ clientChannel = DatagramChannel .open ();
344+ }
334345 } catch (final Exception e ) {
335346 throw new StatsDClientException ("Failed to start StatsD client" , e );
336347 }
@@ -995,10 +1006,11 @@ private boolean isInvalidSample(double sampleRate) {
9951006
9961007 private class QueueConsumer implements Runnable {
9971008 private final ByteBuffer sendBuffer = ByteBuffer .allocate (PACKET_SIZE_BYTES );
1009+ private final Callable <SocketAddress > addressLookup ;
9981010
999- private final Callable <InetSocketAddress > addressLookup ;
10001011
1001- QueueConsumer (final Callable <InetSocketAddress > addressLookup ) {
1012+
1013+ QueueConsumer (final Callable <SocketAddress > addressLookup ) {
10021014 this .addressLookup = addressLookup ;
10031015 }
10041016
@@ -1007,7 +1019,7 @@ private class QueueConsumer implements Runnable {
10071019 try {
10081020 final String message = queue .poll (1 , TimeUnit .SECONDS );
10091021 if (null != message ) {
1010- final InetSocketAddress address = addressLookup .call ();
1022+ final SocketAddress address = addressLookup .call ();
10111023 final byte [] data = message .getBytes (MESSAGE_CHARSET );
10121024 if (sendBuffer .remaining () < (data .length + 1 )) {
10131025 blockingSend (address );
@@ -1026,7 +1038,7 @@ private class QueueConsumer implements Runnable {
10261038 }
10271039 }
10281040
1029- private void blockingSend (final InetSocketAddress address ) throws IOException {
1041+ private void blockingSend (final SocketAddress address ) throws IOException {
10301042 final int sizeOfBuffer = sendBuffer .position ();
10311043 sendBuffer .flip ();
10321044
@@ -1038,10 +1050,9 @@ private void blockingSend(final InetSocketAddress address) throws IOException {
10381050 handler .handle (
10391051 new IOException (
10401052 String .format (
1041- "Could not send entirely stat %s to host %s:%d . Only sent %d bytes out of %d bytes" ,
1053+ "Could not send entirely stat %s to %s . Only sent %d bytes out of %d bytes" ,
10421054 sendBuffer .toString (),
1043- address .getHostName (),
1044- address .getPort (),
1055+ address .toString (),
10451056 sentBytes ,
10461057 sizeOfBuffer )));
10471058 }
@@ -1055,10 +1066,14 @@ private void blockingSend(final InetSocketAddress address) throws IOException {
10551066 * @param port the port of the targeted StatsD server
10561067 * @return a function to perform the lookup
10571068 */
1058- public static Callable <InetSocketAddress > volatileAddressResolution (final String hostname , final int port ) {
1059- return new Callable <InetSocketAddress >() {
1060- @ Override public InetSocketAddress call () throws UnknownHostException {
1061- return new InetSocketAddress (InetAddress .getByName (hostname ), port );
1069+ public static Callable <SocketAddress > volatileAddressResolution (final String hostname , final int port ) {
1070+ return new Callable <SocketAddress >() {
1071+ @ Override public SocketAddress call () throws UnknownHostException {
1072+ if (port == 0 ) { // Hostname is a file path to the socket
1073+ return new UnixSocketAddress (hostname );
1074+ } else {
1075+ return new InetSocketAddress (InetAddress .getByName (hostname ), port );
1076+ }
10621077 }
10631078 };
10641079 }
@@ -1071,16 +1086,16 @@ public static Callable<InetSocketAddress> volatileAddressResolution(final String
10711086 * @return a function that cached the result of the lookup
10721087 * @throws Exception if the lookup fails, i.e. {@link UnknownHostException}
10731088 */
1074- public static Callable <InetSocketAddress > staticAddressResolution (final String hostname , final int port ) throws Exception {
1075- final InetSocketAddress address = volatileAddressResolution (hostname , port ).call ();
1076- return new Callable <InetSocketAddress >() {
1077- @ Override public InetSocketAddress call () {
1089+ public static Callable <SocketAddress > staticAddressResolution (final String hostname , final int port ) throws Exception {
1090+ final SocketAddress address = volatileAddressResolution (hostname , port ).call ();
1091+ return new Callable <SocketAddress >() {
1092+ @ Override public SocketAddress call () {
10781093 return address ;
10791094 }
10801095 };
10811096 }
10821097
1083- private static Callable <InetSocketAddress > staticStatsDAddressResolution (final String hostname , final int port ) throws StatsDClientException {
1098+ private static Callable <SocketAddress > staticStatsDAddressResolution (final String hostname , final int port ) throws StatsDClientException {
10841099 try {
10851100 return staticAddressResolution (hostname , port );
10861101 } catch (final Exception e ) {
0 commit comments