/** * Test TWO is one more step in complexity -- it does the simple * push and peek with the Stumble data -- and so does a compress * and uncompress of the data using the inner UDF. Notice that * the CREATE of this LSTACK BIN must have the correct parameters * set for doing the inner UDF call (e.g. BINARY type, and entry * size). */ int run_test2(char *user_key) { static char * meth = "run_test2()"; int rc = 0; char * ldt_bin_name = "LSET_TEST2_BIN"; char * compress_func = "stumbleCompress5"; as_list *compress_args = as_arraylist_new( 1, 1 ); as_list *uncompress_args = as_arraylist_new( 1, 1 ); as_list_add_integer( compress_args, 1 ); // dummy argument int iterations = g_config->n_iterations; INFO("[DEBUG]<%s:%s>Call ldt_write_with_transform_test()\n", MOD, meth ); rc = ldt_write_list_with_transform_test( user_key, ldt_bin_name, NULL, iterations ); if (rc) { INFO("[ERROR]<%s:%s>write result: RC(%d)\n", MOD, meth, rc); goto Cleanup; } char * uncompress_func = "stumbleUnCompress5"; as_list_add_integer( uncompress_args, 1 ); // dummy argument INFO("[DEBUG]:<%s:%s>: calling ldt_read_with_filter_test()\n", MOD, meth ); rc = ldt_read_list_with_filter_test( user_key, ldt_bin_name, uncompress_func, uncompress_args, g_config->n_iterations ); if (rc) { INFO("[ERROR]:<%s:%s>: ldt_read_with_filter_test() RC(%d)\n", MOD, meth, rc); goto Cleanup; } Cleanup: as_list_destroy( uncompress_args ); as_list_destroy( compress_args ); return ( rc ); } // end run_test2
as_val * lset_gen_list_val(int seed ) { as_list * listp = as_arraylist_new( 5, 0 ); // must destroy later. srand( seed ); int64_t urlid = seed; // Generate URL_ID as_list_add_integer( listp, urlid ); int64_t created = rand() % 500; // Generate CREATED as_list_add_integer( listp, created ); int64_t meth_a = rand() % 50000; // Generate first half of method as_list_add_integer( listp, meth_a ); int64_t meth_b = rand() % 50000; // Generate 2nd half of method as_list_add_integer( listp, meth_b ); int64_t status = rand() % 8000; // Generate status as_list_add_integer( listp, status ); return( as_val * ) listp; } // end gen_list_val()
static bool unpack_list(serial_context *ser_cont, uint32_t size, as_val **value) { if (VERBOSE) { ver("%sList, %u element(s)", indent(ser_cont), size); } as_arraylist *list = as_arraylist_new(size, 8); if (list == NULL) { err("Error while allocating list"); return false; } ser_cont->indent += 2; for (uint32_t i = 0; i < size; ++i) { as_val *element; if (!UNPACK_VALUE(ser_cont, &element)) { err("Error while unpacking list element"); as_arraylist_destroy(list); return false; } if (as_arraylist_set(list, i, element) != AS_ARRAYLIST_OK) { err("Error while populating list"); as_arraylist_destroy(list); return false; } } ser_cont->indent -= 2; *value = (as_val *)list; return true; }
AerospikeQuery * AerospikeQuery_Apply(AerospikeQuery * self, PyObject * args, PyObject * kwds) { as_error err; // Initialize error as_error_init(&err); int nargs = (int) PyTuple_Size(args); // Aerospike API Arguments char * module = NULL; char * function = NULL; as_arraylist * arglist = NULL; // too few args if ( nargs < 2 ) { // some error } // Python Arguments PyObject * py_module = PyTuple_GetItem(args, 0); PyObject * py_function = PyTuple_GetItem(args, 1); if ( PyString_Check(py_module) ) { module = PyString_AsString(py_module); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf module argument must be a string"); goto CLEANUP; } if ( PyString_Check(py_function) ) { function = PyString_AsString(py_function); } else { as_error_update(&err, AEROSPIKE_ERR_CLIENT, "udf function argument must be a string"); goto CLEANUP; } if ( nargs > 2 ) { arglist = as_arraylist_new(nargs, 0); for ( int i = 2; i < nargs; i++ ) { PyObject * py_val = PyTuple_GetItem(args, i); as_val * val = NULL; pyobject_to_val(&err, py_val, &val); if ( err.code != AEROSPIKE_OK ) { goto CLEANUP; } } } as_query_apply(&self->query, module, function, (as_list *) arglist); CLEANUP: if ( err.code != AEROSPIKE_OK ) { PyObject * py_err = NULL; error_to_pyobject(&err, &py_err); PyErr_SetObject(PyExc_Exception, py_err); return NULL; } Py_INCREF(self); return self; }
AerospikeQuery * AerospikeQuery_Apply(AerospikeQuery * self, PyObject * args, PyObject * kwds) { // Python function arguments PyObject * py_module = NULL; PyObject * py_function = NULL; PyObject * py_args = NULL; PyObject * py_policy = NULL; PyObject * py_umodule = NULL; PyObject * py_ufunction = NULL; // Python function keyword arguments static char * kwlist[] = {"module", "function", "arguments", "policy", NULL}; if ( PyArg_ParseTupleAndKeywords(args, kwds, "OO|OO:apply", kwlist, &py_module, &py_function, &py_args, &py_policy) == false ){ return NULL; } // Aerospike error object as_error err; // Initialize error object as_error_init(&err); if ( !self || !self->client->as ){ as_error_update(&err, AEROSPIKE_ERR_PARAM, "Invalid query object"); goto CLEANUP; } if (!self->client->is_conn_16) { as_error_update(&err, AEROSPIKE_ERR_CLUSTER, "No connection to aerospike cluster"); goto CLEANUP; } // Aerospike API Arguments char * module = NULL; char * function = NULL; as_arraylist * arglist = NULL; 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, "udf function argument must be a string or unicode string"); goto CLEANUP; } if ( py_args && PyList_Check(py_args) ){ Py_ssize_t size = PyList_Size(py_args); arglist = as_arraylist_new(size, 0); for ( int i = 0; i < size; i++ ) { PyObject * py_val = PyList_GetItem(py_args, (Py_ssize_t)i); as_val * val = NULL; pyobject_to_val(self->client, &err, py_val, &val, &self->static_pool, SERIALIZER_PYTHON); if ( err.code != AEROSPIKE_OK ) { as_error_update(&err, err.code, NULL); goto CLEANUP; } else { as_arraylist_append(arglist, val); } } } as_query_apply(&self->query, module, function, (as_list *) arglist); CLEANUP: if (py_ufunction) { Py_DECREF(py_ufunction); } if (py_umodule) { Py_DECREF(py_umodule); } 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, "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; } Py_INCREF(self); return self; }
/** * LSET Insert WITH_TRANSFORM TEST * For a single record, perform a series of SET Insert of BYTE-PACKED data. * Create a new record, then repeatedly call stack insert. */ int lset_insert_with_transform_test(char * keystr, char * ldt_bin, int iterations) { static char * meth = "lset_insert_with_transform_test()"; if( LSET_DEBUG ) { INFO(" [ENTER]:<%s:%s>:From %s", MOD, LDT, meth ); } int rc = 0; int i; INFO("[ENTER]:<%s:%s>: It(%d) Key(%s) LSOBin(%s)", MOD, meth, iterations, keystr, ldt_bin ); // Abbreviate for simplicity. cl_cluster * c = lset_g_config->asc; char * ns = lset_g_config->ns; char * set = lset_g_config->set; char * bname = ldt_bin; cl_object o_key; // Set up the Creation Spec parameter -- mostly setting the Package // (which is the name for a canned set of settings). char * create_package = "ProdListValBinStore"; as_map *create_spec = as_hashmap_new(2); as_map_set(create_spec, (as_val *) as_string_new("Package", false), (as_val *) as_string_new( create_package, false)); INFO("[DEBUG]:<%s:%s>: Run insert_with_transform() iterations(%d)", MOD, meth, iterations ); citrusleaf_object_init_str( &o_key, keystr ); for ( i = 0; i < iterations; i++ ) { int val = i * 10; as_list * listp = as_arraylist_new( 5, 5 ); int64_t urlid = val + 1; as_list_add_integer( listp, urlid ); int64_t created = val + 2; as_list_add_integer( listp, created ); int64_t meth_a = val + 3; as_list_add_integer( listp, meth_a ); int64_t meth_b = val + 4; as_list_add_integer( listp, meth_b ); int64_t status = val + 5; as_list_add_integer( listp, status ); rc = aerospike_lset_create_and_insert( c, ns, set, &o_key, bname, (as_val *)listp, create_spec, lset_g_config->timeout_ms); if ( rc != CITRUSLEAF_OK ) { INFO("[ERROR]:<%s:%s>:LSO PUSH WITH TRANSFROM Error: i(%d) rc(%d)", MOD, meth, i, rc ); as_val_destroy ( listp ); goto cleanup; } // Count the write operation for stats gathering lset_g_config->write_ops_counter += 1; lset_g_config->write_vals_counter += 1; as_val_destroy( listp ); // must destroy every iteration. listp = NULL; } // end for cleanup: citrusleaf_object_free( &o_key ); as_val_destroy( create_spec ); return rc; } // end lset_insert_with_transform_test()
/****************************************************************************** * VARIABLES *****************************************************************************/ static as_aerospike as; /****************************************************************************** * TEST CASES *****************************************************************************/ TEST( record_udf_1, "echo bin a of {a = 123, b = 456 }" ) { as_rec * rec = map_rec_new(); as_rec_set(rec, "a", (as_val *) as_integer_new(123)); as_list * arglist = (as_list *) as_arraylist_new(1,0); as_list_append_str(arglist, "a"); as_result * res = as_success_new(NULL); int rc = as_module_apply_record(&mod_lua, &as, "records", "getbin", rec, arglist, res); assert_int_eq( rc, 0 ); assert_true( res->is_success ); assert_not_null( res->value ); assert_int_eq( as_integer_toint((as_integer *) res->value), 123 ); as_rec_destroy(rec); as_list_destroy(arglist); as_result_destroy(res); }
static as_record add_bins_to_rec(lua_State *L, int index, int numBins) { as_record rec; as_record_init(&rec, numBins); // Push another reference to the table on top of the stack (so we know // where it is, and this function can work for negative, positive and // pseudo indices lua_pushvalue(L, index); // stack now contains: -1 => table lua_pushnil(L); // stack now contains: -1 => nil; -2 => table while (lua_next(L, -2)) { // stack now contains: -1 => value; -2 => key; -3 => table // copy the key so that lua_tostring does not modify the original lua_pushvalue(L, -2); // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table const char *binName = lua_tostring(L, -1); // add to record if (lua_isnumber(L, -2)){ int intValue = lua_tointeger(L, -2); as_record_set_int64(&rec, binName, intValue); } else if (lua_isstring(L, -2)){ const char *value = lua_tostring(L, -2); as_record_set_str(&rec, binName, value); } else if (lua_istable(L, -2)){ // make a as_list and populate it as_arraylist *list = as_arraylist_new(3, 3); lua_pushvalue(L, -2); lua_pushnil(L); // This is needed for it to even get the first value while (lua_next(L, -2)) { lua_pushvalue(L, -2); //const char *key = lua_tostring(L, -1); const char *value = lua_tostring(L, -2); // populate the as_list as_arraylist_append_str(list, value); //printf("%s => %s\n", key, value); lua_pop(L, 2); } lua_pop(L, 1); // put the list in a bin as_record_set_list(&rec, binName, (as_list*)as_val_reserve(list)); } // pop value + copy of key, leaving original key lua_pop(L, 2); // stack now contains: -1 => key; -2 => table } // stack now contains: -1 => table (when lua_next returns 0 it pops the key // but does not push anything.) // Pop table lua_pop(L, 1); // Stack is now the same as it was on entry to this function return rec; }