Exemple #1
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);
}
Exemple #2
0
void
zdir_patch_test (bool verbose)
{
    printf (" * zdir_patch: ");

    //  @selftest
    zfile_t *file = zfile_new (".", "bilbo");
    assert (file);
    zdir_patch_t *patch = zdir_patch_new (".", file, patch_create, "/");
    assert (patch);
    zfile_destroy (&file);

    file = zdir_patch_file (patch);
    assert (file);
    assert (streq (zfile_filename (file, "."), "bilbo"));
    assert (streq (zdir_patch_vpath (patch), "/bilbo"));
    zdir_patch_destroy (&patch);

#if defined (__WINDOWS__)
    zsys_shutdown();
#endif
    //  @end

    printf ("OK\n");
}
Exemple #3
0
static int
s_on_read_timer (zloop_t *loop, int timer_id, void *arg)
{
    zdir_watch_t *watch = (zdir_watch_t *) arg;

    void *data;
    for (data = zhash_first (watch->subs); data != NULL; data = zhash_next (watch->subs))
    {
        zdir_watch_sub_t *sub = (zdir_watch_sub_t *) data;

        zdir_t *new_dir = zdir_new (zdir_path (sub->dir), NULL);
        if (!new_dir) {
            if (watch->verbose)
                zsys_error ("zdir_watch: Unable to create new zdir for path %s", zdir_path (sub->dir));
            continue;
        }

        // Determine if anything has changed.
        zlist_t *diff = zdir_diff (sub->dir, new_dir, "");

        // Do memory management before error handling...
        zdir_destroy (&sub->dir);
        sub->dir = new_dir;

        if (!diff) {
            if (watch->verbose)
                zsys_error ("zdir_watch: Unable to create diff for path %s", zdir_path (sub->dir));
            continue;
        }

        if (zlist_size (diff) > 0) {
            if (watch->verbose) {
                zdir_patch_t *patch = (zdir_patch_t *) zlist_first (diff);

                zsys_info ("zdir_watch: Found %d changes in %s:", zlist_size (diff), zdir_path (sub->dir));
                while (patch)
                {
                    zsys_info ("zdir_watch:   %s %s", zfile_filename (zdir_patch_file (patch), NULL), zdir_patch_op (patch) == ZDIR_PATCH_CREATE? "created": "deleted");
                    patch = (zdir_patch_t *) zlist_next (diff);
                }
            }

            if (zsock_send (watch->pipe, "sp", zdir_path (sub->dir), diff) != 0) {
                if (watch->verbose)
                    zsys_error ("zdir_watch: Unable to send patch list for path %s", zdir_path (sub->dir));
                zlist_destroy (&diff);
            }

            // Successfully sent `diff` list - now owned by receiver
        }
        else {
            zlist_destroy (&diff);
        }
    }

    return 0;
}
Exemple #4
0
//  --------------------------------------------------------------------------
//  Self test of this class
int
zdir_patch_test (bool verbose)
{
    printf (" * zdir_patch: ");

    //  @selftest
    zfile_t *file = zfile_new (".", "bilbo");
    zdir_patch_t *patch = zdir_patch_new (".", file, patch_create, "/");
    zfile_destroy (&file);
    
    file = zdir_patch_file (patch);
    assert (streq (zfile_filename (file, "."), "bilbo"));
    assert (streq (zdir_patch_vpath (patch), "/bilbo"));
    zdir_patch_destroy (&patch);
    //  @end

    printf ("OK\n");
    return 0;
}
Exemple #5
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);                                                
    }                                                                           
}
Exemple #6
0
///
//  Return patch file item
QZfile * QZdirPatch::file ()
{
    QZfile *rv = new QZfile (zdir_patch_file (self));
    return rv;
}
Exemple #7
0
void
zdir_test (bool verbose)
{
    printf (" * zdir: ");

    //  @selftest
    // need to create a file in the test directory we're watching
    // in order to ensure the directory exists
    zfile_t *initfile = zfile_new ("./zdir-test-dir", "initial_file");
    assert (initfile);
    zfile_output (initfile);
    fprintf (zfile_handle (initfile), "initial file\n");
    zfile_close (initfile);
    zfile_destroy (&initfile);

    zdir_t *older = zdir_new ("zdir-test-dir", NULL);
    assert (older);
    if (verbose) {
        printf ("\n");
        zdir_dump (older, 0);
    }
    zdir_t *newer = zdir_new (".", NULL);
    assert (newer);
    zlist_t *patches = zdir_diff (older, newer, "/");
    assert (patches);
    while (zlist_size (patches)) {
        zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches);
        zdir_patch_destroy (&patch);
    }
    zlist_destroy (&patches);
    zdir_destroy (&older);
    zdir_destroy (&newer);

    zdir_t *nosuch = zdir_new ("does-not-exist", NULL);
    assert (nosuch == NULL);

    // zdir_watch test:
    zactor_t *watch = zactor_new (zdir_watch, NULL);
    assert (watch);

    int synced;
    if (verbose) {
        zsock_send (watch, "s", "VERBOSE");
        synced = zsock_wait(watch);
        assert ( synced == 0);
    }

    zclock_sleep (1001); // wait for initial file to become 'stable'

    zsock_send (watch, "si", "TIMEOUT", 100);
    synced = zsock_wait(watch);
    assert (synced == 0);

    zsock_send (watch, "ss", "SUBSCRIBE", "zdir-test-dir");
    synced = zsock_wait(watch);
    assert(synced == 0);

    zsock_send (watch, "ss", "UNSUBSCRIBE", "zdir-test-dir");
    synced = zsock_wait(watch);
    assert(synced == 0);

    zsock_send (watch, "ss", "SUBSCRIBE", "zdir-test-dir");
    synced = zsock_wait(watch);
    assert(synced == 0);

    zfile_t *newfile = zfile_new ("zdir-test-dir", "test_abc");
    zfile_output (newfile);
    fprintf (zfile_handle (newfile), "test file\n");
    zfile_close (newfile);

    zpoller_t *watch_poll = zpoller_new (watch, NULL);

    // poll for a certain timeout before giving up and failing the test.
    void* polled = zpoller_wait(watch_poll, 1001);
    assert (polled == watch);

    // wait for notification of the file being added
    char *path;
    int rc = zsock_recv (watch, "sp", &path, &patches);
    assert (rc == 0);

    assert (streq (path, "zdir-test-dir"));
    freen (path);

    assert (zlist_size (patches) == 1);

    zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches);
    assert (streq (zdir_patch_path (patch), "zdir-test-dir"));

    zfile_t *patch_file = zdir_patch_file (patch);
    assert (streq (zfile_filename (patch_file, ""), "zdir-test-dir/test_abc"));

    zdir_patch_destroy (&patch);
    zlist_destroy (&patches);

    // remove the file
    zfile_remove (newfile);
    zfile_destroy (&newfile);

    // poll for a certain timeout before giving up and failing the test.
    polled = zpoller_wait(watch_poll, 1001);
    assert (polled == watch);

    // wait for notification of the file being removed
    rc = zsock_recv (watch, "sp", &path, &patches);
    assert (rc == 0);

    assert (streq (path, "zdir-test-dir"));
    freen (path);

    assert (zlist_size (patches) == 1);

    patch = (zdir_patch_t *) zlist_pop (patches);
    assert (streq (zdir_patch_path (patch), "zdir-test-dir"));

    patch_file = zdir_patch_file (patch);
    assert (streq (zfile_filename (patch_file, ""), "zdir-test-dir/test_abc"));

    zdir_patch_destroy (&patch);
    zlist_destroy (&patches);

    zpoller_destroy (&watch_poll);
    zactor_destroy (&watch);

    // clean up by removing the test directory.
    zdir_t *testdir = zdir_new ("zdir-test-dir", NULL);
    zdir_remove (testdir, true);
    zdir_destroy (&testdir);

#if defined (__WINDOWS__)
    zsys_shutdown();
#endif
    //  @end

    printf ("OK\n");
}