/** * This is the main driver function which can cater to different types of * scan interfaces exposed to the outside world. This functions should not be * exposed to the outside world. This generic function exists because we dont * want to duplicate too much of code. * * @param as - the aerospike cluster to connect to. * @param err - the error is populated if the return value is not AEROSPIKE_OK. * @param policy - the policy to use for this operation. If NULL, then the default policy will be used. * @param node - the name of the node to perform the scan on. * @param scan - the scan to perform * @param callback - the function to be called for each record scanned. * @param udata - user-data to be passed to the callback * * @return AEROSPIKE_OK on success. Otherwise an error occurred. */ static as_status aerospike_scan_generic( aerospike * as, as_error * err, const as_policy_scan * policy, const char * node, const as_scan * scan, aerospike_scan_foreach_callback callback, void * udata) { cl_rv clrv; as_status rc = AEROSPIKE_OK; cl_scan clscan; as_scan_toclscan(scan, policy, &clscan, false, NULL); if ( clscan.udf.type == CL_SCAN_UDF_NONE ) { scan_bridge bridge_udata = { .udata = udata, .callback = callback }; struct cl_scan_parameters_s params = { .fail_on_cluster_change = clscan.params.fail_on_cluster_change, .priority = clscan.params.priority, .concurrent = clscan.params.concurrent, .threads_per_node = 0 }; int n_bins = scan->select.size; cl_bin * bins = NULL; if ( n_bins > 0 ) { bins = (cl_bin *) alloca(sizeof(cl_bin) * n_bins); for( int i = 0; i < n_bins; i++ ) { strcpy(bins[i].bin_name, scan->select.entries[i]); citrusleaf_object_init_null(&bins[i].object); } } // If the user want to execute only on a single node... if (node) { clrv = citrusleaf_scan_node(as->cluster, (char *) node, (char *) scan->ns, (char *) scan->set, bins, n_bins, scan->no_bins, scan->percent, simplescan_cb, &bridge_udata, ¶ms); rc = as_error_fromrc(err, clrv); } else { // We are not using the very old citrusleaf_scan() call here. First of all, its // very inefficient. It makes a single node on the cluster coordinate the job // of scan. Moreover, it does not accept params like priority etc. cf_vector *v = citrusleaf_scan_all_nodes(as->cluster, (char *) scan->ns, (char *) scan->set, bins, n_bins, scan->no_bins, scan->percent, simplescan_cb, &bridge_udata, ¶ms); rc = process_node_response(v, err); } } else { // If the user want to execute only on a single node... if (node) {
cf_vector * citrusleaf_scan_all_nodes (cl_cluster *asc, char *ns, char *set, cl_bin *bins, int n_bins, bool nobindata, uint8_t scan_pct, citrusleaf_get_many_cb cb, void *udata, cl_scan_parameters *scan_param) { char *node_names = NULL; int n_nodes = 0; cl_cluster_get_node_names(asc, &n_nodes, &node_names); if (n_nodes == 0) { cf_error("citrusleaf scan all nodes: don't have any nodes?"); return NULL; } cf_vector *rsp_v = cf_vector_create(sizeof(cl_node_response), n_nodes, 0); if (rsp_v == NULL) { cf_error("citrusleaf scan all nodes: cannot allocate for response array for %d nodes", n_nodes); free(node_names); return NULL; } if (scan_param && scan_param->concurrent_nodes) { cf_error("citrusleaf scan all nodes: concurrent node scanning not yet supported"); } else { char *nptr = node_names; for (int i=0;i< n_nodes; i++) { cl_rv r = citrusleaf_scan_node (asc, nptr, ns, set, bins, n_bins, nobindata, scan_pct, cb, udata, scan_param); cl_node_response resp_s; resp_s.node_response = r; memcpy(resp_s.node_name,nptr,NODE_NAME_SIZE); cf_vector_append(rsp_v, (void *)&resp_s); nptr+=NODE_NAME_SIZE; } } free(node_names); return rsp_v; }