PageRenderTime 37ms CodeModel.GetById 2ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/zeromq/ZMQ.java

https://github.com/thijsterlouw/jzmq
Java | 1043 lines | 351 code | 116 blank | 576 comment | 28 complexity | 42b0bcca4c50e54d688b74095f8fe2dd MD5 | raw file
   1/*
   2  Copyright (c) 2007-2010 iMatix Corporation
   3
   4  This file is part of 0MQ.
   5
   6  0MQ is free software; you can redistribute it and/or modify it under
   7  the terms of the Lesser GNU General Public License as published by
   8  the Free Software Foundation; either version 3 of the License, or
   9  (at your option) any later version.
  10
  11  0MQ is distributed in the hope that it will be useful,
  12  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14  Lesser GNU General Public License for more details.
  15
  16  You should have received a copy of the Lesser GNU General Public License
  17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18*/
  19package org.zeromq;
  20
  21import java.util.LinkedList;
  22
  23/**
  24 * ZeroMQ JNI Bindings.
  25 * 
  26 * @author Gonzalo Diethelm
  27 * 
  28 */
  29public class ZMQ {
  30    static {
  31        System.loadLibrary ("jzmq");
  32    }
  33
  34    // Values for flags in Socket's send and recv functions.
  35    /**
  36     * Socket flag to indicate a nonblocking send or recv mode.
  37     */
  38    public static final int NOBLOCK = 1;
  39    /**
  40     * Socket flag to indicate that more message parts are coming.
  41     */
  42    public static final int SNDMORE = 2;
  43
  44    // Socket types, used when creating a Socket.
  45    /**
  46     * Flag to specify a exclusive pair of sockets.
  47     */
  48    public static final int PAIR = 0;
  49    /**
  50     * Flag to specify a PUB socket, receiving side must be a SUB.
  51     */
  52    public static final int PUB = 1;
  53    /**
  54     * Flag to specify the receiving part of the PUB socket.
  55     */
  56    public static final int SUB = 2;
  57    /**
  58     * Flag to specify a REQ socket, receiving side must be a REP.
  59     */
  60    public static final int REQ = 3;
  61    /**
  62     * Flag to specify the receiving part of a REQ socket.
  63     */
  64    public static final int REP = 4;
  65    /**
  66     * Flag to specify a XREQ socket, receiving side must be a XREP.
  67     */
  68    public static final int XREQ = 5;
  69    /**
  70     * Flag to specify the receiving part of a XREQ socket.
  71     */
  72    public static final int XREP = 6;
  73    /**
  74     * Flag to specify the receiving part of a PUSH socket.
  75     */
  76    public static final int PULL = 7;
  77    /**
  78     * Flag to specify a PUSH socket, receiving side must be a PULL.
  79     */
  80    public static final int PUSH = 8;
  81
  82    /**
  83     * Flag to specify a STREAMER device.
  84     */
  85    public static final int STREAMER = 1;
  86
  87    /**
  88     * Flag to specify a FORWARDER device.
  89     */
  90    public static final int FORWARDER = 2;
  91
  92    /**
  93     * Flag to specify a QUEUE device.
  94     */
  95    public static final int QUEUE = 3;
  96
  97    /**
  98     * @see ZMQ#PULL
  99     */
 100    @Deprecated
 101        public static final int UPSTREAM = PULL;
 102    /**
 103     * @see ZMQ#PUSH
 104     */
 105    @Deprecated
 106        public static final int DOWNSTREAM = PUSH;
 107
 108    protected static native int version_full();
 109    protected static native int version_major();
 110    protected static native int version_minor();
 111    protected static native int version_patch();
 112    protected static native int make_version(int major, int minor, int patch);
 113
 114    protected static native long ENOTSUP();
 115    protected static native long EPROTONOSUPPORT();
 116    protected static native long ENOBUFS();
 117    protected static native long ENETDOWN();
 118    protected static native long EADDRINUSE();
 119    protected static native long EADDRNOTAVAIL();
 120    protected static native long ECONNREFUSED();
 121    protected static native long EINPROGRESS();
 122    protected static native long EMTHREAD();
 123    protected static native long EFSM();
 124    protected static native long ENOCOMPATPROTO();
 125    protected static native long ETERM();         
 126    
 127    /**
 128     * Inner class: Error.
 129     */
 130    public enum Error {
 131        
 132        ENOTSUP(ENOTSUP()),
 133            
 134            EPROTONOSUPPORT(EPROTONOSUPPORT()),
 135		
 136            ENOBUFS(ENOBUFS()),
 137		
 138            ENETDOWN(ENETDOWN()),
 139		
 140            EADDRINUSE(EADDRINUSE()),
 141
 142            EADDRNOTAVAIL(EADDRNOTAVAIL()),
 143		
 144            ECONNREFUSED(ECONNREFUSED()),
 145		
 146            EINPROGRESS(EINPROGRESS()),
 147		
 148            EMTHREAD(EMTHREAD()),
 149		
 150            EFSM(EFSM()),
 151		
 152            ENOCOMPATPROTO(ENOCOMPATPROTO()),
 153		
 154            ETERM(ETERM());
 155
 156        private final long code;
 157
 158        Error(long code) {
 159            this.code = code;
 160        }
 161
 162        public long getCode() {
 163            return code;
 164        }
 165
 166        public static Error findByCode(int code) {
 167            for (Error e : Error.class.getEnumConstants()) {
 168                if (e.getCode() == code) {
 169                    return e;
 170                }
 171            }
 172            throw new IllegalArgumentException("Unknown " + Error.class.getName() + " enum code:" + code);
 173        }
 174    }
 175	
 176    /**
 177     * Create a new Context.
 178     * 
 179     * @param ioThreads
 180     *            Number of threads to use, usually 1 is sufficient for most use cases.
 181     * @return the Context
 182     */
 183    public static Context context (int ioThreads) {
 184        return new Context (ioThreads);
 185    }
 186
 187    /**
 188     * Inner class: Context.
 189     */
 190    public static class Context {
 191
 192        /**
 193         * This is an explicit "destructor". It can be called to ensure the corresponding 0MQ
 194         * Context has been disposed of.
 195         */
 196        public void term () {
 197            finalize ();
 198        }
 199
 200        /**
 201         * Create a new Socket within this context.
 202         * 
 203         * @param type
 204         *            the socket type.
 205         * @return the newly created Socket.
 206         */
 207        public Socket socket (int type) {
 208            return new Socket (this, type);
 209        }
 210
 211        /**
 212         * Create a new Poller within this context, with a default size.
 213         * 
 214         * @return the newly created Poller.
 215         */
 216        public Poller poller () {
 217            return new Poller (this);
 218        }
 219
 220        /**
 221         * Create a new Poller within this context, with a specified initial size.
 222         * 
 223         * @param size
 224         *            the poller initial size.
 225         * @return the newly created Poller.
 226         */
 227        public Poller poller (int size) {
 228            return new Poller (this, size);
 229        }
 230
 231        /**
 232         * Class constructor.
 233         * 
 234         * @param ioThreads
 235         *            size of the threads pool to handle I/O operations.
 236         */
 237        protected Context (int ioThreads) {
 238            construct (ioThreads);
 239        }
 240
 241        /** Initialize the JNI interface */
 242        protected native void construct (int ioThreads);
 243
 244        /** Free all resources used by JNI interface. */
 245        @Override
 246            protected native void finalize ();
 247
 248        /**
 249         * Get the underlying context handle. This is private because it is only accessed from JNI,
 250         * where Java access controls are ignored.
 251         * 
 252         * @return the internal 0MQ context handle.
 253         */
 254        private long getContextHandle () {
 255            return this.contextHandle;
 256        }
 257
 258        /** Opaque data used by JNI driver. */
 259        private long contextHandle;
 260    }
 261
 262    /**
 263     * Inner class: Socket.
 264     */
 265    public static class Socket {
 266        /**
 267         * This is an explicit "destructor". It can be called to ensure the corresponding 0MQ Socket
 268         * has been disposed of.
 269         */
 270        public void close () {
 271            finalize ();
 272        }
 273
 274        /**
 275         * The 'ZMQ_TYPE option shall retrieve the socket type for the specified
 276         * 'socket'.  The socket type is specified at socket creation time and
 277         * cannot be modified afterwards.
 278         *
 279         * @return the socket type.
 280         * @since 2.1.0
 281         */
 282        public long getType () {
 283            if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
 284                return -1;
 285
 286            return getLongSockopt (TYPE);
 287        }
 288
 289        /**
 290         * @see #setLinger(long)
 291         *
 292         * @return the linger period.
 293         * @since 2.1.0
 294         */
 295        public long getLinger () {
 296            if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
 297                return -1;
 298
 299            return getLongSockopt (LINGER);
 300        }
 301
 302        /**
 303         * @see #setHWM(long)
 304         * 
 305         * @return the High Water Mark.
 306         */
 307        public long getHWM () {
 308            return getLongSockopt (HWM);
 309        }
 310
 311        /**
 312         * @see #setSwap(long)
 313         * 
 314         * @return the number of messages to swap at most.
 315         */
 316        public long getSwap () {
 317            return getLongSockopt (SWAP);
 318        }
 319
 320        /**
 321         * @see #setAffinity(long)
 322         * 
 323         * @return the affinity.
 324         */
 325        public long getAffinity () {
 326            return getLongSockopt (AFFINITY);
 327        }
 328
 329        /**
 330         * @see #setIdentity(byte[])
 331         * 
 332         * @return the Identitiy.
 333         */
 334        public byte [] getIdentity () {
 335            return getBytesSockopt (IDENTITY);
 336        }
 337
 338        /**
 339         * @see #setRate(long)
 340         * 
 341         * @return the Rate.
 342         */
 343        public long getRate () {
 344            return getLongSockopt (RATE);
 345        }
 346
 347        /**
 348         * @see #setRecoveryInterval(long)
 349         * 
 350         * @return the RecoveryIntervall.
 351         */
 352        public long getRecoveryInterval () {
 353            return getLongSockopt (RECOVERY_IVL);
 354        }
 355
 356        /**
 357         * @see #setMulticastLoop(boolean)
 358         * 
 359         * @return the Multicast Loop.
 360         */
 361        public boolean hasMulticastLoop () {
 362            return getLongSockopt (MCAST_LOOP) != 0;
 363        }
 364
 365        /**
 366         * @see #setSendBufferSize(long)
 367         * 
 368         * @return the kernel send buffer size.
 369         */
 370        public long getSendBufferSize () {
 371            return getLongSockopt (SNDBUF);
 372        }
 373
 374        /**
 375         * @see #setReceiveBufferSize(long)
 376         * 
 377         * @return the kernel receive buffer size.
 378         */
 379        public long getReceiveBufferSize () {
 380            return getLongSockopt (RCVBUF);
 381        }
 382
 383        /**
 384         * The 'ZMQ_RCVMORE' option shall return a boolean value indicating if the multi-part
 385         * message currently being read from the specified 'socket' has more message parts to
 386         * follow. If there are no message parts to follow or if the message currently being read is
 387         * not a multi-part message a value of zero shall be returned. Otherwise, a value of 1 shall
 388         * be returned.
 389         * 
 390         * @return true if there are more messages to receive.
 391         */
 392        public boolean hasReceiveMore () {
 393            return getLongSockopt (RCVMORE) != 0;
 394        }
 395
 396        /**
 397         * The 'ZMQ_FD' option shall retrieve file descriptor associated with the 0MQ
 398         * socket. The descriptor can be used to integrate 0MQ socket into an existing
 399         * event loop. It should never be used for anything else than polling -- such as
 400         * reading or writing. The descriptor signals edge-triggered IN event when
 401         * something has happened within the 0MQ socket. It does not necessarily mean that
 402         * the messages can be read or written. Check ZMQ_EVENTS option to find out whether
 403         * the 0MQ socket is readable or writeable.
 404         * 
 405         * @return the underlying file descriptor.
 406         * @since 2.1.0
 407         */
 408        public long getFD () {
 409            if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
 410                return -1;
 411
 412            return getLongSockopt (FD);
 413        }
 414
 415        /**
 416         * The 'ZMQ_EVENTS' option shall retrieve event flags for the specified socket.
 417         * If a message can be read from the socket ZMQ_POLLIN flag is set. If message can
 418         * be written to the socket ZMQ_POLLOUT flag is set.
 419         * 
 420         * @return the mask of outstanding events.
 421         * @since 2.1.0
 422         */
 423        public long getEvents () {
 424            if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
 425                return -1;
 426
 427            return getLongSockopt (EVENTS);
 428        }
 429
 430        /**
 431         * The 'ZMQ_LINGER' option shall retrieve the period for pending outbound
 432         * messages to linger in memory after closing the socket. Value of -1 means
 433         * infinite. Pending messages will be kept until they are fully transferred to
 434         * the peer. Value of 0 means that all the pending messages are dropped immediately
 435         * when socket is closed. Positive value means number of milliseconds to keep
 436         * trying to send the pending messages before discarding them.
 437         *
 438         * @param linger
 439         *            the linger period.
 440         * @since 2.1.0
 441         */
 442        public void setLinger (long linger) {
 443            if (ZMQ.version_full() < ZMQ.make_version(2, 1, 0))
 444                return;
 445
 446            setLongSockopt (LINGER, linger);
 447        }
 448
 449        /**
 450         * The 'ZMQ_HWM' option shall set the high water mark for the specified 'socket'. The high
 451         * water mark is a hard limit on the maximum number of outstanding messages 0MQ shall queue
 452         * in memory for any single peer that the specified 'socket' is communicating with.
 453         * 
 454         * If this limit has been reached the socket shall enter an exceptional state and depending
 455         * on the socket type, 0MQ shall take appropriate action such as blocking or dropping sent
 456         * messages. Refer to the individual socket descriptions in the man page of zmq_socket[3] for
 457         * details on the exact action taken for each socket type.
 458         * 
 459         * @param hwm
 460         *            the number of messages to queue.
 461         */
 462        public void setHWM (long hwm) {
 463            setLongSockopt (HWM, hwm);
 464        }
 465
 466        /**
 467         * Get the Swap. The 'ZMQ_SWAP' option shall set the disk offload (swap) size for the
 468         * specified 'socket'. A socket which has 'ZMQ_SWAP' set to a non-zero value may exceed its
 469         * high water mark; in this case outstanding messages shall be offloaded to storage on disk
 470         * rather than held in memory.
 471         * 
 472         * @param swap
 473         *            The value of 'ZMQ_SWAP' defines the maximum size of the swap space in bytes.
 474         */
 475        public void setSwap (long swap) {
 476            setLongSockopt (SWAP, swap);
 477        }
 478
 479        /**
 480         * Get the Affinity. The 'ZMQ_AFFINITY' option shall set the I/O thread affinity for newly
 481         * created connections on the specified 'socket'.
 482         * 
 483         * Affinity determines which threads from the 0MQ I/O thread pool associated with the
 484         * socket's _context_ shall handle newly created connections. A value of zero specifies no
 485         * affinity, meaning that work shall be distributed fairly among all 0MQ I/O threads in the
 486         * thread pool. For non-zero values, the lowest bit corresponds to thread 1, second lowest
 487         * bit to thread 2 and so on. For example, a value of 3 specifies that subsequent
 488         * connections on 'socket' shall be handled exclusively by I/O threads 1 and 2.
 489         * 
 490         * See also  in the man page of zmq_init[3] for details on allocating the number of I/O threads for a
 491         * specific _context_.
 492         * 
 493         * @param affinity
 494         *            the affinity.
 495         */
 496        public void setAffinity (long affinity) {
 497            setLongSockopt (AFFINITY, affinity);
 498        }
 499
 500        /**
 501         * The 'ZMQ_IDENTITY' option shall set the identity of the specified 'socket'. Socket
 502         * identity determines if existing 0MQ infastructure (_message queues_, _forwarding
 503         * devices_) shall be identified with a specific application and persist across multiple
 504         * runs of the application.
 505         * 
 506         * If the socket has no identity, each run of an application is completely separate from
 507         * other runs. However, with identity set the socket shall re-use any existing 0MQ
 508         * infrastructure configured by the previous run(s). Thus the application may receive
 509         * messages that were sent in the meantime, _message queue_ limits shall be shared with
 510         * previous run(s) and so on.
 511         * 
 512         * Identity should be at least one byte and at most 255 bytes long. Identities starting with
 513         * binary zero are reserved for use by 0MQ infrastructure.
 514         * 
 515         * @param identity
 516         */
 517        public void setIdentity (byte [] identity) {
 518            setBytesSockopt (IDENTITY, identity);
 519        }
 520
 521        /**
 522         * The 'ZMQ_SUBSCRIBE' option shall establish a new message filter on a 'ZMQ_SUB' socket.
 523         * Newly created 'ZMQ_SUB' sockets shall filter out all incoming messages, therefore you
 524         * should call this option to establish an initial message filter.
 525         * 
 526         * An empty 'option_value' of length zero shall subscribe to all incoming messages. A
 527         * non-empty 'option_value' shall subscribe to all messages beginning with the specified
 528         * prefix. Mutiple filters may be attached to a single 'ZMQ_SUB' socket, in which case a
 529         * message shall be accepted if it matches at least one filter.
 530         * 
 531         * @param topic
 532         */
 533        public void subscribe (byte [] topic) {
 534            setBytesSockopt (SUBSCRIBE, topic);
 535        }
 536
 537        /**
 538         * The 'ZMQ_UNSUBSCRIBE' option shall remove an existing message filter on a 'ZMQ_SUB'
 539         * socket. The filter specified must match an existing filter previously established with
 540         * the 'ZMQ_SUBSCRIBE' option. If the socket has several instances of the same filter
 541         * attached the 'ZMQ_UNSUBSCRIBE' option shall remove only one instance, leaving the rest in
 542         * place and functional.
 543         * 
 544         * @param topic
 545         */
 546        public void unsubscribe (byte [] topic) {
 547            setBytesSockopt (UNSUBSCRIBE, topic);
 548        }
 549
 550        /**
 551         * The 'ZMQ_RATE' option shall set the maximum send or receive data rate for multicast
 552         * transports such as  in the man page of zmq_pgm[7] using the specified 'socket'.
 553         * 
 554         * @param rate
 555         */
 556        public void setRate (long rate) {
 557            setLongSockopt (RATE, rate);
 558        }
 559
 560        /**
 561         * The 'ZMQ_RECOVERY_IVL' option shall set the recovery interval for multicast transports
 562         * using the specified 'socket'. The recovery interval determines the maximum time in
 563         * seconds that a receiver can be absent from a multicast group before unrecoverable data
 564         * loss will occur.
 565         * 
 566         * CAUTION: Excersize care when setting large recovery intervals as the data needed for
 567         * recovery will be held in memory. For example, a 1 minute recovery interval at a data rate
 568         * of 1Gbps requires a 7GB in-memory buffer. {Purpose of this Method}
 569         * 
 570         * @param recovery_ivl
 571         */
 572        public void setRecoveryInterval (long recovery_ivl) {
 573            setLongSockopt (RECOVERY_IVL, recovery_ivl);
 574        }
 575
 576        /**
 577         * The 'ZMQ_MCAST_LOOP' option shall control whether data sent via multicast transports
 578         * using the specified 'socket' can also be received by the sending host via loopback. A
 579         * value of zero disables the loopback functionality, while the default value of 1 enables
 580         * the loopback functionality. Leaving multicast loopback enabled when it is not required
 581         * can have a negative impact on performance. Where possible, disable 'ZMQ_MCAST_LOOP' in
 582         * production environments.
 583         * 
 584         * @param mcast_loop
 585         */
 586        public void setMulticastLoop (boolean mcast_loop) {
 587            setLongSockopt (MCAST_LOOP, mcast_loop ? 1 : 0);
 588        }
 589
 590        /**
 591         * The 'ZMQ_SNDBUF' option shall set the underlying kernel transmit buffer size for the
 592         * 'socket' to the specified size in bytes. A value of zero means leave the OS default
 593         * unchanged. For details please refer to your operating system documentation for the
 594         * 'SO_SNDBUF' socket option.
 595         * 
 596         * @param sndbuf
 597         */
 598        public void setSendBufferSize (long sndbuf) {
 599            setLongSockopt (SNDBUF, sndbuf);
 600        }
 601
 602        /**
 603         * The 'ZMQ_RCVBUF' option shall set the underlying kernel receive buffer size for the
 604         * 'socket' to the specified size in bytes. A value of zero means leave the OS default
 605         * unchanged. For details refer to your operating system documentation for the 'SO_RCVBUF'
 606         * socket option.
 607         * 
 608         * @param rcvbuf
 609         */
 610        public void setReceiveBufferSize (long rcvbuf) {
 611            setLongSockopt (RCVBUF, rcvbuf);
 612        }
 613
 614        /**
 615         * Bind to network interface. Start listening for new connections.
 616         * 
 617         * @param addr
 618         *            the endpoint to bind to.
 619         */
 620        public native void bind (String addr);
 621
 622        /**
 623         * Connect to remote application.
 624         * 
 625         * @param addr
 626         *            the endpoint to connect to.
 627         */
 628        public native void connect (String addr);
 629
 630        /**
 631         * Send a message.
 632         * 
 633         * @param msg
 634         *            the message to send, as an array of bytes.
 635         * @param flags
 636         *            the flags to apply to the send operation.
 637         * @return true if send was successful, false otherwise.
 638         */
 639        public native boolean send (byte [] msg, int flags);
 640
 641        /**
 642         * Receive a message.
 643         * 
 644         * @param flags
 645         *            the flags to apply to the receive operation.
 646         * @return the message received, as an array of bytes; null on error.
 647         */
 648        public native byte [] recv (int flags);
 649
 650        /**
 651         * Class constructor.
 652         * 
 653         * @param context
 654         *            a 0MQ context previously created.
 655         * @param type
 656         *            the socket type.
 657         */
 658        protected Socket (Context context, int type) {
 659            // We keep a local handle to context so that
 660            // garbage collection won't be too greedy on it.
 661            this.context = context;
 662            construct (context, type);
 663        }
 664
 665        /** Initialize the JNI interface */
 666        protected native void construct (Context ctx, int type);
 667
 668        /** Free all resources used by JNI interface. */
 669        @Override
 670            protected native void finalize ();
 671
 672        /**
 673         * Get the socket option value, as a long.
 674         * 
 675         * @param option
 676         *            ID of the option to set.
 677         * @return The socket option value (as a long).
 678         */
 679        protected native long getLongSockopt (int option);
 680
 681        /**
 682         * Get the socket option value, as a byte array.
 683         * 
 684         * @param option
 685         *            ID of the option to set.
 686         * @return The socket option value (as a byte array).
 687         */
 688        protected native byte [] getBytesSockopt (int option);
 689
 690        /**
 691         * Set the socket option value, given as a long.
 692         * 
 693         * @param option
 694         *            ID of the option to set.
 695         * @param optval
 696         *            value (as a long) to set the option to.
 697         */
 698        protected native void setLongSockopt (int option, long optval);
 699
 700        /**
 701         * Set the socket option value, given as a byte array.
 702         * 
 703         * @param option
 704         *            ID of the option to set.
 705         * @param optval
 706         *            value (as a byte array) to set the option to.
 707         */
 708        protected native void setBytesSockopt (int option, byte [] optval);
 709
 710        /**
 711         * Get the underlying socket handle. This is private because it is only accessed from JNI,
 712         * where Java access controls are ignored.
 713         * 
 714         * @return the internal 0MQ socket handle.
 715         */
 716        private long getSocketHandle () {
 717            return this.socketHandle;
 718        }
 719
 720        /** Opaque data used by JNI driver. */
 721        private long socketHandle;
 722        private Context context = null;
 723        // private Constants use the appropriate setter instead.
 724        private static final int HWM = 1;
 725        // public static final int LWM = 2; // No longer supported
 726        private static final int SWAP = 3;
 727        private static final int AFFINITY = 4;
 728        private static final int IDENTITY = 5;
 729        private static final int SUBSCRIBE = 6;
 730        private static final int UNSUBSCRIBE = 7;
 731        private static final int RATE = 8;
 732        private static final int RECOVERY_IVL = 9;
 733        private static final int MCAST_LOOP = 10;
 734        private static final int SNDBUF = 11;
 735        private static final int RCVBUF = 12;
 736        private static final int RCVMORE = 13;
 737        private static final int FD = 14;
 738        private static final int EVENTS = 15;
 739        private static final int TYPE = 16;
 740        private static final int LINGER = 17;
 741    }
 742
 743    /**
 744     * Inner class: Poller.
 745     */
 746    public static class Poller {
 747        /**
 748         * These values can be ORed to specify what we want to poll for.
 749         */
 750        public static final int POLLIN = 1;
 751        public static final int POLLOUT = 2;
 752        public static final int POLLERR = 4;
 753
 754        /**
 755         * Register a Socket for polling on all events.
 756         * 
 757         * @param socket
 758         *            the Socket we are registering.
 759         * @return the index identifying this Socket in the poll set.
 760         */
 761        public int register (Socket socket) {
 762            return register (socket, POLLIN | POLLOUT | POLLERR);
 763        }
 764
 765        /**
 766         * Register a Socket for polling on the specified events.
 767         *
 768         * Automatically grow the internal representation if needed.
 769         * 
 770         * @param socket
 771         *            the Socket we are registering.
 772         * @param events
 773         *            a mask composed by XORing POLLIN, POLLOUT and POLLERR.
 774         * @return the index identifying this Socket in the poll set.
 775         */
 776        public int register (Socket socket, int events) {
 777            int pos = -1;
 778
 779            if (! this.freeSlots.isEmpty()) {
 780                // If there are free slots in our array, remove one
 781                // from the free list and use it.
 782                pos = this.freeSlots.remove();
 783            } else {
 784                if (this.next >= this.size) {
 785                    // It is necessary to grow the arrays.
 786
 787                    // Compute new size for internal arrays.
 788                    int nsize = this.size + SIZE_INCREMENT;
 789
 790                    // Create new internal arrays.
 791                    Socket [] ns = new Socket [nsize];
 792                    short [] ne = new short [nsize];
 793                    short [] nr = new short [nsize];
 794                    
 795                    // Copy contents of current arrays into new arrays.
 796                    for (int i = 0; i < this.next; ++i) {
 797                        ns[i] = this.sockets[i];
 798                        ne[i] = this.events[i];
 799                        nr[i] = this.revents[i];
 800                    }
 801                    
 802                    // Swap internal arrays and size to new values.
 803                    this.size = nsize;
 804                    this.sockets = ns;
 805                    this.events = ne;
 806                    this.revents = nr;
 807                }
 808                pos = this.next++;
 809            }
 810
 811            this.sockets[pos] = socket;
 812            this.events[pos] = (short) events;
 813            this.used++;
 814            return pos;
 815        }
 816
 817        /**
 818         * Unregister a Socket for polling on the specified events.
 819         *
 820         * @param socket 
 821         *          the Socket to be unregistered
 822         */
 823        public void unregister (Socket socket) {
 824            for (int i = 0; i < this.next; ++i) {
 825                if (this.sockets[i] == socket) {
 826                    this.sockets[i] = null;
 827                    this.events[i] = 0;
 828                    this.revents[i] = 0;
 829                    
 830                    this.freeSlots.add(i);
 831                    --this.used;
 832
 833                    break;
 834                }
 835            }
 836        }
 837
 838        /**
 839         * Get the socket associated with an index.
 840         * 
 841         * @param index
 842         *            the desired index.
 843         * @return the Socket associated with that index (or null).
 844         */
 845        public Socket getSocket (int index) {
 846            if (index < 0 || index >= this.next)
 847                return null;
 848            return this.sockets [index];
 849        }
 850
 851        /**
 852         * Get the current poll timeout.
 853         * 
 854         * @return the current poll timeout in microseconds.
 855         * @deprecated Timeout handling has been moved to the poll() methods.
 856         */
 857        public long getTimeout () {
 858            return this.timeout;
 859        }
 860
 861        /**
 862         * Set the poll timeout.
 863         * 
 864         * @param timeout
 865         *            the desired poll timeout in microseconds.
 866         * @deprecated Timeout handling has been moved to the poll() methods.
 867         */
 868        public void setTimeout (long timeout) {
 869            if (timeout < -1)
 870                return;
 871
 872            this.timeout = timeout;
 873        }
 874
 875        /**
 876         * Get the current poll set size.
 877         * 
 878         * @return the current poll set size.
 879         */
 880        public int getSize () {
 881            return this.size;
 882        }
 883
 884        /**
 885         * Get the index for the next position in the poll set size.
 886         * 
 887         * @return the index for the next position in the poll set size.
 888         */
 889        public int getNext () {
 890            return this.next;
 891        }
 892
 893        /**
 894         * Issue a poll call. If the poller's internal timeout value
 895         * has been set, use that value as timeout; otherwise, block
 896         * indefinitely.
 897         * 
 898         * @return how many objects where signalled by poll ().
 899         */
 900        public long poll () {
 901            long tout = -1;
 902            if (this.timeout > -1) {
 903                tout = this.timeout;
 904            }
 905            return poll(tout);
 906        }
 907
 908        /**
 909         * Issue a poll call, using the specified timeout value.
 910         * 
 911         * @param tout
 912         *            the timeout in microseconds, as per zmq_poll ();
 913         *            if -1, it will block indefinitely until an event
 914         *            happens; if 0, it will return immediately;
 915         *            otherwise, it will wait for at most that many
 916         *            microseconds.
 917         *
 918         * @return how many objects where signalled by poll ()
 919         */
 920        public long poll (long tout) {
 921            if (tout < -1) {
 922                return 0;
 923            }
 924
 925            if (this.size <= 0 || this.next <= 0) {
 926                return 0;
 927            }
 928
 929            for (int i = 0; i < this.next; ++i) {
 930                this.revents [i] = 0;
 931            }
 932            return run_poll (this.used, this.sockets, this.events, this.revents, tout);
 933        }
 934
 935        /**
 936         * Check whether the specified element in the poll set was signalled for input.
 937         * 
 938         * @param index
 939         * 
 940         * @return true if the element was signalled.
 941         */
 942        public boolean pollin (int index) {
 943            return poll_mask (index, POLLIN);
 944        }
 945
 946        /**
 947         * Check whether the specified element in the poll set was signalled for output.
 948         * 
 949         * @param index
 950         * 
 951         * @return true if the element was signalled.
 952         */
 953        public boolean pollout (int index) {
 954            return poll_mask (index, POLLOUT);
 955        }
 956
 957        /**
 958         * Check whether the specified element in the poll set was signalled for error.
 959         * 
 960         * @param index
 961         * 
 962         * @return true if the element was signalled.
 963         */
 964        public boolean pollerr (int index) {
 965            return poll_mask (index, POLLERR);
 966        }
 967
 968        /**
 969         * Class constructor.
 970         * 
 971         * @param context
 972         *            a 0MQ context previously created.
 973         */
 974        protected Poller (Context context) {
 975            this(context, SIZE_DEFAULT);
 976        }
 977
 978        /**
 979         * Class constructor.
 980         * 
 981         * @param context
 982         *            a 0MQ context previously created.
 983         * @param size
 984         *            the number of Sockets this poller will contain.
 985         */
 986        protected Poller (Context context, int size) {
 987            this.context = context;
 988            this.size = size;
 989            this.next = 0;
 990
 991            this.sockets = new Socket [this.size];
 992            this.events = new short [this.size];
 993            this.revents = new short [this.size];
 994
 995            freeSlots = new LinkedList<Integer>();
 996        }
 997
 998        /**
 999         * Issue a poll call on the specified 0MQ sockets.
1000         * 
1001         * @param sockets
1002         *            an array of 0MQ Socket objects to poll.
1003         * @param events
1004         *            an array of short values specifying what to poll for.
1005         * @param revents
1006         *            an array of short values with the results.
1007         * @param timeout
1008         *            the maximum timeout in microseconds.
1009         * @return how many objects where signalled by poll ().
1010         */
1011        private native long run_poll (int count, Socket [] sockets, short [] events, short [] revents, long timeout);
1012
1013        /**
1014         * Check whether a specific mask was signalled by latest poll call.
1015         * 
1016         * @param index
1017         *            the index indicating the socket.
1018         * @param mask
1019         *            a combination of POLLIN, POLLOUT and POLLERR.
1020         * @return true if specific socket was signalled as specified.
1021         */
1022        private boolean poll_mask (int index, int mask) {
1023            if (mask <= 0 || index < 0 || index >= this.next) {
1024                return false;
1025            }
1026            return (this.revents [index] & mask) > 0;
1027        }
1028
1029        private Context context = null;
1030        private long timeout = -2; // mark as uninitialized
1031        private int size = 0;
1032        private int next = 0;
1033        private int used = 0;
1034        private Socket [] sockets = null;
1035        private short [] events = null;
1036        private short [] revents = null;
1037        // When socket is removed from polling, store free slots here
1038        private LinkedList<Integer> freeSlots = null;
1039
1040        private static final int SIZE_DEFAULT = 32;
1041        private static final int SIZE_INCREMENT = 16;
1042    }
1043}