                     if server_id in have_data
                         work.push({project_id:project_id, action:'restore', server_id:server_id})
 
-                if work.length >= opts.end
+                if not opts.reverse and opts.end != -1 and work.length >= opts.end
                     break
+
+            # sort the work by project id
+            work.sort (a,b) ->
+                if a.project_id < b.project_id
+                    return -1
+                else if a.project_id > b.project_id
+                    return 1
+                else 
+                    return 0
+    
             cb()
 
         (cb) ->
-            dbg("do tasks #{opts.start} - #{opts.end} on the work schedule doing #{opts.limit} in parallel")
-
-            exec = (server_id, cmd, cb) ->
-                host = servers_by_id[server_id].host
+            if opts.end == -1
+                opts.end = work.length
+            dbg("do tasks #{opts.start} - #{opts.end-1} on the work schedule doing #{opts.limit} in parallel")
+            #dbg("work to do: #{misc.to_json(work.slice(opts.start, opts.end))}")
+
+            exec_on = (server_id, cmd, cb) ->
+                host = servers_by_id[server_id]?['host']
+                if not host?
+                    dbg("invalid server #{server_id}")
+                    cb("target server #{server_id} not found")
+                    return
+                dbg("on #{host}: #{cmd}")
                 misc_node.execute_code
                     command     : "ssh"
                     args        : ["-o StrictHostKeyChecking=no", "root@#{host}", cmd]
-                    timeout     : 30*60  # 30 minutes
-                    err_on_exit : true
-                    cb          : cb
+                    timeout     : 60*60 
+                    err_on_exit : false
+                    verbose     : false
+                    cb          : (err, output) ->
+                        if err
+                            dbg("#{host}: #{cmd} -- FAIL #{err}")
+                            cb(err)
+                        else 
+                            v = output.stderr.split('\n')
+                            for x in v
+                               x = x.trim()
+                               if x.length > 1 and x.indexOf('chattr:')==-1 and x.indexOf('WARNING') == -1 and x.indexOf('ECDSA') == -1
+                                   dbg("{host}: #{cmd} -- ERROR due to '#{x}'")
+                                   cb(output.stderr); return
+                            cb()
 
             task_delete = (project_id, server_id, cb) ->
                 if project_id.length != 36
                     cb("invalid uuid -- #{project_id}")
                 else
-                    exec(server_id, "rm -rf /bup/bups/#{project_id}", cb)
+                    exec_on(server_id, "rm -rf /bup/bups/#{project_id}", cb)
 
             task_copy = (project_id, src, dest, cb) ->
+                host = servers_by_id[dest]?.host
+                if not host?
+                    cb("target server #{dest} not found")
                 if project_id.length != 36
                     cb("invalid uuid -- #{project_id}")
                 else
-                    exec(src, "rsync -axvH /bup/bups/#{project_id}/ #{dest}:/bup/bups/#{project_id}/", cb)
+                    exec_on(src, "rsync -axH /bup/bups/#{project_id}/ #{host}:/bup/bups/#{project_id}/", cb)
 
             task_restore = (project_id, server_id, cb) ->
                 uid = project_uid(project_id)
-                exec(server_id, "bup restore --outdir=/bup/projects/#{project_id} master/latest && chown -R #{uid}:#{uid} /bup/projects/#{project_id}", cb)
-
-
+                if project_id.length != 36
+                    cb("invalid uuid -- #{project_id}")
+                else
+                    exec_on server_id, "rm -rf /bup/projects/#{project_id} && BUP_DIR=/bup/bups/#{project_id} bup restore --outdir=/bup/projects/#{project_id} master/latest/ ; chown -R #{uid}:#{uid} /bup/projects/#{project_id}", (err) ->
+                       if err
+                           cb(err)
+                       else 
+                           q = "UPDATE projects set bup_last_save[?]=? where project_id=?"
+                           database.cql(q, [server_id, save_time, project_id], cb) 
+
+            i = opts.start
+            goal = opts.end - 1
+        
+           
             do_task = (task, cb) ->
+                dbg("******** #{i}/#{goal} ******* ")
+                i += 1
+                dbg("doing task #{misc.to_json(task)}")
+                if opts.dryrun
+                    cb(); return
                 switch task.action
                     when 'delete'
                         task_delete(task.project_id, task.server_id, cb)

    servers_by_dc = {}
    servers_hosting_project = {}
    projects_on_server = {}

    async.series([
        (cb) ->

                    cb("bug -- we don't have any data--  #{project_id}")
                for server_id in target
                    if server_id not in have_data
                        if server_id.length != 36
                             total.bug
                        work.push({project_id:project_id, action:'copy_and_restore', src:source, dest:server_id})

                # 2. delete data from where we don't want it
