// Apply configuration tree: // * apply client configuration // * print any echo items in top-level sections // * apply sections that match methods static void client_apply_config (client_t *self) { // Apply echo commands and class methods fmq_config_t *section = fmq_config_child (self->config); while (section) { fmq_config_t *entry = fmq_config_child (section); while (entry) { if (streq (fmq_config_name (entry), "echo")) zclock_log (fmq_config_value (entry)); entry = fmq_config_next (entry); } if (streq (fmq_config_name (section), "subscribe")) { char *path = fmq_config_resolve (section, "path", "?"); // Store subscription along with any previous ones // Check we don't already have a subscription for this path self->sub = (sub_t *) zlist_first (self->subs); while (self->sub) { if (streq (path, self->sub->path)) return; self->sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, store it for later replay char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); self->sub = sub_new (self, inbox, path); zlist_append (self->subs, self->sub); } else if (streq (fmq_config_name (section), "set_inbox")) { char *path = fmq_config_resolve (section, "path", "?"); fmq_config_path_set (self->config, "client/inbox", path); } else if (streq (fmq_config_name (section), "set_resync")) { long enabled = atoi (fmq_config_resolve (section, "enabled", "")); // Request resynchronization from server fmq_config_path_set (self->config, "client/resync", enabled? "1" :"0"); } section = fmq_config_next (section); } client_config_self (self); }
static void mount_sub_store (mount_t *self, client_t *client, fmq_msg_t *request) { assert (self); assert (self->subs); // Store subscription along with any previous ones // Coalesce subscriptions that are on same path char *path = fmq_msg_path (request); sub_t *sub = (sub_t *) zlist_first (self->subs); while (sub) { if (client == sub->client) { // If old subscription is superset/same as new, ignore new if (strncmp (path, sub->path, strlen (sub->path)) == 0) return; else // If new subscription is superset of old one, remove old if (strncmp (sub->path, path, strlen (path)) == 0) { zlist_remove (self->subs, sub); sub_destroy (&sub); sub = (sub_t *) zlist_first (self->subs); } else sub = (sub_t *) zlist_next (self->subs); } else sub = (sub_t *) zlist_next (self->subs); } // New subscription for this client, append to our list sub = sub_new (client, path, fmq_msg_cache (request)); zlist_append (self->subs, sub); // If client requested resync, send full mount contents now if (fmq_msg_options_number (client->request, "RESYNC", 0) == 1) { zlist_t *patches = zdir_resync (self->dir, self->alias); while (zlist_size (patches)) { zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); sub_patch_add (sub, patch); zdir_patch_destroy (&patch); } zlist_destroy (&patches); } }
static void client_apply_config (client_t *self) { // Get standard client configuration self->heartbeat = atoi ( fmq_config_resolve (self->config, "client/heartbeat", "1")) * 1000; // Apply echo commands and class methods fmq_config_t *section = fmq_config_child (self->config); while (section) { fmq_config_t *entry = fmq_config_child (section); while (entry) { if (streq (fmq_config_name (entry), "echo")) puts (fmq_config_value (entry)); entry = fmq_config_next (entry); } if (streq (fmq_config_name (section), "subscribe")) { char *path = fmq_config_resolve (section, "path", "?"); // Store subscription along with any previous ones // Check we don't already have a subscription for this path sub_t *sub = (sub_t *) zlist_first (self->subs); while (sub) { if (streq (path, sub->path)) return; sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, so store it for later replay sub = sub_new (self, path); zlist_append (self->subs, sub); // If we're connected, then also send to server if (self->connected) { fmq_msg_path_set (self->request, path); self->next_event = subscribe_event; } } section = fmq_config_next (section); } }
static void control_message (client_t *self) { zmsg_t *msg = zmsg_recv (self->pipe); char *method = zmsg_popstr (msg); if (streq (method, "SUBSCRIBE")) { char *path = zmsg_popstr (msg); // Store subscription along with any previous ones // Check we don't already have a subscription for this path sub_t *sub = (sub_t *) zlist_first (self->subs); while (sub) { if (streq (path, sub->path)) return; sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, so store it for later replay sub = sub_new (self, path); zlist_append (self->subs, sub); // If we're connected, then also send to server if (self->connected) { fmq_msg_path_set (self->request, path); self->next_event = subscribe_event; } free (path); } else if (streq (method, "CONNECT")) { char *endpoint = zmsg_popstr (msg); client_restart (self, endpoint); free (endpoint); } else if (streq (method, "CONFIG")) { char *config_file = zmsg_popstr (msg); fmq_config_destroy (&self->config); self->config = fmq_config_load (config_file); if (self->config) client_apply_config (self); else { printf ("E: cannot load config file '%s'\n", config_file); self->config = fmq_config_new ("root", NULL); } free (config_file); } else if (streq (method, "SETOPTION")) { char *path = zmsg_popstr (msg); char *value = zmsg_popstr (msg); fmq_config_path_set (self->config, path, value); free (path); free (value); } else if (streq (method, "STOP")) { zstr_send (self->pipe, "OK"); self->stopped = true; } free (method); zmsg_destroy (&msg); if (self->next_event) client_execute (self, self->next_event); }
// Process message from pipe static void client_control_message (client_t *self) { zmsg_t *msg = zmsg_recv (self->pipe); char *method = zmsg_popstr (msg); if (streq (method, "SUBSCRIBE")) { char *path = zmsg_popstr (msg); // Store subscription along with any previous ones // Check we don't already have a subscription for this path self->sub = (sub_t *) zlist_first (self->subs); while (self->sub) { if (streq (path, self->sub->path)) return; self->sub = (sub_t *) zlist_next (self->subs); } // Subscription path must start with '/' // We'll do better error handling later assert (*path == '/'); // New subscription, store it for later replay char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); self->sub = sub_new (self, inbox, path); zlist_append (self->subs, self->sub); free (path); } else if (streq (method, "SET INBOX")) { char *path = zmsg_popstr (msg); fmq_config_path_set (self->config, "client/inbox", path); free (path); } else if (streq (method, "SET RESYNC")) { char *enabled_string = zmsg_popstr (msg); long enabled = atoi (enabled_string); free (enabled_string); // Request resynchronization from server fmq_config_path_set (self->config, "client/resync", enabled? "1" :"0"); } else if (streq (method, "CONFIG")) { char *config_file = zmsg_popstr (msg); fmq_config_destroy (&self->config); self->config = fmq_config_load (config_file); if (self->config) client_apply_config (self); else { printf ("E: cannot load config file '%s'\n", config_file); self->config = fmq_config_new ("root", NULL); } free (config_file); } else if (streq (method, "SETOPTION")) { char *path = zmsg_popstr (msg); char *value = zmsg_popstr (msg); fmq_config_path_set (self->config, path, value); client_config_self (self); free (path); free (value); } else if (streq (method, "STOP")) { zstr_send (self->pipe, "OK"); self->stopped = true; } else if (streq (method, "CONNECT")) { char *endpoint = zmsg_popstr (msg); if (self->nbr_servers < MAX_SERVERS) { server_t *server = server_new (self->ctx, endpoint); self->servers [self->nbr_servers++] = server; self->dirty = true; client_server_execute (self, server, initialize_event); } else printf ("E: too many server connections (max %d)\n", MAX_SERVERS); free (endpoint); } free (method); zmsg_destroy (&msg); }
void stock_subscride (stock_t stock, user_t user, Callback cb) { sub_t sub = sub_new(user, cb); stock->subs->sub[stock->subs->count] = sub; stock->subs->count++; }