Esempio n. 1
0
static void
sub_patch_add (sub_t *self, zdir_patch_t *patch)
{
    //  Skip file creation if client already has identical file
    zdir_patch_digest_set (patch);
    if (zdir_patch_op (patch) == patch_create) {
        char *digest = (char *) zhash_lookup (self->cache,
                                    zdir_patch_vpath (patch) + strlen(self->path) + 1);
        if (digest && streq (digest, zdir_patch_digest (patch)))
            return;             //  Just skip patch for this client
    }
    //  Remove any previous patches for the same file
    zdir_patch_t *existing = (zdir_patch_t *) zlist_first (self->client->patches);
    while (existing) {
        if (streq (zdir_patch_vpath (patch), zdir_patch_vpath (existing))) {
            zlist_remove (self->client->patches, existing);
            zdir_patch_destroy (&existing);
            break;
        }
        existing = (zdir_patch_t *) zlist_next (self->client->patches);
    }
    if (zdir_patch_op (patch) == patch_create)
        zhash_insert (self->cache,
            zdir_patch_digest (patch), zdir_patch_vpath (patch));
    //  Track that we've queued patch for client, so we don't do it twice
    zlist_append (self->client->patches, zdir_patch_dup (patch));
}
Esempio n. 2
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);
}
Esempio n. 3
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);                                                
    }                                                                           
}
Esempio n. 4
0
///
//  Return operation
int QZdirPatch::op ()
{
    int rv = zdir_patch_op (self);
    return rv;
}
Esempio n. 5
0
File: zdir.c Progetto: diorcety/czmq
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;
}