Beispiel #1
0
char *
zfile_digest (zfile_t *self)
{
    if (!self->digest) {
        if (zfile_input (self) == -1)
            return NULL;            //  Problem reading file

        //  Now calculate hash for file data, chunk by chunk
        size_t blocksz = 65535;
        off_t offset = 0;

        self->digest = zdigest_new ();
        zchunk_t *chunk = zfile_read (self, blocksz, offset);
        while (zchunk_size (chunk)) {
            zdigest_update (self->digest,
                zchunk_data (chunk), zchunk_size (chunk));
            zchunk_destroy (&chunk);
            offset += blocksz;
            chunk = zfile_read (self, blocksz, offset);
        }
        zchunk_destroy (&chunk);
        zfile_close (self);
    }
    return zdigest_string (self->digest);
}
Beispiel #2
0
const char *
zfile_digest (zfile_t *self)
{
    assert (self);
    if (!self->digest) {
        if (zfile_input (self) == -1)
            return NULL;            //  Problem reading file

        //  Now calculate hash for file data, chunk by chunk
        size_t blocksz = 65535;
        off_t offset = 0;

        self->digest = zdigest_new ();
        if (!self->digest)
            return NULL;
        zchunk_t *chunk = zfile_read (self, blocksz, offset);
        while (zchunk_size (chunk)) {
            zdigest_update (self->digest,
                            zchunk_data (chunk), zchunk_size (chunk));
            zchunk_destroy (&chunk);

            //  off_t is defined as long (32 bit on Windows, 64 bit otherwise)
            //  This guards against overflow in both contexts.
            if (blocksz > LONG_MAX - offset)
                return NULL;

            offset += (off_t) blocksz;
            chunk = zfile_read (self, blocksz, offset);
        }
        zchunk_destroy (&chunk);
        fclose (self->handle);
        self->handle = 0;
    }
    return zdigest_string (self->digest);
}
Beispiel #3
0
static void
server_process_cluster_command (
    server_t *self,
    const char *peer_id,
    const char *peer_name,
    zmsg_t *msg,
    bool unicast)
{
    char *request = zmsg_popstr (msg);
    char *pipename = zmsg_popstr (msg);
    zsys_info ("peer=%s command=%s pipe=%s unicast=%d",
                peer_name, request, pipename? pipename: "-", unicast);

    //  Lookup or create pipe
    //  TODO: remote pipes need cleaning up with some timeout
    pipe_t *pipe = NULL;
    if (pipename) {
        pipe = (pipe_t *) zhash_lookup (self->pipes, pipename);
        if (!pipe)
            pipe = pipe_new (self, pipename);
    }
    if (pipe && streq (request, "HAVE WRITER"))
        pipe_attach_remote_writer (pipe, peer_id, unicast);
    else
    if (pipe && streq (request, "HAVE READER"))
        pipe_attach_remote_reader (pipe, peer_id, unicast);
    else
    if (pipe && streq (request, "DATA")) {
        //  TODO encode these commands as proper protocol
        zframe_t *frame = zmsg_pop (msg);
        zchunk_t *chunk = zchunk_new (zframe_data (frame), zframe_size (frame));
        if (pipe->writer == REMOTE_NODE && pipe->reader) {
            zsys_info ("send %d bytes to pipe", (int) zchunk_size (chunk));
            pipe_send_data (pipe, &chunk); 
        }
        else
            zsys_info ("discard %d bytes, unroutable", (int) zchunk_size (chunk));
            
        zframe_destroy (&frame);
        zchunk_destroy (&chunk);
    }
    else
    if (pipe && streq (request, "DROP READER"))
        pipe_drop_remote_reader (&pipe, peer_id);
    else
    if (pipe && streq (request, "DROP WRITER"))
        pipe_drop_remote_writer (&pipe, peer_id);
    else
    if (streq (request, "DUMP"))
        zyre_dump (self->zyre);
    else
        zsys_warning ("bad request %s from %s", request, peer_name);

    zstr_free (&pipename);
    zstr_free (&request);
}
Beispiel #4
0
void
zchunk_test (bool verbose)
{
    printf (" * zchunk: ");

    //  @selftest
    zchunk_t *chunk = zchunk_new ("1234567890", 10);
    assert (chunk);
    assert (zchunk_size (chunk) == 10);
    assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0);
    zchunk_destroy (&chunk);

    chunk = zchunk_new (NULL, 10);
    zchunk_append (chunk, "12345678", 8);
    zchunk_append (chunk, "90ABCDEF", 8);
    zchunk_append (chunk, "GHIJKLMN", 8);
    assert (memcmp (zchunk_data (chunk), "1234567890", 10) == 0);
    assert (zchunk_size (chunk) == 10);

    zframe_t *frame = zchunk_pack (chunk);
    assert(frame);

    zchunk_t *chunk2 = zchunk_unpack (frame);
    assert (memcmp (zchunk_data (chunk2), "1234567890", 10) == 0);
    zframe_destroy(&frame);
    zchunk_destroy(&chunk2);

    zchunk_t *copy = zchunk_dup (chunk);
    assert (memcmp (zchunk_data (copy), "1234567890", 10) == 0);
    assert (zchunk_size (copy) == 10);
    zchunk_destroy (&copy);
    zchunk_destroy (&chunk);

    copy = zchunk_new ("1234567890abcdefghij", 20);
    chunk = zchunk_new (NULL, 8);
    zchunk_consume (chunk, copy);
    assert (!zchunk_exhausted (copy));
    assert (memcmp (zchunk_data (chunk), "12345678", 8) == 0);
    zchunk_set (chunk, NULL, 0);
    zchunk_consume (chunk, copy);
    assert (!zchunk_exhausted (copy));
    assert (memcmp (zchunk_data (chunk), "90abcdef", 8) == 0);
    zchunk_set (chunk, NULL, 0);
    zchunk_consume (chunk, copy);
    assert (zchunk_exhausted (copy));
    assert (zchunk_size (chunk) == 4);
    assert (memcmp (zchunk_data (chunk), "ghij", 4) == 0);
    zchunk_destroy (&copy);
    zchunk_destroy (&chunk);
    //  @end

    printf ("OK\n");
}
Beispiel #5
0
static void
s_check_directory (s_agent_t *self)
{
    //  Get latest snapshot and build a patches list for any changes
    //  All patches are built using a virtual path starting at "/"
    zdir_t *dir = zdir_new (self->path, NULL);
    zlist_t *patches = zdir_diff (self->dir, dir, "/");

    //  Drop old directory and replace with latest version
    zdir_destroy (&self->dir);
    self->dir = dir;

    while (zlist_size (patches)) {
        zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches);
        if (zdir_patch_op (patch) == patch_create) {
            //  Shout new files to DROPS group
            //  Stupidest possible approach: send whole file as one frame
            //  Truncate file at arbitrary limit of 10MB
            zfile_t *file = zdir_patch_file (patch);
            if (zfile_input (file) == 0) {
                zchunk_t *chunk = zfile_read (file, 10 * 1024 * 1024, 0);
                assert (chunk);
                zmsg_t *msg = zmsg_new ();
                zmsg_addstr (msg, "CREATE");
                zmsg_addstr (msg, zdir_patch_vpath (patch));
                zmsg_add (msg, zframe_new (zchunk_data (chunk), zchunk_size (chunk)));
                zchunk_destroy (&chunk);
                zyre_shout (self->zyre, "DROPS", &msg);
            }
        }
        zdir_patch_destroy (&patch);
    }
    zlist_destroy (&patches);
}
Beispiel #6
0
static void
pass_data_to_reader (client_t *self)
{
    assert (self->pipe);
    zchunk_t *chunk = zpipes_msg_get_chunk (self->request);
    zsys_info ("write %d bytes", (int) zchunk_size (chunk));
    pipe_send_data (self->pipe, &chunk);
}
Beispiel #7
0
static void
client_store_chunk (client_t *self, zchunk_t **chunk_p)
{
    zchunk_t *chunk = *chunk_p;
    assert (chunk);
    zlist_append (self->queue, chunk);
    self->pending += zchunk_size (chunk);
    *chunk_p = NULL;
}
Beispiel #8
0
JNIEXPORT jbyteArray JNICALL
Java_org_zeromq_czmq_Zchunk__1_1data (JNIEnv *env, jclass c, jlong self)
{
    jbyte *data_ = (jbyte *) zchunk_data ((zchunk_t *) (intptr_t) self);
    jint return_size_ = (jint) zchunk_size ((zchunk_t *) (intptr_t) self);
    jbyteArray return_data_ = (*env)->NewByteArray (env, return_size_);
    (*env)->SetByteArrayRegion (env, return_data_, 0, return_size_, (jbyte *) data_);
    return return_data_;
}
Beispiel #9
0
void
hydra_post_set_data (hydra_post_t *self, const void *data, size_t size)
{
    assert (self);
    zstr_free (&self->location);
    zchunk_destroy (&self->content);
    self->content = zchunk_new (data, size);
    strcpy (self->digest, zchunk_digest (self->content));
    self->content_size = zchunk_size (self->content);
}
Beispiel #10
0
static zsync_node_t *
zsync_node_new ()
{
    int rc;
    zsync_node_t *self = (zsync_node_t *) zmalloc (sizeof (zsync_node_t));
   
    self->ctx = zctx_new ();
    assert (self->ctx);
    self->zyre = zyre_new (self->ctx);  
    assert (self->zyre);
    
    // Obtain permanent UUID
    self->own_uuid = zuuid_new ();
    if (zsys_file_exists (UUID_FILE)) {
        // Read uuid from file
        zfile_t *uuid_file = zfile_new (".", UUID_FILE);
        int rc = zfile_input (uuid_file);    // open file for reading        
        assert (rc == 0); 

        zchunk_t *uuid_chunk = zfile_read (uuid_file, 16, 0);
        assert (zchunk_size (uuid_chunk) == 16);    // make sure read succeeded
        zuuid_set (self->own_uuid, zchunk_data (uuid_chunk));
        zfile_destroy (&uuid_file);
    } else {
        // Write uuid to file
        zfile_t *uuid_file = zfile_new (".", UUID_FILE);
        rc = zfile_output (uuid_file); // open file for writing
        assert (rc == 0);
        zchunk_t *uuid_bin = zchunk_new ( zuuid_data (self->own_uuid), 16);
        rc = zfile_write (uuid_file, uuid_bin, 0);
        assert (rc == 0);
        zfile_destroy (&uuid_file);
    }
    
    // Obtain peers and states
    self->peers = zlist_new ();
    if (zsys_file_exists (PEER_STATES_FILE)) {
        zhash_t *peer_states = zhash_new ();
        int rc = zhash_load (peer_states, PEER_STATES_FILE);
        assert (rc == 0);
        zlist_t *uuids = zhash_keys (peer_states);
        char *uuid = zlist_first (uuids);
        while (uuid) {
            char * state_str = zhash_lookup (peer_states, uuid);
            uint64_t state;
            sscanf (state_str, "%"SCNd64, &state);
            zlist_append (self->peers, zsync_peer_new (uuid, state)); 
            uuid = zlist_next (uuids);
        }
    }
    
    self->zyre_peers = zhash_new ();
    self->terminated = false;
    return self;
}
Beispiel #11
0
void
hydra_post_test (bool verbose)
{
    printf (" * hydra_post: ");
    if (verbose)
        printf ("\n");

    //  @selftest
    //  Simple create/destroy test
    zsys_dir_create (".hydra_test");
    zsys_dir_change (".hydra_test");
        
    hydra_post_t *post = hydra_post_new ("Test post");
    assert (post);
    hydra_post_set_content (post, "Hello, World");
    assert (streq (hydra_post_mime_type (post), "text/plain"));
    char *content = hydra_post_content (post);
    assert (content);
    assert (streq (content, "Hello, World"));
    zstr_free (&content);
    int rc = hydra_post_save (post, "testpost");
    assert (rc == 0);
    hydra_post_destroy (&post);

    post = hydra_post_load ("testpost");
    assert (post);
    assert (hydra_post_content_size (post) == 12);
    if (verbose)
        hydra_post_print (post);
    content = hydra_post_content (post);
    assert (content);
    assert (streq (content, "Hello, World"));
    zstr_free (&content);
    zchunk_t *chunk = hydra_post_fetch (
        post, hydra_post_content_size (post), 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 12);
    zchunk_destroy (&chunk);

    hydra_post_t *copy = hydra_post_dup (post);
    assert (streq (hydra_post_ident (copy), hydra_post_ident (post)));
    hydra_post_destroy (&post);
    hydra_post_destroy (&copy);

    //  Delete the test directory
    zsys_dir_change ("..");
    zdir_t *dir = zdir_new (".hydra_test", NULL);
    assert (dir);
    zdir_remove (dir, true);
    zdir_destroy (&dir);
    //  @end

    printf ("OK\n");
}
Beispiel #12
0
void 
pass_chunk (zchunk_t *chunk, char *path, uint64_t sequence, uint64_t offset)
{
    // save chunk
    printf ("[ST] PASS_CHUNK %s, %"PRId64", %"PRId64", %"PRId64"\n", path, sequence, zchunk_size (chunk), offset);
    zfile_t *file = zfile_new("./syncfolder", path);
    zfile_output(file);
    zfile_write(file, chunk, offset);
    zfile_close(file);
    zfile_destroy(&file);
}
Beispiel #13
0
int
zfile_test (bool verbose)
{
    printf (" * zfile: ");

    //  @selftest
    zfile_t *file = zfile_new (".", "bilbo");
    assert (streq (zfile_filename (file, "."), "bilbo"));
    assert (zfile_is_readable (file) == false);
    zfile_destroy (&file);

    //  Create a test file in some random subdirectory
    file = zfile_new ("./this/is/a/test", "bilbo");
    int rc = zfile_output (file);
    assert (rc == 0);
    zchunk_t *chunk = zchunk_new (NULL, 100);
    zchunk_fill (chunk, 0, 100);
    //  Write 100 bytes at position 1,000,000 in the file
    rc = zfile_write (file, chunk, 1000000);
    assert (rc == 0);
    zfile_close (file);
    assert (zfile_is_readable (file));
    assert (zfile_cursize (file) == 1000100);
    assert (!zfile_is_stable (file));
    zchunk_destroy (&chunk);
    zclock_sleep (1001);
    assert (zfile_is_stable (file));

    //  Check we can read from file
    rc = zfile_input (file);
    assert (rc == 0);
    chunk = zfile_read (file, 1000100, 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 1000100);
    zchunk_destroy (&chunk);

    //  Remove file and directory
    zdir_t *dir = zdir_new ("./this", NULL);
    assert (zdir_cursize (dir) == 1000100);
    zdir_remove (dir, true);
    assert (zdir_cursize (dir) == 0);
    zdir_destroy (&dir);

    //  Check we can no longer read from file
    assert (!zfile_is_readable (file));
    rc = zfile_input (file);
    assert (rc == -1);
    zfile_destroy (&file);
    //  @end

    printf ("OK\n");
    return 0;
}
Beispiel #14
0
static void
collect_data_to_send (client_t *self)
{
    zsys_info ("read %d bytes", (int) zpipes_msg_size (self->request));
    //  Do we have enough data to satisfy the read request?
    size_t required = zpipes_msg_size (self->request);
    
    //  If pipe was closed, we'll do a short read with as much
    //  data as we have pending
    if (required > self->pending && self->pipe == NULL)
        required = self->pending;

    if (self->pipe == NULL && self->pending == 0)
        engine_set_exception (self, pipe_shut_event);
    else
    if (self->pending >= required) {
        //  Create a bucket chunk with the required max size
        zchunk_t *bucket = zchunk_new (NULL, required);

        //  Now fill the bucket with chunks from our queue
        while (zchunk_size (bucket) < required) {
            //  Get next chunk and consume as much of it as possible
            zchunk_t *chunk = (zchunk_t *) zlist_pop (self->queue);
            assert (chunk);
            zchunk_consume (bucket, chunk);
            //  If chunk is exhausted, destroy it
            if (zchunk_exhausted (chunk))
                zchunk_destroy (&chunk);
            else {
                //  Push chunk back for next time
                zlist_push (self->queue, chunk);
                assert (zchunk_size (bucket) == required);
            }
        }
        zpipes_msg_set_chunk (self->reply, &bucket);
        self->pending -= required;
    }
    else
        engine_set_exception (self, not_enough_data_event);
}
Beispiel #15
0
zchunk_t *
zconfig_chunk_save (zconfig_t *self)
{
    assert (self);

    int size = s_config_execute (self, s_config_save, NULL, 0);
    //  Allow an extra byte so we can null-terminate the data
    zchunk_t *chunk = zchunk_new (NULL, size + 1);
    if (chunk) {
        s_config_execute (self, s_config_save, chunk, 0);
        //  This lets us treat the chunk data as a string
        zchunk_data (chunk) [zchunk_size (chunk)] = 0;
    }
    return chunk;
}
Beispiel #16
0
ssize_t
zpipes_client_read (zpipes_client_t *self, void *data, size_t size, int timeout)
{
    assert (self);

    zpipes_msg_send_read (self->dealer, size, timeout);
    zpipes_msg_t *reply = zpipes_msg_recv (self->dealer);
    if (!reply) {
        self->error = EINTR;
        return -1;              //  Interrupted
    }
    ssize_t rc = 0;
    if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_OK) {
        zchunk_t *chunk = zpipes_msg_chunk (reply);
        ssize_t bytes = zchunk_size (chunk);
        assert (bytes <= size);
        memcpy (data, zchunk_data (chunk), bytes);
        rc = bytes;
    }
    else
    if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_END)
        rc = 0;
    else
    if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_TIMEOUT) {
        self->error = EAGAIN;
        rc = -1;
    }
    else
    if (zpipes_msg_id (reply) == ZPIPES_MSG_READ_FAILED) {
        //  TODO: better error code?
        //  This happens if we close a pipe while there's a pending read
        self->error = EINTR;
        rc = -1;
    }
    else
    if (zpipes_msg_id (reply) == ZPIPES_MSG_INVALID) {
        self->error = EBADF;
        rc = -1;
    }
    zpipes_msg_destroy (&reply);
    return rc;
}
Beispiel #17
0
zchunk_t *
zfile_read (zfile_t *self, size_t bytes, off_t offset)
{
    assert (self);
    assert (self->handle);

    //  Calculate real number of bytes to read
    if (offset > self->cursize)
        bytes = 0;
    else if (bytes > (size_t) (self->cursize - offset))
        bytes = (size_t) (self->cursize - offset);

    if (fseek (self->handle, (long) offset, SEEK_SET) == -1)
        return NULL;

    self->eof = false;
    zchunk_t *chunk = zchunk_read (self->handle, bytes);
    if (chunk)
        self->eof = zchunk_size (chunk) < bytes;
    return chunk;
}
Beispiel #18
0
static void
pipe_send_data (pipe_t *self, zchunk_t **chunk_p)
{
    assert (self);
    assert (self->reader);

    zchunk_t *chunk = *chunk_p;
    assert (chunk);
    
    if (self->reader == REMOTE_NODE) {
        //  Send chunk to remote node reader
        zmsg_t *msg = zmsg_new ();
        zmsg_addstr (msg, "DATA");
        zmsg_addstr (msg, self->name);
        zmsg_addmem (msg, zchunk_data (chunk), zchunk_size (chunk));
        zyre_whisper (self->server->zyre, self->remote, &msg);
        zchunk_destroy (chunk_p);
    }
    else {
        client_store_chunk (self->reader, chunk_p);
        engine_send_event (self->reader, have_data_event);
    }
}
Beispiel #19
0
zconfig_t *
zconfig_chunk_load (zchunk_t *chunk)
{
    //  Parse the chunk line by line
    zconfig_t *self = zconfig_new ("root", NULL);
    if (!self)
        return NULL;

    bool valid = true;
    int lineno = 0;
    char *data_ptr = (char *) zchunk_data (chunk);
    size_t remaining = zchunk_size (chunk);

    while (remaining) {
        //  Copy stuff into cur_line; not fastest but safest option
        //  since chunk may not be null terminated, etc.
        char *eoln = (char *) memchr (data_ptr, '\n', remaining);
        size_t cur_size;
        if (eoln)
            cur_size = eoln - data_ptr;
        else
            cur_size = remaining;

        if (cur_size > 1024)
            cur_size = 1024;
        char cur_line [1024 + 1];
        memcpy (cur_line, data_ptr, cur_size);
        cur_line [cur_size] = '\0';
        data_ptr = eoln? eoln + 1: NULL;
        remaining -= cur_size + (eoln? 1: 0);

        //  Trim line
        size_t length = strlen (cur_line);
        while (length && isspace ((byte) cur_line [length - 1]))
            cur_line [--length] = 0;

        //  Collect indentation level and name, if any
        lineno++;
        //  Handle whole-line comment if present
        if (cur_line [0] == '#') {
            if (!self->comments) {
                self->comments = zlist_new ();
                assert (self->comments);
                zlist_autofree (self->comments);
            }
            zlist_append (self->comments, cur_line + 1);
        }
        char *scanner = cur_line;
        int level = s_collect_level (&scanner, lineno);
        if (level == -1) {
            valid = false;
            break;
        }
        char *name = s_collect_name (&scanner, lineno);
        if (name == NULL) {
            valid = false;
            break;
        }
        //  If name is not empty, collect property value
        if (*name) {
            char *value = s_collect_value (&scanner, lineno);
            if (value == NULL)
                valid = false;
            else {
                //  Navigate to parent for this element
                zconfig_t *parent = zconfig_at_depth (self, level);
                if (parent) {
                    zconfig_t *item = zconfig_new (name, parent);
                    assert (item);
                    item->value = value;
                }
                else {
                    zclock_log ("E (zconfig): (%d) indentation error", lineno);
                    free (value);
                    valid = false;
                }
            }
        }
        else
        if (s_verify_eoln (scanner, lineno))
            valid = false;

        free (name);
        if (!valid)
            break;
    }
    //  Either the whole ZPL stream is valid or none of it is
    if (!valid)
        zconfig_destroy (&self);
    return self;
}
Beispiel #20
0
void
zfile_test (bool verbose)
{
    printf (" * zfile: ");

    //  @selftest
    zfile_t *file = zfile_new (NULL, "bilbo");
    assert (streq (zfile_filename (file, "."), "bilbo"));
    assert (zfile_is_readable (file) == false);
    zfile_destroy (&file);

    //  Create a test file in some random subdirectory
    file = zfile_new ("./this/is/a/test", "bilbo");
    int rc = zfile_output (file);
    assert (rc == 0);
    zchunk_t *chunk = zchunk_new (NULL, 100);
    zchunk_fill (chunk, 0, 100);
    
    //  Write 100 bytes at position 1,000,000 in the file
    rc = zfile_write (file, chunk, 1000000);
    assert (rc == 0);
    zchunk_destroy (&chunk);
    zfile_close (file);
    assert (zfile_is_readable (file));
    assert (zfile_cursize (file) == 1000100);
    assert (!zfile_is_stable (file));
    
    //  Now append one byte to file from outside
    int handle = open ("./this/is/a/test/bilbo", O_WRONLY | O_TRUNC | O_BINARY, 0);
    assert (handle >= 0);
    rc = write (handle, "Hello, World\n", 13);
    assert (rc == 13);
    close (handle);
    assert (zfile_has_changed (file));
    zclock_sleep (1001);
    assert (zfile_has_changed (file));
    
    assert (!zfile_is_stable (file));
    zfile_restat (file);
    assert (zfile_is_stable (file));
    assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54"));
    
    //  Check we can read from file
    rc = zfile_input (file);
    assert (rc == 0);
    chunk = zfile_read (file, 1000100, 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 13);
    zchunk_destroy (&chunk);
    zfile_close (file);

    //  Try some fun with symbolic links
    zfile_t *link = zfile_new ("./this/is/a/test", "bilbo.ln");
    rc = zfile_output (link);
    assert (rc == 0);
    fprintf (zfile_handle (link), "./this/is/a/test/bilbo\n");
    zfile_destroy (&link);

    link = zfile_new ("./this/is/a/test", "bilbo.ln");
    rc = zfile_input (link);
    assert (rc == 0);
    chunk = zfile_read (link, 1000100, 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 13);
    zchunk_destroy (&chunk);
    zfile_destroy (&link);

    //  Remove file and directory
    zdir_t *dir = zdir_new ("./this", NULL);
    assert (zdir_cursize (dir) == 26);
    zdir_remove (dir, true);
    assert (zdir_cursize (dir) == 0);
    zdir_destroy (&dir);

    //  Check we can no longer read from file
    assert (zfile_is_readable (file));
    zfile_restat (file);
    assert (!zfile_is_readable (file));
    rc = zfile_input (file);
    assert (rc == -1);
    zfile_destroy (&file);
    //  @end

    printf ("OK\n");
}
Beispiel #21
0
static void zhttp_client_actor (zsock_t *pipe, void *args) {
    curl_global_init (CURL_GLOBAL_ALL);
    CURLM *multi = curl_multi_init ();
    CURLSH *share = curl_share_init ();
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_SSL_SESSION);
    curl_share_setopt (share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);

    long verbose = (*(bool *) args) ? 1L : 0L;
    CURLMcode code;

    SOCKET pipefd = zsock_fd (pipe);
    struct curl_waitfd waitfd = {pipefd, CURL_WAIT_POLLIN};

    //  List to hold pending curl handles, in case we are destroy the client
    //  while request are inprogress
    zlistx_t *pending_handles = zlistx_new ();
    zlistx_set_destructor (pending_handles, (zlistx_destructor_fn *) curl_destructor);

    zsock_signal (pipe, 0);

    bool terminated = false;
    while (!terminated) {
        if (!zsock_has_in (pipe)) {
            code = curl_multi_wait (multi, &waitfd, 1, 1000, NULL);
            assert (code == CURLM_OK);
        }

        if (zsock_has_in (pipe)) {
            char *command = zstr_recv (pipe);
            if (!command)
                break;          //  Interrupted

            //  All actors must handle $TERM in this way
            if (streq (command, "$TERM"))
                terminated = true;
            else if (streq (command, "GET")) {
                char *url;
                zlistx_t *headers;
                int timeout;
                void *handler;
                void *arg;
                int rc = zsock_recv (pipe, "slipp", &url, &headers, &timeout, &handler, &arg);
                assert (rc == 0);

                zchunk_t *response = zchunk_new (NULL, 100);
                assert (response);
                struct curl_slist *curl_headers = zlistx_to_slist (headers);
                CURL *curl = curl_easy_init ();
                zlistx_add_end (pending_handles, curl);
                http_request *request = (http_request *) zmalloc (sizeof (http_request));
                assert (request);
                request->handler = handler;
                request->arg = arg;
                request->curl = curl;
                request->response = response;
                request->headers = curl_headers;
                request->body = NULL;

                curl_easy_setopt (curl, CURLOPT_SHARE, share);
                curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long)timeout);
                curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose);
                curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers);
                curl_easy_setopt (curl, CURLOPT_URL, url);
                curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
                curl_easy_setopt (curl, CURLOPT_WRITEDATA, response);
                curl_easy_setopt (curl, CURLOPT_PRIVATE, request);

                code = curl_multi_add_handle (multi, curl);
                assert (code == CURLM_OK);
                zlistx_destroy (&headers);
                zstr_free (&url);
            } else if (streq (command, "POST")) {

                char *url;
                zlistx_t *headers;
                zchunk_t *body;
                int timeout;
                void *handler;
                void *arg;
                int rc = zsock_recv (pipe, "slcipp", &url, &headers, &body, &timeout, &handler, &arg);
                assert (rc == 0);

                zchunk_t *response = zchunk_new (NULL, 100);
                assert (response);
                struct curl_slist *curl_headers = zlistx_to_slist (headers);
                CURL *curl = curl_easy_init ();
                zlistx_add_end (pending_handles, curl);
                http_request *request = (http_request *) zmalloc (sizeof (http_request));
                assert (request);
                request->handler = handler;
                request->arg = arg;
                request->curl = curl;
                request->response = response;
                request->headers = curl_headers;
                request->body = body;

                curl_easy_setopt (curl, CURLOPT_SHARE, share);
                curl_easy_setopt (curl, CURLOPT_TIMEOUT_MS, (long)timeout);
                curl_easy_setopt (curl, CURLOPT_VERBOSE, verbose);
                curl_easy_setopt (curl, CURLOPT_POSTFIELDS, zchunk_data (body));
                curl_easy_setopt (curl, CURLOPT_POSTFIELDSIZE, zchunk_size (body));
                curl_easy_setopt (curl, CURLOPT_HTTPHEADER, curl_headers);
                curl_easy_setopt (curl, CURLOPT_URL, url);
                curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, write_data);
                curl_easy_setopt (curl, CURLOPT_WRITEDATA, response);
                curl_easy_setopt (curl, CURLOPT_PRIVATE, request);

                code = curl_multi_add_handle (multi, curl);
                assert (code == CURLM_OK);
                zlistx_destroy (&headers);
                zstr_free (&url);
            } else {
                puts ("E: invalid message to actor");
                assert (false);
            }
            zstr_free (&command);
        }

        int still_running;
        code = curl_multi_perform (multi, &still_running);
        assert (code == CURLM_OK);

        int msgq = 0;
        struct CURLMsg *msg = curl_multi_info_read (multi, &msgq);

        while (msg) {
            if (msg->msg == CURLMSG_DONE) {
                CURL *curl = msg->easy_handle;
                http_request *request;
                curl_easy_getinfo (curl, CURLINFO_PRIVATE, &request);

                long response_code_long;
                curl_easy_getinfo (curl, CURLINFO_RESPONSE_CODE, &response_code_long);
                int response_code = (int) response_code_long;

                if (response_code == 0 && msg->data.result == CURLE_OPERATION_TIMEDOUT)
                    response_code = -1;

                int rc = zsock_send (pipe, "icpp", response_code, request->response, request->handler, request->arg);
                assert (rc == 0);

                curl_multi_remove_handle (multi, curl);

                //  Remove curl from the pending handles and delete it
                void *handle = zlistx_find (pending_handles, curl);
                assert (handle);
                rc = zlistx_delete (pending_handles, handle);
                assert (rc == 0);
            }

            msg = curl_multi_info_read (multi, &msgq);
        }
    }

    zlistx_destroy (&pending_handles);
    curl_share_cleanup (share);
    curl_multi_cleanup (multi);
    curl_global_cleanup ();
}
Beispiel #22
0
///
//  Return chunk cur size
size_t QZchunk::size ()
{
    size_t rv = zchunk_size (self);
    return rv;
}
Beispiel #23
0
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 = (zdir_patch_t *) zlist_pop (client->patches);           
    if (client->patch == NULL) {                                                
        client->next_event = finished_event;                                    
        return;                                                                 
    }                                                                           
    //  Get virtual path from patch                                             
    fmq_msg_set_filename (client->reply, zdir_patch_vpath (client->patch));     
                                                                                
    //  We can process a delete patch right away                                
    if (zdir_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       
        zdir_patch_destroy (&client->patch);                                    
    }                                                                           
    else                                                                        
    if (zdir_patch_op (client->patch) == patch_create) {                        
        //  Create patch refers to file, open that for input if needed          
        if (client->file == NULL) {                                             
            client->file = zfile_dup (zdir_patch_file (client->patch));         
            if (zfile_input (client->file)) {                                   
                //  File no longer available, skip it                           
                zdir_patch_destroy (&client->patch);                            
                zfile_destroy (&client->file);                                  
                client->next_event = next_patch_event;                          
                return;                                                         
            }                                                                   
            client->offset = 0;                                                 
        }                                                                       
        //  Get next chunk for file                                             
        zchunk_t *chunk = zfile_read (client->file, CHUNK_SIZE, client->offset);
        assert (chunk);                                                         
                                                                                
        //  Check if we have the credit to send chunk                           
        if (zchunk_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 (                      
                zchunk_data (chunk),                                            
                zchunk_size (chunk)));                                          
                                                                                
            client->offset += zchunk_size (chunk);                              
            client->credit -= zchunk_size (chunk);                              
            client->next_event = send_chunk_event;                              
                                                                                
            //  Zero-sized chunk means end of file                              
            if (zchunk_size (chunk) == 0) {                                     
                zfile_destroy (&client->file);                                  
                zdir_patch_destroy (&client->patch);                            
            }                                                                   
        }                                                                       
        else                                                                    
            client->next_event = no_credit_event;                               
                                                                                
        zchunk_destroy (&chunk);                                                
    }                                                                           
}
Beispiel #24
0
int
zproto_example_send (zproto_example_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            frame_size += 2;            //  sequence
            frame_size += 2;            //  version
            frame_size += 1;            //  level
            frame_size += 1;            //  event
            frame_size += 2;            //  node
            frame_size += 2;            //  peer
            frame_size += 8;            //  time
            frame_size += 1 + strlen (self->host);
            frame_size += 4;
            if (self->data)
                frame_size += strlen (self->data);
            break;
        case ZPROTO_EXAMPLE_STRUCTURES:
            frame_size += 2;            //  sequence
            frame_size += 4;            //  Size is 4 octets
            if (self->aliases) {
                char *aliases = (char *) zlist_first (self->aliases);
                while (aliases) {
                    frame_size += 4 + strlen (aliases);
                    aliases = (char *) zlist_next (self->aliases);
                }
            }
            frame_size += 4;            //  Size is 4 octets
            if (self->headers) {
                self->headers_bytes = 0;
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    self->headers_bytes += 1 + strlen (zhash_cursor (self->headers));
                    self->headers_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            frame_size += self->headers_bytes;
            break;
        case ZPROTO_EXAMPLE_BINARY:
            frame_size += 2;            //  sequence
            frame_size += 4;            //  flags
            frame_size += 4;            //  Size is 4 octets
            if (self->public_key)
                frame_size += zchunk_size (self->public_key);
            frame_size += ZUUID_LEN;    //  identifier
            break;
        case ZPROTO_EXAMPLE_TYPES:
            frame_size += 2;            //  sequence
            frame_size += 1 + strlen (self->client_forename);
            frame_size += 1 + strlen (self->client_surname);
            frame_size += 1 + strlen (self->client_mobile);
            frame_size += 1 + strlen (self->client_email);
            frame_size += 1 + strlen (self->supplier_forename);
            frame_size += 1 + strlen (self->supplier_surname);
            frame_size += 1 + strlen (self->supplier_mobile);
            frame_size += 1 + strlen (self->supplier_email);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 0);
    PUT_NUMBER1 (self->id);
    bool have_content = false;
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case ZPROTO_EXAMPLE_LOG:
            PUT_NUMBER2 (self->sequence);
            PUT_NUMBER2 (3);
            PUT_NUMBER1 (self->level);
            PUT_NUMBER1 (self->event);
            PUT_NUMBER2 (self->node);
            PUT_NUMBER2 (self->peer);
            PUT_NUMBER8 (self->time);
            PUT_STRING (self->host);
            if (self->data) {
                PUT_LONGSTR (self->data);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            break;

        case ZPROTO_EXAMPLE_STRUCTURES:
            PUT_NUMBER2 (self->sequence);
            if (self->aliases) {
                PUT_NUMBER4 (zlist_size (self->aliases));
                char *aliases = (char *) zlist_first (self->aliases);
                while (aliases) {
                    PUT_LONGSTR (aliases);
                    aliases = (char *) zlist_next (self->aliases);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty string array
            if (self->headers) {
                PUT_NUMBER4 (zhash_size (self->headers));
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    PUT_STRING (zhash_cursor (self->headers));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            break;

        case ZPROTO_EXAMPLE_BINARY:
            PUT_NUMBER2 (self->sequence);
            PUT_OCTETS (self->flags, 4);
            if (self->public_key) {
                PUT_NUMBER4 (zchunk_size (self->public_key));
                memcpy (self->needle,
                        zchunk_data (self->public_key),
                        zchunk_size (self->public_key));
                self->needle += zchunk_size (self->public_key);
            }
            else
                PUT_NUMBER4 (0);    //  Empty chunk
            if (self->identifier)
                zuuid_export (self->identifier, self->needle);
            else
                memset (self->needle, 0, ZUUID_LEN);
            self->needle += ZUUID_LEN;
            nbr_frames++;
            nbr_frames += self->content? zmsg_size (self->content): 1;
            have_content = true;
            break;

        case ZPROTO_EXAMPLE_TYPES:
            PUT_NUMBER2 (self->sequence);
            PUT_STRING (self->client_forename);
            PUT_STRING (self->client_surname);
            PUT_STRING (self->client_mobile);
            PUT_STRING (self->client_email);
            PUT_STRING (self->supplier_forename);
            PUT_STRING (self->supplier_surname);
            PUT_STRING (self->supplier_mobile);
            PUT_STRING (self->supplier_email);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    //  Now send any frame fields, in order
    if (self->id == ZPROTO_EXAMPLE_BINARY) {
        //  If address isn't set, send an empty frame
        if (self->address)
            zframe_send (&self->address, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
        else
            zmq_send (zsock_resolve (output), NULL, 0, (--nbr_frames? ZMQ_SNDMORE: 0));
    }
    //  Now send the content if necessary
    if (have_content) {
        if (self->content) {
            zframe_t *frame = zmsg_first (self->content);
            while (frame) {
                zframe_send (&frame, output, ZFRAME_REUSE + (--nbr_frames? ZFRAME_MORE: 0));
                frame = zmsg_next (self->content);
            }
        }
        else
            zmq_send (zsock_resolve (output), NULL, 0, 0);
    }
    return 0;
}
Beispiel #25
0
void
zfile_test (bool verbose)
{
    printf (" * zfile: ");

    //  @selftest

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

    const char *testbasedir  = "this";
    const char *testsubdir  = "is/a/test";
    const char *testfile = "bilbo";
    const char *testlink = "bilbo.ln";
    char *basedirpath = NULL;   // subdir in a test, under SELFTEST_DIR_RW
    char *dirpath = NULL;       // subdir in a test, under basedirpath
    char *filepath = NULL;      // pathname to testfile in a test, in dirpath
    char *linkpath = NULL;      // pathname to testlink in a test, in dirpath

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

    // This subtest is specifically for NULL as current directory, so
    // no SELFTEST_DIR_RW here; testfile should have no slashes inside.
    // Normally tests clean up in zfile_destroy(), but if a selftest run
    // dies e.g. on assert(), workspace remains dirty. Better clean it up.
    if (zfile_exists (testfile) ) {
        if (verbose)
            zsys_debug ("zfile_test() has to remove ./%s that should not have been here", testfile);
        zfile_delete (testfile);
    }
    zfile_t *file = zfile_new (NULL, testfile);
    assert (file);
    assert (streq (zfile_filename (file, "."), testfile));
    assert (zfile_is_readable (file) == false);
    zfile_destroy (&file);

    //  Create a test file in some random subdirectory
    if (verbose)
        zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
            "Creating new zfile %s",
            zclock_time(), filepath );

    if (zfile_exists (filepath) ) {
        if (verbose)
            zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath);
        zfile_delete (filepath);
    }

    file = zfile_new (dirpath, testfile);
    assert (file);
    int rc = zfile_output (file);
    assert (rc == 0);
    zchunk_t *chunk = zchunk_new (NULL, 100);
    assert (chunk);
    zchunk_fill (chunk, 0, 100);

    //  Write 100 bytes at position 1,000,000 in the file
    if (verbose)
        zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
            "Writing 100 bytes at position 1,000,000 in the file",
            zclock_time() );
    rc = zfile_write (file, chunk, 1000000);
    if (verbose)
        zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
            "Wrote 100 bytes at position 1,000,000 in the file, result code %d",
            zclock_time(), rc );
    assert (rc == 0);
    zchunk_destroy (&chunk);
    zfile_close (file);
    assert (zfile_is_readable (file));
    assert (zfile_cursize (file) == 1000100);
    if (verbose)
        zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
            "Testing if file is NOT stable (is younger than 1 sec)",
            zclock_time() );
    assert (!zfile_is_stable (file));
    if (verbose)
        zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
            "Passed the lag-dependent tests",
            zclock_time() );
    assert (zfile_digest (file));

    //  Now truncate file from outside
    int handle = open (filepath, O_WRONLY | O_TRUNC | O_BINARY, 0);
    assert (handle >= 0);
    rc = write (handle, "Hello, World\n", 13);
    assert (rc == 13);
    close (handle);
    assert (zfile_has_changed (file));
#ifdef CZMQ_BUILD_DRAFT_API
    zclock_sleep ((int)zsys_file_stable_age_msec() + 50);
#else
    zclock_sleep (5050);
#endif
    assert (zfile_has_changed (file));

    assert (!zfile_is_stable (file));
    zfile_restat (file);
    assert (zfile_is_stable (file));
    assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54"));

    //  Check we can read from file
    rc = zfile_input (file);
    assert (rc == 0);
    chunk = zfile_read (file, 1000100, 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 13);
    zchunk_destroy (&chunk);
    zfile_close (file);

    //  Check we can read lines from file
    rc = zfile_input (file);
    assert (rc == 0);
    const char *line = zfile_readln (file);
    assert (streq (line, "Hello, World"));
    line = zfile_readln (file);
    assert (line == NULL);
    zfile_close (file);

    //  Try some fun with symbolic links
    zfile_t *link = zfile_new (dirpath, testlink);
    assert (link);
    rc = zfile_output (link);
    assert (rc == 0);
    fprintf (zfile_handle (link), "%s\n", filepath);
    zfile_destroy (&link);

    link = zfile_new (dirpath, testlink);
    assert (link);
    rc = zfile_input (link);
    assert (rc == 0);
    chunk = zfile_read (link, 1000100, 0);
    assert (chunk);
    assert (zchunk_size (chunk) == 13);
    zchunk_destroy (&chunk);
    zfile_destroy (&link);

    //  Remove file and directory
    zdir_t *dir = zdir_new (basedirpath, NULL);
    assert (dir);
    assert (zdir_cursize (dir) == 26);
    zdir_remove (dir, true);
    assert (zdir_cursize (dir) == 0);
    zdir_destroy (&dir);

    //  Check we can no longer read from file
    assert (zfile_is_readable (file));
    zfile_restat (file);
    assert (!zfile_is_readable (file));
    rc = zfile_input (file);
    assert (rc == -1);
    zfile_destroy (&file);

    // This set of tests is done, free the strings for reuse
    zstr_free (&basedirpath);
    zstr_free (&dirpath);
    zstr_free (&filepath);
    zstr_free (&linkpath);

    const char *eof_checkfile = "eof_checkfile";
    filepath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, eof_checkfile);
    assert (filepath);

    if (zfile_exists (filepath) ) {
        if (verbose)
            zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath);
        zfile_delete (filepath);
    }
    zstr_free (&filepath);

    file = zfile_new (SELFTEST_DIR_RW, eof_checkfile);
    assert (file);

    //  1. Write something first
    rc = zfile_output (file);
    assert (rc == 0);
    chunk = zchunk_new ("123456789", 9);
    assert (chunk);

    rc = zfile_write (file, chunk, 0);
    assert (rc == 0);
    zchunk_destroy (&chunk);
    zfile_close (file);
    assert (zfile_cursize (file) == 9);

    // 2. Read the written something
    rc = zfile_input (file);
    assert (rc != -1);
    // try to read more bytes than there is in the file
    chunk = zfile_read (file, 1000, 0);
    assert (zfile_eof(file));
    assert (zchunk_streq (chunk, "123456789"));
    zchunk_destroy (&chunk);

    // reading is ok
    chunk = zfile_read (file, 5, 0);
    assert (!zfile_eof(file));
    assert (zchunk_streq (chunk, "12345"));
    zchunk_destroy (&chunk);

    // read from non zero offset until the end
    chunk = zfile_read (file, 5, 5);
    assert (zfile_eof(file));
    assert (zchunk_streq (chunk, "6789"));
    zchunk_destroy (&chunk);
    zfile_remove (file);
    zfile_close (file);
    zfile_destroy (&file);

#ifdef CZMQ_BUILD_DRAFT_API
    zfile_t *tempfile = zfile_tmp ();
    assert (tempfile);
    assert (zfile_filename (tempfile, NULL));
    assert (zsys_file_exists (zfile_filename (tempfile, NULL)));
    zchunk_t *tchunk = zchunk_new ("HELLO", 6);
    assert (zfile_write (tempfile, tchunk, 0) == 0);
    zchunk_destroy (&tchunk);

    char *filename = strdup (zfile_filename (tempfile, NULL));
    zfile_destroy (&tempfile);
    assert (!zsys_file_exists (filename));
    zstr_free (&filename);
#endif // CZMQ_BUILD_DRAFT_API

#if defined (__WINDOWS__)
    zsys_shutdown();
#endif

    //  @end

    printf ("OK\n");
}
Beispiel #26
0
int
fmq_msg_send (fmq_msg_t *self, zsock_t *output)
{
    assert (self);
    assert (output);

    if (zsock_type (output) == ZMQ_ROUTER)
        zframe_send (&self->routing_id, output, ZFRAME_MORE + ZFRAME_REUSE);

    size_t frame_size = 2 + 1;          //  Signature and message ID
    switch (self->id) {
        case FMQ_MSG_OHAI:
            frame_size += 1 + strlen ("FILEMQ");
            frame_size += 2;            //  version
            break;
        case FMQ_MSG_ICANHAZ:
            frame_size += 4;
            if (self->path)
                frame_size += strlen (self->path);
            frame_size += 4;            //  Size is 4 octets
            if (self->options) {
                self->options_bytes = 0;
                char *item = (char *) zhash_first (self->options);
                while (item) {
                    self->options_bytes += 1 + strlen (zhash_cursor (self->options));
                    self->options_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->options);
                }
            }
            frame_size += self->options_bytes;
            frame_size += 4;            //  Size is 4 octets
            if (self->cache) {
                self->cache_bytes = 0;
                char *item = (char *) zhash_first (self->cache);
                while (item) {
                    self->cache_bytes += 1 + strlen (zhash_cursor (self->cache));
                    self->cache_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->cache);
                }
            }
            frame_size += self->cache_bytes;
            break;
        case FMQ_MSG_NOM:
            frame_size += 8;            //  credit
            frame_size += 8;            //  sequence
            break;
        case FMQ_MSG_CHEEZBURGER:
            frame_size += 8;            //  sequence
            frame_size += 1;            //  operation
            frame_size += 4;
            if (self->filename)
                frame_size += strlen (self->filename);
            frame_size += 8;            //  offset
            frame_size += 1;            //  eof
            frame_size += 4;            //  Size is 4 octets
            if (self->headers) {
                self->headers_bytes = 0;
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    self->headers_bytes += 1 + strlen (zhash_cursor (self->headers));
                    self->headers_bytes += 4 + strlen (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            frame_size += self->headers_bytes;
            frame_size += 4;            //  Size is 4 octets
            if (self->chunk)
                frame_size += zchunk_size (self->chunk);
            break;
        case FMQ_MSG_SRSLY:
            frame_size += 1 + strlen (self->reason);
            break;
        case FMQ_MSG_RTFM:
            frame_size += 1 + strlen (self->reason);
            break;
    }
    //  Now serialize message into the frame
    zmq_msg_t frame;
    zmq_msg_init_size (&frame, frame_size);
    self->needle = (byte *) zmq_msg_data (&frame);
    PUT_NUMBER2 (0xAAA0 | 3);
    PUT_NUMBER1 (self->id);
    size_t nbr_frames = 1;              //  Total number of frames to send

    switch (self->id) {
        case FMQ_MSG_OHAI:
            PUT_STRING ("FILEMQ");
            PUT_NUMBER2 (FMQ_MSG_VERSION);
            break;

        case FMQ_MSG_ICANHAZ:
            if (self->path) {
                PUT_LONGSTR (self->path);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            if (self->options) {
                PUT_NUMBER4 (zhash_size (self->options));
                char *item = (char *) zhash_first (self->options);
                while (item) {
                    PUT_STRING (zhash_cursor (self->options));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->options);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            if (self->cache) {
                PUT_NUMBER4 (zhash_size (self->cache));
                char *item = (char *) zhash_first (self->cache);
                while (item) {
                    PUT_STRING (zhash_cursor (self->cache));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->cache);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            break;

        case FMQ_MSG_NOM:
            PUT_NUMBER8 (self->credit);
            PUT_NUMBER8 (self->sequence);
            break;

        case FMQ_MSG_CHEEZBURGER:
            PUT_NUMBER8 (self->sequence);
            PUT_NUMBER1 (self->operation);
            if (self->filename) {
                PUT_LONGSTR (self->filename);
            }
            else
                PUT_NUMBER4 (0);    //  Empty string
            PUT_NUMBER8 (self->offset);
            PUT_NUMBER1 (self->eof);
            if (self->headers) {
                PUT_NUMBER4 (zhash_size (self->headers));
                char *item = (char *) zhash_first (self->headers);
                while (item) {
                    PUT_STRING (zhash_cursor (self->headers));
                    PUT_LONGSTR (item);
                    item = (char *) zhash_next (self->headers);
                }
            }
            else
                PUT_NUMBER4 (0);    //  Empty hash
            if (self->chunk) {
                PUT_NUMBER4 (zchunk_size (self->chunk));
                memcpy (self->needle,
                        zchunk_data (self->chunk),
                        zchunk_size (self->chunk));
                self->needle += zchunk_size (self->chunk);
            }
            else
                PUT_NUMBER4 (0);    //  Empty chunk
            break;

        case FMQ_MSG_SRSLY:
            PUT_STRING (self->reason);
            break;

        case FMQ_MSG_RTFM:
            PUT_STRING (self->reason);
            break;

    }
    //  Now send the data frame
    zmq_msg_send (&frame, zsock_resolve (output), --nbr_frames? ZMQ_SNDMORE: 0);

    return 0;
}
Beispiel #27
0
void
zsync_node_engine (void *args, zctx_t *ctx, void *pipe)
{
    int rc;    
    zsync_node_t *self = zsync_node_new ();
    self->ctx = ctx;
    self->zyre = zyre_new (ctx);
    self->zsync_pipe = pipe;
    
    // Join group
    rc = zyre_join (self->zyre, "ZSYNC");
    assert (rc == 0);

    // Give time to interconnect
    zclock_sleep (250);

    zpoller_t *poller = zpoller_new (zyre_socket (self->zyre), self->zsync_pipe, NULL);
    
    // Create thread for file management
    self->file_pipe = zthread_fork (self->ctx, zsync_ftmanager_engine, NULL);
    zpoller_add (poller, self->file_pipe);
    // Create thread for credit management
    self->credit_pipe = zthread_fork (self->ctx, zsync_credit_manager_engine, NULL);
    zpoller_add (poller, self->credit_pipe);

    // Start receiving messages
    printf("[ND] started\n");
    while (!zpoller_terminated (poller)) {
        void *which = zpoller_wait (poller, -1);
        
        if (which == zyre_socket (self->zyre)) {
            zsync_node_recv_from_zyre (self);
        } 
        else
        if (which == self->zsync_pipe) {
            printf("[ND] Recv Agent\n");
            zsync_node_recv_from_agent (self);
        }
        else
        if (which == self->file_pipe) {
            printf("[ND] Recv FT Manager\n");
            zsync_ftm_msg_t *msg = zsync_ftm_msg_recv (self->file_pipe);
            char *receiver = zsync_ftm_msg_receiver (msg);
            char *zyre_uuid = zsync_node_zyre_uuid (self, receiver);
            if (zyre_uuid) {
                char *path = zsync_ftm_msg_path (msg);
                uint64_t sequence = zsync_ftm_msg_sequence (msg);
                uint64_t chunk_size = zsync_ftm_msg_chunk_size (msg);
                uint64_t offset = zsync_ftm_msg_offset (msg);
                zsync_msg_send_req_chunk (pipe, path, chunk_size, offset);
                zsync_msg_t *zsmsg = zsync_msg_recv (pipe);
                zchunk_t *chunk = zsync_msg_chunk (zsmsg);
                zframe_t *frame = zframe_new (zchunk_data (chunk), zchunk_size (chunk));

                zmsg_t *zmsg = zmsg_new ();
                zs_msg_pack_chunk (zmsg, sequence, path, offset, frame);
                
                zyre_whisper (self->zyre, zyre_uuid, &zmsg);
                zsync_ftm_msg_destroy (&msg);
                zsync_msg_destroy (&zsmsg);
            }
        }
        else
        if (which == self->credit_pipe) {
            printf("[ND] Recv Credit Manager\n");
            zsync_credit_msg_t *cmsg = zsync_credit_msg_recv (self->credit_pipe);
            char *receiver = zsync_credit_msg_receiver (cmsg);
            char *zyre_uuid = zsync_node_zyre_uuid (self, receiver);
            if (zyre_uuid) {
                zmsg_t *credit_msg = zsync_credit_msg_credit (cmsg);
                assert (rc == 0);
                zyre_whisper (self->zyre, zyre_uuid, &credit_msg);
            }
            zsync_credit_msg_destroy (&cmsg);
        }
        if (self->terminated) {
            break;
        }
    }
    zpoller_destroy (&poller);
    zsync_node_destroy (&self);
    printf("[ND] stopped\n");
}
Beispiel #28
0
JNIEXPORT jlong JNICALL
Java_org_zeromq_czmq_Zchunk__1_1size (JNIEnv *env, jclass c, jlong self)
{
    jlong size_ = (jlong) zchunk_size ((zchunk_t *) (intptr_t) self);
    return size_;
}