/** * Set the Record Type bits for a record. Typically, this is how we show that * a record is of type LDT (which requires special handling). This function * allows us to either SET the record type (the "bits" parm is positive), or * UNSET the record type (the "bits" parm is negative). When we want to * turn an "LDT Record" back into a "Normal Record", then we UNSET the LDT * flag (with a negative bits value). */ static int udf_record_set_type(const as_rec * rec, int8_t ldt_rectype_bit_update) { if (!rec || !ldt_rectype_bit_update) { cf_warning(AS_UDF, "Invalid Paramters: record=%p rec_type_bits=%d", rec, ldt_rectype_bit_update); return 2; } int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return ret; } if (!udf_record_ldt_enabled(rec) && (as_ldt_flag_has_parent(ldt_rectype_bit_update) || as_ldt_flag_has_sub(ldt_rectype_bit_update))) { cf_warning(AS_LDT, "Cannot Set Large Object Bits .. Not Enabled !!"); return -2; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (!(urecord->flag & UDF_RECORD_FLAG_ALLOW_UPDATES)) { return -1; } urecord->ldt_rectype_bit_update = ldt_rectype_bit_update; cf_detail(AS_RW, "TO URECORD FROM LUA Digest=%"PRIx64" bits %d", *(uint64_t *)&urecord->rd->keyd.digest[8], urecord->ldt_rectype_bit_update); urecord->flag |= UDF_RECORD_FLAG_METADATA_UPDATED; return 0; }
static uint32_t udf_record_ttl(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return 0; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (urecord->flag & UDF_RECORD_FLAG_IS_SUBRECORD) { cf_debug(AS_UDF, "Return 0 TTL for subrecord "); return 0; } if ((urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) { uint32_t now = as_record_void_time_get(); return urecord->r_ref->r->void_time > now ? urecord->r_ref->r->void_time - now : 0; } else { cf_info(AS_UDF, "Error in getting ttl: no record found"); return 0; // since we can't indicate the record doesn't exist } return 0; }
static uint16_t udf_record_numbins(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return 0; } udf_record *urecord = (udf_record *) as_rec_source(rec); if (urecord && (urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) { if (urecord->rd->ns->single_bin) { return 1; } uint16_t i; as_storage_rd *rd = urecord->rd; for (i = 0; i < rd->n_bins; i++) { as_bin *b = &rd->bins[i]; if (! as_bin_inuse(b)) { break; } } return i; } else { cf_warning(AS_UDF, "Error in getting numbins: no record found"); return 0; } }
/** * Set the flags for a specific bin. This is how LDTs mark Hidden Bins. Other * uses may also apply. */ static int udf_record_set_flags(const as_rec * rec, const char * name, uint8_t flags) { int ret = udf_record_param_check(rec, name, __FILE__, __LINE__); if (ret) { return ret; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (!(urecord->flag & UDF_RECORD_FLAG_ALLOW_UPDATES)) { return -1; } if ( urecord && name ) { if (flags & LDT_FLAG_HIDDEN_BIN || flags & LDT_FLAG_LDT_BIN || flags & LDT_FLAG_CONTROL_BIN ) { cf_debug(AS_UDF, "LDT flag(%d) Designates Hidden Bin", flags); udf_record_cache_sethidden(urecord, name); } else { cf_warning(AS_UDF, "Unidentified flag setting up %d", flags); return -2; } } urecord->flag |= UDF_RECORD_FLAG_METADATA_UPDATED; return 0; }
/* * Check and validate parameter before performing operation * * return: * UDF_ERR * in case of failure * 0 in case of success */ static int udf_aerospike_param_check(const as_aerospike *as, const as_rec *rec, char *fname, int lineno) { if (!as) { cf_debug(AS_UDF, "Invalid Paramters: aerospike=%p", as); return UDF_ERR_INTERNAL_PARAMETER; } int ret = udf_record_param_check(rec, UDF_BIN_NONAME, fname, lineno); if (ret) { return ret; } return 0; }
/********************************************************************* * INTERFACE FUNCTIONS * * * * See the as_aerospike for the API definition * ********************************************************************/ static as_val * udf_record_get(const as_rec * rec, const char * name) { if (udf_record_param_check(rec, name, __FILE__, __LINE__)) { return NULL; } udf_record * urecord = (udf_record *) as_rec_source(rec); as_val * value = NULL; cf_debug(AS_UDF, "[ENTER] rec(%p) name(%s)", rec, name ); // Get from cache value = udf_record_cache_get(urecord, name); // If value not NULL, then return it. if ( value != NULL ) { return value; } // Check in the cache before trying to look up in record // Note: Record may not have been created yet ... Do not // change the order unless you fully understand what you // are doing if ( !(urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN) ) { if (udf_record_open(urecord)) { // lazy read the record from storage return NULL; } } // Check if storage is available if ( !urecord->rd->ns ) { cf_detail(AS_UDF, "udf_record_get: storage unavailable"); return NULL; } value = udf_record_storage_get(urecord, name); // We have a value, so we will cache it. // DO NOT remove this. We need to cache copy to makes sure ref count // gets decremented post handing this as_val over to the lua world if ( urecord && value ) { udf_record_cache_set(urecord, name, value, false); } cf_detail(AS_UDF, "udf_record_get: end (%s) [%p,%p]", name, urecord, value); return value; }
static uint16_t udf_record_gen(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return 0; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (urecord && urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN) { return urecord->r_ref->r->generation; } else { cf_warning(AS_UDF, "Error in getting generation: no record found"); return 0; } }
static int udf_record_set(const as_rec * rec, const char * name, const as_val * value) { int ret = udf_record_param_check(rec, name, __FILE__, __LINE__); if (ret) { return ret; } udf_record * urecord = (udf_record *) as_rec_source(rec); cf_detail(AS_UDF, "udf_record_set: begin (%s)", name); if ( urecord && name ) { udf_record_cache_set(urecord, name, (as_val *) value, true); } cf_detail(AS_UDF, "udf_record_set: end (%s)", name); return 0; }
static const char * udf_record_setname(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return NULL; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (urecord && (urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) { return as_index_get_set_name(urecord->r_ref->r, urecord->rd->ns); } else { cf_warning(AS_UDF, "Error in getting set name: no record found"); return NULL; } }
static int udf_record_set_ttl(const as_rec * rec, uint32_t ttl) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return ret; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (!(urecord->flag & UDF_RECORD_FLAG_ALLOW_UPDATES)) { return -1; } urecord->tr->msgp->msg.record_ttl = ttl; urecord->flag |= UDF_RECORD_FLAG_METADATA_UPDATED; return 0; }
static int udf_record_bin_names(const as_rec *rec, as_rec_bin_names_callback callback, void * udata) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return 1; } udf_record *urecord = (udf_record *)as_rec_source(rec); char * bin_names = NULL; if (urecord && (urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) { uint16_t nbins; if (urecord->rd->ns->single_bin) { nbins = 1; bin_names = alloca(1); *bin_names = 0; } else { nbins = urecord->rd->n_bins; bin_names = alloca(nbins * AS_ID_BIN_SZ); for (uint16_t i = 0; i < nbins; i++) { as_bin *b = &urecord->rd->bins[i]; if (! as_bin_inuse(b)) { nbins = i; break; } const char * name = as_bin_get_name_from_id(urecord->rd->ns, b->id); strcpy(bin_names + (i * AS_ID_BIN_SZ), name); } } callback(bin_names, nbins, AS_ID_BIN_SZ, udata); return 0; } else { cf_warning(AS_UDF, "Error in getting bin names: no record found"); bin_names = alloca(1); *bin_names = 0; callback(bin_names, 1, AS_ID_BIN_SZ, udata); return -1; } }
static as_bytes * udf_record_digest(const as_rec *rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return NULL; } udf_record *urecord = (udf_record *)as_rec_source(rec); if (urecord && urecord->flag & UDF_RECORD_FLAG_OPEN) { cf_digest *keyd = cf_malloc(sizeof(cf_digest)); if (!keyd) { return NULL; } memcpy(keyd, &urecord->keyd, CF_DIGEST_KEY_SZ); as_bytes *b = as_bytes_new_wrap(keyd->digest, CF_DIGEST_KEY_SZ, true); return b; } return NULL; }
static as_val * udf_record_key(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return NULL; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (urecord && (urecord->flag & UDF_RECORD_FLAG_STORAGE_OPEN)) { if (urecord->rd->key) { return as_val_from_flat_key(urecord->rd->key, urecord->rd->key_size); } // TODO - perhaps look for the key in the message. return NULL; } else { cf_warning(AS_UDF, "Error in getting key: no record found"); return NULL; } }
static int udf_record_drop_key(const as_rec * rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return ret; } udf_record * urecord = (udf_record *) as_rec_source(rec); if (!(urecord->flag & UDF_RECORD_FLAG_ALLOW_UPDATES)) { return -1; } // Flag the key to be dropped. if (urecord->rd->key) { urecord->rd->key = NULL; urecord->rd->key_size = 0; } urecord->flag |= UDF_RECORD_FLAG_METADATA_UPDATED; return 0; }