drbqs 0.0.15 → 0.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +3 -0
- data/README.md +137 -128
- data/VERSION +1 -1
- data/docs/FormatExecute.md +119 -0
- data/docs/GettingStarted.md +242 -0
- data/drbqs.gemspec +36 -13
- data/example/command/server_def.rb +4 -5
- data/example/execute/execute.rb +41 -0
- data/example/execute/server.rb +14 -0
- data/example/execute/task.rb +0 -0
- data/example/mandelbrot/README.md +15 -0
- data/example/mandelbrot/execute.rb +10 -0
- data/example/mandelbrot/mandelbrot.rb +56 -0
- data/example/mandelbrot/server.rb +49 -0
- data/example/server/server.rb +3 -6
- data/example/simple/README.md +18 -0
- data/example/simple/execute.rb +11 -0
- data/example/simple/server.rb +8 -0
- data/example/simple/task.rb +11 -0
- data/example/sum/server_def.rb +1 -1
- data/example/sum2/execute_def.rb +21 -8
- data/example/sum2/server_def.rb +8 -7
- data/example/transfer/file.rb +42 -8
- data/example/transfer/server_def.rb +43 -9
- data/lib/drbqs.rb +1 -1
- data/lib/drbqs/command_line/command_execute.rb +3 -3
- data/lib/drbqs/command_line/command_line.rb +1 -1
- data/lib/drbqs/execute/execute_node.rb +50 -0
- data/lib/drbqs/execute/process_define.rb +102 -54
- data/lib/drbqs/execute/register.rb +241 -87
- data/lib/drbqs/execute/server_define.rb +69 -58
- data/lib/drbqs/ext/task.rb +2 -0
- data/lib/drbqs/ext/task/command_task.rb +43 -0
- data/lib/drbqs/manage/manage.rb +5 -4
- data/lib/drbqs/manage/ssh_shell.rb +2 -8
- data/lib/drbqs/node/connection.rb +1 -1
- data/lib/drbqs/node/node.rb +8 -14
- data/lib/drbqs/node/task_client.rb +1 -1
- data/lib/drbqs/server/history.rb +5 -1
- data/lib/drbqs/server/message.rb +7 -34
- data/lib/drbqs/server/queue.rb +14 -2
- data/lib/drbqs/server/server.rb +86 -43
- data/lib/drbqs/server/server_hook.rb +3 -0
- data/lib/drbqs/server/test/node.rb +1 -1
- data/lib/drbqs/server/test/prof.rb +50 -0
- data/lib/drbqs/server/test/server.rb +2 -2
- data/lib/drbqs/server/transfer_setting.rb +23 -11
- data/lib/drbqs/setting/base.rb +15 -0
- data/lib/drbqs/setting/data_container.rb +1 -1
- data/lib/drbqs/setting/execute.rb +3 -3
- data/lib/drbqs/setting/node.rb +1 -1
- data/lib/drbqs/setting/server.rb +2 -2
- data/lib/drbqs/task/registrar.rb +39 -0
- data/lib/drbqs/task/task.rb +139 -59
- data/lib/drbqs/task/task_generator.rb +93 -116
- data/lib/drbqs/utility/misc.rb +15 -10
- data/lib/drbqs/utility/temporary.rb +7 -2
- data/lib/drbqs/utility/transfer/transfer.rb +81 -0
- data/lib/drbqs/utility/transfer/transfer_client.rb +68 -69
- data/lib/drbqs/utility/transfer/transfer_client_connect.rb +83 -0
- data/lib/drbqs/utility/transfer/transfer_file_list.rb +40 -0
- data/spec/execute/def/execute1.rb +4 -4
- data/spec/execute/def/execute2.rb +24 -0
- data/spec/execute/process_define_spec.rb +43 -6
- data/spec/execute/register_spec.rb +403 -9
- data/spec/execute/server_define_spec.rb +1 -1
- data/spec/ext/task/command_task_spec.rb +16 -0
- data/spec/integration_test/01_basic_usage_spec.rb +1 -1
- data/spec/integration_test/02_use_generator_spec.rb +2 -2
- data/spec/integration_test/04_use_unix_domain_spec.rb +1 -1
- data/spec/integration_test/05_server_exit_signal_spec.rb +1 -1
- data/spec/integration_test/06_node_exit_after_task_spec.rb +4 -4
- data/spec/integration_test/08_shutdown_unused_nodes_spec.rb +2 -2
- data/spec/integration_test/09_server_process_data_spec.rb +1 -1
- data/spec/integration_test/definition/server01.rb +4 -5
- data/spec/integration_test/definition/server02.rb +2 -4
- data/spec/node/node_spec.rb +34 -0
- data/spec/server/message_spec.rb +1 -1
- data/spec/server/queue_spec.rb +34 -7
- data/spec/server/server_spec.rb +21 -9
- data/spec/server/transfer_setting_spec.rb +59 -24
- data/spec/setting/base_spec.rb +11 -0
- data/spec/setting/data_container_spec.rb +8 -0
- data/spec/spec_helper.rb +1 -7
- data/spec/task/registrar_spec.rb +34 -0
- data/spec/task/task_generator_spec.rb +15 -15
- data/spec/task/task_spec.rb +132 -23
- data/spec/utility/misc_spec.rb +2 -2
- data/spec/utility/transfer/transfer_client_connect_spec.rb +90 -0
- data/spec/utility/transfer/transfer_file_list_spec.rb +27 -0
- data/spec/{task/file_transfer_spec.rb → utility/transfer/transfer_spec.rb} +24 -24
- metadata +66 -45
- data/lib/drbqs/manage/execute_node.rb +0 -50
- data/lib/drbqs/server/prof.rb +0 -48
- data/lib/drbqs/task/command_task.rb +0 -43
- data/lib/drbqs/utility/transfer/file_transfer.rb +0 -73
@@ -1,142 +1,119 @@
|
|
1
1
|
module DRbQS
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
2
|
+
class Task
|
3
|
+
class Generator
|
4
|
+
# @param [Hash] data Names of instance variables and their values,
|
5
|
+
# which can be accessed in {DRbQS::Task::Generator#set}.
|
6
|
+
def initialize(data = {})
|
7
|
+
@registrar = DRbQS::Task::Registrar.new(data)
|
8
|
+
@fiber = nil
|
9
|
+
@iterate = nil
|
10
|
+
@task_set = nil
|
11
|
+
@fiber_init = nil
|
12
|
+
@wait = false
|
9
13
|
end
|
10
|
-
end
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
when DRbQS::Task
|
15
|
-
Fiber.yield(arg)
|
16
|
-
when Array
|
17
|
-
arg.each { |t| Fiber.yield(t) }
|
18
|
-
else
|
19
|
-
raise "Invalid type of an argument."
|
15
|
+
def have_next?
|
16
|
+
!!@fiber
|
20
17
|
end
|
21
|
-
end
|
22
18
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
def wait_all_tasks
|
28
|
-
Fiber.yield(:wait)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
class TaskGenerator
|
33
|
-
def initialize(data = {})
|
34
|
-
@source = DRbQS::TaskSource.new(data)
|
35
|
-
@fiber = nil
|
36
|
-
@iterate = nil
|
37
|
-
@task_set = nil
|
38
|
-
@fiber_init = nil
|
39
|
-
@wait = false
|
40
|
-
end
|
41
|
-
|
42
|
-
def have_next?
|
43
|
-
!!@fiber
|
44
|
-
end
|
45
|
-
|
46
|
-
def waiting?
|
47
|
-
@wait
|
48
|
-
end
|
49
|
-
|
50
|
-
# The options :generate and :collect are available.
|
51
|
-
# opts[:generate] is the number of tasks per one generation.
|
52
|
-
# The generator creates a task set from opts[:collect] tasks.
|
53
|
-
def set(opts = {}, &block)
|
54
|
-
@iterate = opts[:generate] || 1
|
55
|
-
@task_set = opts[:collect]
|
56
|
-
if @iterate < 1 || (@task_set && @task_set < 1)
|
57
|
-
raise ArgumentError, "Invalid options of task creation on generator."
|
19
|
+
def waiting?
|
20
|
+
@wait
|
58
21
|
end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
22
|
+
|
23
|
+
# @param [Hash] opts The options of task generation
|
24
|
+
# @option opts [Fixnum] :generate Set the number of tasks per one generation
|
25
|
+
# @option opts [Fixnum] :collect The generator creates a task set consisting of opts[:collect] tasks.
|
26
|
+
def set(opts = {}, &block)
|
27
|
+
unless block_given?
|
28
|
+
raise ArgumentError, "Creation of a task generator needs block."
|
29
|
+
end
|
30
|
+
@iterate = opts[:generate] || 1
|
31
|
+
@task_set = opts[:collect]
|
32
|
+
if @iterate < 1 || (@task_set && @task_set < 1)
|
33
|
+
raise ArgumentError, "Invalid options of task creation on generator."
|
34
|
+
end
|
35
|
+
@fiber_init = lambda do
|
36
|
+
@fiber = Fiber.new do
|
37
|
+
begin
|
38
|
+
@registrar.instance_eval(&block)
|
39
|
+
rescue => err
|
40
|
+
new_err = self.class.new("Error on generating tasks: #{err.to_s} (#{err.class})")
|
41
|
+
new_err.set_backtrace(err.backtrace)
|
42
|
+
raise new_err
|
43
|
+
end
|
44
|
+
nil
|
67
45
|
end
|
68
|
-
nil
|
69
46
|
end
|
70
47
|
end
|
71
|
-
end
|
72
48
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
49
|
+
# Initialize fider to create tasks.
|
50
|
+
# This method must be called in thread to create tasks.
|
51
|
+
def init
|
52
|
+
@fiber_init.call if @fiber_init
|
53
|
+
end
|
78
54
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
55
|
+
# Return an array of new tasks.
|
56
|
+
def new_tasks
|
57
|
+
if @fiber
|
58
|
+
@wait = false
|
59
|
+
task_ary = []
|
60
|
+
iteration = @iterate
|
61
|
+
iteration *= @task_set if @task_set
|
62
|
+
iteration.times do |i|
|
63
|
+
if task_new = @fiber.resume
|
64
|
+
case task_new
|
65
|
+
when DRbQS::Task
|
66
|
+
task_ary << task_new
|
67
|
+
when Array
|
68
|
+
task_ary.concat(task_new)
|
69
|
+
when :wait
|
70
|
+
@wait = true
|
71
|
+
break
|
72
|
+
else
|
73
|
+
raise RuntimeError, "Invalid object created by fiber to create tasks."
|
74
|
+
end
|
96
75
|
else
|
97
|
-
|
76
|
+
@fiber = nil
|
77
|
+
break
|
98
78
|
end
|
99
|
-
else
|
100
|
-
@fiber = nil
|
101
|
-
break
|
102
79
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
80
|
+
if task_ary.size > 0
|
81
|
+
if @task_set
|
82
|
+
task_ary = task_ary.each_slice(@task_set).map do |ary|
|
83
|
+
DRbQS::Task::TaskSet.new(ary)
|
84
|
+
end
|
108
85
|
end
|
86
|
+
return task_ary
|
109
87
|
end
|
110
|
-
return task_ary
|
111
88
|
end
|
89
|
+
nil
|
112
90
|
end
|
113
|
-
nil
|
114
|
-
end
|
115
91
|
|
116
|
-
|
92
|
+
DEBUG_TASK_PROGRESS = 1000
|
117
93
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
94
|
+
# Create all tasks for test and return [group_number, task_number] if all tasks created properly.
|
95
|
+
def debug_all_tasks(opts = {})
|
96
|
+
limit = opts[:limit]
|
97
|
+
progress = opts[:progress]
|
98
|
+
group_number = 0
|
99
|
+
task_number = 0
|
100
|
+
while ary = new_tasks
|
101
|
+
ary.each do |t|
|
102
|
+
unless DRbQS::Task === t
|
103
|
+
raise RuntimeError, "Invalid #{i}th task: #{t.inspect}"
|
104
|
+
end
|
105
|
+
task_number += 1
|
106
|
+
if progress && (task_number % DEBUG_TASK_PROGRESS == 0)
|
107
|
+
puts "#{task_number} tasks have been created."
|
108
|
+
end
|
109
|
+
if limit && task_number > limit
|
110
|
+
break
|
111
|
+
end
|
135
112
|
end
|
113
|
+
group_number += 1
|
136
114
|
end
|
137
|
-
group_number
|
115
|
+
[group_number, task_number]
|
138
116
|
end
|
139
|
-
[group_number, task_number]
|
140
117
|
end
|
141
118
|
end
|
142
119
|
end
|
data/lib/drbqs/utility/misc.rb
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
require 'sys/proctable'
|
2
2
|
|
3
3
|
module DRbQS
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
module Misc
|
5
|
+
class LoggerDummy
|
6
|
+
def info(*args)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def warn(*args)
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
def error(*args)
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
+
def debug(*args)
|
16
|
+
end
|
15
17
|
end
|
16
|
-
end
|
17
18
|
|
18
|
-
module Misc
|
19
19
|
# :port
|
20
20
|
# :host
|
21
21
|
# :unix
|
@@ -56,6 +56,11 @@ module DRbQS
|
|
56
56
|
end
|
57
57
|
module_function :time_to_history_string
|
58
58
|
|
59
|
+
def time_to_history_string2(t)
|
60
|
+
t.strftime("%m-%d %H:%M:%S")
|
61
|
+
end
|
62
|
+
module_function :time_to_history_string2
|
63
|
+
|
59
64
|
STRINGS_FOR_KEY = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a
|
60
65
|
|
61
66
|
def random_key(size = 20)
|
@@ -22,8 +22,13 @@ module DRbQS
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# Return new path of temporary file.
|
25
|
-
|
26
|
-
|
25
|
+
# @param [String] basename Set the basename of created filename
|
26
|
+
def self.file(basename = nil)
|
27
|
+
if basename
|
28
|
+
File.join(self.directory, basename)
|
29
|
+
else
|
30
|
+
filename.create(:add => :always)
|
31
|
+
end
|
27
32
|
end
|
28
33
|
|
29
34
|
# Make root of temporary directory empty.
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module DRbQS
|
2
|
+
# To compress files, we use gzip and tar command.
|
3
|
+
# Note that if we compress files then we delete the original files.
|
4
|
+
class Transfer
|
5
|
+
@files = Queue.new
|
6
|
+
|
7
|
+
class << self
|
8
|
+
# Add path to queue of which files is going to be transfered to server.
|
9
|
+
# @param [String] path The file path that we want to send to a server.
|
10
|
+
# @param [Hash] opts The options for transfering a file.
|
11
|
+
# @option opts [true,false] :compress Compress the file by gzip before transfering.
|
12
|
+
# @option opts [String] :rename Change basename to the specified name.
|
13
|
+
def enqueue(path, opts = {})
|
14
|
+
if opts[:rename]
|
15
|
+
new_path = FileName.create(File.join(File.dirname(path), opts[:rename]), :directory => :parent)
|
16
|
+
FileUtils.mv(path, new_path)
|
17
|
+
path = new_path
|
18
|
+
end
|
19
|
+
if opts[:compress]
|
20
|
+
if File.directory?(path)
|
21
|
+
gz_path = "#{path.sub(/\/$/, '')}.tar.gz"
|
22
|
+
cmd = "tar czf #{gz_path} -C #{File.dirname(path)} #{File.basename(path)} > /dev/null 2>&1"
|
23
|
+
else
|
24
|
+
gz_path = path + '.gz'
|
25
|
+
cmd = "gzip --best #{path} > /dev/null 2>&1"
|
26
|
+
end
|
27
|
+
if File.exist?(gz_path)
|
28
|
+
raise "File has already existed: #{gz_path}"
|
29
|
+
elsif !system(cmd)
|
30
|
+
raise "Can not compress: #{path}"
|
31
|
+
end
|
32
|
+
FileUtils.rm_r(path) if File.exist?(path)
|
33
|
+
path_to_send = gz_path
|
34
|
+
else
|
35
|
+
path_to_send = path
|
36
|
+
end
|
37
|
+
@files.enq(path_to_send)
|
38
|
+
File.basename(path_to_send)
|
39
|
+
end
|
40
|
+
|
41
|
+
def compress_enqueue(path)
|
42
|
+
enqueue(path, :compress => true)
|
43
|
+
end
|
44
|
+
|
45
|
+
def dequeue
|
46
|
+
@files.deq
|
47
|
+
end
|
48
|
+
|
49
|
+
def empty?
|
50
|
+
@files.empty?
|
51
|
+
end
|
52
|
+
|
53
|
+
def dequeue_all
|
54
|
+
files = []
|
55
|
+
until empty?
|
56
|
+
files << dequeue
|
57
|
+
end
|
58
|
+
files.empty? ? nil : files
|
59
|
+
end
|
60
|
+
|
61
|
+
# Decompress a file in the file directory of a server.
|
62
|
+
# @param [DRbQS::Server] server Current server
|
63
|
+
# @param [String] filename File path to decompress
|
64
|
+
def decompress(server, filename)
|
65
|
+
dir = server.transfer_directory
|
66
|
+
path = File.join(dir, filename)
|
67
|
+
if File.exist?(path)
|
68
|
+
case path
|
69
|
+
when /\.tar\.gz$/
|
70
|
+
cmd = "tar xvzf #{path} -C #{dir} > /dev/null 2>&1"
|
71
|
+
when /\.gz$/
|
72
|
+
cmd = "gunzip #{path} > /dev/null 2>&1"
|
73
|
+
else
|
74
|
+
cmd = nil
|
75
|
+
end
|
76
|
+
system(cmd) if cmd
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,90 +1,89 @@
|
|
1
|
-
require '
|
1
|
+
require 'drbqs/utility/transfer/transfer_client_connect.rb'
|
2
2
|
|
3
3
|
module DRbQS
|
4
|
+
class Transfer
|
5
|
+
class Client
|
6
|
+
attr_reader :directory, :local, :sftp
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@directory =
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
# Transfer files to directory on DRbQS server over sftp.
|
19
|
-
# Note that after we transfer files we delete the original files.
|
20
|
-
class SFTP < DRbQS::TransferClient::ClientBase
|
21
|
-
attr_reader :user, :host, :directory
|
22
|
-
|
23
|
-
def initialize(user, host, directory)
|
24
|
-
super(directory)
|
25
|
-
@user = user
|
26
|
-
@host = host
|
8
|
+
def initialize(server_directory, same_host, host, user)
|
9
|
+
unless Pathname.new(server_directory).absolute?
|
10
|
+
raise ArgumentError, "Directory of server must be absolute."
|
11
|
+
end
|
12
|
+
@directory = server_directory
|
13
|
+
@same_host = same_host
|
14
|
+
@local = DRbQS::Transfer::Client::Local.new(@directory)
|
15
|
+
if host && user
|
16
|
+
@sftp = DRbQS::Transfer::Client::SFTP.new(user, host, @directory)
|
17
|
+
else
|
18
|
+
@sftp = nil
|
19
|
+
end
|
27
20
|
end
|
28
21
|
|
29
|
-
# Transfer and delete +files+.
|
30
22
|
def transfer(files)
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
23
|
+
transfered = false
|
24
|
+
if @same_host
|
25
|
+
begin
|
26
|
+
@local.transfer(files)
|
27
|
+
transfered = true
|
28
|
+
rescue
|
29
|
+
end
|
30
|
+
end
|
31
|
+
if !transfered
|
32
|
+
unless @sftp
|
33
|
+
raise "Can not transfer files."
|
35
34
|
end
|
35
|
+
@sftp.transfer(files)
|
36
36
|
end
|
37
|
-
rescue => err
|
38
|
-
raise err.class, "user=#{@user}, host=#{@host}, directory=#{@directory}; #{err.to_s}", err.backtrace
|
39
37
|
end
|
40
|
-
end
|
41
38
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
def download(files, readonly = nil)
|
40
|
+
download_files = nil
|
41
|
+
if @same_host
|
42
|
+
begin
|
43
|
+
if readonly
|
44
|
+
download_files = files
|
45
|
+
else
|
46
|
+
download_files = @local.download(files)
|
47
|
+
end
|
48
|
+
rescue
|
49
|
+
end
|
46
50
|
end
|
51
|
+
if !download_files
|
52
|
+
unless @sftp
|
53
|
+
raise "SFTP is not prepared."
|
54
|
+
end
|
55
|
+
download_files = @sftp.download(files)
|
56
|
+
end
|
57
|
+
download_files
|
47
58
|
end
|
48
|
-
end
|
49
|
-
|
50
|
-
attr_reader :directory, :local, :sftp
|
51
|
-
|
52
|
-
def initialize(dir)
|
53
|
-
@directory = File.expand_path(dir)
|
54
|
-
@local = DRbQS::TransferClient::Local.new(@directory)
|
55
|
-
@sftp = nil
|
56
|
-
end
|
57
|
-
|
58
|
-
def make_directory
|
59
|
-
FileUtils.mkdir_p(@directory)
|
60
|
-
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
end
|
60
|
+
class << self
|
61
|
+
@transfer = nil
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
info
|
70
|
-
end
|
63
|
+
def get
|
64
|
+
@transfer
|
65
|
+
end
|
71
66
|
|
72
|
-
|
73
|
-
|
74
|
-
if on_same_host
|
75
|
-
begin
|
76
|
-
@local.transfer(files)
|
77
|
-
transfered = true
|
78
|
-
rescue
|
67
|
+
def set(transfer)
|
68
|
+
@transfer = transfer
|
79
69
|
end
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
70
|
+
|
71
|
+
def transfer_to_server
|
72
|
+
if files = DRbQS::Transfer.dequeue_all
|
73
|
+
if @transfer
|
74
|
+
begin
|
75
|
+
@transfer.transfer(files)
|
76
|
+
rescue Exception => err
|
77
|
+
err_new = err.class.new("#{err.to_s} (#{err.class}); Can not send file: #{files.join(", ")}")
|
78
|
+
err_new.set_backtrace(err.backtrace)
|
79
|
+
raise err_new
|
80
|
+
end
|
81
|
+
else
|
82
|
+
raise "Server does not set transfer settings. Can not send file: #{files.join(", ")}"
|
83
|
+
end
|
84
|
+
end
|
84
85
|
end
|
85
|
-
@sftp.transfer(files)
|
86
86
|
end
|
87
87
|
end
|
88
88
|
end
|
89
|
-
|
90
89
|
end
|