/** * Create the command POST data * * @param sdb the SimpleDB handle * @param params the parameter array * @return the URL, or NULL on error */ char* sdb_post(struct SDB* sdb, struct sdb_params* params) { char* urlencoded; if (SDB_FAILED(sdb_params_export(sdb, params, &urlencoded))) return NULL; return urlencoded; }
/** * Create the command URL * * @param sdb the SimpleDB handle * @param params the parameter array * @return the URL, or NULL on error */ char* sdb_url(struct SDB* sdb, struct sdb_params* params) { char* urlencoded; if (SDB_FAILED(sdb_params_export(sdb, params, &urlencoded))) return NULL; char* url = (char*) malloc(strlen(urlencoded) + 64); strcpy(url, "http://sdb.amazonaws.com/?"); strcat(url, urlencoded); free(urlencoded); return url; }
/** * Parse the response * * @param sdb the SimpleDB handle * @param curl the used Curl handle * @param post_size the post size (for statistics) * @param rec the buffer with the response * @param result the pointer to the result-set * @return the result */ int sdb_parse_result(struct SDB* sdb, CURL* curl, long post_size, struct sdb_buffer* rec, struct sdb_response** response) { // Statistics sdb_update_size_stats(sdb, curl, post_size, rec->size); // Handle internal errors if (strncmp(rec->buffer, "<html", 5) == 0) return SDB_E_AWS_INTERNAL_ERROR_2; #ifdef _DEBUG_PRINT_RESPONSE sdb->rec.buffer[rec->size] = '\0'; printf("\n%s\n\n", rec->buffer); #endif // Parse the response and check for errors if (*response == NULL) { *response = sdb_response_allocate(); } else { sdb_response_prepare_append(*response); } (*response)->internal->errout = sdb->errout; int __ret = sdb_response_parse(*response, rec->buffer, rec->size); if (SDB_FAILED(__ret)) { sdb_free(response); return __ret; } sdb->stat.box_usage += (*response)->box_usage; if ((*response)->error != 0) { __ret = (*response)->error; if (SDB_AWS_ERROR(__ret) != SDB_E_AWS_SERVICE_UNAVAILABLE) sdb_free(response); return SDB_AWS_ERROR(__ret); } return SDB_OK; }
/** * Execute a command using Curl's multi interface * * @param sdb the SimpleDB handle * @param cmd the command name * @param _params the parameters * @param next_token the next token (optional) * @param user_data the user data (optional) * @param user_data_2 the user data (optional) * @return the handle to the deferred call, or SDB_MULTI_ERROR on error */ sdb_multi sdb_execute_multi(struct SDB* sdb, const char* cmd, struct sdb_params* _params, char* next_token, void* user_data, void* user_data_2) { // Prepare the command execution struct sdb_params* params = sdb_params_alloc(_params->size + 8); if (SDB_FAILED(sdb_params_add(params, "Action", cmd))) return SDB_MULTI_ERROR; char timestamp[32]; sdb_timestamp(timestamp); if (SDB_FAILED(sdb_params_add(params, "Timestamp", timestamp))) return SDB_MULTI_ERROR; // Add the command parameters if (SDB_FAILED(sdb_params_add_all(params, _params))) return SDB_MULTI_ERROR; // Add the next token if (next_token != NULL) { if (SDB_FAILED(sdb_params_add(params, "NextToken", next_token))) return SDB_MULTI_ERROR; } // Add the required parameters if (SDB_FAILED(sdb_params_add_required(sdb, params))) return SDB_MULTI_ERROR; char* post = sdb_post(sdb, params); long postsize = strlen(post); sdb_params_free(params); // Allocate a multi-data structure struct sdb_multi_data* m = sdb_multi_alloc(sdb); assert(m); m->post = post; strncpy(m->command, cmd, SDB_LEN_COMMAND - 1); m->command[SDB_LEN_COMMAND - 1] = '\0'; m->params = sdb_params_deep_copy(_params); m->user_data = user_data; m->user_data_2 = user_data_2; m->post_size = postsize; // Create a Curl handle and defer it sdb->rec.size = 0; curl_easy_setopt(m->curl, CURLOPT_URL, AWS_URL); curl_easy_setopt(m->curl, CURLOPT_WRITEDATA, &m->rec); curl_easy_setopt(m->curl, CURLOPT_POST, 1L); curl_easy_setopt(m->curl, CURLOPT_POSTFIELDS, post); CURLMcode cr = curl_multi_add_handle(sdb->curl_multi, m->curl); // Handle Curl errors if (cr != CURLM_OK) { sdb_multi_free_one(sdb, m); return SDB_MULTI_ERROR; } // Statistics (the size statistics would be updated when the response is received) sdb->stat.num_commands++; if (strncmp(cmd, "Put", 3) == 0) sdb->stat.num_puts++; return m->curl; }
/** * Execute a command * * @param sdb the SimpleDB handle * @param cmd the command name * @param params the parameters * @param response the pointer to the result-set * @return the result */ int sdb_execute_rs(struct SDB* sdb, const char* cmd, struct sdb_params* _params, struct sdb_response** response) { // Prepare the command execution struct sdb_params* params = sdb_params_alloc(_params->size + 8); SDB_SAFE(sdb_params_add(params, "Action", cmd)); char timestamp[32]; sdb_timestamp(timestamp); SDB_SAFE(sdb_params_add(params, "Timestamp", timestamp)); // Add the command parameters SDB_SAFE(sdb_params_add_all(params, _params)); // Add the next token if (*response != NULL) { if ((*response)->has_more) { assert((*response)->internal->next_token); SDB_SAFE(sdb_params_add(params, "NextToken", (const char*) (*response)->internal->next_token)); } } // Add the required parameters SDB_SAFE(sdb_params_add_required(sdb, params)); char* post = sdb_post(sdb, params); long postsize = strlen(post); sdb_params_free(params); // Configure Curl and execute the command CURL* curl = sdb->curl_handle; sdb->rec.size = 0; curl_easy_setopt(curl, CURLOPT_URL, AWS_URL); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sdb->rec); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post); #ifdef _DEBUG_PRINT_RESPONSE curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif CURLcode cr = curl_easy_perform(curl); free(post); // Statistics if (cr == CURLE_OK) { sdb->stat.num_commands++; if (strncmp(cmd, "Put", 3) == 0) sdb->stat.num_puts++; sdb_update_size_stats(sdb, curl, postsize, sdb->rec.size); } // Handle Curl errors and internal AWS errors if (cr != CURLE_OK) return SDB_CURL_ERROR(cr); if (strncmp(sdb->rec.buffer, "<html", 5) == 0) return SDB_E_AWS_INTERNAL_ERROR_2; #ifdef _DEBUG_PRINT_RESPONSE sdb->rec.buffer[sdb->rec.size] = '\0'; printf("\n%s\n\n", sdb->rec.buffer); #endif // Parse the response and check for errors if (*response == NULL) { *response = sdb_response_allocate(); } else { sdb_response_prepare_append(*response); } (*response)->internal->errout = sdb->errout; int __ret = sdb_response_parse(*response, sdb->rec.buffer, sdb->rec.size); if (SDB_FAILED(__ret)) { sdb_free(response); return __ret; } sdb->stat.box_usage += (*response)->box_usage; if ((*response)->error != 0) { __ret = (*response)->error; if (SDB_AWS_ERROR(__ret) != SDB_E_AWS_SERVICE_UNAVAILABLE) sdb_free(response); return SDB_AWS_ERROR(__ret); } // Save the parameters in the case manual NEXT handling is allowed if (!sdb->auto_next && (*response)->has_more) { if ((*response)->internal->next == NULL) { (*response)->internal->params = sdb_params_deep_copy(_params); (*response)->internal->command = (char*) malloc(strlen(cmd) + 4); strcpy((*response)->internal->command, cmd); } else if ((*response)->internal->params == NULL) { (*response)->internal->params = (*response)->internal->next->params; (*response)->internal->command = (*response)->internal->next->command; (*response)->internal->next->params = NULL; (*response)->internal->next->command = NULL; assert((*response)->internal->params); assert((*response)->internal->command); } } return SDB_OK; }
/** * Execute a command and ignore the result-set * * @param sdb the SimpleDB handle * @param cmd the command name * @param _params the parameters * @return the result */ int sdb_execute(struct SDB* sdb, const char* cmd, struct sdb_params* _params) { // Prepare the command execution struct sdb_params* params = sdb_params_alloc(_params->size + 8); SDB_SAFE(sdb_params_add(params, "Action", cmd)); char timestamp[32]; sdb_timestamp(timestamp); SDB_SAFE(sdb_params_add(params, "Timestamp", timestamp)); // Add the command parameters SDB_SAFE(sdb_params_add_all(params, _params)); // Add the required parameters SDB_SAFE(sdb_params_add_required(sdb, params)); char* post = sdb_post(sdb, params); long postsize = strlen(post); sdb_params_free(params); // Configure Curl and execute the command CURL* curl = sdb->curl_handle; sdb->rec.size = 0; curl_easy_setopt(curl, CURLOPT_URL, AWS_URL); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &sdb->rec); curl_easy_setopt(curl, CURLOPT_POST, 1L); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post); #ifdef _DEBUG_PRINT_RESPONSE curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); #endif CURLcode cr = curl_easy_perform(curl); free(post); // Statistics if (cr == CURLE_OK) { sdb->stat.num_commands++; if (strncmp(cmd, "Put", 3) == 0) sdb->stat.num_puts++; sdb_update_size_stats(sdb, curl, postsize, sdb->rec.size); } // Handle Curl errors and internal AWS errors if (cr != CURLE_OK) return SDB_CURL_ERROR(cr); if (strncmp(sdb->rec.buffer, "<html", 5) == 0) return SDB_E_AWS_INTERNAL_ERROR_2; #ifdef _DEBUG_PRINT_RESPONSE sdb->rec.buffer[sdb->rec.size] = '\0'; printf("\n%s\n\n", sdb->rec.buffer); #endif // Parse the response and check for errors struct sdb_response response; sdb_response_init(&response); response.internal->errout = sdb->errout; int __ret = sdb_response_parse(&response, sdb->rec.buffer, sdb->rec.size); if (SDB_FAILED(__ret)) { sdb_response_cleanup(&response); return __ret; } sdb->stat.box_usage += response.box_usage; if (response.error != 0) { __ret = response.error; sdb_response_cleanup(&response); return SDB_AWS_ERROR(__ret); } // Cleanup sdb_response_cleanup(&response); return SDB_OK; }