/** * @brief Test whether multiple records exist in the cluster. * * @param[in] argc The argc * @param argv The argv * @param[in] self The object * * @return { description_of_the_return_value } */ static VALUE batch_read(int argc, VALUE * argv, VALUE self) { rb_aero_TIMED(tm); as_error err; as_status status; aerospike * as = rb_aero_CLIENT; VALUE keys; VALUE options; rb_scan_args(argc, argv, "11", &keys, &options); long keys_len = rb_ary_len_long(keys); as_batch batch; as_batch_inita(&batch, keys_len); VALUE return_data = rb_hash_new(); for (long i = 0; i < keys_len; ++i) { VALUE element = rb_ary_entry(keys, i); // set into hash for return values rb_hash_aset(return_data, element, Qfalse); VALUE 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 ); tmp = rb_funcall(element, rb_intern("key"), 0); if ( TYPE(tmp) != T_FIXNUM ) { char * c_key = StringValueCStr( tmp ); as_key_init(as_batch_keyat(&batch,i), c_namespace, c_set, c_key); } else { as_key_init_int64(as_batch_keyat(&batch,i), c_namespace, c_set, FIX2LONG(tmp)); } } if ( aerospike_batch_get(as, &err, NULL, &batch, batch_read_callback, return_data) != AEROSPIKE_OK ) { as_batch_destroy(&batch); raise_as_error(err); } as_batch_destroy(&batch); rb_aero_logger(AS_LOG_LEVEL_DEBUG, &tm, 1, rb_str_new2("[Client][batch_read] success")); return return_data; }
/** ******************************************************************************************************* * 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_get_aerospike_batch_get(as_error *err, AerospikeClient * self, PyObject *py_keys, as_policy_batch * batch_policy_p) { PyObject * py_recs = NULL; LocalData data; data.client = self; as_batch batch; 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); data.py_recs = py_recs; as_batch_init(&batch, 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; } pyobject_to_key(err, py_key, as_batch_keyat(&batch, i)); 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); data.py_recs = py_recs; as_batch_init(&batch, 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; } pyobject_to_key(err, py_key, as_batch_keyat(&batch, i)); 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_get(self->as, err, batch_policy_p, &batch, (aerospike_batch_read_callback) batch_get_cb, &data); Py_END_ALLOW_THREADS 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_destroy(&batch); } return py_recs; }
int main(int argc, char* argv[]) { // Parse command line arguments. if (! example_get_opts(argc, argv, EXAMPLE_MULTI_KEY_OPTS)) { exit(-1); } // Connect to the aerospike database cluster. aerospike as; example_connect_to_aerospike(&as); // Start clean. example_remove_test_records(&as); if (! insert_records(&as)) { cleanup(&as); exit(-1); } as_error err; // Make a batch of all the keys we inserted. as_batch batch; as_batch_inita(&batch, g_n_keys); uint32_t i; for (i = 0; i < g_n_keys; i++) { as_key_init_int64(as_batch_keyat(&batch, i), g_namespace, g_set, (int64_t)i); } // Check existence of these keys - they should all be there. if (aerospike_batch_exists(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_exists() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1); } LOG("batch exists call completed"); // Get all of these keys - they should all be there. if (aerospike_batch_get(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_get() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1); } LOG("batch get call completed"); // Delete some records in the middle. uint32_t n_to_delete = g_n_keys / 5; if (n_to_delete == 0) { n_to_delete = 1; } uint32_t n_start = g_n_keys / 2; if (n_start + n_to_delete > g_n_keys) { n_start = 0; } uint32_t n_end = n_start + n_to_delete; for (i = n_start; i < n_end; i++) { // No need to destroy a stack as_key object, if we only use // as_key_init_int64(). as_key key; as_key_init_int64(&key, g_namespace, g_set, (int64_t)i); if (aerospike_key_remove(&as, &err, NULL, &key) != AEROSPIKE_OK) { LOG("aerospike_key_remove() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1); } } LOG("deleted records %u ... %u", n_start, n_end - 1); // Check existence of these keys - some should not be found. if (aerospike_batch_exists(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_exists() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1); } LOG("second batch exists call completed"); // Get all of these keys - some should not be found. if (aerospike_batch_get(&as, &err, NULL, &batch, batch_read_cb, NULL) != AEROSPIKE_OK) { LOG("aerospike_batch_get() returned %d - %s", err.code, err.message); cleanup(&as); exit(-1); } LOG("second batch get call completed"); // Cleanup and disconnect from the database cluster. cleanup(&as); LOG("batch get example successfully completed"); return 0; }