static void process_the_patch (client_t *self, server_t *server) { char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); char *filename = fmq_msg_filename (server->reply); // Filenames from server must start with slash, which we skip assert (*filename == '/'); filename++; if (fmq_msg_operation (server->reply) == FMQ_MSG_FILE_CREATE) { if (server->file == NULL) { server->file = fmq_file_new (inbox, filename); if (fmq_file_output (server->file)) { // File not writeable, skip patch fmq_file_destroy (&server->file); return; } } // Try to write, ignore errors in this version zframe_t *frame = fmq_msg_chunk (server->reply); fmq_chunk_t *chunk = fmq_chunk_new (zframe_data (frame), zframe_size (frame)); if (fmq_chunk_size (chunk) > 0) { fmq_file_write (server->file, chunk, fmq_msg_offset (server->reply)); server->credit -= fmq_chunk_size (chunk); } else { // Zero-sized chunk means end of file, so report back to caller zstr_sendm (self->pipe, "DELIVER"); zstr_sendm (self->pipe, filename); zstr_sendf (self->pipe, "%s/%s", inbox, filename); fmq_file_destroy (&server->file); } fmq_chunk_destroy (&chunk); } else if (fmq_msg_operation (server->reply) == FMQ_MSG_FILE_DELETE) { zclock_log ("I: delete %s/%s", inbox, filename); fmq_file_t *file = fmq_file_new (inbox, filename); fmq_file_remove (file); fmq_file_destroy (&file); } }
static void process_the_patch (client_t *self) { char *inbox = fmq_config_resolve (self->config, "client/inbox", ".inbox"); char *filename = fmq_msg_filename (self->reply); if (fmq_msg_operation (self->reply) == FMQ_MSG_FILE_CREATE) { if (self->file == NULL) { zclock_log ("I: create %s", filename); self->file = fmq_file_new (inbox, filename); if (fmq_file_output (self->file)) { // File not writeable, skip patch fmq_file_destroy (&self->file); return; } } // Try to write, ignore errors in this version zframe_t *frame = fmq_msg_chunk (self->reply); fmq_chunk_t *chunk = fmq_chunk_new (zframe_data (frame), zframe_size (frame)); if (fmq_chunk_size (chunk) > 0) { fmq_file_write (self->file, chunk, fmq_msg_offset (self->reply)); self->credit -= fmq_chunk_size (chunk); } else // Zero-sized chunk means end of file fmq_file_destroy (&self->file); fmq_chunk_destroy (&chunk); } else if (fmq_msg_operation (self->reply) == FMQ_MSG_FILE_DELETE) { zclock_log ("I: delete %s", filename); fmq_file_t *file = fmq_file_new (inbox, filename); fmq_file_remove (file); fmq_file_destroy (&file); } }
static void get_next_patch_for_client (server_t *self, client_t *client) { // Get next patch for client if we're not doing one already if (client->patch == NULL) client->patch = (fmq_patch_t *) zlist_pop (client->patches); if (client->patch == NULL) { client->next_event = finished_event; return; } // Get virtual filename from patch fmq_msg_set_filename (client->reply, fmq_patch_virtual (client->patch)); // We can process a delete patch right away if (fmq_patch_op (client->patch) == patch_delete) { fmq_msg_set_sequence (client->reply, client->sequence++); fmq_msg_set_operation (client->reply, FMQ_MSG_FILE_DELETE); client->next_event = send_delete_event; // No reliability in this version, assume patch delivered safely fmq_patch_destroy (&client->patch); } else if (fmq_patch_op (client->patch) == patch_create) { // Create patch refers to file, open that for input if needed if (client->file == NULL) { client->file = fmq_file_dup (fmq_patch_file (client->patch)); if (fmq_file_input (client->file)) { // File no longer available, skip it fmq_patch_destroy (&client->patch); fmq_file_destroy (&client->file); client->next_event = next_patch_event; return; } client->offset = 0; } // Get next chunk for file fmq_chunk_t *chunk = fmq_file_read (client->file, CHUNK_SIZE, client->offset); assert (chunk); // Check if we have the credit to send chunk if (fmq_chunk_size (chunk) <= client->credit) { fmq_msg_set_sequence (client->reply, client->sequence++); fmq_msg_set_operation (client->reply, FMQ_MSG_FILE_CREATE); fmq_msg_set_offset (client->reply, client->offset); fmq_msg_set_chunk (client->reply, zframe_new ( fmq_chunk_data (chunk), fmq_chunk_size (chunk))); client->offset += fmq_chunk_size (chunk); client->credit -= fmq_chunk_size (chunk); client->next_event = send_chunk_event; // Zero-sized chunk means end of file if (fmq_chunk_size (chunk) == 0) { fmq_file_destroy (&client->file); fmq_patch_destroy (&client->patch); } } else client->next_event = no_credit_event; fmq_chunk_destroy (&chunk); } }
static int agent_recv_from_api (agent_t *self) { // Get the whole message off the pipe in one go zmsg_t *request = zmsg_recv (self->pipe); char *command = zmsg_popstr (request); if (!command) return -1; // Interrupted if (streq (command, "WHISPER")) { // Get peer to send message to char *identity = zmsg_popstr (request); zre_peer_t *peer = (zre_peer_t *) zhash_lookup (self->peers, identity); // Send frame on out to peer's mailbox, drop message // if peer doesn't exist (may have been destroyed) if (peer) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_WHISPER); zre_msg_content_set (msg, zmsg_pop (request)); zre_peer_send (peer, &msg); } free (identity); } else if (streq (command, "SHOUT")) { // Get group to send message to char *name = zmsg_popstr (request); zre_group_t *group = (zre_group_t *) zhash_lookup (self->peer_groups, name); if (group) { zre_msg_t *msg = zre_msg_new (ZRE_MSG_SHOUT); zre_msg_group_set (msg, name); zre_msg_content_set (msg, zmsg_pop (request)); zre_group_send (group, &msg); } free (name); } else if (streq (command, "JOIN")) { char *name = zmsg_popstr (request); zre_group_t *group = (zre_group_t *) zhash_lookup (self->own_groups, name); if (!group) { // Only send if we're not already in group group = zre_group_new (name, self->own_groups); zre_msg_t *msg = zre_msg_new (ZRE_MSG_JOIN); zre_msg_group_set (msg, name); // Update status before sending command zre_msg_status_set (msg, ++(self->status)); zhash_foreach (self->peers, s_peer_send, msg); zre_msg_destroy (&msg); zre_log_info (self->log, ZRE_LOG_MSG_EVENT_JOIN, NULL, name); } free (name); } else if (streq (command, "LEAVE")) { char *name = zmsg_popstr (request); zre_group_t *group = (zre_group_t *) zhash_lookup (self->own_groups, name); if (group) { // Only send if we are actually in group zre_msg_t *msg = zre_msg_new (ZRE_MSG_LEAVE); zre_msg_group_set (msg, name); // Update status before sending command zre_msg_status_set (msg, ++(self->status)); zhash_foreach (self->peers, s_peer_send, msg); zre_msg_destroy (&msg); zhash_delete (self->own_groups, name); zre_log_info (self->log, ZRE_LOG_MSG_EVENT_LEAVE, NULL, name); } free (name); } else if (streq (command, "SET")) { char *name = zmsg_popstr (request); char *value = zmsg_popstr (request); zhash_update (self->headers, name, value); free (name); free (value); } else if (streq (command, "PUBLISH")) { char *logical = zmsg_popstr (request); char *physical = zmsg_popstr (request); // Virtual filename must start with slash assert (logical [0] == '/'); // We create symbolic link pointing to real file char *symlink = malloc (strlen (logical) + 3); sprintf (symlink, "%s.ln", logical + 1); fmq_file_t *file = fmq_file_new (self->fmq_outbox, symlink); int rc = fmq_file_output (file); assert (rc == 0); fprintf (fmq_file_handle (file), "%s\n", physical); fmq_file_destroy (&file); free (symlink); free (logical); free (physical); } else if (streq (command, "RETRACT")) { char *logical = zmsg_popstr (request); // Logical filename must start with slash assert (logical [0] == '/'); // We create symbolic link pointing to real file char *symlink = malloc (strlen (logical) + 3); sprintf (symlink, "%s.ln", logical + 1); fmq_file_t *file = fmq_file_new (self->fmq_outbox, symlink); fmq_file_remove (file); free (symlink); free (logical); } free (command); zmsg_destroy (&request); return 0; }