aboutsummaryrefslogtreecommitdiff
path: root/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/util.c')
-rw-r--r--src/util.c164
1 files changed, 107 insertions, 57 deletions
diff --git a/src/util.c b/src/util.c
index 7bf13ac..9f8533f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1,5 +1,5 @@
/* This file is part of Eclat.
- Copyright (C) 2012-2015 Sergey Poznyakoff.
+ Copyright (C) 2012-2018 Sergey Poznyakoff.
Eclat is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -213,79 +213,130 @@ describe_request_update(eclat_command_env_t *env, int argc, char **argv,
void
describe_request_create(eclat_command_env_t *env, int argc, char **argv,
- const char *uparm)
+ const char *uparm)
{
describe_request_update(env, argc, argv, uparm, 1, NULL);
}
-
+
+unsigned long max_retry_sleep = 600;
+unsigned long max_retry_time = 1800;
+
int
-eclat_send_request(CURL *curl, struct ec2_request *req)
+eclat_send_request(struct ec2_request *orig, struct grecs_node **ret_tree)
{
char *url;
CURLcode res;
- int rc = 0;
+ int ret = 0;
struct curl_slist *headers = NULL;
+ struct eclat_io *io;
+ time_t endtime;
+ unsigned long tts, t;
- /* Prepare the request */
- if (req->flags & EC2_RF_POST) {
- eclat_request_finalize(req);
- curl_easy_setopt(curl, CURLOPT_POST, 1);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDS, req->postdata);
- curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE,
- strlen(req->postdata));
+ io = eclat_io_init(0);
+ if (!io) {
+ err("cannot initialize IO structure");
+ return -1;
}
- eclat_request_sign(req, secret_key, signature_version);
- url = eclat_request_to_url(req);
- curl_easy_setopt(curl, CURLOPT_URL, url);
- debug(ECLAT_DEBCAT_MAIN, 1, ("using URL: %s", url));
- free(url);
- if (req->headers) {
- struct grecs_list_entry *ep;
- struct grecs_txtacc *acc;
- int rc;
-
- acc = grecs_txtacc_create();
-
- for (ep = req->headers->head; ep; ep = ep->next) {
- struct ec2_param *p = ep->data;
- char *str;
-
- grecs_txtacc_grow_string(acc, p->name);
- grecs_txtacc_grow_char(acc, ':');
- grecs_txtacc_grow_string(acc, p->value);
- grecs_txtacc_grow_char(acc, 0);
- str = grecs_txtacc_finish(acc, 0);
- debug(ECLAT_DEBCAT_MAIN, 1, ("HDR: %s", str));
- headers = curl_slist_append(headers, str);
- grecs_txtacc_free_string(acc, str);
+ endtime = time(NULL) + max_retry_time;
+ tts = 1;
+ do {
+ struct grecs_node *node;
+ /* Prepare the request */
+ struct ec2_request *req = eclat_request_dup(orig);
+ if (req->flags & EC2_RF_POST) {
+ eclat_request_finalize(orig);
+ curl_easy_setopt(io->curl, CURLOPT_POST, 1);
+ curl_easy_setopt(io->curl, CURLOPT_POSTFIELDS,
+ req->postdata);
+ curl_easy_setopt(io->curl, CURLOPT_POSTFIELDSIZE,
+ strlen(req->postdata));
}
+ eclat_request_sign(req, secret_key, signature_version);
+ url = eclat_request_to_url(req);
+ curl_easy_setopt(io->curl, CURLOPT_URL, url);
+ debug(ECLAT_DEBCAT_MAIN, 1, ("using URL: %s", url));
+ free(url);
+ if (req->headers) {
+ struct grecs_list_entry *ep;
+ struct grecs_txtacc *acc;
+ int rc;
+
+ acc = grecs_txtacc_create();
+
+ for (ep = req->headers->head; ep; ep = ep->next) {
+ struct ec2_param *p = ep->data;
+ char *str;
+
+ grecs_txtacc_grow_string(acc, p->name);
+ grecs_txtacc_grow_char(acc, ':');
+ grecs_txtacc_grow_string(acc, p->value);
+ grecs_txtacc_grow_char(acc, 0);
+ str = grecs_txtacc_finish(acc, 0);
+ debug(ECLAT_DEBCAT_MAIN, 1, ("HDR: %s", str));
+
+ headers = curl_slist_append(headers, str);
+ grecs_txtacc_free_string(acc, str);
+ }
- rc = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
- grecs_txtacc_free(acc);
+ rc = curl_easy_setopt(io->curl, CURLOPT_HTTPHEADER,
+ headers);
+ grecs_txtacc_free(acc);
- if (rc)
- die(EX_SOFTWARE,
- "failed to add headers: %s",
- curl_easy_strerror(rc));
- }
+ if (rc)
+ die(EX_SOFTWARE,
+ "failed to add headers: %s",
+ curl_easy_strerror(rc));
+ }
- if (req->flags & EC2_RF_POST)
- debug(ECLAT_DEBCAT_MAIN, 1, ("DATA: %s", req->postdata));
+ if (req->flags & EC2_RF_POST)
+ debug(ECLAT_DEBCAT_MAIN, 1,
+ ("DATA: %s", req->postdata));
- if (dry_run_mode)
- debug(ECLAT_DEBCAT_MAIN, 1, ("not sending request"));
- else {
- res = curl_easy_perform(curl);
+ if (dry_run_mode)
+ debug(ECLAT_DEBCAT_MAIN, 1, ("not sending request"));
+ else {
+ res = curl_easy_perform(io->curl);
+ if (res == CURLE_OK) {
+ *ret_tree = eclat_io_finish(io);
+ } else {
+ err("CURL: %s", curl_easy_strerror(res));
+ ret = 1;
+ }
+ }
+
+ curl_slist_free_all(headers);
+ eclat_request_free(req);
+
+ if (ret)
+ break;
- if (res != CURLE_OK) {
- err("CURL: %s", curl_easy_strerror(res));
- rc = 1;
+ node = grecs_find_node(*ret_tree,
+ ".Response.Errors.Error.Code");
+ if (!node)
+ break;
+ if (node->type != grecs_node_stmt
+ || node->v.value->type == GRECS_TYPE_STRING) {
+ err("unexpectedly formatted error code");
+ break;
}
- }
- eclat_request_free(req);
- curl_slist_free_all(headers);
- return rc;
+
+ if (strcmp(node->v.value->v.string,
+ "Client.RequestLimitExceeded"))
+ break;
+
+ t = random() % tts;
+ sleep(t);
+ if (tts < max_retry_sleep) {
+ tts <<= 1;
+ if (tts == 0 || tts > max_retry_sleep)
+ tts = max_retry_sleep;
+ }
+ } while (time(NULL) < endtime);
+
+ eclat_io_free(io);
+
+ return ret;
}
int
@@ -429,7 +480,6 @@ char *instance_store_credentials_path = "meta-data/iam/security-credentials";
static CURL *
get_curl(struct grecs_txtacc *acc)
{
- CURLcode res;
CURL *curl = instance_store_curl_new(acc);
eclat_set_curl_trace(curl, debug_level(ECLAT_DEBCAT_CURL));

Return to:

Send suggestions and report system problems to the System administrator.