@@ -31,6 +31,12 @@ local FLAGS = {
31
31
[ uv .READABLE + uv .WRITABLE ] = curl .CSELECT_IN + curl .CSELECT_OUT ;
32
32
}
33
33
34
+ local POLL_IO_FLAGS = {
35
+ [ curl .POLL_IN ] = uv .READABLE ;
36
+ [ curl .POLL_OUT ] = uv .WRITABLE ;
37
+ [ curl .POLL_INOUT ] = uv .READABLE + uv .WRITABLE ;
38
+ }
39
+
34
40
local Context = ut .class () do
35
41
36
42
function Context :__init (fd )
@@ -67,6 +73,31 @@ local qtask = ut.Queue.new() -- wait tasks
67
73
local qfree = ut .Queue .new () -- avaliable easy handles
68
74
local qeasy = {} -- all easy handles
69
75
76
+ local function on_begin (handle , url , num )
77
+ local filename = tostring (num ) .. " .download"
78
+ local file = io.open (filename , " w" )
79
+ if not file then
80
+ fprintf (stderr , " Error opening %s\n " , filename )
81
+ return
82
+ end
83
+ handle .data .file = file
84
+ handle :setopt_writefunction (file )
85
+
86
+ fprintf (stderr , " Added download %s -> %s\n " , url , filename );
87
+ return true
88
+ end
89
+
90
+ local function on_end (handle , err , url )
91
+ handle .data .file :close ()
92
+ handle .data .file = nil
93
+
94
+ if err then
95
+ printf (" %s ERROR - %s\n " , url , tostring (err ));
96
+ else
97
+ printf (" %s DONE\n " , url );
98
+ end
99
+ end
100
+
70
101
local function cleanup ()
71
102
timer :close ()
72
103
81
112
local proceed_queue , add_download do
82
113
83
114
proceed_queue = function ()
84
- if qtask :empty () then return end
85
-
86
- if qfree :empty () then
87
- if # qeasy < MAX_REQUESTS then
88
- local easy = assert (curl .easy ())
89
- qeasy [# qeasy + 1 ] = easy
90
- qfree :push (easy )
91
- else
92
- return
115
+ while true do
116
+ if qtask :empty () then return end
117
+
118
+ if qfree :empty () then
119
+ if # qeasy < MAX_REQUESTS then
120
+ local easy = assert (curl .easy ())
121
+ qeasy [# qeasy + 1 ] = easy
122
+ qfree :push (easy )
123
+ else
124
+ return
125
+ end
93
126
end
94
- end
95
127
96
- local task = assert (qtask :pop ())
97
- local url , num = task [1 ], task [2 ]
128
+ local task = assert (qtask :pop ())
129
+ local url , num = task [1 ], task [2 ]
98
130
99
- local filename = tostring (num ) .. " .download"
100
- local file = io.open (filename , " w" )
101
- if not file then
102
- fprintf (stderr , " Error opening %s\n " , filename )
103
- return
104
- end
105
-
106
- local handle = assert (qfree :pop ())
131
+ local handle = assert (qfree :pop ())
107
132
108
- handle :setopt {
109
- url = url ;
110
- writefunction = file ;
111
- }
133
+ handle :setopt {
134
+ url = url ;
135
+ fresh_connect = true ;
136
+ forbid_reuse = true ;
137
+ }
112
138
113
- handle .data = { file = file }
139
+ handle .data = {}
114
140
115
- multi :add_handle (handle )
116
-
117
- fprintf (stderr , " Added download %s -> %s\n " , url , filename );
141
+ if on_begin (handle , url , num ) then
142
+ multi :add_handle (handle )
143
+ else
144
+ handle :reset ().data = nil
145
+ qfree :push (handle )
146
+ end
147
+ end
118
148
end
119
149
120
150
add_download = function (url , num )
@@ -143,17 +173,14 @@ on_curl_action = function(easy, fd, action)
143
173
trace (" CURL::SOCKET" , easy , s , ACTION_NAMES [action ] or action )
144
174
145
175
local context = easy .data .context
146
- if (action == curl .POLL_IN ) or (action == curl .POLL_OUT ) then
176
+
177
+ local flag = POLL_IO_FLAGS [action ]
178
+ if flag then
147
179
if not context then
148
180
context = Context .new (fd )
149
181
easy .data .context = context
150
182
end
151
- end
152
-
153
- assert (context :fileno () == fd )
154
-
155
- if action == curl .POLL_IN then context :poll (uv .READABLE , on_libuv_poll )
156
- elseif action == curl .POLL_OUT then context :poll (uv .WRITABLE , on_libuv_poll )
183
+ context :poll (flag , on_libuv_poll )
157
184
elseif action == curl .POLL_REMOVE then
158
185
if context then
159
186
easy .data .context = nil
@@ -185,20 +212,15 @@ local curl_check_multi_info = function()
185
212
186
213
local context = easy .data .context
187
214
if context then context :close () end
188
- local file = assert (easy .data .file )
189
- file :close ()
190
-
191
- easy .data = nil
192
- qfree :push (easy )
215
+ easy .data .context = nil
193
216
194
- if ok then
195
- printf (" %s DONE\n " , done_url );
196
- elseif data == " error" then
197
- printf (" %s ERROR - %s\n " , done_url , tostring (err ));
198
- end
217
+ if ok then on_end (easy , nil , done_url ) else on_end (easy , err , done_url ) end
199
218
200
- proceed_queue ()
219
+ easy :reset ().data = nil
220
+ qfree :push (easy )
201
221
end
222
+
223
+ proceed_queue ()
202
224
end
203
225
204
226
on_libuv_poll = function (handle , err , events )
0 commit comments