/** ******************************************************************************************************* * This function will get a batch of records from the Aeropike DB. * * @param err as_error object * @param self AerospikeClient object * @param py_keys The list of keys * @param batch_policy_p as_policy_batch object * * Returns the record if key exists otherwise NULL. ******************************************************************************************************* */ static PyObject * batch_select_aerospike_batch_read(as_error *err, AerospikeClient * self, PyObject *py_keys, as_policy_batch * batch_policy_p, char** filter_bins, Py_ssize_t bins_size) { PyObject * py_recs = NULL; as_batch_read_records records; as_batch_read_record* record = NULL; bool batch_initialised = false; // Convert python keys list to as_key ** and add it to as_batch.keys // keys can be specified in PyList or PyTuple if ( py_keys != NULL && PyList_Check(py_keys) ) { Py_ssize_t size = PyList_Size(py_keys); py_recs = PyList_New(size); as_batch_read_inita(&records, size); // Batch object initialised batch_initialised = true; for ( int i = 0; i < size; i++ ) { PyObject * py_key = PyList_GetItem(py_keys, i); if ( !PyTuple_Check(py_key) ){ as_error_update(err, AEROSPIKE_ERR_PARAM, "Key should be a tuple."); goto CLEANUP; } record = as_batch_read_reserve(&records); pyobject_to_key(err, py_key, &record->key); if (bins_size) { record->bin_names = filter_bins; record->n_bin_names = bins_size; } else { record->read_all_bins = true; } if ( err->code != AEROSPIKE_OK ) { goto CLEANUP; } } } else if ( py_keys != NULL && PyTuple_Check(py_keys) ) { Py_ssize_t size = PyTuple_Size(py_keys); py_recs = PyList_New(size); as_batch_read_inita(&records, size); // Batch object initialised batch_initialised = true; for ( int i = 0; i < size; i++ ) { PyObject * py_key = PyTuple_GetItem(py_keys, i); if ( !PyTuple_Check(py_key) ){ as_error_update(err, AEROSPIKE_ERR_PARAM, "Key should be a tuple."); goto CLEANUP; } record = as_batch_read_reserve(&records); pyobject_to_key(err, py_key, &record->key); if (bins_size) { record->bin_names = filter_bins; record->n_bin_names = bins_size; } else { record->read_all_bins = true; } if ( err->code != AEROSPIKE_OK ) { goto CLEANUP; } } } else { as_error_update(err, AEROSPIKE_ERR_PARAM, "Keys should be specified as a list or tuple."); goto CLEANUP; } // Invoke C-client API Py_BEGIN_ALLOW_THREADS aerospike_batch_read(self->as, err, batch_policy_p, &records); Py_END_ALLOW_THREADS if (err->code != AEROSPIKE_OK) { goto CLEANUP; } batch_select_recs(self, err, &records, &py_recs); CLEANUP: if (batch_initialised == true){ // We should destroy batch object as we are using 'as_batch_init' for initialisation // Also, pyobject_to_key is soing strdup() in case of Unicode. So, object destruction // is necessary. as_batch_read_destroy(&records); } return py_recs; }
// ---------------------------------------------------------------------------------- // // getting batch of records in one call // batch size is limited on aerospike server (default: 5000) // // def batch_get(keys, specific_bins = nil, options = {}) // // params: // keys - Array of AerospikeC::Key objects // specific bins - Array of strings representing bin names // options - hash of options: // with_header: returns also generation and expire_in field (default: false) // // ------ // RETURN: Array of hashes where each hash represents record bins // // @TODO options policy // static VALUE batch_get(int argc, VALUE * argv, VALUE self) { rb_aero_TIMED(tm); as_error err; as_status status; aerospike * as = rb_aero_CLIENT; char ** bin_names; long n_bin_names; VALUE keys; VALUE specific_bins; VALUE options; rb_scan_args(argc, argv, "12", &keys, &specific_bins, &options); // default values for optional arguments if ( NIL_P(specific_bins) ) { specific_bins = Qnil; } else { if ( TYPE(specific_bins) != T_ARRAY ) rb_raise(rb_aero_OptionError, "[AerospikeC::Client][batch_get] specific_bins must be an Array"); bin_names = rb_array2bin_names(specific_bins); n_bin_names = rb_ary_len_long(specific_bins); } if ( NIL_P(options) ) { options = rb_hash_new(); rb_hash_aset(options, with_header_sym, Qfalse); } long keys_len = rb_ary_len_long(keys); VALUE records_bins = rb_ary_new(); as_batch_read_records records; as_batch_read_inita(&records, keys_len); // map array into as_batch_read_record * record for (int i = 0; i < keys_len; ++i) { VALUE element = rb_ary_entry(keys, i); VALUE tmp; tmp = rb_funcall(element, rb_intern("namespace"), 0); char * c_namespace = StringValueCStr( tmp ); tmp = rb_funcall(element, rb_intern("set"), 0); char * c_set = StringValueCStr( tmp ); as_batch_read_record * record = as_batch_read_reserve(&records); tmp = rb_funcall(element, rb_intern("key"), 0); if ( TYPE(tmp) != T_FIXNUM ) { char * c_key = StringValueCStr( tmp ); as_key_init(&record->key, c_namespace, c_set, c_key); } else { as_key_init_int64(&record->key, c_namespace, c_set, FIX2LONG(tmp)); } if ( specific_bins == Qnil ) { record->read_all_bins = true; } else { record->bin_names = bin_names; record->n_bin_names = n_bin_names; } } // read here! if ( ( status = aerospike_batch_read(as, &err, NULL, &records) ) != AEROSPIKE_OK ) { if ( status == AEROSPIKE_ERR_RECORD_NOT_FOUND ) { rb_aero_logger(AS_LOG_LEVEL_WARN, &tm, 1, rb_str_new2("[Client][batch_get] AEROSPIKE_ERR_RECORD_NOT_FOUND")); return Qnil; } as_batch_read_destroy(&records); raise_as_error(err); } as_vector list = records.list; // map records into array of hashes for (long i = 0; i < list.size; ++i) { as_batch_read_record * record = as_vector_get(&list, i); as_record rec = record->record; VALUE bins = record2hash(&rec); bins = check_with_header(bins, options, &rec); rb_ary_push(records_bins, bins); } as_batch_read_destroy(&records); if ( specific_bins != Qnil ) bin_names_destroy(bin_names, n_bin_names); rb_aero_logger(AS_LOG_LEVEL_DEBUG, &tm, 1, rb_str_new2("[Client][batch_get] success")); return records_bins; }