Esempio n. 1
0
int
zloop_poller (zloop_t *self, zmq_pollitem_t *item, zloop_fn handler, void *arg)
{
    assert (self);

    if (!item->socket && !item->fd)
        return -1;

    if (item->socket)
        if (streq (zsocket_type_str (item->socket), "UNKNOWN"))
            return -1;

    s_poller_t *poller = s_poller_new (item, handler, arg);
    if (poller) {
        if (zlist_append (self->pollers, poller))
            return -1;

        self->dirty = true;
        if (self->verbose)
            zclock_log ("I: zloop: register %s poller (%p, %d)",
                item->socket? zsocket_type_str (item->socket): "FD",
                item->socket, item->fd);
        return 0;
    }
    else
        return -1;
}
Esempio n. 2
0
int
zsocket_test (Bool verbose)
{
    printf (" * zsocket: ");

    //  @selftest
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    //  Create a detached thread, let it run
    char *interf = "*";
    char *domain = "localhost";
    int service = 5560;

    void *writer = zsocket_new (ctx, ZMQ_PUSH);
    assert (writer);
    void *reader = zsocket_new (ctx, ZMQ_PULL);
    assert (reader);
    assert (streq (zsocket_type_str (writer), "PUSH"));
    assert (streq (zsocket_type_str (reader), "PULL"));
    int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service);
    assert (rc == service);
    rc = zsocket_connect (reader, "tcp://%s:%d", domain, service);
    assert (rc == 0);
    zstr_send (writer, "HELLO");
    char *message = zstr_recv (reader);
    assert (message);
    assert (streq (message, "HELLO"));
    free (message);

    int port = zsocket_bind (writer, "tcp://%s:*", interf);
    assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO);

    assert (zsocket_poll (writer, 100) == FALSE);

    rc = zsocket_connect (reader, "txp://%s:%d", domain, service);
    assert (rc == -1);

    zsocket_destroy (ctx, writer);
    zctx_destroy (&ctx);
    //  @end

    printf ("OK\n");
    return 0;
}
Esempio n. 3
0
void
zsocket_set_unsubscribe (void *zocket, char * unsubscribe)
{
#   if defined (ZMQ_UNSUBSCRIBE)
    if (zsockopt_type (zocket) != ZMQ_SUB) {
        printf ("ZMQ_UNSUBSCRIBE is not valid on %s sockets\n", zsocket_type_str (zocket));
        assert (false);
    }
    int rc = zmq_setsockopt (zocket, ZMQ_UNSUBSCRIBE, unsubscribe, strlen (unsubscribe));
    assert (rc == 0 || errno == ETERM);
#   endif
}
Esempio n. 4
0
void
zsocket_set_xpub_verbose (void *zocket, int xpub_verbose)
{
#   if defined (ZMQ_XPUB_VERBOSE)
    if (zsockopt_type (zocket) != ZMQ_XPUB) {
        printf ("ZMQ_XPUB_VERBOSE is not valid on %s sockets\n", zsocket_type_str (zocket));
        assert (false);
    }
    int rc = zmq_setsockopt (zocket, ZMQ_XPUB_VERBOSE, &xpub_verbose, sizeof (int));
    assert (rc == 0 || errno == ETERM);
#   endif
}
Esempio n. 5
0
void
zsocket_set_router_raw (void *zocket, int router_raw)
{
#   if defined (ZMQ_ROUTER_RAW)
    if (zsockopt_type (zocket) != ZMQ_ROUTER) {
        printf ("ZMQ_ROUTER_RAW is not valid on %s sockets\n", zsocket_type_str (zocket));
        assert (false);
    }
    int rc = zmq_setsockopt (zocket, ZMQ_ROUTER_RAW, &router_raw, sizeof (int));
    assert (rc == 0 || errno == ETERM);
#   endif
}
Esempio n. 6
0
void
zsocket_set_router_mandatory (void *zocket, int router_mandatory)
{
#   if defined (ZMQ_ROUTER_MANDATORY)
    if (zsockopt_type (zocket) != ZMQ_ROUTER) {
        printf ("ZMQ_ROUTER_MANDATORY is not valid on %s sockets\n", zsocket_type_str (zocket));
        assert (false);
    }
    int rc = zmq_setsockopt (zocket, ZMQ_ROUTER_MANDATORY, &router_mandatory, sizeof (int));
    assert (rc == 0 || errno == ETERM);
#   endif
}
Esempio n. 7
0
void
zsocket_set_identity (void *zocket, char * identity)
{
#   if defined (ZMQ_IDENTITY)
    if (zsockopt_type (zocket) != ZMQ_REQ
    &&  zsockopt_type (zocket) != ZMQ_REP
    &&  zsockopt_type (zocket) != ZMQ_DEALER
    &&  zsockopt_type (zocket) != ZMQ_ROUTER) {
        printf ("ZMQ_IDENTITY is not valid on %s sockets\n", zsocket_type_str (zocket));
        assert (false);
    }
    int rc = zmq_setsockopt (zocket, ZMQ_IDENTITY, identity, strlen (identity));
    assert (rc == 0 || errno == ETERM);
#   endif
}
Esempio n. 8
0
void
zloop_poller_end (zloop_t *self, zmq_pollitem_t *item)
{
    assert (self);
    assert (item->socket || item->fd);

    s_poller_t *poller = (s_poller_t *) zlist_first (self->pollers);
    while (poller) {
        if ((item->socket && item->socket == poller->item.socket)
        ||  (item->fd     && item->fd     == poller->item.fd)) {
            zlist_remove (self->pollers, poller);
            free (poller);
            self->dirty = true;
        }
        poller = (s_poller_t *) zlist_next (self->pollers);
    }
    if (self->verbose)
        zclock_log ("I: zloop: cancel %s poller (%p, %d)",
            item->socket? zsocket_type_str (item->socket): "FD",
            item->socket, item->fd);
}
Esempio n. 9
0
void
zloop_poller_end (zloop_t *self, zmq_pollitem_t *item)
{
    assert (self);
    assert (item->socket || item->fd);

    s_poller_t *poller = (s_poller_t *) zlist_first (self->pollers);
    while (poller) {
        if ((item->socket && item->socket == poller->item.socket)
        ||  (item->fd     && item->fd     == poller->item.fd)) {
            zlist_remove (self->pollers, poller);
            free (poller);
            //  Force rebuild to avoid reading from freed poller
            self->need_rebuild = true;
        }
        poller = (s_poller_t *) zlist_next (self->pollers);
    }
    if (self->verbose)
        zsys_debug ("zloop: cancel %s poller (%p, %d)",
            item->socket? zsocket_type_str (item->socket): "FD",
            item->socket, item->fd);
}
Esempio n. 10
0
void
zsocket_test (bool verbose)
{
    printf (" * zsocket (deprecated): ");

    //  @selftest
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    //  Create a detached thread, let it run
    char *interf = "127.0.0.1";
    char *domain = "localhost";
    int service = 5560;

    void *writer = zsocket_new (ctx, ZMQ_PUSH);
    assert (writer);
    void *reader = zsocket_new (ctx, ZMQ_PULL);
    assert (reader);
    assert (streq (zsocket_type_str (writer), "PUSH"));
    assert (streq (zsocket_type_str (reader), "PULL"));
    int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service);
    assert (rc == service);

#if (ZMQ_VERSION >= ZMQ_MAKE_VERSION (3, 2, 0))
    //  Check unbind
    rc = zsocket_unbind (writer, "tcp://%s:%d", interf, service);
    assert (rc == 0);

    //  In some cases and especially when running under Valgrind, doing
    //  a bind immediately after an unbind causes an EADDRINUSE error.
    //  Even a short sleep allows the OS to release the port for reuse.
    zclock_sleep (100);

    //  Bind again
    rc = zsocket_bind (writer, "tcp://%s:%d", interf, service);
    assert (rc == service);
#endif

    rc = zsocket_connect (reader, "tcp://%s:%d", domain, service);
    assert (rc == 0);
    zstr_send (writer, "HELLO");
    char *message = zstr_recv (reader);
    assert (message);
    assert (streq (message, "HELLO"));
    free (message);

    //  Test binding to ports
    int port = zsocket_bind (writer, "tcp://%s:*", interf);
    assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO);

    assert (zsocket_poll (writer, 100) == false);

    //  Test error state when connecting to an invalid socket type
    //  ('txp://' instead of 'tcp://', typo intentional)
    rc = zsocket_connect (reader, "txp://%s:%d", domain, service);
    assert (rc == -1);

    //  Test sending frames to socket
    rc = zsocket_sendmem (writer, "ABC", 3, ZFRAME_MORE);
    assert (rc == 0);
    rc = zsocket_sendmem (writer, "DEFG", 4, 0);
    assert (rc == 0);

    zframe_t *frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "ABC"));
    assert (zframe_more (frame));
    zframe_destroy (&frame);

    frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "DEFG"));
    assert (!zframe_more (frame));
    zframe_destroy (&frame);

    rc = zsocket_signal (writer);
    assert (rc == 0);
    rc = zsocket_wait (reader);
    assert (rc == 0);

    zsocket_destroy (ctx, reader);
    zsocket_destroy (ctx, writer);
    zctx_destroy (&ctx);
    //  @end

    printf ("OK\n");
}
Esempio n. 11
0
int
zsocket_test (bool verbose)
{
    printf (" * zsocket: ");

    //  @selftest
    zctx_t *ctx = zctx_new ();
    assert (ctx);

    //  Create a detached thread, let it run
    char *interf = "*";
    char *domain = "localhost";
    int service = 5560;

    void *writer = zsocket_new (ctx, ZMQ_PUSH);
    assert (writer);
    void *reader = zsocket_new (ctx, ZMQ_PULL);
    assert (reader);
    assert (streq (zsocket_type_str (writer), "PUSH"));
    assert (streq (zsocket_type_str (reader), "PULL"));
    int rc = zsocket_bind (writer, "tcp://%s:%d", interf, service);
    assert (rc == service);
    rc = zsocket_connect (reader, "tcp://%s:%d", domain, service);
    assert (rc == 0);
    zstr_send (writer, "HELLO");
    char *message = zstr_recv (reader);
    assert (message);
    assert (streq (message, "HELLO"));
    free (message);
    
    //  Test binding to ports
    int port = zsocket_bind (writer, "tcp://%s:*", interf);
    assert (port >= ZSOCKET_DYNFROM && port <= ZSOCKET_DYNTO);

    assert (zsocket_poll (writer, 100) == false);

    rc = zsocket_connect (reader, "txp://%s:%d", domain, service);
    assert (rc == -1);

    //  Test sending frames to socket
    rc = zsocket_sendmem (writer,"ABC", 3, ZFRAME_MORE);
    assert (rc == 0);
    rc = zsocket_sendmem (writer, "DEFG", 4, 0);
    assert (rc == 0);
    
    zframe_t *frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "ABC"));
    assert (zframe_more (frame));
    zframe_destroy (&frame);
    
    frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "DEFG"));
    assert (!zframe_more (frame));
    zframe_destroy (&frame);

    //  Test zframe_sendmem_zero_copy
    rc = zsocket_sendmem_zero_copy (writer, strdup ("ABC"), 3,
                                    s_test_free_str_cb, NULL, ZFRAME_MORE);
    assert (rc == 0);
    rc = zsocket_sendmem_zero_copy (writer, strdup ("DEFG"), 4,
                                    s_test_free_str_cb, NULL, 0);
    assert (rc == 0);
    
    frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "ABC"));
    assert (zframe_more (frame));
    zframe_destroy (&frame);
    
    frame = zframe_recv (reader);
    assert (frame);
    assert (zframe_streq (frame, "DEFG"));
    assert (!zframe_more (frame));
    zframe_destroy (&frame);

    zsocket_destroy (ctx, writer);
    zctx_destroy (&ctx);
    //  @end

    printf ("OK\n");
    return 0;
}
Esempio n. 12
0
int
zloop_start (zloop_t *self)
{
    assert (self);
    int rc = 0;

    //  Recalculate all timers now
    s_timer_t *timer = (s_timer_t *) zlist_first (self->timers);
    while (timer) {
        timer->when = timer->delay + zclock_time ();
        timer = (s_timer_t *) zlist_next (self->timers);
    }
    //  Main reactor loop
    while (!zsys_interrupted) {
        if (self->need_rebuild) {
            //  If s_rebuild_pollset() fails, break out of the loop and
            //  return its error
            rc = s_rebuild_pollset (self);
            if (rc)
                break;
        }
        rc = zmq_poll (self->pollset, (int) self->poll_size,
                       s_tickless_timer (self) * ZMQ_POLL_MSEC);
        if (rc == -1 || zsys_interrupted) {
            if (self->verbose)
                zsys_debug ("zloop: interrupted (%d) - %s", rc,
                            zmq_strerror (zmq_errno ()));
            rc = 0;
            break;              //  Context has been shut down
        }
        //  Handle any timers that have now expired
        timer = (s_timer_t *) zlist_first (self->timers);
        while (timer) {
            if (zclock_time () >= timer->when && timer->when != -1) {
                if (self->verbose)
                    zsys_debug ("zloop: call timer id=%d handler", timer->timer_id);
                rc = timer->handler (self, timer->timer_id, timer->arg);
                if (rc == -1)
                    break;      //  Timer handler signaled break
                if (timer->times && --timer->times == 0) {
                    zlist_remove (self->timers, timer);
                    free (timer);
                }
                else
                    timer->when = timer->delay + zclock_time ();
            }
            timer = (s_timer_t *) zlist_next (self->timers);
        }
        //  Handle any readers and pollers that are ready
        size_t item_nbr;
        for (item_nbr = 0; item_nbr < self->poll_size && rc >= 0; item_nbr++) {
            s_reader_t *reader = &self->readact [item_nbr];
            if (reader->handler) {
                if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
                && !reader->tolerant) {
                    if (self->verbose)
                        zsys_warning ("zloop: can't read %s socket: %s",
                            zsock_type_str (reader->sock),
                            zmq_strerror (zmq_errno ()));
                    //  Give handler one chance to handle error, then kill
                    //  reader because it'll disrupt the reactor otherwise.
                    if (reader->errors++) {
                        zloop_reader_end (self, reader->sock);
                        self->pollset [item_nbr].revents = 0;
                    }
                }
                else
                    reader->errors = 0;     //  A non-error happened

                if (self->pollset [item_nbr].revents) {
                    if (self->verbose)
                        zsys_debug ("zloop: call %s socket handler",
                            zsock_type_str (reader->sock));
                    rc = reader->handler (self, reader->sock, reader->arg);
                    if (rc == -1 || self->need_rebuild)
                        break;
                }
            }
            else {
                s_poller_t *poller = &self->pollact [item_nbr];
                assert (self->pollset [item_nbr].socket == poller->item.socket);
            
                if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
                && !poller->tolerant) {
                    if (self->verbose)
                        zsys_warning ("zloop: can't poll %s socket (%p, %d): %s",
                            poller->item.socket?
                                zsocket_type_str (poller->item.socket): "FD",
                            poller->item.socket, poller->item.fd,
                            zmq_strerror (zmq_errno ()));
                    //  Give handler one chance to handle error, then kill
                    //  poller because it'll disrupt the reactor otherwise.
                    if (poller->errors++) {
                        zloop_poller_end (self, &poller->item);
                        self->pollset [item_nbr].revents = 0;
                    }
                }
                else
                    poller->errors = 0;     //  A non-error happened

                if (self->pollset [item_nbr].revents) {
                    if (self->verbose)
                        zsys_debug ("zloop: call %s socket handler (%p, %d)",
                            poller->item.socket?
                                zsocket_type_str (poller->item.socket): "FD",
                            poller->item.socket, poller->item.fd);
                    rc = poller->handler (self, &self->pollset [item_nbr], poller->arg);
                    if (rc == -1 || self->need_rebuild)
                        break;
                }
            }
        }
        //  Now handle any timer zombies
        //  This is going to be slow if we have many timers; we might use
        //  a faster lookup on the timer list.
        while (zlist_size (self->zombies)) {
            //  Get timer_id back from pointer
            int timer_id = (byte *) zlist_pop (self->zombies) - (byte *) NULL;
            s_timer_remove (self, timer_id);
        }
        if (rc == -1)
            break;
    }
    self->terminated = true;
    return rc;
}
Esempio n. 13
0
int
zloop_start (zloop_t *self)
{
    assert (self);
    int rc = 0;

    //  Recalculate all timers now
    s_timer_t *timer = (s_timer_t *) zlist_first (self->timers);
    while (timer) {
        timer->when = timer->delay + zclock_time ();
        timer = (s_timer_t *) zlist_next (self->timers);
    }
    //  Main reactor loop
    while (!zctx_interrupted) {
        if (self->dirty) {
            // If s_rebuild_pollset() fails, break out of the loop and
            // return its error
            rc = s_rebuild_pollset (self);
            if (rc)
                break;
        }
        rc = zmq_poll (self->pollset, (int) self->poll_size,
                       s_tickless_timer (self) * ZMQ_POLL_MSEC);
        if (rc == -1 || zctx_interrupted) {
            if (self->verbose)
                zclock_log ("I: zloop: interrupted (%d) - %s", rc, strerror (errno));
            rc = 0;
            break;              //  Context has been shut down
        }
        //  Handle any timers that have now expired
        timer = (s_timer_t *) zlist_first (self->timers);
        while (timer) {
            if (zclock_time () >= timer->when && timer->when != -1) {
                if (self->verbose)
                    zclock_log ("I: zloop: call timer handler");
                rc = timer->handler (self, NULL, timer->arg);
                if (rc == -1)
                    break;      //  Timer handler signaled break
                if (timer->times && --timer->times == 0) {
                    zlist_remove (self->timers, timer);
                    free (timer);
                }
                else
                    timer->when = timer->delay + zclock_time ();
            }
            timer = (s_timer_t *) zlist_next (self->timers);
        }
        //  Handle any pollers that are ready
        size_t item_nbr;
        for (item_nbr = 0; item_nbr < self->poll_size && rc >= 0; item_nbr++) {
            s_poller_t *poller = &self->pollact [item_nbr];
            assert (self->pollset [item_nbr].socket == poller->item.socket);
            
            if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
            && !poller->ignore_errors) {
                if (self->verbose)
                    zclock_log ("I: zloop: can't poll %s socket (%p, %d): %s",
                        poller->item.socket?
                            zsocket_type_str (poller->item.socket): "FD",
                        poller->item.socket, poller->item.fd,
                        strerror (errno));
                //  Give handler one chance to handle error, then kill
                //  poller because it'll disrupt the reactor otherwise.
                if (poller->errors++) {
                    zloop_poller_end (self, &poller->item);
                    self->pollset [item_nbr].revents = 0;
                }
            }
            else
                poller->errors = 0;     //  A non-error happened

            if (self->pollset [item_nbr].revents) {
                if (self->verbose)
                    zclock_log ("I: zloop: call %s socket handler (%p, %d)",
                        poller->item.socket?
                            zsocket_type_str (poller->item.socket): "FD",
                        poller->item.socket, poller->item.fd);
                rc = poller->handler (self, &self->pollset [item_nbr], poller->arg);
                if (rc == -1)
                    break;      //  Poller handler signaled break
            }
        }
        //  Now handle any timer zombies
        //  This is going to be slow if we have many zombies
        while (zlist_size (self->zombies)) {
            void *arg = zlist_pop (self->zombies);
            timer = (s_timer_t *) zlist_first (self->timers);
            while (timer) {
                if (timer->arg == arg) {
                    zlist_remove (self->timers, timer);
                    free (timer);
                    break;
                }
                timer = (s_timer_t *) zlist_next (self->timers);
            }
        }
        if (rc == -1)
            break;
    }
    return rc;
}
Esempio n. 14
0
//  Main
int
main (int argc, char **argv)
{
        //  Do some initial sanity checking
        assert (TIME_BITLEN + MACHINE_BITLEN + SEQ_BITLEN == 64);

        //  Parse command-line arguments
        int opt;
        int has_port_opt = 0;
        int has_machine_opt = 0;
        int has_config_file_opt = 0;
        int has_daemonize_opt = 0;
        int machine_specified = 0;

        const char *config_file_path;
        int port = DEFAULT_PORT;
        uint64_t machine;
        
        while ((opt = getopt (argc, argv, "hp:m:f:d")) != -1) {
                switch (opt) {
                case 'h':
                        print_help ();
                        exit (EXIT_SUCCESS);
                case 'p':
                        has_port_opt = 1;
                        port = atoi (optarg);
                        break;
                case 'm':
                        has_machine_opt = 1;
                        machine = atoll (optarg);
                        machine_specified = 1;
                        break;
                case 'f':
                        has_config_file_opt = 1;
                        config_file_path = optarg;
                        break;
                case 'd':
                        has_daemonize_opt = 1;
                        break;
                }
        }

        //  Read the config file
        if (has_config_file_opt) {
                config_t cfg;

                config_init (&cfg);

                if (!config_read_file (&cfg, config_file_path)) {
                        config_destroy (&cfg);
                        fprintf (stderr, "Invalid config file\n");
                        exit (EXIT_FAILURE);
                }

                long unsigned int machine_from_file;
                if (config_lookup_int (&cfg, "machine", &machine_from_file) && !has_machine_opt) {
                        machine_specified = 1;
                        machine = (uint64_t) machine_from_file;
                }

                long unsigned int port_from_file;
                if (config_lookup_int (&cfg, "port", &port_from_file) && !has_port_opt)
                        port = (int) port_from_file;

                
        }

        //  Sanity check the machine number
        if (!machine_specified) {
                fprintf (stderr, "No machine number specified.\n");
                exit (EXIT_FAILURE);
        }
        else if (machine > MACHINE_MAX) {
                fprintf (stderr, "Machine number too large. Cannot be greater than %llu\n", MACHINE_MAX);
                exit (EXIT_FAILURE);
        }

        //  Daemonize
        static char *pid_file_path = "/var/run/znowflaked.pid";
        int pid_file;
        
        if (has_daemonize_opt) {
                pid_t pid, sid;

                pid = fork ();
                if (pid < 0) {
                        exit (EXIT_FAILURE);
                }
                if (pid > 0) {
                        exit (EXIT_SUCCESS);
                }

                umask (0);
                
                sid = setsid ();
                if (sid < 0) {
                        exit (EXIT_FAILURE);
                }
        
                if ((chdir ("/")) < 0) {
                        exit (EXIT_FAILURE);
                }

                //  Create and lock the pid file
                pid_file = open (pid_file_path, O_CREAT | O_RDWR, 0666);
                if (pid_file > 0) {
                        int rc = lockf (pid_file, F_TLOCK, 0);
                        if (rc) {
                                switch (errno) {
                                case EACCES:
                                case EAGAIN:
                                        fprintf (stderr, "PID file already locked\n");
                                        break;
                                case EBADF:
                                        fprintf (stderr, "Bad pid file\n");
                                        break;
                                default:
                                        fprintf (stderr, "Could not lock pid file\n");
                                }
                                exit (EXIT_FAILURE);
                        }

                        char *pid_string = NULL;
                        int pid_string_len = asprintf (&pid_string, "%ld", (long) getpid ());
                        write (pid_file, pid_string, pid_string_len);
                }
        
                close (STDIN_FILENO);
                close (STDOUT_FILENO);
                close (STDERR_FILENO);
        }

        //  Sleep for 1ms to prevent collisions
        struct timespec ms;
        ms.tv_sec = 0;
        ms.tv_nsec = 1000000;
        nanosleep (&ms, NULL);

        //  Initialize ZeroMQ
        zctx_t *context = zctx_new ();
        assert (context);
        void *socket = zsocket_new (context, ZMQ_REP);
        assert (socket);
        assert (streq (zsocket_type_str (socket), "REP"));
        int rc = zsocket_bind (socket, "tcp://*:%d", port);
        if (rc != port) {
                printf ("E: bind failed: %s\n", strerror (errno));
                exit (EXIT_FAILURE);
        }

        //  Start remembering the last timer tick
        uint64_t ts = 0;
        uint64_t last_ts = 0;
        uint64_t seq = 0;

        //  Main loop
        s_catch_signals ();        
        while (1) {
                //  Wait for the next request
                zmsg_t *request_msg = zmsg_new ();
                assert (request_msg);
                request_msg = zmsg_recv (socket);
                assert (request_msg);
                zmsg_destroy (&request_msg);

                //  Grab a time click
                last_ts = ts;
                ts = get_ts ();

                //  Make sure the system clock wasn't reversed on us
                if (ts < last_ts) {
                        //  Wait until it catches up
                        while (ts <= last_ts) {
                                nanosleep (&ms, NULL);
                                ts = get_ts ();
                        }
                }

                //  Increment the sequence number
                if (ts != last_ts) {
                        //  We're in a new time click, so reset the sequence
                        seq = 0;
                }
                else if (seq == SEQ_MAX) {
                        //  Wrapped sequence, so wait for the next time tick
                        seq = 0;
                        nanosleep (&ms, NULL);
                }
                else {
                        //  Still in the same time click
                        seq++;
                }

                //  Build the ID and put it in network byte order
                uint64_t id = build_id (ts, machine, seq);
                uint64_t id_be64 = htobe64 (id);

                //  Reply
                zmsg_t *reply_msg = zmsg_new ();
                assert (reply_msg);
                zframe_t *frame = zframe_new (&id_be64, 8);
                assert (frame);
                zmsg_push (reply_msg, frame);
                assert (zmsg_size (reply_msg) == 1);
                assert (zmsg_content_size (reply_msg) == 8);
                zmsg_send (&reply_msg, socket);
                assert (reply_msg == NULL);

                //  Exit program
                if (s_interrupted) {
                        printf ("interrupt received, killing server…\n");
                        break;
                }
        }
        zctx_destroy (&context);
        if (has_daemonize_opt) {
                if (pid_file > 0) {
                        unlink (pid_file_path);
                        close (pid_file);
                }
        }
        exit (EXIT_SUCCESS);
}
Esempio n. 15
0
int
zloop_start (zloop_t *self)
{
    assert (self);
    int rc = 0;

    //  Recalculate all timers now
    s_timer_t *timer = (s_timer_t *) zlist_first (self->timers);
    while (timer) {
        timer->when = timer->delay + zclock_time ();
        timer = (s_timer_t *) zlist_next (self->timers);
    }
    //  Main reactor loop
    while (!zctx_interrupted) {
        if (self->dirty) {
            // If s_rebuild_pollset() fails, break out of the loop and
            // return its error
            rc = s_rebuild_pollset (self);
            if (rc)
                break;
        }
        rc = zmq_poll (self->pollset, (int) self->poll_size,
                       s_tickless_timer (self) * ZMQ_POLL_MSEC);
        if (rc == -1 || zctx_interrupted) {
            if (self->verbose)
                zclock_log ("I: zloop: interrupted (%d) - %s", rc,
                            zmq_strerror (zmq_errno ()));
            rc = 0;
            break;              //  Context has been shut down
        }
        //  Handle any timers that have now expired
        timer = (s_timer_t *) zlist_first (self->timers);
        while (timer) {
            if (zclock_time () >= timer->when && timer->when != -1) {
                if (self->verbose)
                    zclock_log ("I: zloop: call timer id=%d handler", timer->timer_id);
                rc = timer->handler (self, timer->timer_id, timer->arg);
                if (rc == -1)
                    break;      //  Timer handler signaled break
                if (timer->times && --timer->times == 0) {
                    zlist_remove (self->timers, timer);
                    free (timer);
                }
                else
                    timer->when = timer->delay + zclock_time ();
            }
            timer = (s_timer_t *) zlist_next (self->timers);
        }
        //  Handle any pollers that are ready
        size_t item_nbr;
        for (item_nbr = 0; item_nbr < self->poll_size && rc >= 0; item_nbr++) {
            s_poller_t *poller = &self->pollact [item_nbr];
            assert (self->pollset [item_nbr].socket == poller->item.socket);

            if ((self->pollset [item_nbr].revents & ZMQ_POLLERR)
                    && !poller->tolerant) {
                if (self->verbose)
                    zclock_log ("W: zloop: can't poll %s socket (%p, %d): %s",
                                poller->item.socket?
                                zsocket_type_str (poller->item.socket): "FD",
                                poller->item.socket, poller->item.fd,
                                zmq_strerror (zmq_errno ()));
                //  Give handler one chance to handle error, then kill
                //  poller because it'll disrupt the reactor otherwise.
                if (poller->errors++) {
                    zloop_poller_end (self, &poller->item);
                    self->pollset [item_nbr].revents = 0;
                }
            }
            else
                poller->errors = 0;     //  A non-error happened

            if (self->pollset [item_nbr].revents) {
                if (self->verbose)
                    zclock_log ("I: zloop: call %s socket handler (%p, %d)",
                                poller->item.socket?
                                zsocket_type_str (poller->item.socket): "FD",
                                poller->item.socket, poller->item.fd);
                rc = poller->handler (self, &self->pollset [item_nbr], poller->arg);
                if (rc == -1)
                    break;      //  Poller handler signaled break

                //  If the poller handler calls zloop_poller_end on a poller
                //  other than itself, we need to force rebuild in order to
                //  avoid reading from freed memory in the handler.
                if (self->dirty) {
                    if (self->verbose)
                        zclock_log ("I: zloop: pollers canceled, forcing rebuild");
                    break;
                }
            }
        }
        //  Now handle any timer zombies
        //  This is going to be slow if we have many timers; we might use
        //  a faster lookup on the timer list.
        while (zlist_size (self->zombies)) {
            //  This hack lets us convert our pointer back into an integer timer_id
            int timer_id = (byte *) zlist_pop (self->zombies) - (byte *) NULL;
            timer = (s_timer_t *) zlist_first (self->timers);
            while (timer) {
                if (timer->timer_id == timer_id) {
                    zlist_remove (self->timers, timer);
                    free (timer);
                }
                timer = (s_timer_t *) zlist_next (self->timers);
            }
        }
        if (rc == -1)
            break;
    }
    return rc;
}