Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 213 lines (187 sloc) 5.393 kb
807bd87 @jmathai Added EpiCurl.
authored
1 <?php
2 class EpiCurl
3 {
4 const timeout = 3;
5 static $inst = null;
6 static $singleton = 0;
7 private $mc;
8 private $msgs;
9 private $running;
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
10 private $execStatus;
11 private $selectStatus;
12 private $sleepIncrement = 1.1;
807bd87 @jmathai Added EpiCurl.
authored
13 private $requests = array();
14 private $responses = array();
15 private $properties = array();
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
16 private static $timers = array();
807bd87 @jmathai Added EpiCurl.
authored
17
18 function __construct()
19 {
20 if(self::$singleton == 0)
21 {
22 throw new Exception('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = EpiCurl::getInstance();');
23 }
24
25 $this->mc = curl_multi_init();
26 $this->properties = array(
27 'code' => CURLINFO_HTTP_CODE,
28 'time' => CURLINFO_TOTAL_TIME,
29 'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD,
8cd828f @jmathai Adding optimizations to EpiCurl and fixing a bug where it would hang …
authored
30 'type' => CURLINFO_CONTENT_TYPE,
31 'url' => CURLINFO_EFFECTIVE_URL
807bd87 @jmathai Added EpiCurl.
authored
32 );
33 }
34
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
35 public function addEasyCurl($ch)
36 {
37 $key = $this->getKey($ch);
38 $this->requests[$key] = $ch;
39 curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback'));
40 $done = array('handle' => $ch);
41 $this->storeResponse($done, false);
42 $this->startTimer($key);
43 return new EpiCurlManager($key);
44 }
45
807bd87 @jmathai Added EpiCurl.
authored
46 public function addCurl($ch)
47 {
5ce7b8a @jmathai Added support for accessing the response headers.
authored
48 $key = $this->getKey($ch);
807bd87 @jmathai Added EpiCurl.
authored
49 $this->requests[$key] = $ch;
5ce7b8a @jmathai Added support for accessing the response headers.
authored
50 curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback'));
807bd87 @jmathai Added EpiCurl.
authored
51
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
52 $code = curl_multi_add_handle($this->mc, $ch);
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
53 $this->startTimer($key);
aa30f6e @jmathai Added APC cache option to EpiCache.
authored
54
55 // (1)
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
56 if($code === CURLM_OK || $code === CURLM_CALL_MULTI_PERFORM)
807bd87 @jmathai Added EpiCurl.
authored
57 {
aa30f6e @jmathai Added APC cache option to EpiCache.
authored
58 do {
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
59 $code = $this->execStatus = curl_multi_exec($this->mc, $this->running);
60 } while ($this->execStatus === CURLM_CALL_MULTI_PERFORM);
aa30f6e @jmathai Added APC cache option to EpiCache.
authored
61
807bd87 @jmathai Added EpiCurl.
authored
62 return new EpiCurlManager($key);
63 }
64 else
65 {
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
66 return $code;
807bd87 @jmathai Added EpiCurl.
authored
67 }
68 }
69
70 public function getResult($key = null)
71 {
72 if($key != null)
73 {
74 if(isset($this->responses[$key]))
75 {
76 return $this->responses[$key];
77 }
78
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
79 $innerSleepInt = $outerSleepInt = 1;
80 while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM))
807bd87 @jmathai Added EpiCurl.
authored
81 {
360e37e @jmathai Casting value to usleep to int.
authored
82 usleep(intval($outerSleepInt));
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
83 $outerSleepInt = intval(max(1, ($outerSleepInt*$this->sleepIncrement)));
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
84 $ms=curl_multi_select($this->mc, 0);
85 if($ms > 0)
807bd87 @jmathai Added EpiCurl.
authored
86 {
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
87 do{
88 $this->execStatus = curl_multi_exec($this->mc, $this->running);
360e37e @jmathai Casting value to usleep to int.
authored
89 usleep(intval($innerSleepInt));
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
90 $innerSleepInt = intval(max(1, ($innerSleepInt*$this->sleepIncrement)));
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
91 }while($this->execStatus==CURLM_CALL_MULTI_PERFORM);
8cd828f @jmathai Adding optimizations to EpiCurl and fixing a bug where it would hang …
authored
92 $innerSleepInt = 1;
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
93 }
76a2343 @jmathai Fixed some formatting and moved the removal of the curl handle outsid…
authored
94 $this->storeResponses();
5ce7b8a @jmathai Added support for accessing the response headers.
authored
95 if(isset($this->responses[$key]['data']))
76a2343 @jmathai Fixed some formatting and moved the removal of the curl handle outsid…
authored
96 {
97 return $this->responses[$key];
98 }
99 $runningCurrent = $this->running;
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
100 }
101 return null;
807bd87 @jmathai Added EpiCurl.
authored
102 }
103 return false;
104 }
105
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
106 public static function getSequence()
107 {
108 return new EpiSequence(self::$timers);
109 }
110
111 public static function getTimers()
112 {
113 return self::$timers;
114 }
115
5ce7b8a @jmathai Added support for accessing the response headers.
authored
116 private function getKey($ch)
117 {
118 return (string)$ch;
119 }
120
121 private function headerCallback($ch, $header)
122 {
123 $_header = trim($header);
124 $colonPos= strpos($_header, ':');
125 if($colonPos > 0)
126 {
127 $key = substr($_header, 0, $colonPos);
128 $val = preg_replace('/^\W+/','',substr($_header, $colonPos));
129 $this->responses[$this->getKey($ch)]['headers'][$key] = $val;
130 }
131 return strlen($header);
132 }
133
807bd87 @jmathai Added EpiCurl.
authored
134 private function storeResponses()
135 {
136 while($done = curl_multi_info_read($this->mc))
137 {
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
138 $this->storeResponse($done);
139 }
140 }
141
b468694 @jmathai Removing store response call from callback function.
authored
142 private function storeResponse($done, $isAsynchronous = true)
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
143 {
b468694 @jmathai Removing store response call from callback function.
authored
144 $key = $this->getKey($done['handle']);
145 $this->stopTimer($key, $done);
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
146 if($isAsynchronous)
b468694 @jmathai Removing store response call from callback function.
authored
147 $this->responses[$key]['data'] = curl_multi_getcontent($done['handle']);
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
148 else
b468694 @jmathai Removing store response call from callback function.
authored
149 $this->responses[$key]['data'] = curl_exec($done['handle']);
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
150
151 foreach($this->properties as $name => $const)
152 {
b468694 @jmathai Removing store response call from callback function.
authored
153 $this->responses[$key][$name] = curl_getinfo($done['handle'], $const);
807bd87 @jmathai Added EpiCurl.
authored
154 }
c365e61 @jmathai When in synchronous mode use curl instead of multi curl.
authored
155 if($isAsynchronous)
b468694 @jmathai Removing store response call from callback function.
authored
156 curl_multi_remove_handle($this->mc, $done['handle']);
157 curl_close($done['handle']);
807bd87 @jmathai Added EpiCurl.
authored
158 }
159
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
160 private function startTimer($key)
161 {
162 self::$timers[$key]['start'] = microtime(true);
163 }
164
165 private function stopTimer($key, $done)
166 {
167 self::$timers[$key]['end'] = microtime(true);
168 self::$timers[$key]['api'] = curl_getinfo($done['handle'], CURLINFO_EFFECTIVE_URL);
169 self::$timers[$key]['time'] = curl_getinfo($done['handle'], CURLINFO_TOTAL_TIME);
170 self::$timers[$key]['code'] = curl_getinfo($done['handle'], CURLINFO_HTTP_CODE);
171 }
172
807bd87 @jmathai Added EpiCurl.
authored
173 static function getInstance()
174 {
175 if(self::$inst == null)
176 {
177 self::$singleton = 1;
178 self::$inst = new EpiCurl();
179 }
180
181 return self::$inst;
182 }
183 }
184
185 class EpiCurlManager
186 {
187 private $key;
188 private $epiCurl;
189
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
190 public function __construct($key)
807bd87 @jmathai Added EpiCurl.
authored
191 {
192 $this->key = $key;
193 $this->epiCurl = EpiCurl::getInstance();
194 }
195
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
196 public function __get($name)
807bd87 @jmathai Added EpiCurl.
authored
197 {
198 $responses = $this->epiCurl->getResult($this->key);
01a4c0d @jmathai Adding an isset check before returning from EpiCurl. This keeps a no…
authored
199 return isset($responses[$name]) ? $responses[$name] : null;
807bd87 @jmathai Added EpiCurl.
authored
200 }
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
201
b69ce31 @jmathai Adding a sequencer for api calls to see which calls have latency and …
authored
202 public function __isset($name)
68d03f6 @jmathai Fixed cpu usage in EpiCurl. Problem reported by splitweet devs.
authored
203 {
204 $val = self::__get($name);
205 return empty($val);
206 }
807bd87 @jmathai Added EpiCurl.
authored
207 }
aa30f6e @jmathai Added APC cache option to EpiCache.
authored
208
209 /*
210 * Credits:
211 * - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success.
212 */
Something went wrong with that request. Please try again.