/**
 * 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, &params);
			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, &params);
			rc = process_node_response(v, err);
		}

	}
	else {
		// If the user want to execute only on a single node...
		if (node) {
Example #2
0
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;
}