/* 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; }
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; }
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; }
/** ******************************************************************************************************* * 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; }