int Dbtup::realloc_var_part(Fragrecord* fragPtr, Tablerec* tabPtr, PagePtr pagePtr, Var_part_ref* refptr, Uint32 oldsz, Uint32 newsz) { Uint32 add = newsz - oldsz; Var_page* pageP = (Var_page*)pagePtr.p; Local_key oldref; refptr->copyout(&oldref); if (pageP->free_space >= add) { jam(); if(!pageP->is_space_behind_entry(oldref.m_page_idx, add)) { if(0) printf("extra reorg"); jam(); /** * In this case we need to reorganise the page to fit. To ensure we * don't complicate matters we make a little trick here where we * fool the reorg_page to avoid copying the entry at hand and copy * that separately at the end. This means we need to copy it out of * the page before reorg_page to save the entry contents. */ Uint32* copyBuffer= cinBuffer; memcpy(copyBuffer, pageP->get_ptr(oldref.m_page_idx), 4*oldsz); pageP->set_entry_len(oldref.m_page_idx, 0); pageP->free_space += oldsz; pageP->reorg((Var_page*)ctemp_page); memcpy(pageP->get_free_space_ptr(), copyBuffer, 4*oldsz); pageP->set_entry_offset(oldref.m_page_idx, pageP->insert_pos); add += oldsz; } pageP->grow_entry(oldref.m_page_idx, add); update_free_page_list(fragPtr, pagePtr); } else { Local_key newref; Uint32 *src = pageP->get_ptr(oldref.m_page_idx); Uint32 *dst = alloc_var_part(fragPtr, tabPtr, newsz, &newref); if (unlikely(dst == 0)) return -1; ndbassert(oldref.m_page_no != newref.m_page_no); ndbassert(pageP->get_entry_len(oldref.m_page_idx) == oldsz); memcpy(dst, src, 4*oldsz); refptr->assign(&newref); pageP->free_record(oldref.m_page_idx, Var_page::CHAIN); update_free_page_list(fragPtr, pagePtr); } return 0; }
void Dbtup::commit_operation(Signal* signal, Uint32 gci_hi, Uint32 gci_lo, Tuple_header* tuple_ptr, PagePtr pagePtr, Operationrec* regOperPtr, Fragrecord* regFragPtr, Tablerec* regTabPtr) { ndbassert(regOperPtr->op_type != ZDELETE); Uint32 lcpScan_ptr_i= regFragPtr->m_lcp_scan_op; Uint32 save= tuple_ptr->m_operation_ptr_i; Uint32 bits= tuple_ptr->m_header_bits; Tuple_header *disk_ptr= 0; Tuple_header *copy= get_copy_tuple(®OperPtr->m_copy_tuple_location); Uint32 copy_bits= copy->m_header_bits; Uint32 fixsize= regTabPtr->m_offsets[MM].m_fix_header_size; Uint32 mm_vars= regTabPtr->m_attributes[MM].m_no_of_varsize; Uint32 mm_dyns= regTabPtr->m_attributes[MM].m_no_of_dynamic; bool update_gci_at_commit = ! regOperPtr->op_struct.bit_field.m_gci_written; if((mm_vars+mm_dyns) == 0) { jam(); memcpy(tuple_ptr, copy, 4*fixsize); disk_ptr= (Tuple_header*)(((Uint32*)copy)+fixsize); } else { jam(); /** * Var_part_ref is only stored in *allocated* tuple * so memcpy from copy, will over write it... * hence subtle copyout/assign... */ Local_key tmp; Var_part_ref *ref= tuple_ptr->get_var_part_ref_ptr(regTabPtr); ref->copyout(&tmp); memcpy(tuple_ptr, copy, 4*fixsize); ref->assign(&tmp); PagePtr vpagePtr; if (copy_bits & Tuple_header::VAR_PART) { jam(); ndbassert(bits & Tuple_header::VAR_PART); ndbassert(tmp.m_page_no != RNIL); ndbassert(copy_bits & Tuple_header::COPY_TUPLE); Uint32 *dst= get_ptr(&vpagePtr, *ref); Var_page* vpagePtrP = (Var_page*)vpagePtr.p; Varpart_copy*vp =(Varpart_copy*)copy->get_end_of_fix_part_ptr(regTabPtr); /* The first word of shrunken tuple holds the lenght in words. */ Uint32 len = vp->m_len; memcpy(dst, vp->m_data, 4*len); if(copy_bits & Tuple_header::MM_SHRINK) { jam(); ndbassert(vpagePtrP->get_entry_len(tmp.m_page_idx) >= len); if (len) { jam(); ndbassert(regFragPtr->m_varWordsFree >= vpagePtrP->free_space); regFragPtr->m_varWordsFree -= vpagePtrP->free_space; vpagePtrP->shrink_entry(tmp.m_page_idx, len); // Adds the new free space value for the page to the fragment total. update_free_page_list(regFragPtr, vpagePtr); } else { jam(); free_var_part(regFragPtr, vpagePtr, tmp.m_page_idx); tmp.m_page_no = RNIL; ref->assign(&tmp); copy_bits &= ~(Uint32)Tuple_header::VAR_PART; } } else { jam(); ndbassert(vpagePtrP->get_entry_len(tmp.m_page_idx) == len); } /** * Find disk part after * header + fixed MM part + length word + varsize part. */ disk_ptr = (Tuple_header*)(vp->m_data + len); } else { jam(); ndbassert(tmp.m_page_no == RNIL); disk_ptr = (Tuple_header*)copy->get_end_of_fix_part_ptr(regTabPtr); } } if (regTabPtr->m_no_of_disk_attributes && (copy_bits & Tuple_header::DISK_INLINE)) { jam(); Local_key key; memcpy(&key, copy->get_disk_ref_ptr(regTabPtr), sizeof(Local_key)); Uint32 logfile_group_id= regFragPtr->m_logfile_group_id; PagePtr diskPagePtr((Tup_page*)m_pgman_ptr.p, m_pgman_ptr.i); ndbassert(diskPagePtr.p->m_page_no == key.m_page_no); ndbassert(diskPagePtr.p->m_file_no == key.m_file_no); Uint32 sz, *dst; if(copy_bits & Tuple_header::DISK_ALLOC) { jam(); disk_page_alloc(signal, regTabPtr, regFragPtr, &key, diskPagePtr, gci_hi); } if(regTabPtr->m_attributes[DD].m_no_of_varsize == 0) { jam(); sz= regTabPtr->m_offsets[DD].m_fix_header_size; dst= ((Fix_page*)diskPagePtr.p)->get_ptr(key.m_page_idx, sz); } else { jam(); dst= ((Var_page*)diskPagePtr.p)->get_ptr(key.m_page_idx); sz= ((Var_page*)diskPagePtr.p)->get_entry_len(key.m_page_idx); } if(! (copy_bits & Tuple_header::DISK_ALLOC)) { jam(); disk_page_undo_update(diskPagePtr.p, &key, dst, sz, gci_hi, logfile_group_id); } memcpy(dst, disk_ptr, 4*sz); memcpy(tuple_ptr->get_disk_ref_ptr(regTabPtr), &key, sizeof(Local_key)); ndbassert(! (disk_ptr->m_header_bits & Tuple_header::FREE)); copy_bits |= Tuple_header::DISK_PART; } if(lcpScan_ptr_i != RNIL && (bits & Tuple_header::ALLOC)) { jam(); ScanOpPtr scanOp; c_scanOpPool.getPtr(scanOp, lcpScan_ptr_i); Local_key rowid = regOperPtr->m_tuple_location; rowid.m_page_no = pagePtr.p->frag_page_id; if (!is_rowid_lcp_scanned(rowid, *scanOp.p)) { jam(); copy_bits |= Tuple_header::LCP_SKIP; } } Uint32 clear= Tuple_header::ALLOC | Tuple_header::FREE | Tuple_header::COPY_TUPLE | Tuple_header::DISK_ALLOC | Tuple_header::DISK_INLINE | Tuple_header::MM_SHRINK | Tuple_header::MM_GROWN; copy_bits &= ~(Uint32)clear; tuple_ptr->m_header_bits= copy_bits; tuple_ptr->m_operation_ptr_i= save; if (regTabPtr->m_bits & Tablerec::TR_RowGCI && update_gci_at_commit) { jam(); * tuple_ptr->get_mm_gci(regTabPtr) = gci_hi; if (regTabPtr->m_bits & Tablerec::TR_ExtraRowGCIBits) { Uint32 attrId = regTabPtr->getExtraAttrId<Tablerec::TR_ExtraRowGCIBits>(); store_extra_row_bits(attrId, regTabPtr, tuple_ptr, gci_lo, /* truncate */true); } } if (regTabPtr->m_bits & Tablerec::TR_Checksum) { jam(); setChecksum(tuple_ptr, regTabPtr); } }