예제 #1
0
/**
 *	Creates and initializes a heap allocated as_ldt.
 *
 *	~~~~~~~~~~{.c}
 *	as_ldt * ldt = as_ldt_new("mystack", AS_LDT_LSTACK, NULL);
 *	~~~~~~~~~~
 *
 *	Use as_ldt_destroy() to release resources allocated to as_ldt via
 *	this function.
 *
 *	@param name		The name of the bin to contain the ldt.
 *	@param type		The type of ldt data to store in the bin.
 *	@param module	The name of ldt customization module to use for this initialization.
 *
 *	@return The initialized as_key on success. Otherwise NULL.
 *
 *	@relates as_ldt
 *	@ingroup as_ldt_object
 */
as_ldt * as_ldt_new(const as_bin_name name, const as_ldt_type type, const as_udf_module_name module)
{
	as_ldt * ldt = (as_ldt *) malloc(sizeof(as_ldt));
	if ( ldt ) {
		if (!as_ldt_init(ldt, name, type, module)) {
			free (ldt);
			return NULL;
		}
		ldt->_free = true;
	}

	return ldt;
}
예제 #2
0
static bool asc_raw_write(aerospike* p_as, as_key* p_key, uint8_t *buf, uint32_t size)
{
    as_error err;
    as_status status;

    uint32_t lstack_size = (size+(CHUNK_SIZE-1))/CHUNK_SIZE;
    uint32_t offset, chksize;

    // Create a large stack object to use
    as_ldt lstack;
	as_ldt_init(&lstack, "data", AS_LDT_LSTACK, NULL);

    // Make arraylist
    as_arraylist vals;
    as_arraylist_inita(&vals, lstack_size);

    as_bytes *p_bval;
    p_bval = (as_bytes *)alloca(lstack_size * sizeof(as_bytes));
    for (offset = 0; offset < size; offset += chksize, p_bval++) {
        chksize = MIN(size - offset, CHUNK_SIZE);
        as_bytes_init_wrap(p_bval, buf + offset, chksize, false);
        as_arraylist_insert_bytes(&vals, 0, p_bval);
    }

    // Push bytes
#if 1
    // FIXME it's a workaround
    uint32_t i;
    for (i = 0; i < vals.size; i++) {
        status = aerospike_lstack_push(p_as, &err, NULL, p_key, &lstack, vals.elements[i]);
        if (status != AEROSPIKE_OK) {
            ERROR("aerospike_lstack_push() - returned %d - %s", err.code, err.message);
            return false;
        }
    }
#else
    status = aerospike_lstack_push_all(p_as, &err, NULL, p_key, &lstack, (as_list *)&vals);
    if (status != AEROSPIKE_OK) {
        ERROR("aerospike_lstack_push_all() - returned %d - %s", err.code, err.message);
        return false;
    }
#endif

    // Write metadata
    as_record rec;
    as_record_inita(&rec, 1);
    as_record_set_int64(&rec, "size", size);
    aerospike_key_put(p_as, &err, NULL, p_key, &rec);

    return true;
}
예제 #3
0
static bool asc_raw_read(aerospike* p_as, as_key* p_key, uint8_t *buf, uint32_t size)
{
    as_status status;
    as_error err;

    uint32_t lstack_size;
    uint32_t offset, chksize;

    // Create a large stack object to use
    as_ldt lstack;
	as_ldt_init(&lstack, "data", AS_LDT_LSTACK, NULL);

    // Get stack size
    status = aerospike_lstack_size(p_as, &err, NULL, p_key, &lstack, &lstack_size);
    if (status != AEROSPIKE_OK) {
        ERROR("aerospike_lstack_size() returned %d - %s", err.code, err.message);
        return false;
    }

	// Peek all the values back again.
	as_list* p_list = NULL;
	status = aerospike_lstack_peek(p_as, &err, NULL, p_key, &lstack, lstack_size, &p_list);
    if (status != AEROSPIKE_OK) {
        ERROR("aerospike_lstack_peek() returned %d - %s", err.code, err.message);
        return false;
    }

    // Read the content
    as_val** p_val = ((const as_arraylist*)p_list)->elements;
    for (offset = 0; offset < size; offset += chksize) {
        const as_bytes* p_bytes = (const as_bytes*)*p_val++;
        chksize = MIN(size - offset, p_bytes->size);
        memcpy(buf + offset, p_bytes->value, chksize);
    }
	as_list_destroy(p_list);
    p_list = NULL;

    return true;
}
예제 #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_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;
}
예제 #5
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);

	// Create a large map object to use. No need to destroy lmap if using
	// as_ldt_init() on stack object.
	as_ldt lmap;
	if (! as_ldt_init(&lmap, "mylmap", AS_LDT_LMAP, NULL)) {
		LOG("unable to initialize ldt");
		example_cleanup(&as);
		exit(-1);
	}

	as_error err;
	as_boolean ldt_exists;
	as_boolean_init(&ldt_exists, false);

	// Verify that the LDT is not already there.
	if (aerospike_lmap_ldt_exists(&as, &err, NULL, &g_key, &lmap,
			&ldt_exists) != AEROSPIKE_OK) {
		int rc = example_handle_udf_error(&err, "first aerospike_lmap_ldt_exists()");
		example_cleanup(&as);
		exit(rc);
	}

	if (as_boolean_get(&ldt_exists)) {
		LOG("found ldt that should not be present");
		example_cleanup(&as);
		exit(-1);
	}

	LOG("verified that lmap ldt is not present");

	// No need to destroy ikey if using as_integer_init() on stack object.
	as_integer ikey;
	as_integer_init(&ikey, 12345);

	// No need to destroy sval if using as_string_init() on stack object with
	// free parameter false.
	as_string sval;
	as_string_init(&sval, "lmap value", false);

	// Put a string entry to the lmap.
	if (aerospike_lmap_put(&as, &err, NULL, &g_key, &lmap,
			(const as_val*)&ikey, (as_val *)&sval) != AEROSPIKE_OK) {
		LOG("first aerospike_lmap_put() returned %d - %s", err.code,
				err.message);
		example_cleanup(&as);
		exit(-1);
	}

	// Ok to reuse.
	as_integer_init(&ikey, 345);

	as_integer ival;
	as_integer_init(&ival, 1000);

	// Put an integer entry to the lmap.
	if (aerospike_lmap_put(&as, &err, NULL, &g_key, &lmap,
			(const as_val*)&ikey, (as_val*)&ival) != AEROSPIKE_OK) {
		LOG("second aerospike_lmap_put() returned %d - %s", err.code,
				err.message);
		example_cleanup(&as);
		exit(-1);
	}

	LOG("2 entries added to map");

	uint32_t n_elements = 0;

	// See how many elements we have in the lmap now.
	if (aerospike_lmap_size(&as, &err, NULL, &g_key, &lmap, &n_elements) !=
			AEROSPIKE_OK) {
		LOG("aerospike_lmap_size() returned %d - %s", err.code, err.message);
		example_cleanup(&as);
		exit(-1);
	}

	if (n_elements != 2) {
		LOG("unexpected lmap size %u", n_elements);
		example_cleanup(&as);
		exit(-1);
	}

	LOG("lmap size confirmed to be %u", n_elements);

	as_boolean_init(&ldt_exists, false);

	// Verify that the LDT is now present.
	if (aerospike_lmap_ldt_exists(&as, &err, NULL, &g_key, &lmap,
			&ldt_exists) != AEROSPIKE_OK) {
		LOG("first aerospike_lmap_ldt_exists() returned %d - %s", err.code,
				err.message);
		example_cleanup(&as);
		exit(-1);
	}

	if (! as_boolean_get(&ldt_exists)) {
		LOG("did not find ldt that should be be present");
		example_cleanup(&as);
		exit(-1);
	}

	LOG("verified that lmap ldt is present");

	as_map* p_map = NULL;

	// Get all the entries back.
	if (aerospike_lmap_get_all(&as, &err, NULL, &g_key, &lmap, &p_map) !=
			AEROSPIKE_OK) {
		LOG("aerospike_lmap_filter() returned %d - %s", err.code, err.message);
		example_cleanup(&as);
		exit(-1);
	}

	as_hashmap_iterator it;
	as_hashmap_iterator_init(&it, (const as_hashmap*)p_map);

	// See if the elements match what we expect.
	while (as_hashmap_iterator_has_next(&it)) {
		const as_val* p_val = as_hashmap_iterator_next(&it);
		char* p_str = as_val_tostring(p_val);

		LOG("   element type %d, value %s", as_val_type(p_val), p_str);
		free(p_str);
	}

	as_map_destroy(p_map);
	p_map = NULL;

	as_integer_init(&ikey, 12345);

	// Remove an entry from the map.
	if (aerospike_lmap_remove(&as, &err, NULL, &g_key, &lmap,
			(const as_val*)&ikey) != AEROSPIKE_OK) {
		LOG("aerospike_lmap_remove() returned %d - %s", err.code, err.message);
		example_cleanup(&as);
		exit(-1);
	}

	as_val* p_val = NULL;

	// Make sure we can't get the value any more.
	as_status result = aerospike_lmap_get(&as, &err, NULL, &g_key, &lmap,
			(const as_val*)&ikey, &p_val);

	if (result == AEROSPIKE_OK) {
		// Server version >= 3.4.1 returns empty map if element doesn't exist.
		if (p_val && (as_val_type(p_val) != AS_MAP ||
				as_map_size((as_map*)p_val) != 0)) {
			char* p_str = as_val_tostring(p_val);

			LOG("entry was not successfully removed");
			LOG("   element type %d, value %s", as_val_type(p_val), p_str);
			free(p_str);

			as_val_destroy(p_val);
			example_cleanup(&as);
			exit(-1);
		}
	}
	else if (result != AEROSPIKE_ERR_LARGE_ITEM_NOT_FOUND) {
		LOG("aerospike_lmap_get() returned %d - %s", err.code, err.message);
		example_cleanup(&as);
		exit(-1);
	}

	LOG("entry successfully removed");

	// Destroy the lmap.
	if (aerospike_lmap_destroy(&as, &err, NULL, &g_key, &lmap) !=
			AEROSPIKE_OK) {
		LOG("aerospike_lmap_destroy() returned %d - %s", err.code, err.message);
		example_cleanup(&as);
		exit(-1);
	}

	n_elements = 0;

	// See if we can still do any lmap operations.
	if (aerospike_lmap_size(&as, &err, NULL, &g_key, &lmap, &n_elements) ==
			AEROSPIKE_OK) {
		LOG("aerospike_lmap_size() did not return error");
		example_cleanup(&as);
		exit(-1);
	}

	LOG("lmap successfully destroyed");

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

	LOG("lmap example successfully completed");

	return 0;
}
예제 #6
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_ldt lmap;

    // Create a lmap bin to use. No need to destroy as_ldt if using
    // as_ldt_init() on stack object.
    if (! as_ldt_init(&lmap, "mylmap", AS_LDT_LMAP, 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 ikey;
    as_integer_init(&ikey, 12345);

    // No need to destroy as_string if using as_string_init() on stack object
    // with free parameter false.
    as_string sval;
    as_string_init(&sval, "lmap value", false);

    // Put a string entry to the lmap.
    if (aerospike_lmap_put(&as, &err, NULL, &g_key, &lmap,
                           (const as_val*)&ikey, (as_val *)&sval) != AEROSPIKE_OK) {
        LOG("first aerospike_lmap_put() returned %d - %s", err.code,
            err.message);
        example_cleanup(&as);
        exit(-1);
    }

    as_integer ival;
    as_integer_init(&ival, 1000);

    // It's ok to reset the as_integer.
    as_integer_init(&ikey, 345);

    // Put an integer entry to the lmap.
    if (aerospike_lmap_put(&as, &err, NULL, &g_key, &lmap,
                           (const as_val*)&ikey, (as_val*)&ival) != AEROSPIKE_OK) {
        LOG("second aerospike_lmap_put() returned %d - %s", err.code,
            err.message);
        example_cleanup(&as);
        exit(-1);
    }

    LOG("2 entries added to map");

    uint32_t n_elements = 0;

    // See how many elements we have in the lmap now.
    if (aerospike_lmap_size(&as, &err, NULL, &g_key, &lmap, &n_elements) !=
            AEROSPIKE_OK) {
        LOG("aerospike_lmap_size() returned %d - %s", err.code, err.message);
        example_cleanup(&as);
        exit(-1);
    }

    if (n_elements != 2) {
        LOG("unexpected lmap size %u", n_elements);
        example_cleanup(&as);
        exit(-1);
    }

    LOG("lmap size confirmed to be %u", n_elements);

    as_ldt lmap2;
    as_ldt_init(&lmap2, "mylmap", AS_LDT_LMAP, NULL);

    as_map* p_map = NULL;

    // Get all the entries back.
    if (aerospike_lmap_get_all(&as, &err, NULL, &g_key, &lmap, &p_map) !=
            AEROSPIKE_OK) {
        LOG("aerospike_lmap_filter() returned %d - %s", err.code, err.message);
        example_cleanup(&as);
        exit(-1);
    }

    // See if the elements match what we expect.
    as_hashmap_iterator it;
    as_hashmap_iterator_init(&it, (const as_hashmap*)p_map);

    while (as_hashmap_iterator_has_next(&it)) {
        const as_val* p_val = as_hashmap_iterator_next(&it);
        char* p_str = as_val_tostring(p_val);

        LOG("   element - type = %d, value = %s", as_val_type(p_val), p_str);
        free(p_str);
    }

    as_map_destroy(p_map);
    p_map = NULL;

    as_integer_init(&ikey, 345);
    as_integer_init(&ival, 2000);

    // Remove an entry from the map.
    as_integer_init(&ikey, 12345);
    if (aerospike_lmap_remove(&as, &err, NULL, &g_key, &lmap,
                              (const as_val*)&ikey) != AEROSPIKE_OK) {
        LOG("aerospike_lmap_remove() returned %d - %s", err.code,
            err.message);
        example_cleanup(&as);
        exit(-1);
    }

    as_val* p_val = NULL;

    // Make sure we cannot get the value any more.
    if (aerospike_lmap_get(&as, &err, NULL, &g_key, &lmap,
                           (const as_val*)&ikey, &p_val) == AEROSPIKE_OK) {
        LOG("unexpected success getting a removed entry");
        as_val_destroy(p_val);
        example_cleanup(&as);
        exit(-1);
    }

    LOG("entry successfully removed");

    // Destroy the lmap.
    if (aerospike_lmap_destroy(&as, &err, NULL, &g_key, &lmap) !=
            AEROSPIKE_OK) {
        LOG("aerospike_lmap_destroy() returned %d - %s", err.code, err.message);
        example_cleanup(&as);
        exit(-1);
    }

    n_elements = 0;

    // See if we can still do any lmap operations.
    if (aerospike_lmap_size(&as, &err, NULL, &g_key, &lmap, &n_elements) ==
            AEROSPIKE_OK) {
        LOG("aerospike_lmap_size() did not return error");
        example_cleanup(&as);
        exit(-1);
    }

    LOG("lmap successfully destroyed");

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

    LOG("lmap example successfully completed");

    return 0;
}
예제 #7
0
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;
}