/**************************************************************//** Copies the stored position of a pcur to another pcur. */ UNIV_INTERN void btr_pcur_copy_stored_position( /*==========================*/ btr_pcur_t* pcur_receive, /*!< in: pcur which will receive the position info */ btr_pcur_t* pcur_donate) /*!< in: pcur from which the info is copied */ { if (pcur_receive->old_rec_buf) { mem_free(pcur_receive->old_rec_buf); } ut_memcpy(pcur_receive, pcur_donate, sizeof(btr_pcur_t)); if (pcur_donate->old_rec_buf) { pcur_receive->old_rec_buf = mem_alloc(pcur_donate->buf_size); ut_memcpy(pcur_receive->old_rec_buf, pcur_donate->old_rec_buf, pcur_donate->buf_size); pcur_receive->old_rec = pcur_receive->old_rec_buf + (pcur_donate->old_rec - pcur_donate->old_rec_buf); } pcur_receive->old_n_fields = pcur_donate->old_n_fields; }
void rec_copy_prefix_to_dtuple( /*======================*/ dtuple_t* tuple, /* in: data tuple */ rec_t* rec, /* in: physical record */ ulint n_fields, /* in: number of fields to copy */ mem_heap_t* heap) /* in: memory heap */ { dfield_t* field; byte* data; ulint len; byte* buf = NULL; ulint i; ut_ad(rec_validate(rec)); ut_ad(dtuple_check_typed(tuple)); dtuple_set_info_bits(tuple, rec_get_info_bits(rec)); for (i = 0; i < n_fields; i++) { field = dtuple_get_nth_field(tuple, i); data = rec_get_nth_field(rec, i, &len); if (len != UNIV_SQL_NULL) { buf = mem_heap_alloc(heap, len); ut_memcpy(buf, data, len); } dfield_set_data(field, buf, len); } }
int lwip_sock_read(void *conn, unsigned char *buff, unsigned long len) { struct netbuf *new_buf=0; unsigned char *data; int data_len=0; int ret,newret; SYSCALL_DEBUG(" SOCK read :%x len:%d \n",buff,len); mutexLock(g_netBH_lock); ret=netconn_recv(conn, &new_buf); mutexUnLock(g_netBH_lock); if (ret!=ERR_OK){ SYSCALL_DEBUG(" Fail to recv data: %x newret:%x(%d) \n",ret,-ret,-ret); return 0; } netbuf_data(new_buf,&data,&data_len); SYSCALL_DEBUG(" SUCESS to recv data:%d ret:%d\n",data_len,ret); if (data_len > 0){ ut_memcpy(buff,data,ut_min(data_len,len)); ret = ut_min(data_len,len); }else{ ret = 0; } mutexLock(g_netBH_lock); netbuf_delete(new_buf); mutexUnLock(g_netBH_lock); return ret; }
/**********************************************************************//** Implements realloc. This is needed by /pars/lexyy.c. Otherwise, you should not use this function because the allocation functions in mem0mem.h are the recommended ones in InnoDB. man realloc in Linux, 2004: realloc() changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged to the minimum of the old and new sizes; newly allocated mem- ory will be uninitialized. If ptr is NULL, the call is equivalent to malloc(size); if size is equal to zero, the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an earlier call to malloc(), calloc() or realloc(). RETURN VALUE realloc() returns a pointer to the newly allocated memory, which is suitably aligned for any kind of variable and may be different from ptr, or NULL if the request fails. If size was equal to 0, either NULL or a pointer suitable to be passed to free() is returned. If realloc() fails the original block is left untouched - it is not freed or moved. @return own: pointer to new mem block or NULL */ UNIV_INTERN void* ut_realloc( /*=======*/ void* ptr, /*!< in: pointer to old block or NULL */ ulint size) /*!< in: desired size */ { ut_mem_block_t* block; ulint old_size; ulint min_size; void* new_ptr; if (UNIV_LIKELY(srv_use_sys_malloc)) { return(realloc(ptr, size)); } if (ptr == NULL) { return(ut_malloc(size)); } if (size == 0) { ut_free(ptr); return(NULL); } block = (ut_mem_block_t*)((byte*)ptr - sizeof(ut_mem_block_t)); ut_a(block->magic_n == UT_MEM_MAGIC_N); old_size = block->size - sizeof(ut_mem_block_t); if (size < old_size) { min_size = size; } else { min_size = old_size; } new_ptr = ut_malloc(size); if (new_ptr == NULL) { return(NULL); } /* Copy the old data from ptr */ ut_memcpy(new_ptr, ptr, min_size); ut_free(ptr); return(new_ptr); }
static void netfront_input(struct netif *netif, unsigned char* data, int len) { struct eth_hdr *ethhdr; struct pbuf *p, *q; int ret; #if ETH_PAD_SIZE len += ETH_PAD_SIZE; /* allow room for Ethernet padding */ #endif /* move received packet into a new pbuf */ mutexLock(g_netBH_lock); p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL); mutexUnLock(g_netBH_lock); if (p == NULL) { LINK_STATS_INC(link.memerr); LINK_STATS_INC(link.drop); error_mem++; return; } #if ETH_PAD_SIZE pbuf_header(p, -ETH_PAD_SIZE); /* drop the padding word */ #endif /* We iterate over the pbuf chain until we have read the entire * packet into the pbuf. */ for (q = p; q != NULL && len > 0; q = q->next) { /* Read enough bytes to fill this pbuf in the chain. The * available data in the pbuf is given by the q->len * variable. */ ut_memcpy(q->payload, data, len < q->len ? len : q->len); data += q->len; len -= q->len; } #if ETH_PAD_SIZE pbuf_header(p, ETH_PAD_SIZE); /* reclaim the padding word */ #endif LINK_STATS_INC(link.recv); /* points to packet payload, which starts with an Ethernet header */ ethhdr = p->payload; mutexLock(g_netBH_lock); if (ethernet_input(p, netif) != ERR_OK){ BUG(); pbuf_free(p); } mutexUnLock(g_netBH_lock); }
int elf_initialize_userspace_stack(struct elfhdr elf_ex,unsigned long aux_addr,unsigned long tmp_stack, unsigned long stack_len,unsigned long load_addr) { unsigned long *aux_vec, aux_index; Elf64_Addr p_entry; p_entry = elf_ex.e_entry; vm_mmap(0, USERSTACK_ADDR, USERSTACK_LEN, PROT_READ | PROT_WRITE, MAP_ANONYMOUS, 0, "userstack"); if (stack_len > 0) { aux_vec = (unsigned long *) aux_addr; if (aux_vec != 0) { int aux_last; aux_index = 0; aux_last = (MAX_AUX_VEC_ENTRIES - 2) * 2; AUX_ENT(AT_HWCAP, 0xbfebfbff); /* TODO: need to modify*/ AUX_ENT(AT_PAGESZ, PAGE_SIZE); AUX_ENT(AT_CLKTCK, 100); AUX_ENT(AT_PHDR, load_addr + elf_ex.e_phoff); AUX_ENT(AT_PHENT, sizeof(struct elf_phdr)); AUX_ENT(AT_PHNUM, elf_ex.e_phnum); AUX_ENT(AT_BASE, 0); AUX_ENT(AT_FLAGS, 0); AUX_ENT(AT_ENTRY, p_entry); AUX_ENT(AT_UID, 0x1f4); /* TODO : remove UID hard coded to 0x1f4 for the next four entries */ AUX_ENT(AT_EUID, 0x1f4); AUX_ENT(AT_GID, 0x1f4); AUX_ENT(AT_EGID, 0x1f4); AUX_ENT(AT_SECURE, 0x0); aux_vec[aux_last] = 0x1234567887654321; aux_vec[aux_last + 1] = 0x1122334455667788; AUX_ENT(AT_RANDOM, userstack_addr((unsigned long)&aux_vec[aux_last])); aux_vec[aux_last + 2] = 0x34365f363878; /* This is string "x86_64" */ AUX_ENT(AT_PLATFORM, userstack_addr((unsigned long)&aux_vec[aux_last+2])); } if (stack_len > 0){ ut_memcpy((unsigned char *) USERSTACK_ADDR + USERSTACK_LEN - stack_len, (unsigned char *) tmp_stack, stack_len); } return JSUCCESS; } return JFAIL; }
rec_t* rec_copy_prefix_to_buf( /*===================*/ /* out, own: copied record */ rec_t* rec, /* in: physical record */ ulint n_fields, /* in: number of fields to copy */ byte** buf, /* in/out: memory buffer for the copied prefix, or NULL */ ulint* buf_size) /* in/out: buffer size */ { rec_t* copy_rec; ulint area_start; ulint area_end; ulint prefix_len; ut_ad(rec_validate(rec)); area_end = rec_get_field_start_offs(rec, n_fields); if (rec_get_1byte_offs_flag(rec)) { area_start = REC_N_EXTRA_BYTES + n_fields; } else { area_start = REC_N_EXTRA_BYTES + 2 * n_fields; } prefix_len = area_start + area_end; if ((*buf == NULL) || (*buf_size < prefix_len)) { if (*buf != NULL) { mem_free(*buf); } *buf = mem_alloc(prefix_len); *buf_size = prefix_len; } ut_memcpy(*buf, rec - area_start, prefix_len); copy_rec = *buf + area_start; rec_set_n_fields(copy_rec, n_fields); return(copy_rec); }
/******************************************************************//** Adds a string literal to a symbol table. @return symbol table node */ UNIV_INTERN sym_node_t* sym_tab_add_str_lit( /*================*/ sym_tab_t* sym_tab, /*!< in: symbol table */ byte* str, /*!< in: string with no quotes around it */ ulint len) /*!< in: string length */ { sym_node_t* node; byte* data; node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); node->common.type = QUE_NODE_SYMBOL; node->resolved = TRUE; node->token_type = SYM_LIT; node->indirection = NULL; dtype_set(dfield_get_type(&node->common.val), DATA_VARCHAR, DATA_ENGLISH, 0); if (len) { data = mem_heap_alloc(sym_tab->heap, len); ut_memcpy(data, str, len); } else { data = NULL; } dfield_set_data(&(node->common.val), data, len); node->common.val_buf_size = 0; node->prefetch_buf = NULL; node->cursor_def = NULL; UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); node->sym_table = sym_tab; return(node); }
/***********************************************************//** Parses a redo log record of adding an undo log record. @return end of log record or NULL */ UNIV_INTERN byte* trx_undo_parse_add_undo_rec( /*========================*/ byte* ptr, /*!< in: buffer */ byte* end_ptr,/*!< in: buffer end */ page_t* page) /*!< in: page or NULL */ { ulint len; byte* rec; ulint first_free; if (end_ptr < ptr + 2) { return(NULL); } len = mach_read_from_2(ptr); ptr += 2; if (end_ptr < ptr + len) { return(NULL); } if (page == NULL) { return(ptr + len); } first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); rec = page + first_free; mach_write_to_2(rec, first_free + 4 + len); mach_write_to_2(rec + 2 + len, first_free); mach_write_to_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, first_free + 4 + len); ut_memcpy(rec + 2, ptr, len); return(ptr + len); }
void mlog_write_string( /*==============*/ byte* ptr, /* in: pointer where to write */ const byte* str, /* in: string to write */ ulint len, /* in: string length */ mtr_t* mtr) /* in: mini-transaction handle */ { byte* log_ptr; if (UNIV_UNLIKELY(ptr < buf_pool->frame_zero) || UNIV_UNLIKELY(ptr >= buf_pool->high_end)) { fprintf(stderr, "InnoDB: Error: trying to write to" " a stray memory location %p\n", (void*) ptr); ut_error; } ut_ad(ptr && mtr); ut_a(len < UNIV_PAGE_SIZE); ut_memcpy(ptr, str, len); log_ptr = mlog_open(mtr, 30); /* If no logging is requested, we may return now */ if (log_ptr == NULL) { return; } log_ptr = mlog_write_initial_log_record_fast(ptr, MLOG_WRITE_STRING, log_ptr, mtr); mach_write_to_2(log_ptr, ptr - buf_frame_align(ptr)); log_ptr += 2; mach_write_to_2(log_ptr, len); log_ptr += 2; mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, str, len); }
ib_err_t ib_cfg_init(void) /*=============*/ { /* Initialize the mutex that protects cfg_vars[]. */ os_fast_mutex_init(&cfg_vars_mutex); ut_memcpy(cfg_vars, cfg_vars_defaults, sizeof(cfg_vars)); /* Set the default options. */ srv_file_flush_method_str = NULL; srv_unix_file_flush_method = SRV_UNIX_FSYNC; srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED; os_aio_print_debug = FALSE; os_aio_use_native_aio = FALSE; #define IB_CFG_SET(name, var) \ if (ib_cfg_set(name, var) != DB_SUCCESS) ut_error IB_CFG_SET("additional_mem_pool_size", 4 * 1024 * 1024); IB_CFG_SET("buffer_pool_size", 8 * 1024 * 1024); IB_CFG_SET("data_file_path", "ibdata1:32M:autoextend"); IB_CFG_SET("data_home_dir", "./"); IB_CFG_SET("file_per_table", IB_TRUE); #ifndef __WIN__ IB_CFG_SET("flush_method", "fsync"); #endif IB_CFG_SET("lock_wait_timeout", 60); IB_CFG_SET("log_buffer_size", 384 * 1024); IB_CFG_SET("log_file_size", 16 * 1024 * 1024); IB_CFG_SET("log_files_in_group", 2); IB_CFG_SET("log_group_home_dir", "."); IB_CFG_SET("lru_old_blocks_pct", 3 * 100 / 8); IB_CFG_SET("lru_block_access_recency", 0); IB_CFG_SET("rollback_on_timeout", IB_TRUE); IB_CFG_SET("read_io_threads", 4); IB_CFG_SET("write_io_threads", 4); #undef IB_CFG_SET return(DB_SUCCESS); }
byte* mlog_parse_string( /*==============*/ /* out: parsed record end, NULL if not a complete record */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ byte* page) /* in: page where to apply the log record, or NULL */ { ulint offset; ulint len; if (end_ptr < ptr + 4) { return(NULL); } offset = mach_read_from_2(ptr); ptr += 2; if (offset >= UNIV_PAGE_SIZE) { recv_sys->found_corrupt_log = TRUE; return(NULL); } len = mach_read_from_2(ptr); ptr += 2; ut_a(len + offset < UNIV_PAGE_SIZE); if (end_ptr < ptr + len) { return(NULL); } if (page) { ut_memcpy(page + offset, ptr, len); } return(ptr + len); }
int lwip_sock_read_from(void *conn, unsigned char *buff, unsigned long len,struct sockaddr *sockaddr, int addr_len) { struct netbuf *new_buf=0; unsigned char *data; int data_len=0; int ret=0; SYSCALL_DEBUG(" SOCK recvfrom :%x len:%d \n",buff,len); mutexLock(g_netBH_lock); ret=netconn_recv(conn, &new_buf); mutexUnLock(g_netBH_lock); if (ret == ERR_TIMEOUT){ if (g_current_task->killed == 1){ return 0; } } if (ret!=ERR_OK){ SYSCALL_DEBUG(" Fail to recvfrom data: %x newret:%x(%d) \n",ret,-ret,-ret); return 0; } SYSCALL_DEBUG(" SUCESS to recv data:%d \n",ret); netbuf_data(new_buf,&data,&data_len); if (data_len > 0){ if (sockaddr != 0){ sockaddr->addr = new_buf->addr.addr; sockaddr->sin_port = new_buf->port; } ut_memcpy(buff,data,ut_min(data_len,len)); ret = ut_min(data_len,len); }else{ ret =0; } mutexLock(g_netBH_lock); netbuf_delete(new_buf); mutexUnLock(g_netBH_lock); return ret; }
/************************************************************************ Posts a buffer page for writing. If the doublewrite memory buffer is full, calls buf_flush_buffered_writes and waits for for free space to appear. */ static void buf_flush_post_to_doublewrite_buf( /*==============================*/ buf_block_t* block) /* in: buffer block to write */ { try_again: mutex_enter(&(trx_doublewrite->mutex)); ut_a(block->state == BUF_BLOCK_FILE_PAGE); if (trx_doublewrite->first_free >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { mutex_exit(&(trx_doublewrite->mutex)); buf_flush_buffered_writes(); goto try_again; } ut_memcpy(trx_doublewrite->write_buf + UNIV_PAGE_SIZE * trx_doublewrite->first_free, block->frame, UNIV_PAGE_SIZE); trx_doublewrite->buf_block_arr[trx_doublewrite->first_free] = block; trx_doublewrite->first_free++; if (trx_doublewrite->first_free >= 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) { mutex_exit(&(trx_doublewrite->mutex)); buf_flush_buffered_writes(); return; } mutex_exit(&(trx_doublewrite->mutex)); }
void row_upd_index_write_log( /*====================*/ upd_t* update, /* in: update vector */ byte* log_ptr,/* in: pointer to mlog buffer: must contain at least MLOG_BUF_MARGIN bytes of free space; the buffer is closed within this function */ mtr_t* mtr) /* in: mtr into whose log to write */ { upd_field_t* upd_field; dfield_t* new_val; ulint len; ulint n_fields; byte* buf_end; ulint i; n_fields = upd_get_n_fields(update); buf_end = log_ptr + MLOG_BUF_MARGIN; mach_write_to_1(log_ptr, update->info_bits); log_ptr++; log_ptr += mach_write_compressed(log_ptr, n_fields); for (i = 0; i < n_fields; i++) { ut_ad(MLOG_BUF_MARGIN > 30); if (log_ptr + 30 > buf_end) { mlog_close(mtr, log_ptr); log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); buf_end = log_ptr + MLOG_BUF_MARGIN; } upd_field = upd_get_nth_field(update, i); new_val = &(upd_field->new_val); len = new_val->len; log_ptr += mach_write_compressed(log_ptr, upd_field->field_no); log_ptr += mach_write_compressed(log_ptr, len); if (len != UNIV_SQL_NULL) { if (log_ptr + len < buf_end) { ut_memcpy(log_ptr, new_val->data, len); log_ptr += len; } else { mlog_close(mtr, log_ptr); mlog_catenate_string(mtr, new_val->data, len); log_ptr = mlog_open(mtr, MLOG_BUF_MARGIN); buf_end = log_ptr + MLOG_BUF_MARGIN; } } } mlog_close(mtr, log_ptr); }
/************************************************************************ Loads definitions for index fields. */ static void dict_load_fields( /*=============*/ dict_table_t* table, /* in: table */ dict_index_t* index, /* in: index whose fields to load */ mem_heap_t* heap) /* in: memory heap for temporary storage */ { dict_table_t* sys_fields; dict_index_t* sys_index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; char* col_name; rec_t* rec; byte* field; ulint len; byte* buf; ulint i; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); UT_NOT_USED(table); mtr_start(&mtr); sys_fields = dict_table_get_low("SYS_FIELDS"); sys_index = UT_LIST_GET_FIRST(sys_fields->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); buf = mem_heap_alloc(heap, 8); mach_write_to_8(buf, index->id); dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (i = 0; i < index->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); ut_a(ut_memcmp(buf, field, len) == 0); field = rec_get_nth_field(rec, 1, &len); ut_ad(len == 4); ut_a(i == mach_read_from_4(field)); ut_a(0 == ut_strcmp("COL_NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_fields), 4))->name)); field = rec_get_nth_field(rec, 4, &len); col_name = mem_heap_alloc(heap, len + 1); ut_memcpy(col_name, field, len); col_name[len] = '\0'; dict_mem_index_add_field(index, col_name, 0); btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
/**********************************************************************//** Reports in the undo log of an update or delete marking of a clustered index record. @return byte offset of the inserted undo log entry on the page if succeed, 0 if fail */ static ulint trx_undo_page_report_modify( /*========================*/ page_t* undo_page, /*!< in: undo log page */ trx_t* trx, /*!< in: transaction */ dict_index_t* index, /*!< in: clustered index where update or delete marking is done */ const rec_t* rec, /*!< in: clustered index record which has NOT yet been modified */ const ulint* offsets, /*!< in: rec_get_offsets(rec, index) */ const upd_t* update, /*!< in: update vector which tells the columns to be updated; in the case of a delete, this should be set to NULL */ ulint cmpl_info, /*!< in: compiler info on secondary index updates */ mtr_t* mtr) /*!< in: mtr */ { dict_table_t* table; ulint first_free; byte* ptr; const byte* field; ulint flen; ulint col_no; ulint type_cmpl; byte* type_cmpl_ptr; ulint i; trx_id_t trx_id; ibool ignore_prefix = FALSE; byte ext_buf[REC_MAX_INDEX_COL_LEN + BTR_EXTERN_FIELD_REF_SIZE]; ut_a(dict_index_is_clust(index)); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); table = index->table; first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 50) { /* NOTE: the value 50 must be big enough so that the general fields written below fit on the undo log page */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ if (!update) { type_cmpl = TRX_UNDO_DEL_MARK_REC; } else if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { type_cmpl = TRX_UNDO_UPD_DEL_REC; /* We are about to update a delete marked record. We don't typically need the prefix in this case unless the delete marking is done by the same transaction (which we check below). */ ignore_prefix = TRUE; } else { type_cmpl = TRX_UNDO_UPD_EXIST_REC; } type_cmpl |= cmpl_info * TRX_UNDO_CMPL_INFO_MULT; type_cmpl_ptr = ptr; *ptr++ = (byte) type_cmpl; ptr += mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += mach_dulint_write_much_compressed(ptr, table->id); /*----------------------------------------*/ /* Store the state of the info bits */ *ptr++ = (byte) rec_get_info_bits(rec, dict_table_is_comp(table)); /* Store the values of the system columns */ field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos( index, DATA_TRX_ID), &flen); ut_ad(flen == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); /* If it is an update of a delete marked record, then we are allowed to ignore blob prefixes if the delete marking was done by some other trx as it must have committed by now for us to allow an over-write. */ if (ignore_prefix) { ignore_prefix = ut_dulint_cmp(trx_id, trx->id) != 0; } ptr += mach_dulint_write_compressed(ptr, trx_id); field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos( index, DATA_ROLL_PTR), &flen); ut_ad(flen == DATA_ROLL_PTR_LEN); ptr += mach_dulint_write_compressed(ptr, trx_read_roll_ptr(field)); /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record which will be modified in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { field = rec_get_nth_field(rec, offsets, i, &flen); /* The ordering columns must not be stored externally. */ ut_ad(!rec_offs_nth_extern(offsets, i)); ut_ad(dict_index_get_nth_col(index, i)->ord_part); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } ptr += mach_write_compressed(ptr, flen); if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } /*----------------------------------------*/ /* Save to the undo log the old values of the columns to be updated. */ if (update) { if (trx_undo_left(undo_page, ptr) < 5) { return(0); } ptr += mach_write_compressed(ptr, upd_get_n_fields(update)); for (i = 0; i < upd_get_n_fields(update); i++) { ulint pos = upd_get_nth_field(update, i)->field_no; /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5) { return(0); } ptr += mach_write_compressed(ptr, pos); /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (trx_undo_left(undo_page, ptr) < 15) { return(0); } if (rec_offs_nth_extern(offsets, pos)) { ptr = trx_undo_page_report_modify_ext( ptr, dict_index_get_nth_col(index, pos) ->ord_part && !ignore_prefix && flen < REC_MAX_INDEX_COL_LEN ? ext_buf : NULL, dict_table_zip_size(table), &field, &flen); /* Notify purge that it eventually has to free the old externally stored field */ trx->update_undo->del_marks = TRUE; *type_cmpl_ptr |= TRX_UNDO_UPD_EXTERN; } else { ptr += mach_write_compressed(ptr, flen); } if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } /*----------------------------------------*/ /* In the case of a delete marking, and also in the case of an update where any ordering field of any index changes, store the values of all columns which occur as ordering fields in any index. This info is used in the purge of old versions where we use it to build and search the delete marked index records, to look if we can remove them from the index tree. Note that starting from 4.0.14 also externally stored fields can be ordering in some index. Starting from 5.2, we no longer store REC_MAX_INDEX_COL_LEN first bytes to the undo log record, but we can construct the column prefix fields in the index by fetching the first page of the BLOB that is pointed to by the clustered index. This works also in crash recovery, because all pages (including BLOBs) are recovered before anything is rolled back. */ if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { byte* old_ptr = ptr; trx->update_undo->del_marks = TRUE; if (trx_undo_left(undo_page, ptr) < 5) { return(0); } /* Reserve 2 bytes to write the number of bytes the stored fields take in this undo record */ ptr += 2; for (col_no = 0; col_no < dict_table_get_n_cols(table); col_no++) { const dict_col_t* col = dict_table_get_nth_col(table, col_no); if (col->ord_part) { ulint pos; /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5 + 15) { return(0); } pos = dict_index_get_nth_col_pos(index, col_no); ptr += mach_write_compressed(ptr, pos); /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (rec_offs_nth_extern(offsets, pos)) { ptr = trx_undo_page_report_modify_ext( ptr, flen < REC_MAX_INDEX_COL_LEN && !ignore_prefix ? ext_buf : NULL, dict_table_zip_size(table), &field, &flen); } else { ptr += mach_write_compressed( ptr, flen); } if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } mach_write_to_2(old_ptr, ptr - old_ptr); } /*----------------------------------------*/ /* Write pointers to the previous and the next undo log records */ if (trx_undo_left(undo_page, ptr) < 2) { return(0); } mach_write_to_2(ptr, first_free); ptr += 2; mach_write_to_2(undo_page + first_free, ptr - undo_page); mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, ptr - undo_page); /* Write to the REDO log about this change in the UNDO log */ trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); return(first_free); }
/**********************************************************************//** Reports in the undo log of an insert of a clustered index record. @return offset of the inserted entry on the page if succeed, 0 if fail */ static ulint trx_undo_page_report_insert( /*========================*/ page_t* undo_page, /*!< in: undo log page */ trx_t* trx, /*!< in: transaction */ dict_index_t* index, /*!< in: clustered index */ const dtuple_t* clust_entry, /*!< in: index entry which will be inserted to the clustered index */ mtr_t* mtr) /*!< in: mtr */ { ulint first_free; byte* ptr; ulint i; ut_ad(dict_index_is_clust(index)); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT); first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 2 + 1 + 11 + 11) { /* Not enough space for writing the general parameters */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ *ptr++ = TRX_UNDO_INSERT_REC; ptr += mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += mach_dulint_write_much_compressed(ptr, index->table->id); /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record to be inserted in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { const dfield_t* field = dtuple_get_nth_field(clust_entry, i); ulint flen = dfield_get_len(field); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } ptr += mach_write_compressed(ptr, flen); if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, dfield_get_data(field), flen); ptr += flen; } } return(trx_undo_page_set_next_prev_and_add(undo_page, ptr, mtr)); }
/************************************************************************ Loads foreign key constraint col names (also for the referenced table). */ static void dict_load_foreign_cols( /*===================*/ char* id, /* in: foreign constraint id as a null- terminated string */ dict_foreign_t* foreign)/* in: foreign constraint object */ { dict_table_t* sys_foreign_cols; dict_index_t* sys_index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; char* col_name; rec_t* rec; byte* field; ulint len; ulint i; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); foreign->foreign_col_names = mem_heap_alloc(foreign->heap, foreign->n_fields * sizeof(void*)); foreign->referenced_col_names = mem_heap_alloc(foreign->heap, foreign->n_fields * sizeof(void*)); mtr_start(&mtr); sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS"); sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes); tuple = dtuple_create(foreign->heap, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, id, ut_strlen(id)); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (i = 0; i < foreign->n_fields; i++) { rec = btr_pcur_get_rec(&pcur); ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr)); ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 0, &len); ut_a(len == ut_strlen(id)); ut_a(ut_memcmp(id, field, len) == 0); field = rec_get_nth_field(rec, 1, &len); ut_a(len == 4); ut_a(i == mach_read_from_4(field)); field = rec_get_nth_field(rec, 4, &len); col_name = mem_heap_alloc(foreign->heap, len + 1); ut_memcpy(col_name, field, len); col_name[len] = '\0'; foreign->foreign_col_names[i] = col_name; field = rec_get_nth_field(rec, 5, &len); col_name = mem_heap_alloc(foreign->heap, len + 1); ut_memcpy(col_name, field, len); col_name[len] = '\0'; foreign->referenced_col_names[i] = col_name; btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
static unsigned long setup_userstack(unsigned char **argv, unsigned char **env, unsigned long *stack_len, unsigned long *t_argc, unsigned long *t_argv, unsigned long *p_aux, unsigned char *elf_interp) { int i, len, total_args = 0; int total_envs =0; unsigned char *p, *stack; unsigned long real_stack, addr; unsigned char **target_argv; unsigned char **target_env; int max_stack_len=MAX_USERSPACE_STACK_TEMPLEN; int max_list_len=(PAGE_SIZE/sizeof(void *))-1; unsigned long ret=0; if (argv == 0 && env == 0) { ut_printf(" ERROR in setuo_userstack argv:0\n"); return 0; } target_argv = (unsigned char **) alloc_page(MEM_CLEAR); target_env = (unsigned char **) alloc_page(MEM_CLEAR); if (target_argv==0 || target_env==0){ BUG(); } stack = (unsigned char *) vmalloc(MAX_USERSPACE_STACK_TEMPLEN,MEM_CLEAR); if (stack ==0){ goto error; } ret = stack; p = stack + max_stack_len; len = 0; real_stack = USERSTACK_ADDR + USERSTACK_LEN; if (elf_interp != 0){ //BUG(); len = ut_strlen(elf_interp); p = p - len - 1; real_stack = real_stack - len - 1; ut_strcpy(p, elf_interp); target_argv[total_args] = (unsigned char *)real_stack; total_args++; } for (i = 0; argv[i] != 0 && i < max_list_len; i++) { len = ut_strlen(argv[i]); if ((p - len - 1) > stack) { p = p - len - 1; real_stack = real_stack - len - 1; DEBUG(" argument :%d address:%x \n",i,real_stack); ut_strcpy(p, argv[i]); target_argv[total_args] = (unsigned char *)real_stack; total_args++; } else { ret=0 ; goto error; } } target_argv[total_args] = 0; for (i = 0; env[i] != 0 && i < max_list_len; i++) { total_envs++; len = ut_strlen(env[i]); if ((p - len - 1) > stack) { p = p - len - 1; real_stack = real_stack - len - 1; DEBUG(" envs :%d address:%x \n",i,real_stack); ut_strcpy(p, env[i]); target_env[i] = (unsigned char *)real_stack; } else { ret=0 ; goto error; } } target_env[i] = 0; addr = (unsigned long)p; addr = (unsigned long)((addr / 8) * 8); p = (unsigned char *)addr; p = p - (MAX_AUX_VEC_ENTRIES * 16); real_stack = USERSTACK_ADDR + USERSTACK_LEN + p - (stack + max_stack_len); *p_aux = (unsigned long)p; len = (1+total_args + 1 + total_envs+1) * 8; /* total_args+args+0+envs+0 */ if ((p - len - 1) > stack) { unsigned long *t; p = p - (total_envs+1)*8; ut_memcpy(p, (unsigned char *)target_env, (total_envs+1)*8); p = p - (1+total_args+1)*8; ut_memcpy(p+8, (unsigned char *)target_argv, (total_args+1)*8); t = (unsigned long *)p; *t = total_args; /* store argc at the top of stack */ DEBUG("Target ARG arg0:%x arg1:%x arg2:%x len:%d \n",target_argv[0],target_argv[1],target_argv[2],len); DEBUG("Target ENV arg0:%x arg1:%x arg2:%x len:%d \n",target_env[0],target_env[1],target_env[2],len); real_stack = real_stack - len; } else { ret=0; goto error; } *stack_len = max_stack_len - (p - stack); *t_argc = total_args; *t_argv = real_stack; error: if (ret ==0 ){ ut_log(" Error: user stack creation failed :%s:\n",g_current_task->name); vfree((unsigned long)stack); } mm_putFreePages((unsigned long)target_argv, 0); mm_putFreePages((unsigned long)target_env, 0); return ret; }
//unsigned long fs_loadElfLibrary(struct file *file, unsigned long tmp_stack, unsigned long stack_len, unsigned long aux_addr) { unsigned long fs_elf_load(struct file *file,unsigned long tmp_stack, unsigned long stack_len, unsigned long aux_addr) { struct elf_phdr *elf_phdata; struct elf_phdr *eppnt; unsigned long elf_bss, bss_start, bss, len; int retval, error, i, j; struct elfhdr elf_ex; Elf64_Addr p_entry; unsigned long *aux_vec, aux_index, load_addr; struct task_struct *task=g_current_task; error = 0; fs_lseek(file, 0, 0); retval = fs_read(file, (unsigned char *) &elf_ex, sizeof(elf_ex)); if (retval != sizeof(elf_ex)) { error = -1; goto out; } if (ut_memcmp((unsigned char *) elf_ex.e_ident, (unsigned char *) ELFMAG, SELFMAG) != 0) { error = -2; goto out; } if (elf_ex.e_type == ET_DYN) elf_ex.e_type=ET_EXEC; /* First of all, some simple consistency checks */ //if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || if (elf_ex.e_type != ET_EXEC || !elf_check_arch(&elf_ex)) { DEBUG("error:(not executable type or mismatch in architecture %x %x %x \n",elf_ex.e_type,elf_ex.e_phnum,elf_check_arch(&elf_ex)); error = -3; goto out; } /* Now read in all of the header information */ j = sizeof(struct elf_phdr) * elf_ex.e_phnum; /* j < ELF_MIN_ALIGN because elf_ex.e_phnum <= 2 */ elf_phdata = mm_malloc(j, 0); if (!elf_phdata) { error = -4; goto out; } eppnt = elf_phdata; fs_lseek(file, (unsigned long) elf_ex.e_phoff, 0); retval = fs_read(file, (unsigned char *) eppnt, j); if (retval != j) { error = -5; goto out; } DEBUG("START address : %x offset :%x \n",ELF_PAGESTART(eppnt->p_vaddr),eppnt->p_offset); for (j = 0, i = 0; i < elf_ex.e_phnum; i++){ if ((eppnt + i)->p_type == PT_LOAD) j++; } if (j == 0) { error = -6; goto out; } load_addr = ELF_PAGESTART(eppnt->p_vaddr); p_entry = elf_ex.e_entry; task->mm->start_code = 0; task->mm->end_code =0; for (i = 0; i < elf_ex.e_phnum; i++, eppnt++) /* mmap all loadable program headers */ { if (eppnt->p_type != PT_LOAD) continue; //ut_log("%d: LOAD section: vaddr:%x filesz:%x offset:%x flags:%x \n",i,ELF_PAGESTART(eppnt->p_vaddr),eppnt->p_filesz,eppnt->p_offset,eppnt->p_flags); /* Now use mmap to map the library into memory. */ error = 1; if (eppnt->p_filesz > 0) { unsigned long addr; unsigned long start_addr = ELF_PAGESTART(eppnt->p_vaddr); unsigned long end_addr= eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); addr = vm_mmap(file, start_addr, end_addr, eppnt->p_flags, 0, (eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr)),"text"); if (addr == 0) error = 0; if (task->mm->start_code ==0 || task->mm->start_code > start_addr ) task->mm->start_code = start_addr; if (task->mm->end_code < end_addr ) task->mm->end_code = end_addr; } //if (error != ELF_PAGESTART(eppnt->p_vaddr)) if (error != 1) { error = -6; goto out; } elf_bss = eppnt->p_vaddr + eppnt->p_filesz; // padzero(elf_bss); /* TODO : bss start address in not at the PAGE_ALIGN or ELF_MIN_ALIGN , need to club this partial page with the data */ // len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); bss_start = eppnt->p_filesz + eppnt->p_vaddr; bss = eppnt->p_memsz + eppnt->p_vaddr; //ut_log(" bss start :%x end:%x memsz:%x elf_bss:%x \n",bss_start, bss,eppnt->p_memsz,elf_bss); if (bss > bss_start) { vm_setupBrk(bss_start, bss - bss_start); } error = 0; } out: if (elf_phdata) { mm_free(elf_phdata); } if (error != 0) { ut_log(" ERROR in elf loader filename :%s :%d\n",file->filename,-error); } else { task->mm->stack_bottom = USERSTACK_ADDR+USERSTACK_LEN; elf_initialize_userspace_stack(elf_ex,aux_addr,tmp_stack, stack_len,load_addr); vm_mmap(0, USER_SYSCALL_PAGE, 0x1000, PROT_READ | PROT_EXEC |PROT_WRITE, MAP_ANONYMOUS, 0,"fst_syscal"); //ut_memset((unsigned char *)SYSCALL_PAGE,(unsigned char )0xcc,0x1000); ut_memcpy((unsigned char *)USER_SYSCALL_PAGE,(unsigned char *)&__vsyscall_page,0x1000); if (g_conf_syscall_debug==1){ //pagetable_walk(4,g_current_task->mm->pgd,1,0); } } DEBUG(" Program start address(autod) : %x \n",elf_ex.e_entry); if (error == 0) return p_entry; else return 0; }
/*************************************************************************** Loads a foreign key constraint to the dictionary cache. */ static ulint dict_load_foreign( /*==============*/ /* out: DB_SUCCESS or error code */ char* id) /* in: foreign constraint id as a null-terminated string */ { dict_foreign_t* foreign; dict_table_t* sys_foreign; btr_pcur_t pcur; dict_index_t* sys_index; dtuple_t* tuple; mem_heap_t* heap2; dfield_t* dfield; rec_t* rec; byte* field; ulint len; ulint err; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); heap2 = mem_heap_create(1000); mtr_start(&mtr); sys_foreign = dict_table_get_low("SYS_FOREIGN"); sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes); tuple = dtuple_create(heap2, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, id, ut_strlen(id)); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr) || rec_get_deleted_flag(rec)) { /* Not found */ fprintf(stderr, "InnoDB: Error A: cannot load foreign constraint %s\n", id); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); return(DB_ERROR); } field = rec_get_nth_field(rec, 0, &len); /* Check if the id in record is the searched one */ if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) { fprintf(stderr, "InnoDB: Error B: cannot load foreign constraint %s\n", id); btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap2); return(DB_ERROR); } /* Read the table names and the number of columns associated with the constraint */ mem_heap_free(heap2); foreign = dict_mem_foreign_create(); foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len)); ut_a(len == 4); foreign->id = mem_heap_alloc(foreign->heap, ut_strlen(id) + 1); ut_memcpy(foreign->id, id, ut_strlen(id) + 1); field = rec_get_nth_field(rec, 3, &len); foreign->foreign_table_name = mem_heap_alloc(foreign->heap, 1 + len); ut_memcpy(foreign->foreign_table_name, field, len); foreign->foreign_table_name[len] = '\0'; field = rec_get_nth_field(rec, 4, &len); foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len); ut_memcpy(foreign->referenced_table_name, field, len); foreign->referenced_table_name[len] = '\0'; btr_pcur_close(&pcur); mtr_commit(&mtr); dict_load_foreign_cols(id, foreign); /* Note that there may already be a foreign constraint object in the dictionary cache for this constraint: then the following call only sets the pointers in it to point to the appropriate table and index objects and frees the newly created object foreign. */ err = dict_foreign_add_to_cache(foreign); return(err); }
big_rec_t* dtuple_convert_big_rec( /*===================*/ /* out, own: created big record vector, NULL if we are not able to shorten the entry enough, i.e., if there are too many short fields in entry */ dict_index_t* index, /* in: index */ dtuple_t* entry, /* in: index entry */ ulint* ext_vec,/* in: array of externally stored fields, or NULL: if a field already is externally stored, then we cannot move it to the vector this function returns */ ulint n_ext_vec)/* in: number of elements is ext_vec */ { mem_heap_t* heap; big_rec_t* vector; dfield_t* dfield; ulint size; ulint n_fields; ulint longest; ulint longest_i = ULINT_MAX; ibool is_externally_stored; ulint i; ulint j; ut_a(dtuple_check_typed_no_assert(entry)); size = rec_get_converted_size(index, entry); if (UNIV_UNLIKELY(size > 1000000000)) { fprintf(stderr, "InnoDB: Warning: tuple size very big: %lu\n", (ulong) size); fputs("InnoDB: Tuple contents: ", stderr); dtuple_print(stderr, entry); putc('\n', stderr); } heap = mem_heap_create(size + dtuple_get_n_fields(entry) * sizeof(big_rec_field_t) + 1000); vector = mem_heap_alloc(heap, sizeof(big_rec_t)); vector->heap = heap; vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry) * sizeof(big_rec_field_t)); /* Decide which fields to shorten: the algorithm is to look for the longest field whose type is DATA_BLOB */ n_fields = 0; while (rec_get_converted_size(index, entry) >= ut_min(page_get_free_space_of_empty( index->table->comp) / 2, REC_MAX_DATA_SIZE)) { longest = 0; for (i = dict_index_get_n_unique_in_tree(index); i < dtuple_get_n_fields(entry); i++) { /* Skip over fields which already are externally stored */ is_externally_stored = FALSE; if (ext_vec) { for (j = 0; j < n_ext_vec; j++) { if (ext_vec[j] == i) { is_externally_stored = TRUE; } } } if (!is_externally_stored) { dfield = dtuple_get_nth_field(entry, i); if (dfield->len != UNIV_SQL_NULL && dfield->len > longest) { longest = dfield->len; longest_i = i; } } } /* We do not store externally fields which are smaller than DICT_MAX_INDEX_COL_LEN */ ut_a(DICT_MAX_INDEX_COL_LEN > REC_1BYTE_OFFS_LIMIT); if (longest < BTR_EXTERN_FIELD_REF_SIZE + 10 + DICT_MAX_INDEX_COL_LEN) { /* Cannot shorten more */ mem_heap_free(heap); return(NULL); } /* Move data from field longest_i to big rec vector; we do not let data size of the remaining entry drop below 128 which is the limit for the 2-byte offset storage format in a physical record. This we accomplish by storing 128 bytes of data in entry itself, and only the remaining part to big rec vec. We store the first bytes locally to the record. Then we can calculate all ordering fields in all indexes from locally stored data. */ dfield = dtuple_get_nth_field(entry, longest_i); vector->fields[n_fields].field_no = longest_i; ut_a(dfield->len > DICT_MAX_INDEX_COL_LEN); vector->fields[n_fields].len = dfield->len - DICT_MAX_INDEX_COL_LEN; vector->fields[n_fields].data = mem_heap_alloc(heap, vector->fields[n_fields].len); /* Copy data (from the end of field) to big rec vector */ ut_memcpy(vector->fields[n_fields].data, ((byte*)dfield->data) + dfield->len - vector->fields[n_fields].len, vector->fields[n_fields].len); dfield->len = dfield->len - vector->fields[n_fields].len + BTR_EXTERN_FIELD_REF_SIZE; /* Set the extern field reference in dfield to zero */ memset(((byte*)dfield->data) + dfield->len - BTR_EXTERN_FIELD_REF_SIZE, 0, BTR_EXTERN_FIELD_REF_SIZE); n_fields++; } vector->n_fields = n_fields; return(vector); }
/************************************************************************ Loads definitions for table indexes. Adds them to the data dictionary cache. */ static void dict_load_indexes( /*==============*/ dict_table_t* table, /* in: table */ mem_heap_t* heap) /* in: memory heap for temporary storage */ { dict_table_t* sys_indexes; dict_index_t* sys_index; dict_index_t* index; btr_pcur_t pcur; dtuple_t* tuple; dfield_t* dfield; rec_t* rec; byte* field; ulint len; ulint name_len; char* name_buf; ulint type; ulint space; ulint page_no; ulint n_fields; byte* buf; ibool is_sys_table; dulint id; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); if ((ut_dulint_get_high(table->id) == 0) && (ut_dulint_get_low(table->id) < DICT_HDR_FIRST_ID)) { is_sys_table = TRUE; } else { is_sys_table = FALSE; } mtr_start(&mtr); sys_indexes = dict_table_get_low("SYS_INDEXES"); sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); buf = mem_heap_alloc(heap, 8); mach_write_to_8(buf, table->id); dfield_set_data(dfield, buf, 8); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); for (;;) { if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { break; } rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); ut_ad(len == 8); if (ut_memcmp(buf, field, len) != 0) { break; } ut_a(!rec_get_deleted_flag(rec)); field = rec_get_nth_field(rec, 1, &len); ut_ad(len == 8); id = mach_read_from_8(field); ut_a(0 == ut_strcmp("NAME", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_indexes), 4))->name)); field = rec_get_nth_field(rec, 4, &name_len); name_buf = mem_heap_alloc(heap, name_len + 1); ut_memcpy(name_buf, field, name_len); name_buf[name_len] = '\0'; field = rec_get_nth_field(rec, 5, &len); n_fields = mach_read_from_4(field); field = rec_get_nth_field(rec, 6, &len); type = mach_read_from_4(field); field = rec_get_nth_field(rec, 7, &len); space = mach_read_from_4(field); ut_a(0 == ut_strcmp("PAGE_NO", dict_field_get_col( dict_index_get_nth_field( dict_table_get_first_index(sys_indexes), 8))->name)); field = rec_get_nth_field(rec, 8, &len); page_no = mach_read_from_4(field); if (is_sys_table && ((type & DICT_CLUSTERED) || ((table == dict_sys->sys_tables) && (name_len == ut_strlen("ID_IND")) && (0 == ut_memcmp(name_buf, "ID_IND", name_len))))) { /* The index was created in memory already in booting */ } else { index = dict_mem_index_create(table->name, name_buf, space, type, n_fields); index->page_no = page_no; index->id = id; dict_load_fields(table, index, heap); dict_index_add_to_cache(table, index); } btr_pcur_move_to_next_user_rec(&pcur, &mtr); } btr_pcur_close(&pcur); mtr_commit(&mtr); }
ulint dict_load_foreigns( /*===============*/ /* out: DB_SUCCESS or error code */ char* table_name) /* in: table name */ { btr_pcur_t pcur; mem_heap_t* heap; dtuple_t* tuple; dfield_t* dfield; dict_index_t* sec_index; dict_table_t* sys_foreign; rec_t* rec; byte* field; ulint len; char* id ; ulint err; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); sys_foreign = dict_table_get_low("SYS_FOREIGN"); if (sys_foreign == NULL) { /* No foreign keys defined yet in this database */ fprintf(stderr, "InnoDB: Error: no foreign key system tables in the database\n"); return(DB_ERROR); } mtr_start(&mtr); /* Get the secondary index based on FOR_NAME from table SYS_FOREIGN */ sec_index = dict_table_get_next_index( dict_table_get_first_index(sys_foreign)); start_load: heap = mem_heap_create(256); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, table_name, ut_strlen(table_name)); dict_index_copy_types(tuple, sec_index, 1); btr_pcur_open_on_user_rec(sec_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); loop: rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { /* End of index */ goto load_next_index; } /* Now we have the record in the secondary index containing a table name and a foreign constraint ID */ rec = btr_pcur_get_rec(&pcur); field = rec_get_nth_field(rec, 0, &len); /* Check if the table name in record is the one searched for */ if (len != ut_strlen(table_name) || 0 != ut_memcmp(field, table_name, len)) { goto load_next_index; } if (rec_get_deleted_flag(rec)) { goto next_rec; } /* Now we get a foreign key constraint id */ field = rec_get_nth_field(rec, 1, &len); id = mem_heap_alloc(heap, len + 1); ut_memcpy(id, field, len); id[len] = '\0'; btr_pcur_store_position(&pcur, &mtr); mtr_commit(&mtr); /* Load the foreign constraint definition to the dictionary cache */ err = dict_load_foreign(id); if (err != DB_SUCCESS) { btr_pcur_close(&pcur); mem_heap_free(heap); return(err); } mtr_start(&mtr); btr_pcur_restore_position(BTR_SEARCH_LEAF, &pcur, &mtr); next_rec: btr_pcur_move_to_next_user_rec(&pcur, &mtr); goto loop; load_next_index: btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); sec_index = dict_table_get_next_index(sec_index); if (sec_index != NULL) { mtr_start(&mtr); goto start_load; } return(DB_SUCCESS); }
/************************************************************************** Reports in the undo log of an update or delete marking of a clustered index record. */ static ulint trx_undo_page_report_modify( /*========================*/ /* out: byte offset of the inserted undo log entry on the page if succeed, 0 if fail */ page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index where update or delete marking is done */ rec_t* rec, /* in: clustered index record which has NOT yet been modified */ const ulint* offsets, /* in: rec_get_offsets(rec, index) */ upd_t* update, /* in: update vector which tells the columns to be updated; in the case of a delete, this should be set to NULL */ ulint cmpl_info, /* in: compiler info on secondary index updates */ mtr_t* mtr) /* in: mtr */ { dict_table_t* table; upd_field_t* upd_field; ulint first_free; byte* ptr; ulint len; byte* field; ulint flen; ulint pos; dulint roll_ptr; dulint trx_id; ulint bits; ulint col_no; byte* old_ptr; ulint type_cmpl; byte* type_cmpl_ptr; ulint i; ut_a(index->type & DICT_CLUSTERED); ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE); table = index->table; first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 50) { /* NOTE: the value 50 must be big enough so that the general fields written below fit on the undo log page */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ if (update) { if (rec_get_deleted_flag(rec, dict_table_is_comp(table))) { type_cmpl = TRX_UNDO_UPD_DEL_REC; } else { type_cmpl = TRX_UNDO_UPD_EXIST_REC; } } else { type_cmpl = TRX_UNDO_DEL_MARK_REC; } type_cmpl = type_cmpl | (cmpl_info * TRX_UNDO_CMPL_INFO_MULT); mach_write_to_1(ptr, type_cmpl); type_cmpl_ptr = ptr; ptr++; len = mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += len; len = mach_dulint_write_much_compressed(ptr, table->id); ptr += len; /*----------------------------------------*/ /* Store the state of the info bits */ bits = rec_get_info_bits(rec, dict_table_is_comp(table)); mach_write_to_1(ptr, bits); ptr += 1; /* Store the values of the system columns */ field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos( index, DATA_TRX_ID), &len); ut_ad(len == DATA_TRX_ID_LEN); trx_id = trx_read_trx_id(field); field = rec_get_nth_field(rec, offsets, dict_index_get_sys_col_pos( index, DATA_ROLL_PTR), &len); ut_ad(len == DATA_ROLL_PTR_LEN); roll_ptr = trx_read_roll_ptr(field); len = mach_dulint_write_compressed(ptr, trx_id); ptr += len; len = mach_dulint_write_compressed(ptr, roll_ptr); ptr += len; /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record which will be modified in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { field = rec_get_nth_field(rec, offsets, i, &flen); if (trx_undo_left(undo_page, ptr) < 4) { return(0); } len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } /*----------------------------------------*/ /* Save to the undo log the old values of the columns to be updated. */ if (update) { if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, upd_get_n_fields(update)); ptr += len; for (i = 0; i < upd_get_n_fields(update); i++) { upd_field = upd_get_nth_field(update, i); pos = upd_field->field_no; /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, pos); ptr += len; /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } if (rec_offs_nth_extern(offsets, pos)) { /* If a field has external storage, we add to flen the flag */ len = mach_write_compressed( ptr, UNIV_EXTERN_STORAGE_FIELD + flen); /* Notify purge that it eventually has to free the old externally stored field */ trx->update_undo->del_marks = TRUE; *type_cmpl_ptr = *type_cmpl_ptr | TRX_UNDO_UPD_EXTERN; } else { len = mach_write_compressed(ptr, flen); } ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } /*----------------------------------------*/ /* In the case of a delete marking, and also in the case of an update where any ordering field of any index changes, store the values of all columns which occur as ordering fields in any index. This info is used in the purge of old versions where we use it to build and search the delete marked index records, to look if we can remove them from the index tree. Note that starting from 4.0.14 also externally stored fields can be ordering in some index. But we always store at least 384 first bytes locally to the clustered index record, which means we can construct the column prefix fields in the index from the stored data. */ if (!update || !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) { trx->update_undo->del_marks = TRUE; if (trx_undo_left(undo_page, ptr) < 5) { return(0); } old_ptr = ptr; /* Reserve 2 bytes to write the number of bytes the stored fields take in this undo record */ ptr += 2; for (col_no = 0; col_no < dict_table_get_n_cols(table); col_no++) { const dict_col_t* col = dict_table_get_nth_col(table, col_no); if (col->ord_part > 0) { pos = dict_index_get_nth_col_pos(index, col_no); /* Write field number to undo log */ if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, pos); ptr += len; /* Save the old value of field */ field = rec_get_nth_field(rec, offsets, pos, &flen); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, field, flen); ptr += flen; } } } mach_write_to_2(old_ptr, ptr - old_ptr); } /*----------------------------------------*/ /* Write pointers to the previous and the next undo log records */ if (trx_undo_left(undo_page, ptr) < 2) { return(0); } mach_write_to_2(ptr, first_free); ptr += 2; mach_write_to_2(undo_page + first_free, ptr - undo_page); mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, ptr - undo_page); /* Write to the REDO log about this change in the UNDO log */ trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); return(first_free); }
/************************************************************************** Reports in the undo log of an insert of a clustered index record. */ static ulint trx_undo_page_report_insert( /*========================*/ /* out: offset of the inserted entry on the page if succeed, 0 if fail */ page_t* undo_page, /* in: undo log page */ trx_t* trx, /* in: transaction */ dict_index_t* index, /* in: clustered index */ dtuple_t* clust_entry, /* in: index entry which will be inserted to the clustered index */ mtr_t* mtr) /* in: mtr */ { ulint first_free; byte* ptr; ulint len; dfield_t* field; ulint flen; ulint i; ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE) == TRX_UNDO_INSERT); first_free = mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE); ptr = undo_page + first_free; ut_ad(first_free <= UNIV_PAGE_SIZE); if (trx_undo_left(undo_page, ptr) < 30) { /* NOTE: the value 30 must be big enough such that the general fields written below fit on the undo log page */ return(0); } /* Reserve 2 bytes for the pointer to the next undo log record */ ptr += 2; /* Store first some general parameters to the undo log */ mach_write_to_1(ptr, TRX_UNDO_INSERT_REC); ptr++; len = mach_dulint_write_much_compressed(ptr, trx->undo_no); ptr += len; len = mach_dulint_write_much_compressed(ptr, (index->table)->id); ptr += len; /*----------------------------------------*/ /* Store then the fields required to uniquely determine the record to be inserted in the clustered index */ for (i = 0; i < dict_index_get_n_unique(index); i++) { field = dtuple_get_nth_field(clust_entry, i); flen = dfield_get_len(field); if (trx_undo_left(undo_page, ptr) < 5) { return(0); } len = mach_write_compressed(ptr, flen); ptr += len; if (flen != UNIV_SQL_NULL) { if (trx_undo_left(undo_page, ptr) < flen) { return(0); } ut_memcpy(ptr, dfield_get_data(field), flen); ptr += flen; } } if (trx_undo_left(undo_page, ptr) < 2) { return(0); } /*----------------------------------------*/ /* Write pointers to the previous and the next undo log records */ if (trx_undo_left(undo_page, ptr) < 2) { return(0); } mach_write_to_2(ptr, first_free); ptr += 2; mach_write_to_2(undo_page + first_free, ptr - undo_page); mach_write_to_2(undo_page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE, ptr - undo_page); /* Write the log entry to the REDO log of this change in the UNDO log */ trx_undof_page_add_undo_rec_log(undo_page, first_free, ptr - undo_page, mtr); return(first_free); }
ibool os_awe_map_physical_mem_to_window( /*==============================*/ /* out: TRUE if success; the function calls exit(1) in case of an error */ byte* ptr, /* in: a page-aligned pointer to somewhere in the virtual address space window; we map the physical mem pages here */ ulint n_mem_pages, /* in: number of 4 kB mem pages to map */ os_awe_t* page_info) /* in: array of page infos for those pages; each page has one slot in the array */ { #ifdef UNIV_SIMULATE_AWE ulint i; byte** map; byte* page; byte* phys_page; ut_a(ptr >= os_awe_simulate_window); ut_a(ptr < os_awe_simulate_window + os_awe_simulate_window_size); ut_a(page_info >= os_awe_simulate_page_info); ut_a(page_info < os_awe_simulate_page_info + (os_awe_simulate_mem_size / 4096)); /* First look if some other 'physical pages' are mapped at ptr, and copy them back to where they were if yes */ map = os_awe_simulate_map + ((ulint)(ptr - os_awe_simulate_window)) / 4096; page = ptr; for (i = 0; i < n_mem_pages; i++) { if (*map != NULL) { ut_memcpy(*map, page, 4096); } map++; page += 4096; } /* Then copy to ptr the 'physical pages' determined by page_info; we assume page_info is a segment of the array we created at the start */ phys_page = os_awe_simulate_mem + (ulint)(page_info - os_awe_simulate_page_info) * 4096; ut_memcpy(ptr, phys_page, n_mem_pages * 4096); /* Update the map */ map = os_awe_simulate_map + ((ulint)(ptr - os_awe_simulate_window)) / 4096; for (i = 0; i < n_mem_pages; i++) { *map = phys_page; map++; phys_page += 4096; } return(TRUE); #elif defined(__WIN2000__) BOOL bResult; os_awe_t n_pages; n_pages = (os_awe_t)n_mem_pages; if (!(ptr >= os_awe_window)) { fprintf(stderr, "InnoDB: AWE: Error: trying to map to address %lx" " but AWE window start %lx\n", (ulint)ptr, (ulint)os_awe_window); ut_a(0); } if (!(ptr <= os_awe_window + os_awe_window_size - UNIV_PAGE_SIZE)) { fprintf(stderr, "InnoDB: AWE: Error: trying to map to address %lx" " but AWE window end %lx\n", (ulint)ptr, (ulint)os_awe_window + os_awe_window_size); ut_a(0); } if (!(page_info >= os_awe_page_info)) { fprintf(stderr, "InnoDB: AWE: Error: trying to map page info" " at %lx but array start %lx\n", (ulint)page_info, (ulint)os_awe_page_info); ut_a(0); } if (!(page_info <= os_awe_page_info + (os_awe_n_pages - 4))) { fprintf(stderr, "InnoDB: AWE: Error: trying to map page info" " at %lx but array end %lx\n", (ulint)page_info, (ulint)(os_awe_page_info + os_awe_n_pages)); ut_a(0); } bResult = MapUserPhysicalPages((PVOID)ptr, n_pages, page_info); if (bResult != TRUE) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: AWE: Mapping of %lu physical pages" " to address %lx failed,\n" "InnoDB: error %lu.\n" "InnoDB: Cannot continue operation.\n", n_mem_pages, (ulint)ptr, (ulint)GetLastError()); exit(1); } return(TRUE); #else UT_NOT_USED(ptr); UT_NOT_USED(n_mem_pages); UT_NOT_USED(page_info); return(FALSE); #endif }
byte* row_upd_index_parse( /*================*/ /* out: log data end or NULL */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ mem_heap_t* heap, /* in: memory heap where update vector is built */ upd_t** update_out)/* out: update vector */ { upd_t* update; upd_field_t* upd_field; dfield_t* new_val; ulint len; ulint n_fields; byte* buf; ulint info_bits; ulint i; if (end_ptr < ptr + 1) { return(NULL); } info_bits = mach_read_from_1(ptr); ptr++; ptr = mach_parse_compressed(ptr, end_ptr, &n_fields); if (ptr == NULL) { return(NULL); } update = upd_create(n_fields, heap); update->info_bits = info_bits; for (i = 0; i < n_fields; i++) { upd_field = upd_get_nth_field(update, i); new_val = &(upd_field->new_val); ptr = mach_parse_compressed(ptr, end_ptr, &(upd_field->field_no)); if (ptr == NULL) { return(NULL); } ptr = mach_parse_compressed(ptr, end_ptr, &len); if (ptr == NULL) { return(NULL); } new_val->len = len; if (len != UNIV_SQL_NULL) { if (end_ptr < ptr + len) { return(NULL); } else { buf = mem_heap_alloc(heap, len); ut_memcpy(buf, ptr, len); ptr += len; new_val->data = buf; } } } *update_out = update; return(ptr); }
char* dict_get_first_table_name_in_db( /*============================*/ /* out, own: table name, NULL if does not exist; the caller must free the memory in the string! */ char* name) /* in: database name which ends to '/' */ { dict_table_t* sys_tables; btr_pcur_t pcur; dict_index_t* sys_index; dtuple_t* tuple; mem_heap_t* heap; dfield_t* dfield; rec_t* rec; byte* field; ulint len; char* table_name; mtr_t mtr; ut_ad(mutex_own(&(dict_sys->mutex))); heap = mem_heap_create(1000); mtr_start(&mtr); sys_tables = dict_table_get_low("SYS_TABLES"); sys_index = UT_LIST_GET_FIRST(sys_tables->indexes); tuple = dtuple_create(heap, 1); dfield = dtuple_get_nth_field(tuple, 0); dfield_set_data(dfield, name, ut_strlen(name)); dict_index_copy_types(tuple, sys_index, 1); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_SEARCH_LEAF, &pcur, &mtr); loop: rec = btr_pcur_get_rec(&pcur); if (!btr_pcur_is_on_user_rec(&pcur, &mtr)) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } field = rec_get_nth_field(rec, 0, &len); if (len < strlen(name) || ut_memcmp(name, field, strlen(name)) != 0) { /* Not found */ btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(NULL); } if (!rec_get_deleted_flag(rec)) { /* We found one */ table_name = mem_alloc(len + 1); ut_memcpy(table_name, field, len); table_name[len] = '\0'; btr_pcur_close(&pcur); mtr_commit(&mtr); mem_heap_free(heap); return(table_name); } btr_pcur_move_to_next_user_rec(&pcur, &mtr); goto loop; }