/*
 *******************************************************************************************************
 * 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);
}
Пример #2
0
/**
 ******************************************************************************************************
 * 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);
}
Пример #3
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;
}
Пример #4
0
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;
}
Пример #5
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);
	}
}