示例#1
0
/* gets information back from any of the nodes in the cluster */
int
citrusleaf_info_cluster(as_cluster *cluster, char *names, char **values_r, bool send_asis, bool check_bounds, int timeout_ms)
{
	if (timeout_ms == 0) {
		timeout_ms = 100; // milliseconds
	}
	
	uint64_t start = cf_getms();
	uint64_t end = start + timeout_ms;
	int ret = -1;

	as_nodes* nodes = as_nodes_reserve(cluster);
	
	for (uint32_t i = 0; i < nodes->size; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		char* values = 0;
		
		if (citrusleaf_info_host_auth(cluster, sa_in, names, &values, (int)(end - cf_getms()), send_asis, check_bounds) == 0) {
			*values_r = values;
			ret = 0;
			break;
		}
		
		if (cf_getms() >= end) {
			ret = -2;
			break;
		}
	}
	as_nodes_release(nodes);
	return ret;
}
static bool
aerospike_udf_put_is_done(aerospike* as, as_error * err, const as_policy_info* policy, char* filter)
{
	// Query all nodes for task completion status.
	bool done = true;
	as_nodes* nodes = as_nodes_reserve(as->cluster);
	
	for (uint32_t i = 0; i < nodes->size && done; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		
		char* response = 0;
		as_status status = aerospike_info_socket_address(as, err, policy, sa_in, "udf-list", &response);
		
		if (status == AEROSPIKE_OK) {
			char* p = strstr(response, filter);
			
			if (! p) {
				done = false;
			}
			free(response);
		}
	}
	as_nodes_release(nodes);
	return done;
}
示例#3
0
as_status
aerospike_job_info(
	aerospike* as, as_error* err, const as_policy_info* policy, const char* module, uint64_t job_id,
	bool stop_if_in_progress, as_job_info* info)
{
	as_error_reset(err);
	
	if (! policy) {
		policy = &as->config.policies.info;
	}

	char command[128];
	sprintf(command, "jobs:module=%s;cmd=get-job;trid=%" PRIu64 "\n", module, job_id);

	info->status = AS_JOB_STATUS_UNDEF;
	info->progress_pct = 0;
	info->records_read = 0;
		
	as_status status = AEROSPIKE_ERR_CLUSTER;
	uint64_t deadline = as_socket_deadline(policy->timeout);
	as_cluster* cluster = as->cluster;
	as_nodes* nodes = as_nodes_reserve(cluster);
	
	for (uint32_t i = 0; i < nodes->size; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		char* response = 0;
		
		status = as_info_command_host(cluster, err, sa_in, command, true, deadline, &response);
		
		if (status == AEROSPIKE_OK) {
			as_job_process(response, info);
			free(response);
			
			if (stop_if_in_progress && info->status == AS_JOB_STATUS_INPROGRESS) {
				break;
			}
		}
		else if (status == AEROSPIKE_ERR_RECORD_NOT_FOUND) {
			if (info->status == AS_JOB_STATUS_UNDEF) {
				info->status = AS_JOB_STATUS_COMPLETED;
			}
			as_error_reset(err);
			status = AEROSPIKE_OK;
		}
		else {
			if (status != AEROSPIKE_ERR_CLUSTER) {
				break;
			}
		}
	}
	as_nodes_release(nodes);
	return status;
}
示例#4
0
int
citrusleaf_info_cluster_foreach(
	as_cluster *cluster, const char *command, bool send_asis, bool check_bounds, int timeout_ms, void *udata,
	bool (*callback)(const as_node * node, const struct sockaddr_in * sa_in, const char *command, char *value, void *udata)
)
{
	//Usage Notes:
	//udata = memory allocated by caller, passed back to the caller callback function, ufn()
	//command = command string, memory allocated by caller, caller must free it, passed to server for execution
	//value = memory allocated by c-client for caller, caller must free it after using it.
	
	if (timeout_ms == 0) {
		timeout_ms = 100; // milliseconds
	}
	
	uint64_t start = cf_getms();
	uint64_t end = start + timeout_ms;
	int ret = 0;

	as_nodes* nodes = as_nodes_reserve(cluster);
	
	for (uint32_t i = 0; i < nodes->size; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		char* value = 0;

		if (citrusleaf_info_host_auth(cluster, sa_in, (char *)command, &value, (int)(end - cf_getms()), send_asis, check_bounds) == 0) {
			bool status = callback(node, sa_in, command, value, udata);
			
			if (value) {
				free(value);
			}
			
			if(! status) {
				ret = -1;
				break;
			}
		}
		
		if (cf_getms() >= end) {
			ret = -2;
			break;
		}
	}
	as_nodes_release(nodes);
	return ret;
}
/**
 *	Send an info request to the entire cluster.
 *
 *	~~~~~~~~~~{.c}
 *	if ( aerospike_info_foreach(&as, &err, NULL, "info", callback, NULL) != AEROSPIKE_OK ) {
 *		// handle error
 *	}
 *	~~~~~~~~~~
 *
 *	The callback takes a response string. The caller should not free this string.
 *
 *	~~~~~~~~~~{.c}
 *	bool callback(const as_error * err, const as_node * node, const char * req, char * res, void * udata) {
 *		// handle response
 *	}
 *	~~~~~~~~~~
 *
 *
 *	@param as			The aerospike instance to use for this operation.
 *	@param err			The as_error to be populated if an error occurs.
 *	@param policy		The policy to use for this operation. If NULL, then the default policy will be used.
 *	@param req			The info request to send.
 *	@param callback		The function to call when a response is received.
 *	@param udata		User-data to send to the callback.
 *
 *	@return AEROSPIKE_OK on success. Otherwise an error.
 *
 *	@ingroup info_operations
 */
as_status aerospike_info_foreach(
	aerospike * as, as_error * err, const as_policy_info * policy, const char * req,
	aerospike_info_foreach_callback callback, void * udata)
{
	as_error_reset(err);
	
	if (! policy) {
		policy = &as->config.policies.info;
	}
	
	as_status status = AEROSPIKE_ERR_CLUSTER;
	uint64_t deadline = as_socket_deadline(policy->timeout);
	as_cluster* cluster = as->cluster;
	as_nodes* nodes = as_nodes_reserve(cluster);
	
	for (uint32_t i = 0; i < nodes->size; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		char* response = 0;
	
		status = as_info_command_host(cluster, err, sa_in, (char*)req, policy->send_as_is, deadline, &response);
		
		if (status == AEROSPIKE_OK) {
			bool result = callback(err, node, req, response, udata);
			free(response);
			
			if (! result) {
				status = AEROSPIKE_ERR_QUERY_ABORTED;
				break;
			}
		}
		else {
			if (status != AEROSPIKE_ERR_CLUSTER) {
				break;
			}
		}
	}
	as_nodes_release(nodes);
	return status;
}
static bool
aerospike_index_create_is_done(aerospike* as, as_error * err, as_policy_info* policy, char* command)
{
	// Index is not done if any node reports percent completed < 100.
	// Errors are ignored and considered done.
	bool done = true;
	as_nodes* nodes = as_nodes_reserve(as->cluster);
	
	for (uint32_t i = 0; i < nodes->size && done; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		
		char* response = 0;
		as_status status = aerospike_info_socket_address(as, err, policy, sa_in, command, &response);
		
		if (status == AEROSPIKE_OK) {
			char* find = "load_pct=";
			char* p = strstr(response, find);
			
			if (p) {
				p += strlen(find);
				char* q = strchr(p, ';');
				
				if (q) {
					*q = 0;
				}
				
				int pct = atoi(p);
				
				if (pct >= 0 && pct < 100) {
					done = false;
				}
			}
			cf_free(response);
		}
	}
	as_nodes_release(nodes);
	return done;
}
/**
 *	Send an info request to a node in the cluster.  If node request fails, send request to the next
 *	node in the cluster.  Repeat until the node request succeeds. The response must be freed by 
 *	the caller on success.
 *
 *	~~~~~~~~~~{.c}
 *	char * res = NULL;
 *	if ( aerospike_info_any(&as, &err, NULL, "info", &res) != AEROSPIKE_OK ) {
 *		// handle error
 *	}
 *	else {
 *		// handle response
 *		free(res);
 *		res = NULL;
 *	}
 *	~~~~~~~~~~
 *
 *	@param as			The aerospike instance to use for this operation.
 *	@param err			The as_error to be populated if an error occurs.
 *	@param policy		The policy to use for this operation. If NULL, then the default policy will be used.
 *	@param req			The info request to send.
 *	@param res			The response from the node. The response will be a NULL terminated string, allocated by the function, and must be freed by the caller.
 *
 *	@return AEROSPIKE_OK on success. Otherwise an error.
 *
 *	@ingroup info_operations
 */
as_status aerospike_info_any(
	aerospike * as, as_error * err, const as_policy_info * policy,
	const char * req, char ** res)
{
	as_error_reset(err);
	
	if (! policy) {
		policy = &as->config.policies.info;
	}
	
	as_status status = AEROSPIKE_ERR_CLUSTER;
	uint64_t deadline = as_socket_deadline(policy->timeout);
	as_cluster* cluster = as->cluster;
	as_nodes* nodes = as_nodes_reserve(cluster);
	bool loop = true;
	
	for (uint32_t i = 0; i < nodes->size && loop; i++) {
		as_node* node = nodes->array[i];
		struct sockaddr_in* sa_in = as_node_get_address(node);
		status = as_info_command_host(cluster, err, sa_in, (char*)req, policy->send_as_is, deadline, res);
		
		switch (status) {
			case AEROSPIKE_OK:
			case AEROSPIKE_ERR_TIMEOUT:
			case AEROSPIKE_ERR_INDEX_FOUND:
			case AEROSPIKE_ERR_INDEX_NOT_FOUND:
				loop = false;
				break;
				
			default:
				break;
		}
	}
	as_nodes_release(nodes);
	return status;
}
/**
 *******************************************************************************************************
 * Callback for as_info_foreach().
 *
 * @param err                   The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param node                  The current as_node object for which the
 *                              callback is fired by c client.
 * @param req                   The info request string.
 * @param res                   The info response string for current node.
 * @pram udata                  The callback udata containing the host_lookup
 *                              array and the return zval to be populated with
 *                              an entry for current node's info response with
 *                              the node's ID as the key.
 *
 * Returns true if callback is successful, Otherwise false.
 *******************************************************************************************************
 */
static bool AerospikeClient_Info_each(as_error * err, const as_node * node, const char * req, char * res, void * udata)
{
	PyObject * py_err = NULL;
	PyObject * py_ustr = NULL;
	PyObject * py_out = NULL;
	foreach_callback_info_udata* udata_ptr = (foreach_callback_info_udata *) udata;
	struct sockaddr_in* addr = NULL;


	if ( err && err->code != AEROSPIKE_OK ) {
		as_error_update(err, err->code, NULL);
        goto CLEANUP;
	}
	else if ( res != NULL ) {
		char * out = strchr(res,'\t');
		if ( out != NULL ) {
			out++;
			py_out = PyStr_FromString(out);
		}
		else {
			py_out = PyStr_FromString(res);
		}
	}

	if ( py_err == NULL ) {
		Py_INCREF(Py_None);
		py_err = Py_None;
	}

	if ( py_out == NULL ) {
		Py_INCREF(Py_None);
		py_out = Py_None;
	}

	PyObject * py_res = PyTuple_New(2);
	PyTuple_SetItem(py_res, 0, py_err);
	PyTuple_SetItem(py_res, 1, py_out);

	if(udata_ptr->host_lookup_p) {
		PyObject * py_hosts = (PyObject *)udata_ptr->host_lookup_p;
			if ( py_hosts && PyList_Check(py_hosts) ) {
				addr = as_node_get_address((as_node *)node);
				int size = (int) PyList_Size(py_hosts);
				for ( int i = 0; i < size && i < AS_CONFIG_HOSTS_SIZE; i++ ) {
					char * host_addr = NULL;
					int port = -1;
					PyObject * py_host = PyList_GetItem(py_hosts, i);
					if ( PyTuple_Check(py_host) && PyTuple_Size(py_host) == 2 ) {
						PyObject * py_addr = PyTuple_GetItem(py_host,0);
						PyObject * py_port = PyTuple_GetItem(py_host,1);
						if ( PyStr_Check(py_addr) ) {
							host_addr = PyStr_AsString(py_addr);
						}
						else if (PyUnicode_Check(py_addr)) {
							py_ustr = PyUnicode_AsUTF8String(py_addr);
							host_addr = PyStr_AsString(py_ustr);
						} else {
							as_error_update(&udata_ptr->error, AEROSPIKE_ERR_PARAM, "Host address is of type incorrect");
							if (py_res) {
								Py_DECREF(py_res);
							}
							return false;
						}
						if ( PyInt_Check(py_port) ) {
							port = (uint16_t) PyInt_AsLong(py_port);
						}
						else if ( PyLong_Check(py_port) ) {
							port = (uint16_t) PyLong_AsLong(py_port);
						} else {
							break;
						}
						char ip_port[IP_PORT_MAX_LEN];
						inet_ntop(addr->sin_family, &(addr->sin_addr), ip_port, INET_ADDRSTRLEN);
						if( (!strcmp(host_addr,ip_port)) && (port
												== ntohs(addr->sin_port))) {
							PyObject * py_nodes = (PyObject *) udata_ptr->udata_p;
							PyDict_SetItemString(py_nodes, node->name, py_res);
						}	
					}
				}
			} else if ( !PyList_Check( py_hosts )){
				as_error_update(&udata_ptr->error, AEROSPIKE_ERR_PARAM, "Hosts should be specified in a list.");
				goto CLEANUP;
			}
	} else {
		PyObject * py_nodes = (PyObject *) udata_ptr->udata_p;
		PyDict_SetItemString(py_nodes, node->name, py_res);
	}
	Py_DECREF(py_res);
CLEANUP:
	if ( udata_ptr->error.code != AEROSPIKE_OK ) {
		PyObject * py_err = NULL;
		error_to_pyobject( &udata_ptr->error, &py_err);
		PyObject *exception_type = raise_exception(&udata_ptr->error);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		return NULL;
	}
	if ( err->code != AEROSPIKE_OK ) {
		PyObject * py_err = NULL;
		error_to_pyobject(err, &py_err);
		PyObject *exception_type = raise_exception(err);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		return NULL;
	}
	return true;
}
示例#9
0
/**
 *******************************************************************************************************
 * Callback for as_info_foreach().
 *
 * @param err                   The as_error to be populated by the function
 *                              with the encountered error if any.
 * @param node                  The current as_node object for which the
 *                              callback is fired by c client.
 * @param req                   The info request string.
 * @param res                   The info response string for current node.
 * @pram udata                  The callback udata containing the host_lookup
 *                              array and the return zval to be populated with
 *                              an entry for current node's info response with
 *                              the node's ID as the key.
 *
 * Returns true if callback is successful, Otherwise false.
 *******************************************************************************************************
 */
static bool AerospikeClient_Info_each(as_error * err, const as_node * node, const char * req, char * res, void * udata)
{
	PyObject * py_err = NULL;
	PyObject * py_ustr = NULL;
	PyObject * py_out = NULL;
	foreach_callback_info_udata* udata_ptr = (foreach_callback_info_udata *) udata;
	as_address* addr = NULL;

	// Need to make sure we have the GIL since we're back in python land now
	PyGILState_STATE gil_state = PyGILState_Ensure();

	if (err && err->code != AEROSPIKE_OK) {
		as_error_update(err, err->code, NULL);
		goto CLEANUP;
	}
	else if (res) {
		char * out = strchr(res,'\t');
		if (out) {
			out++;
			py_out = PyString_FromString(out);
		}
		else {
			py_out = PyString_FromString(res);
		}
	}

	if (!py_err) {
		Py_INCREF(Py_None);
		py_err = Py_None;
	}

	if (!py_out) {
		Py_INCREF(Py_None);
		py_out = Py_None;
	}

	PyObject * py_res = PyTuple_New(2);
	PyTuple_SetItem(py_res, 0, py_err);
	PyTuple_SetItem(py_res, 1, py_out);

	if (udata_ptr->host_lookup_p) {
		PyObject * py_hosts = (PyObject *)udata_ptr->host_lookup_p;
			if (py_hosts && PyList_Check(py_hosts)) {
				addr = as_node_get_address((as_node *)node);
				int size = (int) PyList_Size(py_hosts);
				for (int i = 0; i < size; i++) {
					char * host_addr = NULL;
					int port = -1;
					PyObject * py_host = PyList_GetItem(py_hosts, i);
					if (PyTuple_Check(py_host) && PyTuple_Size(py_host) == 2) {
						PyObject * py_addr = PyTuple_GetItem(py_host,0);
						PyObject * py_port = PyTuple_GetItem(py_host,1);
						if (PyUnicode_Check(py_addr)) {
							py_ustr = PyUnicode_AsUTF8String(py_addr);
							host_addr = PyBytes_AsString(py_ustr);
						} else if (PyString_Check(py_addr)) {
							host_addr = PyString_AsString(py_addr);
						} else {
							as_error_update(&udata_ptr->error, AEROSPIKE_ERR_PARAM, "Host address is of type incorrect");
							if (py_res) {
								Py_DECREF(py_res);
							}
							PyGILState_Release(gil_state);
							return false;
						}
						if (PyInt_Check(py_port)) {
							port = (uint16_t) PyInt_AsLong(py_port);
						}
						else if (PyLong_Check(py_port)) {
							port = (uint16_t) PyLong_AsLong(py_port);
						} else {
							break;
						}
						char ip_port[IP_PORT_MAX_LEN];
						// If the address is longer than the max length of an ipv6 address, raise an error and exit
						if (strnlen(host_addr, INET6_ADDRSTRLEN) >= INET6_ADDRSTRLEN) {
							as_error_update(&udata_ptr->error, AEROSPIKE_ERR_PARAM, "Host address is too long");
							if (py_res) {
								Py_DECREF(py_res);
							}
							goto CLEANUP;
						}
						sprintf(ip_port, "%s:%d", host_addr, port);
						if ( !strcmp(ip_port, addr->name) ) {
							PyObject * py_nodes = (PyObject *) udata_ptr->udata_p;
							PyDict_SetItemString(py_nodes, node->name, py_res);
						} else {
							sprintf(ip_port, "[%s]:%d", host_addr, port);
							if ( !strcmp(ip_port, addr->name) ) {
								PyObject * py_nodes = (PyObject *) udata_ptr->udata_p;
								PyDict_SetItemString(py_nodes, node->name, py_res);
							}
						}
					}

					if (py_ustr) {
						Py_DECREF(py_ustr);
						py_ustr = NULL;
					}
				}
			} else if (!PyList_Check(py_hosts)) {
				as_error_update(&udata_ptr->error, AEROSPIKE_ERR_PARAM, "Hosts should be specified in a list.");
				goto CLEANUP;
			}
	} else {
		PyObject * py_nodes = (PyObject *) udata_ptr->udata_p;
		PyDict_SetItemString(py_nodes, node->name, py_res);
	}

	Py_DECREF(py_res);

CLEANUP:
	if (py_ustr) {
		Py_DECREF(py_ustr);
	}
	if (udata_ptr->error.code != AEROSPIKE_OK) {
		PyObject * py_err = NULL;
		error_to_pyobject( &udata_ptr->error, &py_err);
		PyObject *exception_type = raise_exception(&udata_ptr->error);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		PyGILState_Release(gil_state);
		return NULL;
	}
	if (err->code != AEROSPIKE_OK) {
		PyObject * py_err = NULL;
		error_to_pyobject(err, &py_err);
		PyObject *exception_type = raise_exception(err);
		PyErr_SetObject(exception_type, py_err);
		Py_DECREF(py_err);
		PyGILState_Release(gil_state);
		return NULL;
	}

	PyGILState_Release(gil_state);
	return true;
}