@@ -6,8 +6,10 @@ class MultiCurl
6
6
{
7
7
public $ baseUrl = null ;
8
8
public $ multiCurl ;
9
- public $ curls = array ();
10
- private $ nextCurlId = 1 ;
9
+ public $ windowSize = 25 ;
10
+
11
+ private $ curls = array ();
12
+ private $ activeCurls = array ();
11
13
private $ isStarted = false ;
12
14
13
15
private $ beforeSendFunction = null ;
@@ -56,7 +58,7 @@ public function addDelete($url, $query_parameters = array(), $data = array())
56
58
$ curl ->setURL ($ url , $ query_parameters );
57
59
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'DELETE ' );
58
60
$ curl ->setOpt (CURLOPT_POSTFIELDS , $ curl ->buildPostData ($ data ));
59
- $ this ->addHandle ($ curl );
61
+ $ this ->queueHandle ($ curl );
60
62
return $ curl ;
61
63
}
62
64
@@ -90,7 +92,7 @@ public function addDownload($url, $mixed_filename)
90
92
$ curl ->setOpt (CURLOPT_FILE , $ curl ->fileHandle );
91
93
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'GET ' );
92
94
$ curl ->setOpt (CURLOPT_HTTPGET , true );
93
- $ this ->addHandle ($ curl );
95
+ $ this ->queueHandle ($ curl );
94
96
return $ curl ;
95
97
}
96
98
@@ -113,7 +115,7 @@ public function addGet($url, $data = array())
113
115
$ curl ->setURL ($ url , $ data );
114
116
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'GET ' );
115
117
$ curl ->setOpt (CURLOPT_HTTPGET , true );
116
- $ this ->addHandle ($ curl );
118
+ $ this ->queueHandle ($ curl );
117
119
return $ curl ;
118
120
}
119
121
@@ -136,7 +138,7 @@ public function addHead($url, $data = array())
136
138
$ curl ->setURL ($ url , $ data );
137
139
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'HEAD ' );
138
140
$ curl ->setOpt (CURLOPT_NOBODY , true );
139
- $ this ->addHandle ($ curl );
141
+ $ this ->queueHandle ($ curl );
140
142
return $ curl ;
141
143
}
142
144
@@ -159,7 +161,7 @@ public function addOptions($url, $data = array())
159
161
$ curl ->setURL ($ url , $ data );
160
162
$ curl ->unsetHeader ('Content-Length ' );
161
163
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'OPTIONS ' );
162
- $ this ->addHandle ($ curl );
164
+ $ this ->queueHandle ($ curl );
163
165
return $ curl ;
164
166
}
165
167
@@ -183,7 +185,7 @@ public function addPatch($url, $data = array())
183
185
$ curl ->unsetHeader ('Content-Length ' );
184
186
$ curl ->setOpt (CURLOPT_CUSTOMREQUEST , 'PATCH ' );
185
187
$ curl ->setOpt (CURLOPT_POSTFIELDS , $ data );
186
- $ this ->addHandle ($ curl );
188
+ $ this ->queueHandle ($ curl );
187
189
return $ curl ;
188
190
}
189
191
@@ -225,7 +227,7 @@ public function addPost($url, $data = array(), $follow_303_with_post = false)
225
227
226
228
$ curl ->setOpt (CURLOPT_POST , true );
227
229
$ curl ->setOpt (CURLOPT_POSTFIELDS , $ curl ->buildPostData ($ data ));
228
- $ this ->addHandle ($ curl );
230
+ $ this ->queueHandle ($ curl );
229
231
return $ curl ;
230
232
}
231
233
@@ -252,7 +254,7 @@ public function addPut($url, $data = array())
252
254
$ curl ->setHeader ('Content-Length ' , strlen ($ put_data ));
253
255
}
254
256
$ curl ->setOpt (CURLOPT_POSTFIELDS , $ put_data );
255
- $ this ->addHandle ($ curl );
257
+ $ this ->queueHandle ($ curl );
256
258
return $ curl ;
257
259
}
258
260
@@ -279,7 +281,7 @@ public function addSearch($url, $data = array())
279
281
$ curl ->setHeader ('Content-Length ' , strlen ($ put_data ));
280
282
}
281
283
$ curl ->setOpt (CURLOPT_POSTFIELDS , $ put_data );
282
- $ this ->addHandle ($ curl );
284
+ $ this ->queueHandle ($ curl );
283
285
return $ curl ;
284
286
}
285
287
@@ -522,40 +524,47 @@ public function start()
522
524
return ;
523
525
}
524
526
525
- foreach ($ this ->curls as $ ch ) {
526
- $ this ->initHandle ($ ch );
527
+ $ this ->isStarted = true ;
528
+
529
+ $ window_size = $ this ->windowSize ;
530
+ if ($ window_size > count ($ this ->curls )) {
531
+ $ window_size = count ($ this ->curls );
527
532
}
528
533
529
- $ this ->isStarted = true ;
534
+ for ($ i = 0 ; $ i < $ window_size ; $ i ++) {
535
+ $ this ->initHandle (array_pop ($ this ->curls ));
536
+ }
530
537
531
538
do {
532
539
curl_multi_select ($ this ->multiCurl );
533
540
curl_multi_exec ($ this ->multiCurl , $ active );
534
541
535
542
while (!($ info_array = curl_multi_info_read ($ this ->multiCurl )) === false ) {
536
543
if ($ info_array ['msg ' ] === CURLMSG_DONE ) {
537
- foreach ($ this ->curls as $ key => $ ch ) {
544
+ foreach ($ this ->activeCurls as $ key => $ ch ) {
538
545
if ($ ch ->curl === $ info_array ['handle ' ]) {
539
546
// Set the error code for multi handles using the "result" key in the array returned by
540
547
// curl_multi_info_read(). Using curl_errno() on a multi handle will incorrectly return 0
541
548
// for errors.
542
549
$ ch ->curlErrorCode = $ info_array ['result ' ];
543
550
$ ch ->exec ($ ch ->curl );
544
- curl_multi_remove_handle ($ this ->multiCurl , $ ch ->curl );
545
- unset($ this ->curls [$ key ]);
546
551
547
- // Close open file handles and reset the curl instance.
548
- if (!($ ch ->fileHandle === null )) {
549
- $ ch ->downloadComplete ($ ch ->fileHandle );
552
+ unset($ this ->activeCurls [$ key ]);
553
+
554
+ // Start a new request before removing the handle of the completed one.
555
+ if (count ($ this ->curls ) >= 1 ) {
556
+ $ this ->initHandle (array_pop ($ this ->curls ));
550
557
}
558
+ curl_multi_remove_handle ($ this ->multiCurl , $ ch ->curl );
559
+
551
560
break ;
552
561
}
553
562
}
554
563
}
555
564
}
556
565
557
566
if (!$ active ) {
558
- $ active = count ($ this ->curls );
567
+ $ active = count ($ this ->activeCurls );
559
568
}
560
569
} while ($ active > 0 );
561
570
@@ -614,31 +623,22 @@ public function __destruct()
614
623
}
615
624
616
625
/**
617
- * Add Handle
626
+ * Queue Handle
618
627
*
619
628
* @access private
620
629
* @param $curl
621
- * @throws \ErrorException
622
630
*/
623
- private function addHandle ($ curl )
631
+ private function queueHandle ($ curl )
624
632
{
625
- $ curlm_error_code = curl_multi_add_handle ($ this ->multiCurl , $ curl ->curl );
626
- if (!($ curlm_error_code === CURLM_OK )) {
627
- throw new \ErrorException ('cURL multi add handle error: ' . curl_multi_strerror ($ curlm_error_code ));
628
- }
629
- $ this ->curls [] = $ curl ;
630
- $ curl ->id = $ this ->nextCurlId ++;
631
-
632
- if ($ this ->isStarted ) {
633
- $ this ->initHandle ($ curl );
634
- }
633
+ $ this ->curls [$ curl ->id ] = $ curl ;
635
634
}
636
635
637
636
/**
638
637
* Init Handle
639
638
*
640
639
* @access private
641
640
* @param $curl
641
+ * @throws \ErrorException
642
642
*/
643
643
private function initHandle ($ curl )
644
644
{
@@ -664,6 +664,13 @@ private function initHandle($curl)
664
664
}
665
665
$ curl ->setJsonDecoder ($ this ->jsonDecoder );
666
666
$ curl ->setXmlDecoder ($ this ->xmlDecoder );
667
+
668
+ $ curlm_error_code = curl_multi_add_handle ($ this ->multiCurl , $ curl ->curl );
669
+ if (!($ curlm_error_code === CURLM_OK )) {
670
+ throw new \ErrorException ('cURL multi add handle error: ' . curl_multi_strerror ($ curlm_error_code ));
671
+ }
672
+
673
+ $ this ->activeCurls [$ curl ->id ] = $ curl ;
667
674
$ curl ->call ($ curl ->beforeSendFunction );
668
675
}
669
676
}
0 commit comments