/* ******************************************************************************************************* * Wrapper function to remove bin(s) from a record. * * @param as_object_p The C client's aerospike object. * @param as_key_p The C client's as_key that identifies the record. * @param bins_p The PHP array of bins to be removed from the record. * @param error_p The as_error to be populated by the function * with the encountered error if any. * @param options_p The user's optional policy options to be used if set, else defaults. * ******************************************************************************************************* */ extern as_status aerospike_record_operations_remove_bin(aerospike* as_object_p, as_key* as_key_p, zval* bins_p, as_error* error_p, zval* options_p) { as_status status = AEROSPIKE_OK; as_record rec; HashTable *bins_array_p = Z_ARRVAL_P(bins_p); HashPosition pointer; zval **bin_names; as_policy_write write_policy; as_record_inita(&rec, zend_hash_num_elements(bins_array_p)); if ((!as_object_p) || (!error_p) || (!as_key_p) || (!bins_array_p)) { status = AEROSPIKE_ERR; goto exit; } set_policy(NULL, &write_policy, NULL, NULL, NULL, NULL, options_p, error_p); if (AEROSPIKE_OK != (status = (error_p->code))) { DEBUG_PHP_EXT_DEBUG("Unable to set policy"); goto exit; } foreach_hashtable(bins_array_p, pointer, bin_names) { if (IS_STRING == Z_TYPE_PP(bin_names)) { if (!(as_record_set_nil(&rec, Z_STRVAL_PP(bin_names)))) { status = AEROSPIKE_ERR; goto exit; } } else { status = AEROSPIKE_ERR; goto exit; } } if (AEROSPIKE_OK != (status = aerospike_key_put(as_object_p, error_p, NULL, as_key_p, &rec))) { goto exit; } exit: as_record_destroy(&rec); return(status); }
/** ****************************************************************************************************** * Removes a bin from a record. * * @param self AerospikeClient object * @prama py_key The key for the record. * @pram py_binList The name of the bins to be removed from the record. * @param py_policy The optional policies. * @param err The C client's as_error to be set to the encountered error. * * Returns an integer status. 0(Zero) is success value. * In case of error,appropriate exceptions will be raised. ******************************************************************************************************* */ static PyObject * AerospikeClient_RemoveBin_Invoke( AerospikeClient * self, PyObject * py_key,PyObject* py_binList ,PyObject * py_policy, PyObject * py_meta, as_error *err) { // Aerospike Client Arguments as_policy_write write_policy; as_policy_write * write_policy_p = NULL; as_key key; as_record rec; char* binName = NULL; int count = 0; PyObject * py_ustr = NULL; // Get the bin list size; Py_ssize_t size = PyList_Size(py_binList); // Initialize record as_record_inita(&rec, size); // Convert python key object to as_key pyobject_to_key(err, py_key, &key); if ( err->code != AEROSPIKE_OK ) { goto CLEANUP; } // Convert python policy object to as_policy_write pyobject_to_policy_write(err, py_policy, &write_policy, &write_policy_p, &self->as->config.policies.write); if ( err->code != AEROSPIKE_OK ) { as_error_update(err, AEROSPIKE_ERR_CLIENT, "Incorrect policy"); goto CLEANUP; } // Invoke operation for ( count = 0; count < size; count++ ) { PyObject * py_val = PyList_GetItem(py_binList, count); if( PyUnicode_Check(py_val) ){ py_ustr = PyUnicode_AsUTF8String(py_val); binName = PyStr_AsString(py_ustr); } else if( PyStr_Check(py_val) ) { binName = PyStr_AsString(py_val); } else { as_error_update(err, AEROSPIKE_ERR_CLIENT, "Invalid bin name, bin name should be a string or unicode string") goto CLEANUP; } if (!as_record_set_nil(&rec, binName)){ goto CLEANUP; } if (py_ustr) { Py_DECREF(py_ustr); py_ustr = NULL; } } if ( py_meta && PyDict_Check(py_meta) ) { PyObject * py_gen = PyDict_GetItemString(py_meta, "gen"); PyObject * py_ttl = PyDict_GetItemString(py_meta, "ttl"); if( py_ttl != NULL ){ if ( PyInt_Check(py_ttl) ) { rec.ttl = (uint32_t) PyInt_AsLong(py_ttl); } else if ( PyLong_Check(py_ttl) ) { rec.ttl = (uint32_t) PyLong_AsLongLong(py_ttl); if((uint32_t)-1 == rec.ttl) { as_error_update(err, AEROSPIKE_ERR_PARAM, "integer value for ttl exceeds sys.maxsize"); goto CLEANUP; } } else { as_error_update(err, AEROSPIKE_ERR_PARAM, "Ttl should be an int or long"); goto CLEANUP; } } if( py_gen != NULL ){ if ( PyInt_Check(py_gen) ) { rec.gen = (uint16_t) PyInt_AsLong(py_gen); } else if ( PyLong_Check(py_gen) ) { rec.gen = (uint16_t) PyLong_AsLongLong(py_gen); if((uint16_t)-1 == rec.gen) { as_error_update(err, AEROSPIKE_ERR_PARAM, "integer value for gen exceeds sys.maxsize"); goto CLEANUP; } } else { as_error_update(err, AEROSPIKE_ERR_PARAM, "Generation should be an int or long"); goto CLEANUP; } } } Py_BEGIN_ALLOW_THREADS aerospike_key_put(self->as, err, write_policy_p, &key, &rec); Py_END_ALLOW_THREADS if (err->code != AEROSPIKE_OK) { as_error_update(err, err->code, NULL); goto CLEANUP; } CLEANUP: as_record_destroy(&rec); 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_key); } 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 PyLong_FromLong(0); }
static int as_record_rec_remove(const as_rec * r, const char * name) { return r && name ? as_record_set_nil((as_record *) r, name) : 1; }
int main(int argc, char* argv[]) { // Parse command line arguments. if (! example_get_opts(argc, argv, EXAMPLE_BASIC_OPTS)) { exit(-1); } // Connect to the aerospike database cluster. aerospike as; example_connect_to_aerospike(&as); // Start clean. example_remove_test_record(&as); as_error err; // Create an as_record object with two bins with different value types. By // using as_record_inita(), we won't need to destroy the record if we only // set bins using as_record_set_int64(), as_record_set_str(), and // as_record_set_nil(). as_record rec; as_record_inita(&rec, 2); as_record_set_int64(&rec, "test-bin-1", 1234); as_record_set_str(&rec, "test-bin-2", "test-bin-2-data"); // Log its contents. LOG("as_record object to write to database:"); example_dump_record(&rec); // Write the record to the database. if (aerospike_key_put(&as, &err, NULL, &g_key, &rec) != AEROSPIKE_OK) { LOG("aerospike_key_put() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("write succeeded"); if (! example_read_test_record(&as)) { example_cleanup(&as); exit(-1); } // Generate a different as_record object to write. In general it's ok to // reuse the stack object by calling as_record_inita() again, as long as the // previous contents are destroyed if necessary. as_record_inita(&rec, 2); as_record_set_int64(&rec, "test-bin-2", 2222); as_record_set_str(&rec, "test-bin-3", "test-bin-3-data"); // Log its contents. LOG("as_record object to write to database:"); example_dump_record(&rec); // Write the record to the database. This will change the type and value of // test-bin-2, will add test-bin-3, and will leave test-bin-one unchanged. if (aerospike_key_put(&as, &err, NULL, &g_key, &rec) != AEROSPIKE_OK) { LOG("aerospike_key_put() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("write succeeded"); if (! example_read_test_record(&as)) { example_cleanup(&as); exit(-1); } // Generate another as_record object to write. as_record_inita(&rec, 1); as_record_set_nil(&rec, "test-bin-3"); // Log its contents. LOG("as_record object to write to database:"); example_dump_record(&rec); // Write the record to the database. This will remove test-bin-3 and // will leave test-bin-1 and test-bin-2 unchanged. if (aerospike_key_put(&as, &err, NULL, &g_key, &rec) != AEROSPIKE_OK) { LOG("aerospike_key_put() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("write succeeded"); if (! example_read_test_record(&as)) { example_cleanup(&as); exit(-1); } // Generate another as_record object to write. as_record_inita(&rec, 1); as_record_set_int64(&rec, "test-bin-1", 1111); // Require that the write succeeds only if the record doesn't exist. as_policy_write wpol; as_policy_write_init(&wpol); wpol.exists = AS_POLICY_EXISTS_CREATE; // Log its contents. LOG("as_record object to create in database:"); example_dump_record(&rec); // Try to create the record. This should fail since the record already // exists in the database. if (aerospike_key_put(&as, &err, &wpol, &g_key, &rec) != AEROSPIKE_ERR_RECORD_EXISTS) { LOG("aerospike_key_put() returned %d - %s, expected " "AEROSPIKE_ERR_RECORD_EXISTS", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("create failed as expected"); // Remove the record from the database so we can demonstrate create success. if (aerospike_key_remove(&as, &err, NULL, &g_key) != AEROSPIKE_OK) { LOG("aerospike_key_remove() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("record removed from database, trying create again"); // Try to create the record again. This should succeed since the record is // not currently in the database. if (aerospike_key_put(&as, &err, &wpol, &g_key, &rec) != AEROSPIKE_OK) { LOG("aerospike_key_put() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("create succeeded"); if (! example_read_test_record(&as)) { example_cleanup(&as); exit(-1); } // Cleanup and disconnect from the database cluster. example_cleanup(&as); LOG("put example successfully completed"); return 0; }
void clbin_to_asval(cl_bin * bin, as_serializer * ser, as_val ** val) { if ( val == NULL ) return; switch( bin->object.type ) { case CL_NULL :{ *val = (as_val *) &as_nil; break; } case CL_INT : { *val = (as_val *) as_integer_new(bin->object.u.i64); break; } case CL_STR : { // steal the pointer from the object into the val *val = (as_val *) as_string_new(strdup(bin->object.u.str), true /*ismalloc*/); // TODO: re-evaluate the follow zero-copy for strings from cl_bins // *val = (as_val *) as_string_new(bin->object.u.str, true /*ismalloc*/); // bin->object.free = NULL; break; } case CL_LIST : case CL_MAP : { // use a temporary buffer, which doesn't need to be destroyed as_buffer buf = { .capacity = (uint32_t) bin->object.sz, .size = (uint32_t) bin->object.sz, .data = (uint8_t *) bin->object.u.blob }; // print_buffer(&buf); as_serializer_deserialize(ser, &buf, val); break; } case CL_BLOB: case CL_JAVA_BLOB: case CL_CSHARP_BLOB: case CL_PYTHON_BLOB: case CL_RUBY_BLOB: case CL_ERLANG_BLOB: default : { *val = NULL; uint8_t * raw = malloc(sizeof(bin->object.sz)); memcpy(raw, bin->object.u.blob, bin->object.sz); as_bytes * b = as_bytes_new_wrap(raw, (uint32_t)bin->object.sz, true /*ismalloc*/); b->type = (as_bytes_type)bin->object.type; *val = (as_val *) b; break; } } } void clbin_to_asrecord(cl_bin * bin, as_record * r) { switch(bin->object.type) { case CL_NULL: { as_record_set_nil(r, bin->bin_name); break; } case CL_INT: { as_record_set_int64(r, bin->bin_name, bin->object.u.i64); break; } case CL_STR: { as_record_set_strp(r, bin->bin_name, bin->object.u.str, true); // the following completes the handoff of the value. bin->object.free = NULL; break; } case CL_LIST: case CL_MAP: { as_val * val = NULL; as_buffer buffer; buffer.data = (uint8_t *) bin->object.u.blob; buffer.size = (uint32_t)bin->object.sz; as_serializer ser; as_msgpack_init(&ser); as_serializer_deserialize(&ser, &buffer, &val); as_serializer_destroy(&ser); as_record_set(r, bin->bin_name, (as_bin_value *) val); break; } default: { as_record_set_rawp(r, bin->bin_name, bin->object.u.blob, (uint32_t)bin->object.sz, true); // the following completes the handoff of the value. bin->object.free = NULL; break; } } } void clbins_to_asrecord(cl_bin * bins, uint32_t nbins, as_record * r) { uint32_t n = nbins < r->bins.capacity ? nbins : r->bins.capacity; for ( int i = 0; i < n; i++ ) { clbin_to_asrecord(&bins[i], r); } }