|
11 | 11 | #include "reader.h"
|
12 | 12 | #include "recorder_utils.h"
|
13 | 13 | #include "private/region.h"
|
| 14 | +#include "private/code.h" |
14 | 15 | #include <curl/curl.h>
|
15 | 16 |
|
16 | 17 | /*============================================================================*/
|
@@ -58,20 +59,27 @@ CURL *Qiniu_Client_reset(Qiniu_Client *self);
|
58 | 59 |
|
59 | 60 | Qiniu_Error Qiniu_callex(CURL *curl, Qiniu_Buffer *resp, Qiniu_Json **ret, Qiniu_Bool simpleError, Qiniu_Buffer *resph);
|
60 | 61 |
|
61 |
| -static Qiniu_Error Get_Qiniu_UpHost(Qiniu_Client *client, const char *accessKey, const char *bucketName, Qiniu_Io_PutExtra *extra, const char **upHost) |
| 62 | +static Qiniu_Error Get_Qiniu_UpHosts(Qiniu_Client *client, const char *accessKey, const char *bucketName, Qiniu_Io_PutExtra *extra, const char *const **upHosts, size_t *upHostsCount) |
62 | 63 | {
|
63 | 64 | if (extra && extra->ipCount != 0)
|
64 | 65 | {
|
65 | 66 | Qiniu_Count oldIndex = Qiniu_Count_Inc(&extra->ipIndex);
|
66 |
| - *upHost = extra->upIps[abs(oldIndex % extra->ipCount)]; |
| 67 | + *upHosts = &extra->upIps[labs(oldIndex % extra->ipCount)]; |
| 68 | + *upHostsCount = 1; |
67 | 69 | }
|
68 | 70 | else if (extra && extra->upHost != NULL)
|
69 | 71 | {
|
70 |
| - *upHost = extra->upHost; |
| 72 | + *upHosts = &extra->upHost; |
| 73 | + *upHostsCount = 1; |
| 74 | + } |
| 75 | + else if (extra && extra->upHosts != NULL && extra->upHostsCount != 0) |
| 76 | + { |
| 77 | + *upHosts = extra->upHosts; |
| 78 | + *upHostsCount = extra->upHostsCount; |
71 | 79 | }
|
72 | 80 | else
|
73 | 81 | {
|
74 |
| - Qiniu_Error err = _Qiniu_Region_Get_Up_Host(client, accessKey, bucketName, upHost); |
| 82 | + Qiniu_Error err = _Qiniu_Region_Get_Up_Hosts(client, accessKey, bucketName, upHosts, upHostsCount); |
75 | 83 | if (err.code != Qiniu_OK.code)
|
76 | 84 | {
|
77 | 85 | return err;
|
@@ -150,48 +158,61 @@ static Qiniu_Error Qiniu_Io_call(
|
150 | 158 | {
|
151 | 159 | int retCode = 0;
|
152 | 160 | Qiniu_Error err;
|
153 |
| - struct curl_slist *headers = NULL; |
154 |
| - const char *upHost = NULL; |
| 161 | + struct curl_slist *headers; |
| 162 | + const char *const *upHosts; |
| 163 | + const char *defaultUpHosts[] = {QINIU_UP_HOST}; |
| 164 | + size_t upHostsCount; |
155 | 165 |
|
156 |
| - err = Qiniu_Client_config(self); |
| 166 | + headers = curl_slist_append(NULL, "Expect:"); |
| 167 | + err = Get_Qiniu_UpHosts(self, accessKey, bucketName, extra, &upHosts, &upHostsCount); |
157 | 168 | if (err.code != Qiniu_OK.code)
|
158 | 169 | {
|
159 | 170 | return err;
|
160 | 171 | }
|
161 |
| - err = Get_Qiniu_UpHost(self, accessKey, bucketName, extra, &upHost); |
162 |
| - if (err.code != Qiniu_OK.code) |
| 172 | + if (upHostsCount == 0) |
163 | 173 | {
|
164 |
| - return err; |
| 174 | + upHosts = defaultUpHosts; |
| 175 | + upHostsCount = 1; |
165 | 176 | }
|
166 | 177 |
|
167 |
| - headers = curl_slist_append(NULL, "Expect:"); |
168 |
| - |
169 |
| - CURL *curl = Qiniu_Client_reset(self); |
170 |
| - curl_easy_setopt(curl, CURLOPT_URL, upHost); |
171 |
| - curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
172 |
| - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |
173 |
| - |
174 |
| - //// For aborting uploading file. |
175 |
| - if (extra->upAbortCallback) |
| 178 | + for (size_t retries = 0; retries < upHostsCount && retries <= self->retriesMax; retries++) |
176 | 179 | {
|
177 |
| - curl_easy_setopt(curl, CURLOPT_READFUNCTION, Qiniu_Rd_Reader_Callback); |
178 |
| - } // if |
| 180 | + CURL *curl = Qiniu_Client_reset(self); |
| 181 | + err = Qiniu_Client_config(self); |
| 182 | + if (err.code != Qiniu_OK.code) |
| 183 | + { |
| 184 | + return err; |
| 185 | + } |
| 186 | + curl_easy_setopt(curl, CURLOPT_URL, upHosts[retries]); |
| 187 | + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
| 188 | + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |
179 | 189 |
|
180 |
| - err = Qiniu_callex(curl, &self->b, &self->root, Qiniu_False, &self->respHeader); |
181 |
| - if (err.code == Qiniu_OK.code && ret != NULL) |
182 |
| - { |
183 |
| - if (extra->callbackRetParser != NULL) |
| 190 | + //// For aborting uploading file. |
| 191 | + if (extra->upAbortCallback) |
184 | 192 | {
|
185 |
| - err = (*extra->callbackRetParser)(extra->callbackRet, self->root); |
| 193 | + curl_easy_setopt(curl, CURLOPT_READFUNCTION, Qiniu_Rd_Reader_Callback); |
| 194 | + } // if |
| 195 | + |
| 196 | + err = Qiniu_callex(curl, &self->b, &self->root, Qiniu_False, &self->respHeader); |
| 197 | + if (err.code == Qiniu_OK.code) |
| 198 | + { |
| 199 | + if (extra->callbackRetParser != NULL) |
| 200 | + { |
| 201 | + err = (*extra->callbackRetParser)(extra->callbackRet, self->root); |
| 202 | + } |
| 203 | + else if (ret != NULL) |
| 204 | + { |
| 205 | + ret->hash = Qiniu_Json_GetString(self->root, "hash", NULL); |
| 206 | + ret->key = Qiniu_Json_GetString(self->root, "key", NULL); |
| 207 | + ret->persistentId = Qiniu_Json_GetString(self->root, "persistentId", NULL); |
| 208 | + } |
| 209 | + break; |
186 | 210 | }
|
187 |
| - else |
| 211 | + else if (_Qiniu_Should_Retry(err.code) == QINIU_DONT_RETRY) |
188 | 212 | {
|
189 |
| - ret->hash = Qiniu_Json_GetString(self->root, "hash", NULL); |
190 |
| - ret->key = Qiniu_Json_GetString(self->root, "key", NULL); |
191 |
| - ret->persistentId = Qiniu_Json_GetString(self->root, "persistentId", NULL); |
| 213 | + break; |
192 | 214 | }
|
193 | 215 | }
|
194 |
| - |
195 | 216 | curl_formfree(formpost);
|
196 | 217 | curl_slist_free_all(headers);
|
197 | 218 | return err;
|
@@ -327,42 +348,56 @@ static Qiniu_Error Qiniu_Io_call_with_callback(
|
327 | 348 | {
|
328 | 349 | int retCode = 0;
|
329 | 350 | Qiniu_Error err;
|
330 |
| - struct curl_slist *headers = NULL; |
331 |
| - const char *upHost; |
| 351 | + struct curl_slist *headers; |
| 352 | + const char *const *upHosts; |
| 353 | + const char *defaultUpHosts[] = {QINIU_UP_HOST}; |
| 354 | + size_t upHostsCount; |
332 | 355 |
|
333 |
| - CURL *curl = Qiniu_Client_reset(self); |
334 |
| - err = Qiniu_Client_config(self); |
| 356 | + headers = curl_slist_append(NULL, "Expect:"); |
| 357 | + err = Get_Qiniu_UpHosts(self, accessKey, bucketName, extra, &upHosts, &upHostsCount); |
335 | 358 | if (err.code != Qiniu_OK.code)
|
336 | 359 | {
|
337 | 360 | return err;
|
338 | 361 | }
|
339 |
| - err = Get_Qiniu_UpHost(self, accessKey, bucketName, extra, &upHost); |
340 |
| - if (err.code != Qiniu_OK.code) |
| 362 | + if (upHostsCount == 0) |
341 | 363 | {
|
342 |
| - return err; |
| 364 | + upHosts = defaultUpHosts; |
| 365 | + upHostsCount = 1; |
343 | 366 | }
|
344 | 367 |
|
345 |
| - headers = curl_slist_append(NULL, "Expect:"); |
| 368 | + for (size_t retries = 0; retries < upHostsCount && retries <= self->retriesMax; retries++) |
| 369 | + { |
| 370 | + CURL *curl = Qiniu_Client_reset(self); |
| 371 | + err = Qiniu_Client_config(self); |
| 372 | + if (err.code != Qiniu_OK.code) |
| 373 | + { |
| 374 | + return err; |
| 375 | + } |
346 | 376 |
|
347 |
| - curl_easy_setopt(curl, CURLOPT_URL, upHost); |
348 |
| - curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
349 |
| - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |
350 |
| - curl_easy_setopt(curl, CURLOPT_READFUNCTION, rdr); |
| 377 | + curl_easy_setopt(curl, CURLOPT_URL, upHosts[retries]); |
| 378 | + curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); |
| 379 | + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); |
| 380 | + curl_easy_setopt(curl, CURLOPT_READFUNCTION, rdr); |
351 | 381 |
|
352 |
| - err = Qiniu_callex(curl, &self->b, &self->root, Qiniu_False, &self->respHeader); |
353 |
| - if (err.code == Qiniu_OK.code && ret != NULL) |
354 |
| - { |
355 |
| - if (extra->callbackRetParser != NULL) |
| 382 | + err = Qiniu_callex(curl, &self->b, &self->root, Qiniu_False, &self->respHeader); |
| 383 | + if (err.code == Qiniu_OK.code) |
356 | 384 | {
|
357 |
| - err = (*extra->callbackRetParser)(extra->callbackRet, self->root); |
| 385 | + if (extra->callbackRetParser != NULL) |
| 386 | + { |
| 387 | + err = (*extra->callbackRetParser)(extra->callbackRet, self->root); |
| 388 | + } |
| 389 | + else if (ret != NULL) |
| 390 | + { |
| 391 | + ret->hash = Qiniu_Json_GetString(self->root, "hash", NULL); |
| 392 | + ret->key = Qiniu_Json_GetString(self->root, "key", NULL); |
| 393 | + } |
| 394 | + break; |
358 | 395 | }
|
359 |
| - else |
| 396 | + else if (_Qiniu_Should_Retry(err.code) == QINIU_DONT_RETRY) |
360 | 397 | {
|
361 |
| - ret->hash = Qiniu_Json_GetString(self->root, "hash", NULL); |
362 |
| - ret->key = Qiniu_Json_GetString(self->root, "key", NULL); |
| 398 | + break; |
363 | 399 | }
|
364 | 400 | }
|
365 |
| - |
366 | 401 | curl_formfree(formpost);
|
367 | 402 | curl_slist_free_all(headers);
|
368 | 403 | return err;
|
|
0 commit comments