// ======================================================================= // 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()
// ======================================================================= 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; }
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_ldt lstack; // Create a large stack bin to use. No need to destroy as_ldt if using // as_ldt_init() on stack object. if (! as_ldt_init(&lstack, "mystack", AS_LDT_LSTACK, NULL)) { LOG("unable to initialize ldt"); example_cleanup(&as); exit(-1); } as_error err; // No need to destroy as_integer if using as_integer_init() on stack object. as_integer ival; as_integer_init(&ival, 123); // Push a few values onto the stack. if (aerospike_lstack_push(&as, &err, NULL, &g_key, &lstack, (const as_val*)&ival) != AEROSPIKE_OK) { LOG("first aerospike_lstack_push() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } // No need to destroy as_string if using as_string_init() on stack object. as_string sval; as_string_init(&sval, "string stack value", false); if (aerospike_lstack_push(&as, &err, NULL, &g_key, &lstack, (const as_val*)&sval) != AEROSPIKE_OK) { LOG("second aerospike_lstack_push() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } LOG("2 values pushed"); uint32_t n_elements = 0; // Look at the stack size right now. if (aerospike_lstack_size(&as, &err, NULL, &g_key, &lstack, &n_elements) != AEROSPIKE_OK) { LOG("aerospike_lstack_size() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } if (n_elements != 2) { LOG("unexpected stack size %u", n_elements); example_cleanup(&as); exit(-1); } LOG("stack size confirmed to be %u", n_elements); as_ldt lstack2; as_ldt_init(&lstack2, "mystack", AS_LDT_LSTACK, NULL); uint32_t peek_count = 3; as_list* p_list = NULL; // Peek a few values back. if (aerospike_lstack_peek(&as, &err, NULL, &g_key, &lstack2, peek_count, &p_list) != AEROSPIKE_OK) { LOG("first aerospike_lstack_peek() returned %d - %s", err.code, err.message); as_list_destroy(p_list); example_cleanup(&as); exit(-1); } as_arraylist_iterator it; as_arraylist_iterator_init(&it, (const as_arraylist*)p_list); // See if the elements match what we expect. while (as_arraylist_iterator_has_next(&it)) { const as_val* p_val = as_arraylist_iterator_next(&it); char* p_str = as_val_tostring(p_val); LOG(" peek - type = %d, value = %s", as_val_type(p_val), p_str); free(p_str); } as_list_destroy(p_list); p_list = NULL; // Push 3 more items onto the stack. By using as_arraylist_inita() we avoid // some but not all internal heap usage, so we must call // as_arraylist_destroy(). as_arraylist vals; as_arraylist_inita(&vals, 3); as_arraylist_append_int64(&vals, 1000); as_arraylist_append_int64(&vals, 2000); as_arraylist_append_int64(&vals, 3000); if (aerospike_lstack_push_all(&as, &err, NULL, &g_key, &lstack, (const as_list*)&vals) != AEROSPIKE_OK) { LOG("aerospike_lstack_pushall() returned %d - %s", err.code, err.message); as_arraylist_destroy(&vals); example_cleanup(&as); exit(-1); } as_arraylist_destroy(&vals); LOG("3 more values pushed"); as_ldt_init(&lstack2, "mystack", AS_LDT_LSTACK, NULL); peek_count = 10; // Peek all the values back again. if (aerospike_lstack_peek(&as, &err, NULL, &g_key, &lstack2, peek_count, &p_list) != AEROSPIKE_OK) { LOG("second aerospike_lstack_peek() returned %d - %s", err.code, err.message); as_list_destroy(p_list); example_cleanup(&as); exit(-1); } // See if the elements match what we expect. as_arraylist_iterator_init(&it, (const as_arraylist*)p_list); while (as_arraylist_iterator_has_next(&it)) { const as_val* p_val = as_arraylist_iterator_next(&it); char* p_str = as_val_tostring(p_val); LOG(" peek - type = %d, value = %s", as_val_type(p_val), p_str); free(p_str); } as_list_destroy(p_list); // Set capacity for the lstack. if (aerospike_lstack_set_capacity(&as, &err, NULL, &g_key, &lstack, 10000) != AEROSPIKE_OK) { LOG("aerospike_lstack_set_capacity() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } uint32_t cap_size = 0; // Get capacity from the lstack. if (aerospike_lstack_get_capacity(&as, &err, NULL, &g_key, &lstack, &cap_size) != AEROSPIKE_OK) { LOG("aerospike_lstack_get_capacity() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } if (cap_size != 10000) { LOG("unexpected capacity size %u", cap_size); example_cleanup(&as); exit(-1); } // Destroy the lstack. if (aerospike_lstack_destroy(&as, &err, NULL, &g_key, &lstack) != AEROSPIKE_OK) { LOG("aerospike_lstack_destroy() returned %d - %s", err.code, err.message); example_cleanup(&as); exit(-1); } n_elements = 0; // See if we can still do any lstack operations. if (aerospike_lstack_size(&as, &err, NULL, &g_key, &lstack, &n_elements) == AEROSPIKE_OK) { LOG("aerospike_lstack_size() did not return error"); example_cleanup(&as); exit(-1); } // Cleanup and disconnect from the database cluster. example_cleanup(&as); LOG("lstack example successfully completed"); return 0; }
// ======================================================================= static as_status aerospike_lstack_peek_with_filter( aerospike * as, as_error * err, const as_policy_apply * policy, const as_key * key, const as_ldt * ldt, uint32_t peek_count, 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 || !peek_count || !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_LSTACK) { return as_error_set(err, AEROSPIKE_ERR_PARAM, "invalid parameter. " "not stack type"); } int list_argc = filter ? 5 : 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_arraylist_append_int64(&arglist, peek_count ); if (filter){ as_string ldt_module; as_string_init(&ldt_module, (char *)ldt->module, false); as_arraylist_append_string(&arglist, &ldt_module); 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_LSTACK_PACKAGE, filter ? LDT_STACK_OP_FILTER : LDT_STACK_OP_PEEK, (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_lstack_peek_with_filter()
/** * Creates 100 records and 9 indexes. * * Records are structured as: * {a: String, b: Integer, c: Integer, d: Integer, e: Integer} * * The key is "a-b-c-d-e" * * The values are: * a = "abc" * b = 100 * c = <current index> * d = c % 10 * e = b + (c + 1) * (d + 1) / 2 */ bool query_foreach_create() { as_error err; as_error_reset(&err); int n_recs = 100; as_status status; as_index_task task; // create index on "a" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "a", "idx_test_a", AS_INDEX_STRING); index_process_return_code(status, &err, &task); // create index on "b" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "b", "idx_test_b", AS_INDEX_NUMERIC); index_process_return_code(status, &err, &task); // create index on "c" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "c", "idx_test_c", AS_INDEX_NUMERIC); index_process_return_code(status, &err, &task); // create index on "d" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "d", "idx_test_d", AS_INDEX_NUMERIC); index_process_return_code(status, &err, &task); // create complex index on "x" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "x", "idx_test_x", AS_INDEX_TYPE_LIST, AS_INDEX_STRING); index_process_return_code(status, &err, &task); // create complex index on "y" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "y", "idx_test_y", AS_INDEX_TYPE_MAPKEYS, AS_INDEX_STRING); index_process_return_code(status, &err, &task); // create complex index on "y" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "y", "idx_test_y1", AS_INDEX_TYPE_MAPVALUES, AS_INDEX_STRING); index_process_return_code(status, &err, &task); // create complex index on "z" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "z", "idx_test_z", AS_INDEX_TYPE_LIST, AS_INDEX_NUMERIC); index_process_return_code(status, &err, &task); char* buffer = alloca(n_recs * 1024 + 1); uint32_t the_ttl = AS_RECORD_NO_EXPIRE_TTL; // insert records for ( int i = 0; i < n_recs; i++ ) { if (i == 10) { // We change the TTL from never to 100 days the_ttl = 100 * 24 * 60 * 60; } else if (i == 42) { // NOTE - We pause on the 42nd iteration for a few // milliseconds and note the time. We can then use the // as_predexp_rec_last_update_after predicate below to find // the later records. as_sleep(5); g_epochns = cf_clock_getabsolute() * 1000 * 1000; as_sleep(5); // Also on the 42nd iteration we change the TTL to // 10 days for the remaining records. the_ttl = 10 * 24 * 60 * 60; } char * a = "abc"; int b = n_recs; int c = i; int d = i % 10; int e = b + (c + 1) * (d + 1) / 2; int g = i; // Only set on odd records. char f[64]; snprintf(f, sizeof(f), "0x%04x", i); char keystr[64] = { '\0' }; snprintf(keystr, 64, "%s-%d-%d-%d-%d", a, b, c, d, e); // Make list as_arraylist list; as_arraylist_init(&list, 3, 0); if ( (i%3) == 0) { as_arraylist_append_str(&list, "x"); as_arraylist_append_str(&list, "x1"); as_arraylist_append_str(&list, "x2"); } else { as_arraylist_append_str(&list, "not_x1"); as_arraylist_append_str(&list, "not_x2"); as_arraylist_append_str(&list, "not_x3"); } // Make map as_hashmap map; as_hashmap_init(&map, 1); if ( (i%7) == 0) { as_stringmap_set_str((as_map *) &map, "ykey", "yvalue"); } else { as_stringmap_set_str((as_map *) &map, "ykey_not", "yvalue_not"); } // Make list of integers as_arraylist list2; as_arraylist_init(&list2, 5, 0); as_arraylist_append_int64(&list2, i); as_arraylist_append_int64(&list2, i+1); as_arraylist_append_int64(&list2, i+2); as_arraylist_append_int64(&list2, i+3); as_arraylist_append_int64(&list2, i+4); // Make a string of variable size for (int jj = 0; jj < i * 1024; ++jj) { buffer[jj] = 'X'; } buffer[i * 1024] = '\0'; // We only create the g bin for odd records. bool create_g_bin = i % 2 == 1; as_record r; as_record_init(&r, 10 + (create_g_bin ? 1 : 0)); as_record_set_str(&r, "a", a); as_record_set_int64(&r, "b", b); as_record_set_int64(&r, "c", c); as_record_set_int64(&r, "d", d); as_record_set_int64(&r, "e", e); as_record_set_str(&r, "f", f); if (create_g_bin) { as_record_set_int64(&r, "g", g); } as_record_set_list(&r, "x", (as_list *) &list); as_record_set_map(&r, "y", (as_map *) &map); as_record_set_list(&r, "z", (as_list *) &list2); as_record_set_str(&r, "bigstr", buffer); r.ttl = the_ttl; as_key key; as_key_init(&key, NAMESPACE, SET, keystr); aerospike_key_put(as, &err, NULL, &key, &r); as_record_destroy(&r); if (err.code != AEROSPIKE_OK) { error("aerospike_key_put() failed %d %s", err.code, err.message); return false; } as_record *r1 = NULL; aerospike_key_exists(as, &err, NULL, &key, &r1); as_key_destroy(&key); if (err.code != AEROSPIKE_OK) { error("aerospike_key_exists() failed %d %s", err.code, err.message); return false; } if (! r1) { error("key not found %s", keystr); return false; } as_record_destroy(r1); } return true; }
static int _as_arraylist_list_append_int64(as_list * l, int64_t v) { return as_arraylist_append_int64((as_arraylist *) l, v); }
/** * Creates 100 records and 9 indexes. * * Records are structured as: * {a: String, b: Integer, c: Integer, d: Integer, e: Integer} * * The key is "a-b-c-d-e" * * The values are: * a = "abc" * b = 100 * c = <current index> * d = c % 10 * e = b + (c + 1) * (d + 1) / 2 */ bool query_foreach_create() { as_error err; as_error_reset(&err); int n_recs = 100; as_status status; as_index_task task; // create index on "a" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "a", "idx_test_a", AS_INDEX_STRING); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create index on "b" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "b", "idx_test_b", AS_INDEX_NUMERIC); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create index on "c" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "c", "idx_test_c", AS_INDEX_NUMERIC); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create index on "d" status = aerospike_index_create(as, &err, &task, NULL, NAMESPACE, SET, "d", "idx_test_d", AS_INDEX_NUMERIC); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create complex index on "x" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "x", "idx_test_x", AS_INDEX_TYPE_LIST, AS_INDEX_STRING); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create complex index on "y" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "y", "idx_test_y", AS_INDEX_TYPE_MAPKEYS, AS_INDEX_STRING); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create complex index on "y" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "y", "idx_test_y1", AS_INDEX_TYPE_MAPVALUES, AS_INDEX_STRING); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // create complex index on "z" status = aerospike_index_create_complex(as, &err, &task, NULL, NAMESPACE, SET, "z", "idx_test_z", AS_INDEX_TYPE_LIST, AS_INDEX_NUMERIC); if ( status == AEROSPIKE_OK ) { aerospike_index_create_wait(&err, &task, 0); } else { info("error(%d): %s", err.code, err.message); } // insert records for ( int i = 0; i < n_recs; i++ ) { char * a = "abc"; int b = n_recs; int c = i; int d = i % 10; int e = b + (c + 1) * (d + 1) / 2; char keystr[64] = { '\0' }; snprintf(keystr, 64, "%s-%d-%d-%d-%d", a, b, c, d, e); // Make list as_arraylist list; as_arraylist_init(&list, 3, 0); if ( (i%3) == 0) { as_arraylist_append_str(&list, "x"); as_arraylist_append_str(&list, "x1"); as_arraylist_append_str(&list, "x2"); } else { as_arraylist_append_str(&list, "not_x1"); as_arraylist_append_str(&list, "not_x2"); as_arraylist_append_str(&list, "not_x3"); } // Make map as_hashmap map; as_hashmap_init(&map, 1); if ( (i%7) == 0) { as_stringmap_set_str((as_map *) &map, "ykey", "yvalue"); } else { as_stringmap_set_str((as_map *) &map, "ykey_not", "yvalue_not"); } // Make list of integers as_arraylist list2; as_arraylist_init(&list2, 5, 0); as_arraylist_append_int64(&list2, i); as_arraylist_append_int64(&list2, i+1); as_arraylist_append_int64(&list2, i+2); as_arraylist_append_int64(&list2, i+3); as_arraylist_append_int64(&list2, i+4); as_record r; as_record_init(&r, 9); as_record_set_str(&r, "a", a); as_record_set_int64(&r, "b", b); as_record_set_int64(&r, "c", c); as_record_set_int64(&r, "d", d); as_record_set_int64(&r, "e", e); as_record_set_list(&r, "x", (as_list *) &list); as_record_set_map(&r, "y", (as_map *) &map); as_record_set_list(&r, "z", (as_list *) &list2); as_key key; as_key_init(&key, NAMESPACE, SET, keystr); aerospike_key_put(as, &err, NULL, &key, &r); as_record_destroy(&r); if (err.code != AEROSPIKE_OK) { error("aerospike_key_put() failed %d %s", err.code, err.message); return false; } as_record *r1 = NULL; aerospike_key_exists(as, &err, NULL, &key, &r1); as_key_destroy(&key); if (err.code != AEROSPIKE_OK) { error("aerospike_key_exists() failed %d %s", err.code, err.message); return false; } if (! r1) { error("key not found %s", keystr); return false; } as_record_destroy(r1); } return true; }
int main(int argc, char* argv[]) { aerospike as; as_error err; as_boolean ldt_exists; as_ldt lstack, lstack2; as_integer ival; as_string sval; as_bytes bval; uint32_t n_elements, cap_size; as_arraylist_iterator it; as_list* p_list = NULL; // Parse command line arguments. if (! example_get_opts(argc, argv, EXAMPLE_BASIC_OPTS)) { exit(-1); } // Connect to the aerospike database cluster. example_connect_to_aerospike(&as); // Start clean. example_remove_test_record(&as); // Create a large stack object to use. No need to destroy lstack if using // as_ldt_init() on stack object. as_ldt_init(&lstack, "mystack", AS_LDT_LSTACK, NULL); // Verify that the LDT is not already there. as_boolean_init(&ldt_exists, false); assert (aerospike_lstack_ldt_exists(&as, &err, NULL, &g_key, &lstack, &ldt_exists) == AEROSPIKE_OK); assert (as_boolean_get(&ldt_exists) == false); LOG("verified that lstack ldt is not present"); // Push a few values onto the stack. // No need to destroy sval if using as_string_init() on stack object. // Push an integer as_integer_init(&ival, 123); assert (aerospike_lstack_push(&as, &err, NULL, &g_key, &lstack, (const as_val*)&ival) == AEROSPIKE_OK); // Push a string as_string_init(&sval, "string stack value", false); assert (aerospike_lstack_push(&as, &err, NULL, &g_key, &lstack, (const as_val*)&sval) == AEROSPIKE_OK); // Push bytes uint8_t buf[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; as_bytes_init_wrap(&bval, buf, 16, false); assert (aerospike_lstack_push(&as, &err, NULL, &g_key, &lstack, (const as_val*)&bval) == AEROSPIKE_OK); // Look at the stack size right now. assert (aerospike_lstack_size(&as, &err, NULL, &g_key, &lstack, &n_elements) == AEROSPIKE_OK); LOG("%d values pushed", n_elements); // Peek a few values back. as_ldt_init(&lstack2, "mystack", AS_LDT_LSTACK, NULL); assert (aerospike_lstack_peek(&as, &err, NULL, &g_key, &lstack2, 3, &p_list) == AEROSPIKE_OK); // See if the elements match what we expect. as_arraylist_iterator_init(&it, (const as_arraylist*)p_list); while (as_arraylist_iterator_has_next(&it)) { const as_val* p_val = as_arraylist_iterator_next(&it); char* p_str = as_val_tostring(p_val); LOG(" peek - type = %d, value = %s", as_val_type(p_val), p_str); free(p_str); } as_list_destroy(p_list); p_list = NULL; // Push 3 more items onto the stack. By using as_arraylist_inita() we avoid // some but not all internal heap usage, so we must call // as_arraylist_destroy(). as_arraylist vals; as_arraylist_inita(&vals, 3); as_arraylist_append_int64(&vals, 1000); as_arraylist_append_int64(&vals, 2000); as_arraylist_append_int64(&vals, 3000); assert (aerospike_lstack_push_all(&as, &err, NULL, &g_key, &lstack, (const as_list*)&vals) == AEROSPIKE_OK); as_arraylist_destroy(&vals); LOG("3 more values pushed"); // Peek all the values back again. as_ldt_init(&lstack2, "mystack", AS_LDT_LSTACK, NULL); assert (aerospike_lstack_peek(&as, &err, NULL, &g_key, &lstack2, 10, &p_list) == AEROSPIKE_OK); // See if the elements match what we expect. #if 0 as_arraylist_iterator_init(&it, (const as_arraylist*)p_list); while (as_arraylist_iterator_has_next(&it)) { const as_val* p_val = as_arraylist_iterator_next(&it); char* p_str = as_val_tostring(p_val); LOG(" peek - type = %d, value = %s", as_val_type(p_val), p_str); free(p_str); } #else const as_arraylist* p_array = (const as_arraylist*)p_list; int i; for (i = 0; i < p_array->size; i++) { const as_val* p_val = p_array->elements[i]; char* p_str = as_val_tostring(p_val); LOG(" peek - type = %d, value = %s", as_val_type(p_val), p_str); free(p_str); } #endif as_list_destroy(p_list); p_list = NULL; // Set capacity for the lstack. assert (aerospike_lstack_set_capacity(&as, &err, NULL, &g_key, &lstack, 10000) == AEROSPIKE_OK); // Get capacity from the lstack. assert (aerospike_lstack_get_capacity(&as, &err, NULL, &g_key, &lstack, &cap_size) == AEROSPIKE_OK); assert (cap_size == 10000); // Verify that the LDT is now present. as_boolean_init(&ldt_exists, false); assert (aerospike_lstack_ldt_exists(&as, &err, NULL, &g_key, &lstack, &ldt_exists) == AEROSPIKE_OK); assert (as_boolean_get(&ldt_exists) == true); LOG("verified that lstack ldt is present"); // Destroy the lstack. assert (aerospike_lstack_destroy(&as, &err, NULL, &g_key, &lstack) == AEROSPIKE_OK); // See if we can still do any lstack operations. assert (aerospike_lstack_size(&as, &err, NULL, &g_key, &lstack, &n_elements) != AEROSPIKE_OK); // Cleanup and disconnect from the database cluster. example_cleanup(&as); LOG("lstack example successfully completed"); return 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; }