PageRenderTime 56ms CodeModel.GetById 2ms app.highlight 46ms RepoModel.GetById 1ms app.codeStats 0ms

/tools-zeromq/src/main/java/org/zeromq/ZMQ.java

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