// Create bin name list from message. static cf_vector* as_binlist_from_op(as_msg* msg) { if (msg->n_ops == 0) { return 0; } cf_vector* binlist = cf_vector_create(AS_ID_BIN_SZ, 5, 0); as_msg_op* op = 0; int n = 0; int len; char name[AS_ID_BIN_SZ]; while ((op = as_msg_op_iterate(msg, op, &n))) { len = (op->name_sz <= AS_ID_BIN_SZ - 1)? op->name_sz : AS_ID_BIN_SZ - 1; memcpy(name, op->name, len); name[len] = 0; cf_vector_append(binlist, name); } return binlist; }
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; }
cf_vector * cl_scan_execute(cl_cluster * cluster, const cl_scan * scan, char * node_name, cl_rv * res, int (* callback)(as_val *, void *), void * udata) { cl_rv rc = CITRUSLEAF_OK; uint8_t wr_stack_buf[STACK_BUF_SZ] = { 0 }; uint8_t * wr_buf = wr_stack_buf; size_t wr_buf_sz = sizeof(wr_stack_buf); int node_count = 0; cl_node_response response; rc = scan_compile(scan, &wr_buf, &wr_buf_sz); if ( rc != CITRUSLEAF_OK ) { LOG("[ERROR] cl_scan_execute: scan compile failed: \n"); *res = rc; return NULL; } // Setup worker cl_scan_task task = { .asc = cluster, .ns = scan->ns, .scan_buf = wr_buf, .scan_sz = wr_buf_sz, .udata = udata, .callback = callback, .job_id = scan->job_id, .type = scan->udf.type, }; task.complete_q = cf_queue_create(sizeof(cl_node_response), true); cf_vector * result_v = NULL; // If node_name is not null, we are executing scan on a particular node if (node_name) { // Copy the node name in the task and push it in the global scan queue. One task for each node strcpy(task.node_name, node_name); cf_queue_push(cluster->scan_q, &task); node_count = 1; } else { // Node name is NULL, we have to scan all nodes char *node_names = NULL; // Get a list of the node names, so we can can send work to each node cl_cluster_get_node_names(cluster, &node_count, &node_names); if ( node_count == 0 ) { LOG("[ERROR] cl_scan_execute: don't have any nodes?\n"); *res = CITRUSLEAF_FAIL_CLIENT; goto Cleanup; } // Dispatch work to the worker queue to allow the transactions in parallel // NOTE: if a new node is introduced in the middle, it is NOT taken care of node_name = node_names; for ( int i=0; i < node_count; i++ ) { // fill in per-request specifics strcpy(task.node_name, node_name); cf_queue_push(cluster->scan_q, &task); node_name += NODE_NAME_SIZE; } free(node_names); node_names = NULL; } // Wait for the work to complete from all the nodes. // For every node, fill in the return value in the result vector result_v = cf_vector_create(sizeof(cl_node_response), node_count, 0); for ( int i=0; i < node_count; i++ ) { // Pop the response structure cf_queue_pop(task.complete_q, &response, CF_QUEUE_FOREVER); cf_vector_append(result_v, &response); } Cleanup: if ( wr_buf && (wr_buf != wr_stack_buf) ) { free(wr_buf); wr_buf = 0; } cf_queue_destroy(task.complete_q); return result_v; } /** * Allocates and initializes a new cl_scan. */ cl_scan * cl_scan_new(const char * ns, const char * setname, uint64_t *job_id) { cl_scan * scan = (cl_scan*) malloc(sizeof(cl_scan)); memset(scan, 0, sizeof(cl_scan)); return cl_scan_init(scan, ns, setname, job_id); }