void as_bin_allocate_bin_space(as_record *r, as_storage_rd *rd, int32_t delta) { if (rd->n_bins == 0) { rd->n_bins = (uint16_t)delta; as_bin_space* bin_space = (as_bin_space*) cf_malloc(sizeof(as_bin_space) + (rd->n_bins * sizeof(as_bin))); rd->bins = bin_space->bins; as_bin_set_all_empty(rd); bin_space->n_bins = rd->n_bins; as_index_set_bin_space(r, bin_space); } else { uint16_t new_n_bins = (uint16_t)((int32_t)rd->n_bins + delta); if (delta < 0) { as_record_clean_bins_from(rd, new_n_bins); } uint16_t old_n_bins = rd->n_bins; rd->n_bins = new_n_bins; if (new_n_bins != 0) { as_bin_space* bin_space = (as_bin_space*) cf_realloc((void*)as_index_get_bin_space(r), sizeof(as_bin_space) + (rd->n_bins * sizeof(as_bin))); rd->bins = bin_space->bins; if (delta > 0) { as_bin_set_empty_from(rd, old_n_bins); } bin_space->n_bins = rd->n_bins; as_index_set_bin_space(r, bin_space); } else { cf_free((void*)as_index_get_bin_space(r)); as_index_set_bin_space(r, NULL); rd->bins = NULL; } } }
// Called only if data-in-memory, and not single-bin. void as_record_free_bin_space(as_record *r) { as_bin_space *bin_space = as_index_get_bin_space(r); if (bin_space) { cf_free((void*)bin_space); as_index_set_bin_space(r, NULL); } }
static inline as_bin_space* safe_bin_space(const as_record *r) { return r->dim ? as_index_get_bin_space(r) : NULL; }
// TODO - old pickle - remove in "six months". int old_record_apply_dim(as_remote_record *rr, as_storage_rd *rd, bool skip_sindex, bool *is_delete) { as_namespace* ns = rr->rsv->ns; as_record* r = rd->r; // Set rd->n_bins! as_storage_rd_load_n_bins(rd); // Set rd->bins! as_storage_rd_load_bins(rd, NULL); // For memory accounting, note current usage. uint64_t memory_bytes = as_storage_record_get_n_bytes_memory(rd); // Keep old bins intact for sindex adjustment and unwinding. uint16_t n_old_bins = rd->n_bins; as_bin* old_bins = rd->bins; uint16_t n_new_bins = cf_swap_from_be16(*(uint16_t *)rr->pickle); as_bin new_bins[n_new_bins]; memset(new_bins, 0, sizeof(new_bins)); rd->n_bins = n_new_bins; rd->bins = new_bins; // Fill the new bins and particles. int result = unpickle_bins(rr, rd, NULL); if (result != 0) { cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed unpickle bins ", ns->name); destroy_stack_bins(new_bins, n_new_bins); return result; } // Apply changes to metadata in as_index needed for and writing. index_metadata old_metadata; update_index_metadata(rr, &old_metadata, r); // Prepare to store or drop key, as determined by message. rd->key = rr->key; rd->key_size = rr->key_size; // Write the record to storage. if ((result = as_record_write_from_pickle(rd)) < 0) { cf_warning_digest(AS_RECORD, rr->keyd, "{%s} record replace: failed write ", ns->name); unwind_index_metadata(&old_metadata, r); destroy_stack_bins(new_bins, n_new_bins); return -result; } // Success - adjust sindex, looking at old and new bins. if (! (skip_sindex && next_generation(r->generation, (uint16_t)rr->generation, ns)) && record_has_sindex(r, ns)) { write_sindex_update(ns, as_index_get_set_name(r, ns), rr->keyd, old_bins, n_old_bins, new_bins, n_new_bins); } // Cleanup - destroy relevant bins, can't unwind after. destroy_stack_bins(old_bins, n_old_bins); // Fill out new_bin_space. as_bin_space* new_bin_space = NULL; if (n_new_bins != 0) { new_bin_space = (as_bin_space*) cf_malloc_ns(sizeof(as_bin_space) + sizeof(new_bins)); new_bin_space->n_bins = rd->n_bins; memcpy((void*)new_bin_space->bins, new_bins, sizeof(new_bins)); } // Swizzle the index element's as_bin_space pointer. as_bin_space* old_bin_space = as_index_get_bin_space(r); if (old_bin_space) { cf_free(old_bin_space); } as_index_set_bin_space(r, new_bin_space); // Now ok to store or drop key, as determined by message. as_record_finalize_key(r, ns, rd->key, rd->key_size); as_storage_record_adjust_mem_stats(rd, memory_bytes); *is_delete = n_new_bins == 0; return AS_OK; }