Exemplo n.º 1
0
/**
 * 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;
}
Exemplo n.º 2
0
/**
 * 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;
}
Exemplo n.º 3
0
/**
 * 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;
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
/**
 * 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;
}
Exemplo n.º 6
0
/**
 * 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;
}