int test_getall(cl_cluster *clc){ // set up the key. cl_object key_obj; citrusleaf_object_init_str(&key_obj, myKey); // create variables to return all values cl_bin *bins; int n_bins; // do the get citrusleaf_get_all(clc, ns, myset, &key_obj, &bins, &n_bins, 0, NULL); // check the contained values int haveStr = 0; int haveInt = 0; int haveBlob = 0; if( n_bins != 3 ){ printf(" TEST FAILED - get_all returns wrong number of bins, %d\n", n_bins); return -1; } for (int i=0;i<n_bins;i++) { printf (" bin %d name %s\n",i,bins[i].bin_name); if (bins[i].object.type == CL_STR){ if( strcmp(bins[i].object.u.str, strData) ){ printf(" TEST FAILED - str output of get_all does not match input\n"); return -1; } if( !bins[i].object.free ){ printf(" TEST FAILED - string allocated, but free pointer not set\n"); return -1; } haveStr = 1; }else if (bins[i].object.type == CL_INT ){ if( bins[i].object.u.i64 != intData ){ printf(" TEST FAILED - int output of get_all does not match input\n"); return -1; } if( bins[i].object.free ){ printf(" TEST FAILED - int output indicated as allocated but is not\n"); return -1; } haveInt = 1; }else if( bins[i].object.type == CL_BLOB ){ haveBlob = 1; if( strcmp(bins[i].object.u.blob, blobData) ){ printf(" TEST FAILED - blob output does not match input\n"); return -1; } // check - free pointer set? if( !bins[i].object.free ){ printf(" TEST FAILED - blob allocated, but free pointer not set\n"); return -1; } }else{ printf("TEST FAILED - unexpected bin type %d\n",(int) bins[i].object.type); return(-1); } } if( !(haveInt && haveStr && haveBlob ) ){ printf("TEST FAILED - not all values have correct types\n"); return -1; } // free the allocated memory for( int i=0; i<n_bins;i++) { citrusleaf_object_free(&bins[i].object); } free(bins); return 0; }
int do_example(config *c) { int rv; // Put some test values cl_object o_key; citrusleaf_object_init_str(&o_key, "example_key"); cl_bin values[2]; strcpy(values[0].bin_name, "test_bin_one"); citrusleaf_object_init_str(&values[0].object, "example_value_one"); strcpy(values[1].bin_name, "test_bin_two"); citrusleaf_object_init_int(&values[1].object, 0xDEADBEEF); // set a non-default write parameter cl_write_parameters cl_wp; cl_write_parameters_set_default(&cl_wp); cl_wp.timeout_ms = 1000; if (0 != (rv = citrusleaf_put(c->asc, c->ns, c->set, &o_key, values, 2, &cl_wp))) { fprintf(stderr, "citrusleaf put failed: error %d\n",rv); return(-1); } fprintf(stderr, "citrusleaf put succeeded\n"); // Get all the values in this key (enjoy the fine c99 standard) cl_bin *cl_v = 0; uint32_t generation; int cl_v_len; if (0 != (rv = citrusleaf_get_all(c->asc, c->ns, c->set, &o_key, &cl_v, &cl_v_len, c->timeout_ms, &generation))) { fprintf(stderr, "get after put failed, but there should be a key here - %d\n",rv); if (cl_v) free(cl_v); return(-1); } fprintf(stderr, "get all returned %d bins\n",cl_v_len); for (int i=0;i<cl_v_len;i++) { fprintf(stderr, "%d: bin %s ",i,cl_v[i].bin_name); switch (cl_v[i].object.type) { case CL_STR: fprintf(stderr, "type string: value %s\n", cl_v[i].object.u.str); break; case CL_INT: fprintf(stderr, "type int: value %"PRId64"\n",cl_v[i].object.u.i64); break; default: fprintf(stderr, "type unknown! (%d)\n",(int)cl_v[i].object.type); break; } // could have done this -- but let's free the objects in the bins later // citrusleaf_object_free(&cl_v[i].object); } if (cl_v) { citrusleaf_bins_free(cl_v, cl_v_len); free(cl_v); // only one free for all bins } fprintf(stderr,"citrusleaf getall succeeded\n"); // Delete the key you just set if (0 != (rv = citrusleaf_delete(c->asc, c->ns, c->set, &o_key, 0/*default write params*/))) { fprintf(stderr, "citrusleaf delete failed: error %d\n",rv); return(-1); } fprintf(stderr, "citrusleaf delete succeeded\n"); return(0); }
void * work_fn(void *gcc_is_ass) { // Forever, do { // Pick a key to use. Look it up to see if anyone else is using it. uint32_t key = rand_64() % g_config.n_keys; uint32_t die = rand_64() & 0x03; if (SHASH_OK == shash_put_unique(g_config.in_progress_hash, &key, 0) ) { cl_rv rv; // Make the key into a string char key_s[g_config.key_len+1]; my_itoa(key_s, key, g_config.key_len); // Make an cl_object that represents the key cl_object key_o; citrusleaf_object_init_str(&key_o, key_s); cf_digest d; citrusleaf_calculate_digest(g_config.set, &key_o, &d); if (VALUE_UNINIT == g_config.values[key]) { // simply set the value to something - can't really check anything because we don't know the state if (0 != write_new_value(key, &key_o, &d)) { if (g_config.strict) goto Fail; } atomic_int_add(g_config.key_counter, 1); } else if (VALUE_DELETED == g_config.values[key]) { // Shouldn't exist cl_bin *cl_v = 0; int cl_v_len; rv = citrusleaf_get_all(g_config.asc, g_config.ns, g_config.set, &key_o, &cl_v, &cl_v_len, g_config.timeout_ms, NULL); if (rv != CITRUSLEAF_FAIL_NOTFOUND) { fprintf(stderr, "Get after delete returned improper value when should be deleted %d key %s digest %"PRIx64"\n",rv,key_s, *(uint64_t *)&d); if (g_config.strict) goto Fail; } if (cl_v) free(cl_v); atomic_int_add(g_config.read_counter, 1); // did two ops here // write a new value if (die < 2) { if (0 != write_new_value(key, &key_o, &d)) { if (g_config.strict) goto Fail; } atomic_int_add(g_config.key_counter, 1); } } // Value is well known. Check to see that it's still right. else { cl_bin values[1]; strcpy(values[0].bin_name, g_config.bin); citrusleaf_object_init(&values[0].object); // Make string version of old value for checking char new_value_str[g_config.value_len+1]; my_itoa(new_value_str, g_config.values[key], g_config.value_len); citrusleaf_object_init_str(&values[0].object, new_value_str); rv = citrusleaf_verify(g_config.asc, g_config.ns, g_config.set, &key_o, values, 1, g_config.timeout_ms, NULL); if (rv != 0) { fprintf(stderr, "Get returned improper value %d when should be set : key %d digest %"PRIx64"\n",rv,key, *(uint64_t *)&d); if (g_config.strict) goto Fail; goto V1; } // test! if (values[0].object.type != CL_STR) { fprintf(stderr, "read value has wrong type: expect string (3) got %d\n",(int)values[0].object.type); if (g_config.strict) return((void *)-1); } else if (strcmp(values[0].object.u.str, new_value_str) != 0) { fprintf(stderr, "read value does not match set value.\n"); fprintf(stderr, " expecting: %s\n",new_value_str); fprintf(stderr, " got: %s\n",values[0].object.u.str); if (g_config.strict) goto Fail; } citrusleaf_object_free(&values[0].object); atomic_int_add(g_config.read_counter, 1); // Delete, write new value, what's your pleasure? V1: if (die < 2) { if (0 != write_new_value(key, &key_o, &d)) { if (g_config.strict) return((void *)-1); } } // Delete! else if (die == 2) { rv = citrusleaf_delete_verify(g_config.asc, g_config.ns, g_config.set, &key_o, 0); if (rv != 0) { fprintf(stderr, "Delete returned improper value %d, fail: key %d digest %"PRIx64"\n",rv, key, *(uint64_t *)&d); if (g_config.strict) goto Fail; } cl_bin values[1]; strcpy(values[0].bin_name, g_config.bin); citrusleaf_object_init(&values[0].object); rv = citrusleaf_get(g_config.asc, g_config.ns, g_config.set, &key_o, values, 1, g_config.timeout_ms, NULL); if (rv != CITRUSLEAF_FAIL_NOTFOUND) { fprintf(stderr, "Get after delete returned improper value %d digest %"PRIx64"\n",rv, *(uint64_t *)&d); if (g_config.strict) goto Fail; } citrusleaf_object_free(&values[0].object); g_config.values[key] = VALUE_DELETED; atomic_int_add(g_config.read_counter, 1); // did two ops here atomic_int_add(g_config.delete_counter, 1); atomic_int_add(g_config.key_counter, -1); } } // remove my lock on this key shash_delete(g_config.in_progress_hash, &key); } } while (1); Fail: abort(); return((void *)-1); }
/** * Look up a record by key, then return all bins. * * @param as The aerospike instance to use for this operation. * @param err The as_error to be populated if an error occurs. * @param policy The policy to use for this operation. If NULL, then the default policy will be used. * @param key The key of the record. * @param rec The record to be populated with the data from request. * * @return AEROSPIKE_OK if successful. Otherwise an error. */ as_status aerospike_key_get( aerospike * as, as_error * err, const as_policy_read * policy, const as_key * key, as_record ** rec) { // we want to reset the error so, we have a clean state as_error_reset(err); // resolve policies as_policy_read p; as_policy_read_resolve(&p, &as->config.policies, policy); uint32_t timeout = p.timeout == UINT32_MAX ? 0 : p.timeout; uint32_t gen = 0; uint32_t ttl = 0; int nvalues = 0; cl_bin * values = NULL; cl_rv rc = CITRUSLEAF_OK; switch ( p.key ) { case AS_POLICY_KEY_DIGEST: { as_digest * digest = as_key_digest((as_key *) key); rc = citrusleaf_get_all_digest_getsetname(as->cluster, key->ns, (cf_digest *) digest->value, &values, &nvalues, timeout, &gen, NULL, &ttl); break; } case AS_POLICY_KEY_SEND: { cl_object okey; asval_to_clobject((as_val *) key->valuep, &okey); as_digest * digest = as_key_digest((as_key *) key); rc = citrusleaf_get_all(as->cluster, key->ns, key->set, &okey, (cf_digest*)digest->value, &values, &nvalues, timeout, &gen, &ttl); break; } default: { // ERROR CASE break; } } if ( rc == CITRUSLEAF_OK && rec != NULL ) { as_record * r = *rec; if ( r == NULL ) { r = as_record_new(0); } if ( r->bins.entries == NULL ) { r->bins.capacity = nvalues; r->bins.size = 0; r->bins.entries = malloc(sizeof(as_bin) * nvalues); r->bins._free = true; } clbins_to_asrecord(values, nvalues, r); r->gen = (uint16_t) gen; r->ttl = ttl; *rec = r; } if ( values != NULL ) { // We are freeing the bins' objects, as opposed to bins themselves. citrusleaf_bins_free(values, nvalues); free(values); } return as_error_fromrc(err,rc); }