/** * The is the proxy callback function. This will be passed to the old simple-scan * mechanism. When this gets called, it will create an as_val structure out of the * record and will call the callback that user supplied (folded into the udata structure) */ static int simplescan_cb(char *ns, cf_digest *keyd, char *set, cl_object *key, int result, uint32_t generation, uint32_t record_void_time, cl_bin *bins, uint16_t n_bins, void *udata) { scan_bridge * bridge = (scan_bridge *) udata; // Fill the bin data as_record _rec, * rec = &_rec; as_record_inita(rec, n_bins); clbins_to_asrecord(bins, (uint32_t)n_bins, rec); // Fill the metadata askey_from_clkey(&rec->key, ns, set, key); memcpy(rec->key.digest.value, keyd, sizeof(cf_digest)); rec->key.digest.init = true; rec->gen = generation; rec->ttl = record_void_time; // Call the callback that user wanted to callback bool rv = bridge->callback((as_val *) rec, bridge->udata); // The responsibility to free the bins is on the called callback function // In scan case, only LIST & MAP will have an active free citrusleaf_bins_free(bins, (int)n_bins); // release the record as_record_destroy(rec); return rv ? 0 : 1; }
static int cl_batch_cb(char *ns, cf_digest *keyd, char *set, cl_object *key, int result, uint32_t generation, uint32_t ttl, cl_bin *bins, uint16_t n_bins, void *udata) { batch_bridge * p_bridge = (batch_bridge *) udata; aerospike * as = p_bridge->as; as_batch_read * p_r = NULL; // Find the digest. for (uint32_t i = 0; i < p_bridge->n; i++) { p_r = &p_bridge->results[i]; if (memcmp(keyd, p_r->key->digest.value, AS_DIGEST_VALUE_SIZE) == 0) { // Not bothering to check set, which is not always filled. break; } p_r = NULL; } if (! p_r) { as_err(LOGGER, "couldn't find digest"); return -1; // not that this is even checked... } // Fill out this result slot. as_error err; p_r->result = as_error_fromrc(&err, result); // If the result wasn't success, we won't have any record data or metadata. if (result != 0) { return 0; } as_record_init(&p_r->record, n_bins); // works even if n_bins is 0 // There should be record metadata. p_r->record.gen = (uint16_t)generation; p_r->record.ttl = ttl; // There may be bin data. if (n_bins != 0) { clbins_to_asrecord(bins, (uint32_t)n_bins, &p_r->record); } return 0; }
/** * 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); }
/** * Lookup a record by key, then return specified 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 bins The bins to select. A NULL terminated array of NULL terminated strings. * @param rec The record to be populated with the data from request. * * @return AEROSPIKE_OK if successful. Otherwise an error. */ as_status aerospike_key_select( aerospike * as, as_error * err, const as_policy_read * policy, const as_key * key, const char * bins[], 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; for (nvalues = 0; bins[nvalues] != NULL && bins[nvalues][0] != '\0'; nvalues++) ; values = (cl_bin *) alloca(sizeof(cl_bin) * nvalues); for ( int i = 0; i < nvalues; i++ ) { if ( strlen(bins[i]) > AS_BIN_NAME_MAX_LEN ) { return as_error_update(err, AEROSPIKE_ERR_PARAM, "bin name too long: %s", bins[i]); } strcpy(values[i].bin_name, bins[i]); citrusleaf_object_init(&values[i].object); } 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_digest(as->cluster, key->ns, (cf_digest *) digest->value, values, nvalues, timeout, &gen, &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(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); } return as_error_fromrc(err,rc); }