/** ********************************************************************* * This function will invoke aerospike_batch_get_bins to get filtered * bins from all the records in a batches. * * @param self AerospikeClient object * @param py_keys List of keys passed on by user * @param py_bins List of filter bins passed on by user * @param py_policy User specified Policy dictionary * ********************************************************************* **/ static PyObject * AerospikeClient_Select_Many_Invoke( AerospikeClient * self, PyObject * py_keys, PyObject * py_bins, PyObject * py_policy) { // Python Return Value PyObject * py_recs = NULL; // Aerospike Client Arguments as_error err; as_policy_batch policy; as_policy_batch * batch_policy_p = NULL; Py_ssize_t bins_size = 0; char **filter_bins = NULL; bool has_batch_index = false; // Unicode object's pool UnicodePyObjects u_objs; u_objs.size = 0; int i = 0; // Initialize error as_error_init(&err); if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; } if (!self->is_conn_16) { as_error_update(&err, AEROSPIKE_ERR_CLUSTER, "No connection to aerospike cluster"); goto CLEANUP; } // Check the type of bins and get it's size // i.e. number of bins provided if (py_bins != NULL && PyList_Check(py_bins)){ bins_size = PyList_Size(py_bins); } else if (py_bins != NULL && PyTuple_Check(py_bins)){ bins_size = PyTuple_Size(py_bins); } else { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Filter bins should be specified as a list or tuple."); goto CLEANUP; } filter_bins = (char **)malloc(sizeof(long int) * bins_size); for (i = 0; i < bins_size; i++){ PyObject *py_bin = NULL; if(PyList_Check(py_bins)){ py_bin = PyList_GetItem(py_bins, i); } if(PyTuple_Check(py_bins)){ py_bin = PyTuple_GetItem(py_bins, i); } if (PyUnicode_Check(py_bin)){ // Store the unicode object into a pool // It is DECREFed at later stages // So, no need of DECREF here. filter_bins[i] = PyBytes_AsString( store_unicode_bins(&u_objs, PyUnicode_AsUTF8String(py_bin))); } else if (PyString_Check(py_bin)){ filter_bins[i] = PyString_AsString(py_bin); } else{ as_error_update(&err, AEROSPIKE_ERR_PARAM, "Bin name should be a string or unicode string."); goto CLEANUP; } } // Convert python policy object to as_policy_batch pyobject_to_policy_batch(&err, py_policy, &policy, &batch_policy_p, &self->as->config.policies.batch); if ( err.code != AEROSPIKE_OK ) { goto CLEANUP; } has_batch_index = aerospike_has_batch_index(self->as); if (has_batch_index && !(self->as->config.policies.batch.use_batch_direct)) { py_recs = batch_select_aerospike_batch_read(&err, self, py_keys, batch_policy_p, filter_bins, bins_size); } else { py_recs = batch_select_aerospike_batch_get(&err, self, py_keys, batch_policy_p, filter_bins, bins_size); } CLEANUP: if (filter_bins != NULL){ free(filter_bins); } // DECREFed all the unicode objects stored in Pool for ( i = 0; i< u_objs.size; i++){ Py_DECREF(u_objs.ob[i]); } if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyObject *exception_type = raise_exception(&err); if(PyObject_HasAttrString(exception_type, "key")) { PyObject_SetAttrString(exception_type, "key", py_keys); } if(PyObject_HasAttrString(exception_type, "bin")) { PyObject_SetAttrString(exception_type, "bin", Py_None); } PyErr_SetObject(exception_type, py_err); Py_DECREF(py_err); return NULL; } return py_recs; }
/** ********************************************************************* * This function will invoke aerospike_batch_get_bins to get filtered * bins from all the records in a batches. * * @param self AerospikeClient object * @param py_keys List of keys passed on by user * @param py_bins List of filter bins passed on by user * @param py_policy User specified Policy dictionary * ********************************************************************* **/ static PyObject * AerospikeClient_Select_Many_Invoke( AerospikeClient * self, PyObject * py_keys, PyObject * py_bins, PyObject * py_policy) { // Python Return Value PyObject * py_recs = PyDict_New(); // Aerospike Client Arguments as_error err; as_batch batch; as_policy_batch policy; as_policy_batch * batch_policy_p = NULL; Py_ssize_t bins_size = 0; char **filter_bins = NULL; // Unicode object's pool UnicodePyObjects u_objs; u_objs.size = 0; int i = 0; // Initialisation flags bool batch_initialised = false; // Initialize error as_error_init(&err); if (!self || !self->as) { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid aerospike object"); goto CLEANUP; } if (!self->is_conn_16) { as_error_update(&err, AEROSPIKE_ERR_CLUSTER, "No connection to aerospike cluster"); goto CLEANUP; } // 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); as_batch_init(&batch, size); // Batch object initialised batch_initialised = true; for ( 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); as_batch_init(&batch, size); // Batch object initialised. batch_initialised = true; for ( 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; } // Check the type of bins and get it's size // i.e. number of bins provided if (py_bins != NULL && PyList_Check(py_bins)){ bins_size = PyList_Size(py_bins); } else if (py_bins != NULL && PyTuple_Check(py_bins)){ bins_size = PyTuple_Size(py_bins); } else { as_error_update(&err, AEROSPIKE_ERR_PARAM, "Filter bins should be specified as a list or tuple."); goto CLEANUP; } filter_bins = (char **)malloc(sizeof(long int) * bins_size); for (i = 0; i < bins_size; i++){ PyObject *py_bin = NULL; if(PyList_Check(py_bins)){ py_bin = PyList_GetItem(py_bins, i); } if(PyTuple_Check(py_bins)){ py_bin = PyTuple_GetItem(py_bins, i); } if (PyUnicode_Check(py_bin)){ // Store the unicode object into a pool // It is DECREFed at later stages // So, no need of DECREF here. filter_bins[i] = PyString_AsString( store_unicode_bins(&u_objs, PyUnicode_AsUTF8String(py_bin))); } else if (PyString_Check(py_bin)){ filter_bins[i] = PyString_AsString(py_bin); } else{ as_error_update(&err, AEROSPIKE_ERR_PARAM, "Bin name should be a string or unicode string."); goto CLEANUP; } } // Convert python policy object to as_policy_batch pyobject_to_policy_batch(&err, py_policy, &policy, &batch_policy_p, &self->as->config.policies.batch); if ( err.code != AEROSPIKE_OK ) { goto CLEANUP; } // Invoke C-client API aerospike_batch_get_bins(self->as, &err, batch_policy_p, &batch, (const char **) filter_bins, bins_size, (aerospike_batch_read_callback) batch_select_cb, py_recs); CLEANUP: if (filter_bins != NULL){ free(filter_bins); } // DECREFed all the unicode objects stored in Pool for ( i = 0; i< u_objs.size; i++){ Py_DECREF(u_objs.ob[i]); } 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); } if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyObject *exception_type = raise_exception(&err); if(PyObject_HasAttrString(exception_type, "key")) { PyObject_SetAttrString(exception_type, "key", py_keys); } if(PyObject_HasAttrString(exception_type, "bin")) { PyObject_SetAttrString(exception_type, "bin", Py_None); } PyErr_SetObject(exception_type, py_err); Py_DECREF(py_err); return NULL; } return py_recs; }