Example #1
0
static long
s_tickless (zloop_t *self)
{
    //  Calculate tickless timer, up to 1 hour
    int64_t tickless = zclock_mono () + 1000 * 3600;
    
    //  Scan timers, which are not sorted
    //  TODO: sort timers properly on insertion
    s_timer_t *timer = (s_timer_t *) zlistx_first (self->timers);
    while (timer) {
        //  Find earliest timer
        if (tickless > timer->when)
            tickless = timer->when;
        timer = (s_timer_t *) zlistx_next (self->timers);
    }
    //  Tickets are sorted, so check first ticket
    s_ticket_t *ticket = (s_ticket_t *) zlistx_first (self->tickets);
    if (ticket && tickless > ticket->when)
        tickless = ticket->when;

    long timeout = (long) (tickless - zclock_mono ());
    if (timeout < 0)
        timeout = 0;
    if (self->verbose)
        zsys_debug ("zloop polling for %d msec", (int) timeout);
    
    return timeout * ZMQ_POLL_MSEC;
}
Example #2
0
void
s_service_dispatch (service_t *self)
{
    //  for each message, check regexp and dispatch if possible
    if (zlistx_size (self->offers)) {
        mlm_msg_t *message = (mlm_msg_t *) zlistx_first (self->queue);
        while (message) {
            offer_t *offer = (offer_t *) zlistx_first (self->offers);
            while (offer) {
                if (zrex_matches (offer->rex, mlm_msg_subject (message))) {
                    client_t *target = offer->client;
                    assert (target);
                    assert (!target->msg);
                    target->msg = (mlm_msg_t *) zlistx_detach (
                        self->queue, zlistx_cursor (self->queue));
                    engine_send_event (target, service_message_event);
                    zlistx_move_end (self->offers, zlistx_cursor (self->offers));
                    break;
                }
                offer = (offer_t *) zlistx_next (self->offers);
            }
            message = (mlm_msg_t *) zlistx_next (self->queue);
        }
    }
}
Example #3
0
static void
deregister_the_client (client_t *self)
{
    if (*self->address)
        zsys_info ("client address='%s' - de-registering", self->address);

    //  Cancel all stream subscriptions
    stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL);
    while (stream) {
        zsock_send (stream->actor, "sp", "CANCEL", self);
        stream = (stream_t *) zlistx_detach (self->readers, NULL);
    }
    //  Cancel all service offerings
    service_t *service = (service_t *) zhashx_first (self->server->services);
    while (service) {
        offer_t *offer = (offer_t *) zlistx_first (service->offers);
        while (offer) {
            if (offer->client == self)
                zlistx_delete (service->offers, zlistx_cursor (service->offers));
            offer = (offer_t *) zlistx_next (service->offers);
        }
        service = (service_t *) zhashx_next (self->server->services);
    }
    if (*self->address)
        zhashx_delete (self->server->clients, self->address);
    mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS);
}
Example #4
0
void
zloop_destroy (zloop_t **self_p)
{
    assert (self_p);
    if (*self_p) {
        zloop_t *self = *self_p;

        //  If we never started the loop, yet manipulated timers, we'll have
        //  a zombie list
        while (zlistx_first (self->zombies)) {
            //  Get timer_id back from pointer
            int timer_id = (byte *) zlistx_detach (self->zombies, NULL) - (byte *) NULL;
            s_timer_remove (self, timer_id);
        }
        zlistx_destroy (&self->zombies);
        zlistx_destroy (&self->readers);
        zlistx_destroy (&self->pollers);
        zlistx_destroy (&self->timers);
        zlistx_destroy (&self->tickets);
        free (self->pollset);
        free (self->readact);
        free (self->pollact);
        free (self);
        *self_p = NULL;
    }
}
Example #5
0
static void
deregister_the_client (client_t *self)
{
	// If the client never sent CONNECTION_OPEN then self->address was
	// never set, so avoid trying to dereference it.  Nothing needs to
    // be cleaned up.
    if (self->address) {
        if (*self->address)
            zsys_info ("client %u address='%s' - de-registering", self->unique_id, self->address);

        //  Cancel all stream subscriptions
        stream_t *stream = (stream_t *) zlistx_detach (self->readers, NULL);
        while (stream) {
            zsock_send (stream->actor, "sp", "CANCEL", self);
            stream = (stream_t *) zlistx_detach (self->readers, NULL);
        }
        //  Cancel all service offerings
        service_t *service = (service_t *) zhashx_first (self->server->services);
        while (service) {
            offer_t *offer = (offer_t *) zlistx_first (service->offers);
            while (offer) {
                if (offer->client == self)
                    zlistx_delete (service->offers, zlistx_cursor (service->offers));
                offer = (offer_t *) zlistx_next (service->offers);
            }
            service = (service_t *) zhashx_next (self->server->services);
        }
        if (*self->address)
            zhashx_delete (self->server->clients, self->address);
    }
    mlm_proto_set_status_code (self->message, MLM_PROTO_SUCCESS);
}
Example #6
0
File: zhashx.c Project: claws/czmq
int
zhashx_save (zhashx_t *self, const char *filename)
{
    assert (self);

    FILE *handle = fopen (filename, "w");
    if (!handle)
        return -1;              //  Failed to create file

    if (self->comments) {
        char *comment = (char *) zlistx_first (self->comments);
        while (comment) {
            fprintf (handle, "#   %s\n", comment);
            comment = (char *) zlistx_next (self->comments);
        }
        fprintf (handle, "\n");
    }
    uint index;
    size_t limit = primes [self->prime_index];
    for (index = 0; index < limit; index++) {
        item_t *item = self->items [index];
        while (item) {
            fprintf (handle, "%s=%s\n", (char *) item->key, (char *) item->value);
            item = item->next;
        }
    }
    fclose (handle);
    return 0;
}
Example #7
0
void
zloop_poller_end (zloop_t *self, zmq_pollitem_t *item)
{
    assert (self);

    s_poller_t *poller = (s_poller_t *) zlistx_first (self->pollers);
    while (poller) {
        bool match = false;
        if (item->socket) {
            if (item->socket == poller->item.socket)
                match = true;
        }
        else {
            if (item->fd == poller->item.fd)
                match = true;
        }
        if (match) {
            zlistx_delete (self->pollers, poller->list_handle);
            //  Force rebuild to avoid reading from freed poller
            self->need_rebuild = true;
        }
        poller = (s_poller_t *) zlistx_next (self->pollers);
    }
    if (self->verbose)
        zsys_debug ("zloop: cancel %s poller (%p, %d)",
                    item->socket ? zsys_sockname (zsock_type (item->socket)) : "FD",
                    item->socket, item->fd);
}
Example #8
0
static void
s_ztrie_destroy_children (ztrie_node_t *node)
{
    ztrie_node_t *child = (ztrie_node_t *) zlistx_first (node->children);
    while (child) {
        s_ztrie_destroy_children (child);
        s_ztrie_node_destroy (&child);
        child = (ztrie_node_t *) zlistx_next (node->children);
    }
}
Example #9
0
const char *
ziflist_first (ziflist_t *self)
{
    assert (self);
    interface_t *iface = (interface_t *) zlistx_first ((zlistx_t *) self);
    if (iface)
        return iface->name;
    else
        return NULL;
}
Example #10
0
static int
s_rebuild_pollset (zloop_t *self)
{
    free (self->pollset);
    free (self->readact);
    free (self->pollact);
    self->pollset = NULL;
    self->readact = NULL;
    self->pollact = NULL;

    self->poll_size = zlistx_size (self->readers) + zlistx_size (self->pollers);
    self->pollset = (zmq_pollitem_t *) zmalloc (self->poll_size * sizeof (zmq_pollitem_t));
    if (!self->pollset)
        return -1;

    self->readact = (s_reader_t *) zmalloc (self->poll_size * sizeof (s_reader_t));
    if (!self->readact)
        return -1;

    self->pollact = (s_poller_t *) zmalloc (self->poll_size * sizeof (s_poller_t));
    if (!self->pollact)
        return -1;

    s_reader_t *reader = (s_reader_t *) zlistx_first (self->readers);
    uint item_nbr = 0;
    while (reader) {
        zmq_pollitem_t poll_item = { zsock_resolve (reader->sock), 0, ZMQ_POLLIN };
        self->pollset [item_nbr] = poll_item;
        self->readact [item_nbr] = *reader;
        item_nbr++;
        reader = (s_reader_t *) zlistx_next (self->readers);
    }
    s_poller_t *poller = (s_poller_t *) zlistx_first (self->pollers);
    while (poller) {
        self->pollset [item_nbr] = poller->item;
        self->pollact [item_nbr] = *poller;
        item_nbr++;
        poller = (s_poller_t *) zlistx_next (self->pollers);
    }
    self->need_rebuild = false;
    return 0;
}
Example #11
0
static void
s_stream_engine_cancel (stream_engine_t *self, void *client)
{
    selector_t *selector = (selector_t *) zlistx_first (self->selectors);
    while (selector) {
        void *handle = zlistx_find (selector->clients, client);
        if (handle)
            zlistx_delete (selector->clients, handle);
        selector = (selector_t *) zlistx_next (self->selectors);
    }
}
Example #12
0
static void
s_ztrie_print_tree (ztrie_node_t *self)
{
    //  Print tree like structure
    s_ztrie_print_tree_line (self, true);
    ztrie_node_t *child = (ztrie_node_t *) zlistx_first (self->children);
    while (child) {
        s_ztrie_print_tree (child);
        child = (ztrie_node_t *) zlistx_next (self->children);
    }
}
Example #13
0
static struct curl_slist * zlistx_to_slist (zlistx_t *zlist) {
    struct curl_slist *slist = NULL;

    char *header = zlistx_first (zlist);

    while (header) {
        slist = curl_slist_append(slist, header);
        header = zlistx_next (zlist);
    }

    return slist;
}
Example #14
0
static ztrie_node_t *
s_ztrie_compare_token (ztrie_node_t *parent, char *token, int len)
{
    ztrie_node_t *child = (ztrie_node_t *) zlistx_first (parent->children);
    while (child) {
        if (child->token_len == len &&
            strncmp (child->token, token, MIN_LEN (child->token_len, len)) == 0)
            return child;
        child = (ztrie_node_t *) zlistx_next (parent->children);
    }
    return NULL;
}
Example #15
0
static void
s_timer_remove (zloop_t *self, int timer_id)
{
    s_timer_t *timer = (s_timer_t *) zlistx_first (self->timers);
    while (timer) {
        if (timer->timer_id == timer_id) {
            zlistx_delete (self->timers, timer->list_handle);
            break;
        }
        timer = (s_timer_t *) zlistx_next (self->timers);
    }
}
Example #16
0
void
ziflist_print (ziflist_t *self)
{
    interface_t *iface;
    for (iface = (interface_t *) zlistx_first ((zlistx_t *) self);
         iface != NULL;
         iface = (interface_t *) zlistx_next ((zlistx_t *) self)) {
        zsys_info (" - interface name : %s", iface->name);
        zsys_info (" - interface address : %s", iface->address);
        zsys_info (" - interface netmask : %s", iface->netmask);
        zsys_info (" - interface broadcast : %s", iface->broadcast);
    }
}
Example #17
0
void
zloop_reader_set_tolerant (zloop_t *self, zsock_t *sock)
{
    assert (self);
    assert (sock);

    s_reader_t *reader = (s_reader_t *) zlistx_first (self->readers);
    while (reader) {
        if (reader->sock == sock)
            reader->tolerant = true;
        reader = (s_reader_t *) zlistx_next (self->readers);
    }
}
Example #18
0
static int
s_stream_engine_handle_message (stream_engine_t *self)
{
    void *sender;
    mlm_msg_t *msg;
    zsock_brecv (self->msgpipe, "pp", &sender, &msg);

    selector_t *selector = (selector_t *) zlistx_first (self->selectors);
    while (selector) {
        if (zrex_matches (selector->rex, mlm_msg_subject (msg))) {
            void *client = zlistx_first (selector->clients);
            while (client) {
                if (client != sender)
                    zsock_bsend (self->msgpipe, "pp", client, mlm_msg_link (msg));
                client = zlistx_next (selector->clients);
            }
        }
        selector = (selector_t *) zlistx_next (self->selectors);
    }
    mlm_msg_unlink (&msg);
    return 0;
}
Example #19
0
static void
s_stream_engine_compile (stream_engine_t *self, void *client, const char *pattern)
{
    selector_t *selector = (selector_t *) zlistx_first (self->selectors);
    while (selector) {
        if (streq (selector->pattern, pattern)) {
            void *compare = zlistx_first (selector->clients);
            while (compare) {
                if (compare == client)
                    break;      //  Duplicate client, ignore
               compare = zlistx_next (selector->clients);
            }
            //  Add client, if it's new
            if (!compare)
                zlistx_add_end (selector->clients, client);
            break;
        }
        selector = (selector_t *) zlistx_next (self->selectors);
    }
    //  Add selector, if it's new
    if (!selector)
        zlistx_add_end (self->selectors, s_selector_new (client, pattern));
}
Example #20
0
void
zloop_reader_end (zloop_t *self, zsock_t *sock)
{
    assert (self);
    assert (sock);

    s_reader_t *reader = (s_reader_t *) zlistx_first (self->readers);
    while (reader) {
        if (reader->sock == sock) {
            zlistx_delete (self->readers, reader->list_handle);
            self->need_rebuild = true;
        }
        reader = (s_reader_t *) zlistx_next (self->readers);
    }
    if (self->verbose)
        zsys_debug ("zloop: cancel %s reader", zsock_type_str (sock));
}
Example #21
0
static ztrie_node_t *
s_ztrie_matches_token (ztrie_node_t *parent, char *token, int len)
{
    char firstbyte = *token;
    ztrie_node_t *child = (ztrie_node_t *) zlistx_first (parent->children);
    while (child) {
        if (child->token_type == NODE_TYPE_STRING) {
            if (firstbyte == *child->token  //  This achieves a small performance boost
                && child->token_len == len
                && strncmp (child->token, token, MIN_LEN (child->token_len, len)) == 0)
                    return child;
        }
        else
        if (child->token_type == NODE_TYPE_ASTERISK) {
            child->asterisk_match = strdup (token);
            return child;
        }
        else {
            //  Need to copy token as zrex_matches expects '\0' terminated string
            char *token_term = s_strndup (token, len);
            if (zrex_matches (child->regex, token_term)) {
                if (child->token_type == NODE_TYPE_PARAM) {
                    //  One hit means no capturing group was defined
                    //  More than one hit indicates that at least on capturing group.
                    //  In this case only the values of the capturing groups are considered.
                    if (zrex_hits (child->regex) == 1)
                        s_ztrie_node_update_param (child, 1, zrex_hit (child->regex, 0));
                    else
                    if (zrex_hits (child->regex) > 1) {
                        int index;
                        for (index = 1; index < zrex_hits (child->regex); index++)
                            s_ztrie_node_update_param (child, index, zrex_hit (child->regex, index));
                    }
                }
                free (token_term);
                return child;
            }
            free (token_term);
        }
        child = (ztrie_node_t *) zlistx_next (parent->children);
    }
    return NULL;
}
Example #22
0
static bool
s_service_dispatch_message (service_t *self, mlm_msg_t *message)
{
    offer_t *offer = (offer_t *) zlistx_first (self->offers);
    while (offer) {
        if (zrex_matches (offer->rex, mlm_msg_subject (message))) {
            client_t *target = offer->client;
            assert (target);
            assert (!target->msg);
            target->msg = message;
            engine_send_event (target, service_message_event);
            zlistx_move_end (self->offers, zlistx_cursor (self->offers));
            return true;
        }
        offer = (offer_t *) zlistx_next (self->offers);
    }

    return false;
}
Example #23
0
static ztrie_node_t *
s_ztrie_node_new (ztrie_node_t *parent, char *token, int token_len, zlistx_t *param_keys, int token_type)
{
    ztrie_node_t *self = (ztrie_node_t *) zmalloc (sizeof (ztrie_node_t));
    assert (self);

    //  Initialize properties
    self->token = s_strndup (token, token_len);
    self->token_type = token_type;
    self->token_len = token_len;
    self->endpoint = false;
    self->parameter_count = 0;
    self->parameter_names = NULL;
    self->parameter_values = NULL;
    if (param_keys && zlistx_size (param_keys) > 0) {
        self->parameter_count = zlistx_size (param_keys);
        self->parameter_names = (char **) malloc (sizeof (char *) * self->parameter_count);
        self->parameter_values = (char **) malloc (sizeof (char *) * self->parameter_count);
        char *key = (char *) zlistx_first (param_keys);
        int index;
        for (index = 0; index < zlistx_size (param_keys); index++) {
            self->parameter_names [index] = key;
            self->parameter_values [index] = NULL;
            key = (char *) zlistx_next (param_keys);
        }
    }
    if (self->token_type == NODE_TYPE_REGEX || self->token_type == NODE_TYPE_PARAM)
        self->regex = zrex_new (self->token);
    self->data = NULL;
    //  Initialize relationships
    self->parent = parent;
    if (self->parent) {
        zlistx_add_end (self->parent->children, self);
        //  Sort regexes to the end to avoid conlficts
        zlistx_sort (self->parent->children);
    }
    size_t parent_path_len = self->parent? self->parent->path_len: 0;
    self->path_len = parent_path_len + strlen (self->token) + 1; // +1 path delimiter
    self->children = zlistx_new ();
    zlistx_set_comparator (self->children, s_ztrie_node_compare);

    return self;
}
Example #24
0
static void twps_destroy(twps_server_t **self_p) {
    assert(self_p);
    if (*self_p) {
        twps_server_t *self = *self_p;
        if (self->verbose) {
            zsys_info("twps server: shutdowning application server");
        }
        zactor_t *t_printer = zlistx_first(self->ticket_printers);
        while (t_printer != NULL) {
            zactor_destroy(&t_printer);
            t_printer = zlistx_next(self->ticket_printers);
        }
        zlistx_destroy(&self->ticket_printers);
        zsock_destroy(&self->printer_store_sub);
        zactor_destroy(&self->ticket_store);
        zactor_destroy(&self->printer_store);
        zactor_destroy(&self->client_proxy);
        free(self);
        *self_p = NULL;
    }
}
Example #25
0
void
zloop_poller_set_tolerant (zloop_t *self, zmq_pollitem_t *item)
{
    assert (self);

    //  Find matching poller(s) and mark as tolerant
    s_poller_t *poller = (s_poller_t *) zlistx_first (self->pollers);
    while (poller) {
        bool match = false;
        if (item->socket) {
            if (item->socket == poller->item.socket)
                match = true;
        }
        else {
            if (item->fd == poller->item.fd)
                match = true;
        }
        if (match)
            poller->tolerant = true;
        
        poller = (s_poller_t *) zlistx_next (self->pollers);
    }
}
Example #26
0
static void
server_accept (server_t *self, const char *key, const char *value)
{
    tuple_t *tuple = (tuple_t *) zhashx_lookup (self->tuples, key);
    if (tuple && streq (tuple->value, value))
        return;                 //  Duplicate tuple, do nothing

    //  Create new tuple
    tuple = (tuple_t *) zmalloc (sizeof (tuple_t));
    assert (tuple);
    tuple->container = self->tuples;
    tuple->key = strdup (key);
    tuple->value = strdup (value);

    //  Store new tuple
    zhashx_update (tuple->container, key, tuple);
    zhashx_freefn (tuple->container, key, tuple_free);

    //  Deliver to calling application
    zstr_sendx (self->pipe, "DELIVER", key, value, NULL);

    //  Hold in server context so we can broadcast to all clients
    self->cur_tuple = tuple;
    engine_broadcast_event (self, NULL, forward_event);

    //  Copy new tuple announcement to all remotes
    zgossip_msg_t *gossip = zgossip_msg_new ();
    zgossip_msg_set_id (gossip, ZGOSSIP_MSG_PUBLISH);
    zsock_t *remote = (zsock_t *) zlistx_first (self->remotes);
    while (remote) {
        zgossip_msg_set_key (gossip, tuple->key);
        zgossip_msg_set_value (gossip, tuple->value);
        zgossip_msg_send (gossip, remote);
        remote = (zsock_t *) zlistx_next (self->remotes);
    }
    zgossip_msg_destroy (&gossip);
}
Example #27
0
///
//  Return the item at the head of list. If the list is empty, returns NULL.
//  Leaves cursor pointing at the head item, or NULL if the list is empty.  
void * QZlistx::first ()
{
    void * rv = zlistx_first (self);
    return rv;
}
Example #28
0
void
zcertstore_test (bool verbose)
{
    printf (" * zcertstore: ");
    if (verbose)
        printf ("\n");

    //  @selftest

    const char *SELFTEST_DIR_RW = "src/selftest-rw";

    const char *testbasedir  = ".test_zcertstore";
    const char *testfile = "mycert.txt";
    char *basedirpath = NULL;   // subdir in a test, under SELFTEST_DIR_RW
    char *filepath = NULL;      // pathname to testfile in a test, in dirpath

    basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir);
    assert (basedirpath);
    filepath = zsys_sprintf ("%s/%s", basedirpath, testfile);
    assert (filepath);

    // Make sure old aborted tests do not hinder us
    zdir_t *dir = zdir_new (basedirpath, NULL);
    if (dir) {
        zdir_remove (dir, true);
        zdir_destroy (&dir);
    }
    zsys_file_delete (filepath);
    zsys_dir_delete  (basedirpath);

    //  Create temporary directory for test files
    zsys_dir_create (basedirpath);

    //  Load certificate store from disk; it will be empty
    zcertstore_t *certstore = zcertstore_new (basedirpath);
    assert (certstore);

    //  Create a single new certificate and save to disk
    zcert_t *cert = zcert_new ();
    assert (cert);
    char *client_key = strdup (zcert_public_txt (cert));
    assert (client_key);
    zcert_set_meta (cert, "name", "John Doe");
    zcert_save (cert, filepath);
    zcert_destroy (&cert);

    //  Check that certificate store refreshes as expected
    cert = zcertstore_lookup (certstore, client_key);
    assert (cert);
    assert (streq (zcert_meta (cert, "name"), "John Doe"));

#ifdef CZMQ_BUILD_DRAFT_API
    //  DRAFT-API: Security
    // Iterate through certs
    zlistx_t *certs = zcertstore_certs(certstore);
    cert = (zcert_t *) zlistx_first(certs);
    int cert_count = 0;
    while (cert) {
        assert (streq (zcert_meta (cert, "name"), "John Doe"));
        cert = (zcert_t *) zlistx_next(certs);
        cert_count++;
    }
    assert(cert_count==1);
    zlistx_destroy(&certs);
#endif

    //  Test custom loader
    test_loader_state *state = (test_loader_state *) zmalloc (sizeof (test_loader_state));
    state->index = 0;
    zcertstore_set_loader (certstore, s_test_loader, s_test_destructor, (void *)state);
#if (ZMQ_VERSION_MAJOR >= 4)
    cert = zcertstore_lookup (certstore, client_key);
    assert (cert == NULL);
    cert = zcertstore_lookup (certstore, "abcdefghijklmnopqrstuvwxyzabcdefghijklmn");
    assert (cert);
#endif

    freen (client_key);

    if (verbose)
        zcertstore_print (certstore);
    zcertstore_destroy (&certstore);

    //  Delete all test files
    dir = zdir_new (basedirpath, NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);

    zstr_free (&basedirpath);
    zstr_free (&filepath);

#if defined (__WINDOWS__)
    zsys_shutdown();
#endif
    //  @end
    printf ("OK\n");
}
Example #29
0
void
zlistx_test (bool verbose)
{
    printf (" * zlistx: ");

    //  @selftest
    zlistx_t *list = zlistx_new ();
    assert (list);
    assert (zlistx_size (list) == 0);

    //  Test operations on an empty list
    assert (zlistx_first (list) == NULL);
    assert (zlistx_last (list) == NULL);
    assert (zlistx_next (list) == NULL);
    assert (zlistx_prev (list) == NULL);
    assert (zlistx_find (list, "hello") == NULL);
    assert (zlistx_delete (list, NULL) == -1);
    assert (zlistx_detach (list, NULL) == NULL);
    assert (zlistx_delete (list, NULL) == -1);
    assert (zlistx_detach (list, NULL) == NULL);
    zlistx_purge (list);
    zlistx_sort (list);

    //  Use item handlers
    zlistx_set_destructor (list, (zlistx_destructor_fn *) zstr_free);
    zlistx_set_duplicator (list, (zlistx_duplicator_fn *) strdup);
    zlistx_set_comparator (list, (zlistx_comparator_fn *) strcmp);

    //  Try simple insert/sort/delete/next
    assert (zlistx_next (list) == NULL);
    zlistx_add_end (list, "world");
    assert (streq ((char *) zlistx_next (list), "world"));
    zlistx_add_end (list, "hello");
    assert (streq ((char *) zlistx_prev (list), "hello"));
    zlistx_sort (list);
    assert (zlistx_size (list) == 2);
    void *handle = zlistx_find (list, "hello");
    char *item1 = (char *) zlistx_item (list);
    char *item2 = (char *) zlistx_handle_item (handle);
    assert (item1 == item2);
    assert (streq (item1, "hello"));
    zlistx_delete (list, handle);
    assert (zlistx_size (list) == 1);
    char *string = (char *) zlistx_detach (list, NULL);
    assert (streq (string, "world"));
    free (string);
    assert (zlistx_size (list) == 0);

    //  Check next/back work
    //  Now populate the list with items
    zlistx_add_start (list, "five");
    zlistx_add_end   (list, "six");
    zlistx_add_start (list, "four");
    zlistx_add_end   (list, "seven");
    zlistx_add_start (list, "three");
    zlistx_add_end   (list, "eight");
    zlistx_add_start (list, "two");
    zlistx_add_end   (list, "nine");
    zlistx_add_start (list, "one");
    zlistx_add_end   (list, "ten");

    //  Test our navigation skills
    assert (zlistx_size (list) == 10);
    assert (streq ((char *) zlistx_last (list), "ten"));
    assert (streq ((char *) zlistx_prev (list), "nine"));
    assert (streq ((char *) zlistx_prev (list), "eight"));
    assert (streq ((char *) zlistx_prev (list), "seven"));
    assert (streq ((char *) zlistx_prev (list), "six"));
    assert (streq ((char *) zlistx_prev (list), "five"));
    assert (streq ((char *) zlistx_first (list), "one"));
    assert (streq ((char *) zlistx_next (list), "two"));
    assert (streq ((char *) zlistx_next (list), "three"));
    assert (streq ((char *) zlistx_next (list), "four"));

    //  Sort by alphabetical order
    zlistx_sort (list);
    assert (streq ((char *) zlistx_first (list), "eight"));
    assert (streq ((char *) zlistx_last (list), "two"));

    //  Moving items around
    handle = zlistx_find (list, "six");
    zlistx_move_start (list, handle);
    assert (streq ((char *) zlistx_first (list), "six"));
    zlistx_move_end (list, handle);
    assert (streq ((char *) zlistx_last (list), "six"));
    zlistx_sort (list);
    assert (streq ((char *) zlistx_last (list), "two"));

    //  Copying a list
    zlistx_t *copy = zlistx_dup (list);
    assert (copy);
    assert (zlistx_size (copy) == 10);
    assert (streq ((char *) zlistx_first (copy), "eight"));
    assert (streq ((char *) zlistx_last (copy), "two"));
    zlistx_destroy (&copy);

    //  Delete items while iterating
    string = (char *) zlistx_first (list);
    assert (streq (string, "eight"));
    string = (char *) zlistx_next (list);
    assert (streq (string, "five"));
    zlistx_delete (list, zlistx_cursor (list));
    string = (char *) zlistx_next (list);
    assert (streq (string, "four"));

    zlistx_purge (list);
    zlistx_destroy (&list);
    //  @end

    printf ("OK\n");
}
Example #30
0
int
zloop_start (zloop_t *self)
{
    assert (self);
    int rc = 0;

    //  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 (self));
        if (rc == -1 || zsys_interrupted) {
            if (self->verbose)
                zsys_debug ("zloop: interrupted");
            rc = 0;
            break;              //  Context has been shut down
        }
        
        //  Handle any timers that have now expired
        int64_t time_now = zclock_mono ();
        s_timer_t *timer = (s_timer_t *) zlistx_first (self->timers);
        while (timer) {
            if (time_now >= timer->when) {
                if (self->verbose)
                    zsys_debug ("zloop: call timer handler id=%d", 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)
                    zlistx_delete (self->timers, timer->list_handle);
                else
                    timer->when += timer->delay;
            }
            timer = (s_timer_t *) zlistx_next (self->timers);
        }
        
        //  Handle any tickets that have now expired
        s_ticket_t *ticket = (s_ticket_t *) zlistx_first (self->tickets);
        while (ticket && time_now >= ticket->when) {
            if (self->verbose)
                zsys_debug ("zloop: call ticket handler");
            rc = ticket->handler (self, 0, ticket->arg);
            if (rc == -1)
                break;      //  Timer handler signaled break
            zlistx_delete (self->tickets, ticket->list_handle);
            ticket = (s_ticket_t *) zlistx_next (self->tickets);
        }
        
        //  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 ?
                                      zsys_sockname (zsock_type (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 ?
                                    zsys_sockname (zsock_type (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 (zlistx_first (self->zombies)) {
            //  Get timer_id back from pointer
            int timer_id = (byte *) zlistx_detach (self->zombies, NULL) - (byte *) NULL;
            s_timer_remove (self, timer_id);
        }
        if (rc == -1)
            break;
    }
    self->terminated = true;
    return rc;
}