/*
 ******************************************************************************************************
 Applies a UDF to a record at the Aerospike DB.
 *
 * @param aerospike_obj_p           The C client's aerospike object.
 * @param as_key_p                  The C client's as_key that identifies the
 *                                  record on which UDF will be applied.
 * @param error_p                   The C client's as_error to be set to the encountered error.
 * @param module_p                  The name of the UDF module registered
 *                                  against the Aerospike DB.
 * @param function_p                The name of the function to be applied to
 *                                  the record.
 * @param args_pp                   An array of arguments for the UDF.
 * @param return_value_p            It will contain result value of calling the
 *                                  UDF.
 * @param options_p                 The optional policy.
 *
 * @return AEROSPIKE_OK if success. Otherwise AEROSPIKE_x.
 ******************************************************************************************************
 */
extern as_status
aerospike_udf_apply(Aerospike_object* aerospike_obj_p,
        as_key* as_key_p, as_error* error_p, char* module_p, char* function_p,
        zval** args_pp, zval* return_value_p, zval* options_p)
{
    as_arraylist                args_list;
    as_arraylist*               args_list_p = NULL;
    as_static_pool              udf_pool = {0};
    as_val*                     udf_result_p = NULL;
    foreach_callback_udata      udf_result_callback_udata;
    uint32_t                    serializer_policy = -1;
    as_policy_apply             apply_policy;
    TSRMLS_FETCH_FROM_CTX(aerospike_obj_p->ts);

    set_policy_udf_apply(&aerospike_obj_p->as_ref_p->as_p->config, &apply_policy, &serializer_policy,
            options_p, error_p TSRMLS_CC);

    if (AEROSPIKE_OK != (error_p->code)) {
        DEBUG_PHP_EXT_DEBUG("Unable to set policy");
        goto exit;
    }

    if ((*args_pp)) {
        as_arraylist_inita(&args_list,
                zend_hash_num_elements(Z_ARRVAL_PP(args_pp)));
        args_list_p = &args_list;
        AS_LIST_PUT(NULL, args_pp, args_list_p, &udf_pool, serializer_policy, error_p TSRMLS_CC);
    }

    if (AEROSPIKE_OK != (aerospike_key_apply(aerospike_obj_p->as_ref_p->as_p,
                    error_p, &apply_policy, as_key_p, module_p, function_p,
                    (as_list *) args_list_p, &udf_result_p))) {
        DEBUG_PHP_EXT_DEBUG("%s", error_p->message);
        goto exit;
    }

    if (return_value_p) {
        udf_result_callback_udata.udata_p = return_value_p;
        udf_result_callback_udata.error_p = error_p;
        AS_DEFAULT_GET(NULL, udf_result_p, &udf_result_callback_udata);
    }
     
exit:
    if (udf_result_p) {
        as_val_destroy(udf_result_p);
    }
    
    if (args_list_p) {
        as_arraylist_destroy(args_list_p);
    }

    /* clean up the as_* objects that were initialised */
    aerospike_helper_free_static_pool(&udf_pool);

    return error_p->code;
}
as_status aerospike_lset_exists(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, const as_val * val,
    as_boolean *exists)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !exists) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/n cannot be null");
	}
	if (ldt->type != AS_LDT_LSET) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not lset type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, 2);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_val_reserve( val ); // bump the ref count
	as_arraylist_append(&arglist, (as_val *)val);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSET_PACKAGE, LDT_SET_OP_EXISTS,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	if (!p_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"no value returned from server");
	}
	int64_t ival = as_integer_getorelse(as_integer_fromval(p_return_val), -1);
	as_val_destroy(p_return_val);

	if (ival == -1) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"value returned from server not parse-able");
	}

	as_boolean_init(exists, ival==1 ? true: false);

	return err->code;
} // aerospike_lset_exists()
// =======================================================================
// Pass in a value into the UDF -- and then get it back.  Simple.
// This is used to measure the performance of the end to end
// call infrastructure.
// Pass in LDT Bin and Value.
// Return Value.
// =======================================================================
as_status aerospike_lstack_same(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, uint32_t  in_val,
    uint32_t * out_valp)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !out_valp) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/out_valp cannot be null");
	}
	if (ldt->type != AS_LDT_LSTACK) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not LSTACK type");
	}

	// stack allocate the arg list.
    // Pass in the LDT Bin and the IN VALUE.
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, 2);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_arraylist_append_int64(&arglist, in_val);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSTACK_PACKAGE, LDT_STACK_OP_SAME,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	int64_t ival = as_integer_getorelse(as_integer_fromval(p_return_val), -1);
	as_val_destroy(p_return_val);

	if (ival == -1) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"value returned from server not parse-able");
	}
	if (ival !=0 ) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"same() Function Failed");
	}
    *out_valp = (uint32_t)ival;

	return err->code;
} // end as_status aerospike_lstack_same()
// =======================================================================
static as_status aerospike_lstack_push_internal(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, const as_val * val,
    const char *operation)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !val) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/n cannot be null");
	}
	if (ldt->type != AS_LDT_LSTACK) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not stack type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, ldt->module[0] == 0 ? 2 : 3);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_val_reserve( val );
	as_arraylist_append(&arglist, (as_val *) val);

	if (ldt->module[0] != 0) {
		as_string ldt_module;
		as_string_init(&ldt_module, (char *)ldt->module, false);
		as_arraylist_append_string(&arglist, &ldt_module);
	}

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSTACK_PACKAGE, operation,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	// return value is the input
	if (p_return_val) {
		as_val_destroy(p_return_val);
	}

	return err->code;
} // end aerospike_lstack_push_internal()
// =======================================================================
as_status aerospike_lstack_set_capacity(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, uint32_t elements_capacity
	)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !elements_capacity) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/capacity cannot be null");
	}
	if (ldt->type != AS_LDT_LSTACK) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not stack type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, 2);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_arraylist_append_int64(&arglist, elements_capacity);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSTACK_PACKAGE, LDT_STACK_OP_CAPACITY_SET,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	int64_t ival = as_integer_getorelse(as_integer_fromval(p_return_val), -1);
	as_val_destroy(p_return_val);

	if (ival == -1) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"value returned from server not parse-able");
	}
	if (ival !=0 ) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"capacity setting failed");
	}

	return err->code;
}
// =======================================================================
// Internal function to handle all of the functions that get an int back
// from a call.
// size()
// one()
// =======================================================================
as_status aerospike_lstack_ask_internal(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, uint32_t *n, const char *operation )
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !n) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/n cannot be null");
	}
	if (ldt->type != AS_LDT_LSTACK) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not stack type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

    // All we need to pass in is the LDT Bin Name
	as_arraylist arglist;
	as_arraylist_inita(&arglist, 1);
	as_arraylist_append_string(&arglist, &ldt_bin);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSTACK_PACKAGE, operation,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	if (!p_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"no value returned from server");
	}
	int64_t ival = as_integer_getorelse(as_integer_fromval(p_return_val), -1);
	as_val_destroy(p_return_val);

	if (ival == -1) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"value returned from server not parse-able");
	}
	*n = (uint32_t)ival;

	return err->code;
} // end as_status aerospike_lstack_ask_internal()
as_status aerospike_llist_find(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, const as_val * search_val,
	as_list ** elements )
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !search_val || !elements) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/search_val/elements cannot be null");
	}
	if (ldt->type != AS_LDT_LLIST) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not llist type");
	}

	int list_argc = 2;
	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, list_argc);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_val_reserve( search_val ); // bump the ref count so the arraylist_destroy will not reset the search_val
	as_arraylist_append(&arglist, (as_val *) search_val);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LLIST_PACKAGE, LDT_LIST_OP_FIND,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	if (!p_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"no value returned from server");
	}

	*elements = (as_list *)p_return_val;

	return err->code;

} // aerospike_llist_find()
Exemple #8
0
// ----------------------------------------------------------------------------------
//
// execute udf on record
//
// def execute_udf(key, module_name, func_name, udf_args = [], options = {})
//
// params:
//   key - AeropsikeC::Key object
//   module_name - string, registered module name
//   func_name - string, function name in module to execute
//   udf_args - arguments passed to udf
//   options:
//     policy - AerospikeC::ApplyPolicy
//
//  ------
//  RETURN:
//    1. data returned from udf
//
static VALUE execute_udf(int argc, VALUE * argv, VALUE self) {
  rb_aero_TIMED(tm);

  as_error err;
  as_status status;
  aerospike * as = rb_aero_CLIENT;

  VALUE key;
  VALUE module_name;
  VALUE func_name;
  VALUE udf_args;
  VALUE options;

  rb_scan_args(argc, argv, "32", &key, &module_name, &func_name, &udf_args, &options);

  // default values for optional arguments
  if ( NIL_P(options) ) options = rb_hash_new();
  if ( NIL_P(udf_args) ) udf_args = rb_ary_new();

  as_key * k               = rb_aero_KEY;
  as_arraylist * args      = array2as_list(udf_args);
  as_policy_apply * policy = get_policy(options);

  as_val * res = NULL;

  char * c_module_name = StringValueCStr(module_name);
  char * c_func_name   = StringValueCStr(func_name);

  if ( ( status = aerospike_key_apply(as, &err, policy, k, c_module_name, c_func_name, (as_list *)args, &res) ) != AEROSPIKE_OK ) {
    as_arraylist_destroy(args);

    if ( status == AEROSPIKE_ERR_RECORD_NOT_FOUND ) {
      rb_aero_logger(AS_LOG_LEVEL_WARN, &tm, 3, rb_str_new2("[Client][execute_udf] AEROSPIKE_ERR_RECORD_NOT_FOUND"), rb_aero_KEY_INFO, rb_aero_MOD_INFO);
      return Qnil;
    }

    raise_as_error(err);
  }

  VALUE result = as_val2rb_val(res);

  as_val_destroy(&res);
  as_arraylist_destroy(args);

  VALUE key_info = rb_aero_KEY_INFO;

  rb_aero_logger(AS_LOG_LEVEL_DEBUG, &tm, 3, rb_str_new2("[Client][execute_udf] success"), rb_aero_KEY_INFO, rb_aero_MOD_INFO);

  return result;
}
as_status aerospike_llist_remove(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, const as_val *val
	)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/capacity cannot be null");
	}
	if (ldt->type != AS_LDT_LLIST) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not llist type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, 2);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_val_reserve( val );
	as_arraylist_append(&arglist, (as_val *) val);

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LLIST_PACKAGE, LDT_LIST_OP_REMOVE,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
			return err->code;
	}

	if (p_return_val != NULL) {
		as_val_destroy(p_return_val);
	}

	return err->code;
}
as_status aerospike_lset_get(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt, const as_val * val,
    as_val **pp_return_val)
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (!as || !key || !ldt || !pp_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/return cannot be null");
	}
	if (ldt->type != AS_LDT_LSET) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not lset type");
	}

	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, 2);
	as_arraylist_append_string(&arglist, &ldt_bin);
	as_val_reserve( val ); // bump the ref count
	as_arraylist_append(&arglist, (as_val *)val);

	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LSET_PACKAGE, LDT_SET_OP_GET,
		(as_list *)&arglist, pp_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	if (! *pp_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"no value returned from server");
	}

	return err->code;
} // aerospike_lset_get()
as_status aerospike_llist_filter(
	aerospike * as, as_error * err, const as_policy_apply * policy,
	const as_key * key, const as_ldt * ldt,
	const as_udf_function_name filter, const as_list *filter_args,
	as_list ** elements )
{
	if ( !err ) {
		return AEROSPIKE_ERR_PARAM;
	}
	as_error_reset(err);

	if (filter_args && !filter) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"filter arguments without filter name specification");
	}
	if (!as || !key || !ldt || !elements) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"as/key/ldt/peek_count/elements cannot be null");
	}
	if (ldt->type != AS_LDT_LLIST) {
		return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. "
				"not llist type");
	}

	int list_argc = filter ? 3 : 1;
	/* stack allocate the arg list */
	as_string ldt_bin;
	as_string_init(&ldt_bin, (char *)ldt->name, false);

	as_arraylist arglist;
	as_arraylist_inita(&arglist, list_argc);
	as_arraylist_append_string(&arglist, &ldt_bin);

	if (filter){
		as_string filter_name;
		as_string_init(&filter_name, (char *)filter, false);
		as_arraylist_append_string(&arglist, &filter_name );
		as_val_reserve( filter_args ); // bump the ref count
		as_arraylist_append(&arglist, (as_val *) filter_args );
	}

	as_val* p_return_val = NULL;
	aerospike_key_apply(
		as, err, policy, key, DEFAULT_LLIST_PACKAGE, filter ? LDT_LIST_OP_FILTER : LDT_LIST_OP_SCAN,
		(as_list *)&arglist, &p_return_val);

	as_arraylist_destroy(&arglist);

	if (ldt_parse_error(err) != AEROSPIKE_OK) {
		return err->code;
	}

	if (!p_return_val) {
		return as_error_set(err, AEROSPIKE_ERR_LDT_INTERNAL,
				"no value returned from server");
	}

	*elements = (as_list *)p_return_val;

	return err->code;

} // aerospike_llist_filter()
/**
 *******************************************************************************************************
 * This function applies a registered udf module on a particular record.
 *
 * @param self                  AerospikeClient object
 * @param py_key                The key under which to store the record.
 * @param py_module             The module name.
 * @param py_function           The UDF function to be applied on a record.
 * @param py_arglist            The arguments to the UDF function
 * @param py_policy             The optional policy parameters
 *
 * Returns the result of UDF function.
 *******************************************************************************************************
 */
PyObject * AerospikeClient_Apply_Invoke(
    AerospikeClient * self,
    PyObject * py_key, PyObject * py_module, PyObject * py_function,
    PyObject * py_arglist, PyObject * py_policy)
{
    // Python Return Value
    PyObject * py_result = NULL;

    // Aerospike Client Arguments
    as_error err;
    as_policy_apply apply_policy;
    as_policy_apply * apply_policy_p = NULL;
    as_key key;
    char * module = NULL;
    char * function = NULL;
    as_list * arglist = NULL;
    as_val * result = NULL;

    PyObject * py_umodule   = NULL;
    PyObject * py_ufunction = NULL;

    // Initialisation flags
    bool key_initialised = false;

    // Initialize error
    as_error_init(&err);

    if( !PyList_Check(py_arglist) ) {
        PyErr_SetString(PyExc_TypeError, "expected UDF method arguments in a 'list'");
        return NULL;
    }

    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 key object to as_key
    pyobject_to_key(&err, py_key, &key);
    if ( err.code != AEROSPIKE_OK ) {
        goto CLEANUP;
    }
    // Key is initialiased successfully
    key_initialised = true;

    // Convert python list to as_list
    pyobject_to_list(self, &err, py_arglist, &arglist, NULL, -1);
    if ( err.code != AEROSPIKE_OK ) {
        goto CLEANUP;
    }

    // Convert python policy object to as_policy_apply
    pyobject_to_policy_apply(&err, py_policy, &apply_policy, &apply_policy_p,
                             &self->as->config.policies.apply);
    if ( err.code != AEROSPIKE_OK ) {
        goto CLEANUP;
    }

    if ( PyUnicode_Check(py_module) ) {
        py_umodule = PyUnicode_AsUTF8String(py_module);
        module = PyStr_AsString(py_umodule);
    }
    else if ( PyStr_Check(py_module) ) {
        module = PyStr_AsString(py_module);
    }
    else {
        as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf module argument must be a string or unicode string");
        goto CLEANUP;
    }

    if ( PyUnicode_Check(py_function) ) {
        py_ufunction = PyUnicode_AsUTF8String(py_function);
        function = PyStr_AsString(py_ufunction);
    }
    else if ( PyStr_Check(py_function) ) {
        function = PyStr_AsString(py_function);
    }
    else {
        as_error_update(&err, AEROSPIKE_ERR_CLIENT, "function name must be a string or unicode string");
        goto CLEANUP;
    }

    // Invoke operation
    aerospike_key_apply(self->as, &err, apply_policy_p, &key, module, function, arglist, &result);

    if ( err.code == AEROSPIKE_OK ) {
        val_to_pyobject(&err, result, &py_result);
    } else {
        as_error_update(&err, err.code, NULL);
    }

CLEANUP:

    if (py_umodule) {
        Py_DECREF(py_umodule);
    }

    if (py_ufunction) {
        Py_DECREF(py_ufunction);
    }

    if (key_initialised == true) {
        // Destroy the key if it is initialised successfully.
        as_key_destroy(&key);
    }
    as_list_destroy(arglist);
    as_val_destroy(result);

    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);
        }
        if(PyObject_HasAttrString(exception_type, "module")) {
            PyObject_SetAttrString(exception_type, "module", py_module);
        }
        if(PyObject_HasAttrString(exception_type, "func")) {
            PyObject_SetAttrString(exception_type, "func", py_function);
        }
        PyErr_SetObject(exception_type, py_err);
        Py_DECREF(py_err);
        return NULL;
    }

    return py_result;
}
	as_hashmap map;
	as_hashmap_init(&map, 1);

	as_stringmap_set_int64((as_map *) &map, "x", (int64_t)7);
	as_stringmap_set_int64((as_map *) &map, "y", (int64_t)8);
	as_stringmap_set_int64((as_map *) &map, "z", (int64_t)9);

	as_val_reserve((as_map *) &map);
	as_arraylist_append(&arglist, (as_val *)((as_map *) &map));

	as_val * res = NULL;

	as_key key;
	as_key_init(&key, NAMESPACE, SET, "foo");

	as_status rc = aerospike_key_apply(as, &err, NULL, &key, UDF_FILE, "map_arg", (as_list*) &arglist, &res);

	as_key_destroy(&key);
	as_hashmap_destroy(&map);
	
    assert_int_eq( rc, AEROSPIKE_OK );
	assert_not_null( res );

    as_val_destroy(&arglist);
    as_val_destroy(res);
}

TEST( key_apply_put , "put: (test,test,foo) = {a: 123, b: 'abc', c: 456, d: 'def', e: [1,2,3], f: {x: 7, y: 8, z: 9}}" ) {

	as_error err;
	as_error_reset(&err);
Exemple #14
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);

    // Register the UDF in the database cluster.
    if (! example_register_udf(&as, UDF_FILE_PATH)) {
        example_cleanup(&as);
        exit(-1);
    }

    // Write a record to the database.
    if (! write_record(&as)) {
        cleanup(&as);
        exit(-1);
    }

    as_error err;

    // Apply a simple UDF, with no arguments and no return value.
    if (aerospike_key_apply(&as, &err, NULL, &g_key, UDF_MODULE,
                            "test_bin_1_add_1000", NULL, NULL) != AEROSPIKE_OK) {
        LOG("aerospike_key_apply() returned %d - %s", err.code, err.message);
        cleanup(&as);
        exit(-1);
    }

    LOG("test_bin_1_add_1000() was successfully applied");

    if (! example_read_test_record(&as)) {
        example_cleanup(&as);
        exit(-1);
    }

    // Create an argument list for a (different) UDF. By using
    // as_arraylist_inita() we avoid some but not all internal heap usage, so we
    // must call as_arraylist_destroy().
    as_arraylist args;
    as_arraylist_inita(&args, 3);
    as_arraylist_append_str(&args, "test-bin-2");
    as_arraylist_append_int64(&args, 4);
    as_arraylist_append_int64(&args, 400);

    // Expect an integer return value.
    as_val* p_return_val = NULL;

    // Apply a UDF with arguments and a return value.
    if (aerospike_key_apply(&as, &err, NULL, &g_key, UDF_MODULE,
                            "bin_transform", (as_list*)&args, &p_return_val) != AEROSPIKE_OK) {
        LOG("aerospike_key_apply() returned %d - %s", err.code, err.message);
        as_arraylist_destroy(&args);
        cleanup(&as);
        exit(-1);
    }

    as_arraylist_destroy(&args);

    if (! p_return_val) {
        LOG("aerospike_key_apply() retrieved null as_val object");
        cleanup(&as);
        exit(-1);
    }

    // Extract an integer from the as_val returned.
    int64_t i_val = as_integer_getorelse(as_integer_fromval(p_return_val), -1);

    // Caller's responsibility to destroy as_val returned.
    as_val_destroy(p_return_val);

    if (i_val == -1) {
        LOG("aerospike_key_apply() retrieved non-as_integer object");
        cleanup(&as);
        exit(-1);
    }

    LOG("bin_transform() was successfully applied - returned %" PRId64, i_val);

    if (! example_read_test_record(&as)) {
        example_cleanup(&as);
        exit(-1);
    }

    // Cleanup and disconnect from the database cluster.
    cleanup(&as);

    LOG("udf example successfully completed");

    return 0;
}