bool user_callback_wrapper(const as_val *val, void *udata) { zval retval; ZVAL_NULL(&retval); if (!val) { return false; } as_record* record = as_record_fromval(val); user_callback_function* callback_info = (user_callback_function*)udata; pthread_mutex_lock(callback_info->cb_mutex); callback_info->callback.retval = &retval; if (execute_user_callback(record, callback_info) != AEROSPIKE_OK) { as_error_update(callback_info->err, AEROSPIKE_ERR_PARAM, "Callback raised an error"); pthread_mutex_unlock(callback_info->cb_mutex); return false; } if (callback_info->callback.retval && Z_TYPE_P(callback_info->callback.retval) == IS_FALSE) { pthread_mutex_unlock(callback_info->cb_mutex); return false; } zval_dtor(&retval); pthread_mutex_unlock(callback_info->cb_mutex); return true; }
bool scan_cb(const as_val* p_val, void* udata) { if (! p_val) { LOG("scan callback returned null - scan is complete"); return true; } // The scan didn't use a UDF, so the as_val object should be an as_record. as_record* p_rec = as_record_fromval(p_val); if (! p_rec) { LOG("scan callback returned non-as_record object"); return true; } LOG("scan callback returned record:"); example_dump_record(p_rec); return true; }
static bool scan_check_callback(const as_val * val, void * udata) { int i; // NULL is END OF SCAN if ( !val ) { return false; } scan_check * check = (scan_check *) udata; as_record * rec = as_record_fromval(val); if ( !rec ) { error("Expected a record, but got type %d", as_val_type(val)); return !(check->failed = true); } const char * set = rec->key.set[0] == '\0' ? NULL : rec->key.set; check->count++; // Find the number of unique threads spawned under the hood. // Note that the scan callback will be called in the thread context. // As the number of threads is same as node count, they will be limited. // A linear search is good enough for this. pthread_t cur_thread = pthread_self(); for (i=0; i<check->unique_tcount; i++) { if (check->threadids[i] == cur_thread) { break; } } // Found a new thread if (i == check->unique_tcount) { check->threadids[check->unique_tcount] = cur_thread; check->unique_tcount++; } // Check if we are getting the results only from the set the scan is triggered for // If scan is called with NULL set, all the recs will come. So, no checks in this case. if ( check->set ) { // Do the check only if the rec also have a setname if ( !set ) { error("Expected set '%s', but got set NULL", check->set); return !(check->failed = true); } else if ( strcmp(check->set, set) != 0) { error("Expected set '%s', but got set '%s'", check->set, set); return !(check->failed = true); } } // Check that we got the right number of bins int numbins = as_record_numbins(rec); if ( check->nobindata ) { if ( numbins != 0 ) { error("Expected 0 bins, but got %d", numbins); return !(check->failed = true); } return !(check->failed = false); } // only validate data if in sb_set1 or sb_set2 if ( check->set && strcmp(set, SET1) != 0 && strcmp(set, SET2) != 0 ) { return !(check->failed = false); } // validate bins int nbins = sizeof(check->bins) / sizeof(char *); for( int i = 0; check->bins[i] && i < nbins; i++ ) { char * bin = check->bins[i]; if ( strcmp(bin, "bin1") == 0 ) { if ( !check_bin1(rec, check) ) { error("Failed check of bin1"); return !(check->failed = true); } } else if ( strcmp(bin, "bin2") == 0 ) { if ( !check_bin2(rec, check) ) { error("Failed check of bin2"); return !(check->failed = true); } } else if ( strcmp(bin, "bin3") == 0 ) { if ( !check_bin3(rec, check) ) { error("Failed check of bin3"); return !(check->failed = true); } } else if ( strcmp(bin, "bin4") == 0 ) { if ( !check_bin4(rec, check) ) { error("Failed check of bin4"); return !(check->failed = true); } } else { error("Unknown bin %s", bin); return !(check->failed = true); } } return !(check->failed = false); }