shpid_t lg_tag_indirect_h::_pid(uint4_t pid_num) const { FUNC(lg_tag_indirect_h::_pid); // get the root page lpid_t root_pid(stid(), _iref.indirect_root); lgindex_p root; W_IGNORE( root.fix(root_pid, LATCH_SH) ); // PAGEFIXBUG if (!root.is_fixed()) return 0; // if the tree is only 1 level, return the correct pid easily if (indirect_type(_page_cnt) == t_large_1) { return root.pids(pid_num); } w_assert9(indirect_type(_page_cnt) == t_large_2); // find "slot" containing pointer to page with pid_num w_assert9( (pid_num/lgindex_p::max_pids) < max_uint2); slotid_t idx = (slotid_t)(pid_num/lgindex_p::max_pids); lpid_t indirect_pid(stid(), root.pids(idx)); lgindex_p indirect; W_IGNORE( indirect.fix(indirect_pid, LATCH_SH) ); // PAGEFIXBUG if (!indirect.is_fixed()) return 0; return indirect.pids(pid_num % lgindex_p::max_pids); }
rc_t lg_tag_indirect_h::append(uint4_t num_pages, const lpid_t new_pages[]) { FUNC(lg_tag_indirect_h::append); const uint max_pages = 64; shpid_t page_list[max_pages]; w_assert9(num_pages <= max_pages); for (uint i=0; i<num_pages; i++) page_list[i]=new_pages[i].page; if (_iref.indirect_root == 0) { // allocate a root indirect page, near last page in store lpid_t root_pid; W_DO(smlevel_0::io->alloc_a_page(stid(), lpid_t::eof, // near hint root_pid, // npages, array for output pids false, // not may_realloc EX, // lock on the allocated pages false // do not search file for free pages )); _iref.indirect_root = root_pid.page; lgindex_p root; W_DO( root.fix(root_pid, LATCH_EX, root.t_virgin) ); // perform fake read of the new page } // calculate the number of pages to append to last index page uint space_on_last = lgindex_p::max_pids- _pages_on_last_indirect(); uint4_t pages_on_last = MIN(num_pages, space_on_last); // number of pages to place on a new indirect_page uint4_t pages_on_new = num_pages - pages_on_last; // append pages to lpid_t last_index_pid(stid(), _last_indirect()); lgindex_p last_index; W_DO( last_index.fix(last_index_pid, LATCH_EX) ); w_assert1(last_index.is_fixed()); W_DO(last_index.append(pages_on_last, page_list)); if (pages_on_new) { lpid_t new_pid; W_DO(_add_new_indirect(new_pid)); lgindex_p last_index2; W_DO( last_index2.fix(new_pid, LATCH_EX) ); w_assert1(last_index2.is_fixed()); W_DO(last_index2.append(pages_on_new, page_list+pages_on_last)); } return RCOK; }
int main() { string id; int count=0; cout<<"注意英文大寫,不需要空格,要跳出請輸入00"<<endl<<endl; while(1) { cout<<"------------------------------"<<endl; cout<<++count<<" : "<<endl; cout<<"輸入學號 : "; cin>>id; if(id=="00")break;//exit(1); Student stid(id); //cout<<stid.getStudentId()<<endl; cout<<"就讀科系 : "<<stid.getDepartment()<<endl; cout<<"目前身份 : "<<stid.getIdentity()<<endl; cout<<"入學年度 : "<<stid.getEntryYear()<<endl; cout<<"入學方式 : "<<stid.getEntryMethod()<<endl; cout<<"班級座號 : "<<stid.getNumber()<<endl<<endl; if(stid.getCheck()) { stid.setCheck(false); cout<<"沒有這個人喔!!!!"<<endl; } } return 0; }
rc_t lg_tag_indirect_h::_add_new_indirect(lpid_t& new_pid) { FUNC(lg_tag_indirect_h::_add_new_indirect); // flags for new pages w_base_t::uint4_t flags = lgindex_p::t_virgin; if (indirect_type(_page_cnt) == t_large_1) { // must allocate a new root pid and point it to the current one lpid_t root_pid; W_DO(smlevel_0::io->alloc_a_page(stid(), lpid_t::eof, // near hint root_pid, // npages, array for output pids false, // not may_realloc EX, // lock on pages false // do not search file for free pages )); lgindex_p root; W_DO( root.fix(root_pid, LATCH_EX, flags) ); w_assert1(root.is_fixed()); W_DO(root.append(1, &_iref.indirect_root)); w_assert9(root_pid.stid() == stid()); _iref.indirect_root = root_pid.page; } // allocate a new page and point to it from the root W_DO(smlevel_0::io->alloc_a_page(stid(), lpid_t::eof, // near hint new_pid, // npages, array of output pids false, // not may_realloc EX, // lock on new pages false // do not search file for free pages )); lgindex_p new_page; W_DO( new_page.fix(new_pid, LATCH_EX, flags) ); // format page lpid_t root_pid(stid(), _iref.indirect_root); lgindex_p root; W_DO( root.fix(root_pid, LATCH_EX) ); w_assert1(root.is_fixed()); W_DO(root.append(1, &new_pid.page)); return RCOK; }
shpid_t lg_tag_indirect_h::_last_pid() const { FUNC(lg_tag_indirect_h::_last_pid); lpid_t last_indirect_pid(stid(), _last_indirect()); if (last_indirect_pid.page == 0) return 0; // 0-length record lgindex_p last_indirect; W_IGNORE( last_indirect.fix(last_indirect_pid, LATCH_SH) ); // PAGEFIXBUG if (!last_indirect.is_fixed()) return 0; return last_indirect.last_pid(); }
shpid_t lg_tag_indirect_h::_last_indirect() const { FUNC(lg_tag_indirect_h::_last_indirect); if (indirect_type(_page_cnt) == t_large_1) { return _iref.indirect_root; } // read the root page lpid_t root_pid(stid(), _iref.indirect_root); lgindex_p root; W_IGNORE( root.fix(root_pid, LATCH_SH) ); // PAGEFIXBUG if (!root.is_fixed()) return 0; shpid_t* pids = (shpid_t*)root.tuple_addr(0); w_assert9(pids); return(pids[(_page_cnt-1)/lgindex_p::max_pids]); }
rc_t lg_tag_indirect_h::update(uint4_t start_byte, const vec_t& data) const { FUNC(lg_tag_indirect_h::update); uint4_t amount; // amount to update on page uint page_to_update = start_byte/lgdata_p::data_sz; // first page uint4_t data_size = data.size(); lpid_t curr_pid(stid(), 0); uint4_t offset = start_byte%lgdata_p::data_sz; uint4_t num_bytes = 0; while (num_bytes < data_size) { amount = MIN(lgdata_p::data_sz-offset, data_size-num_bytes); curr_pid.page = _pid(page_to_update); lgdata_p lgdata; W_DO( lgdata.fix(curr_pid, LATCH_EX) ); W_DO(lgdata.update(offset, data, num_bytes, amount)); offset = 0; num_bytes += amount; page_to_update++; } w_assert9(page_to_update-1 == (start_byte+data.size()-1)/lgdata_p::data_sz); return RCOK; }
/* * truncate() removes pages at the end of large records * implemented as indirect blocks */ rc_t lg_tag_indirect_h::truncate(uint4_t num_pages) { FUNC(lg_tag_indirect_h::truncate); int i; int first_dealloc = (int)(_page_cnt-num_pages); int last_dealloc = (int)(_page_cnt-1); recflags_t rec_type = indirect_type(_page_cnt); for (i = first_dealloc; i <= last_dealloc; i++) { W_DO(smlevel_0::io->free_page(pid(i))); } int indirect_rm_count = 0; // # indirect pages to remove int pids_rm_by_indirect = 0; // # data pids removed // by removing indirect pages int pids_to_rm = 0; // # of pids to rm from last indirect // indirect pages are only removed if t_large_2 if (rec_type == t_large_2) { uint pids_on_last = _pages_on_last_indirect(); if (pids_on_last > num_pages) { indirect_rm_count = 0; } else { indirect_rm_count = (num_pages-1)/lgindex_p::max_pids+1; pids_rm_by_indirect = pids_on_last+(indirect_rm_count-1)*lgindex_p::max_pids; } } pids_to_rm = num_pages-pids_rm_by_indirect; // remove any indirect pages we can if (indirect_rm_count > 0) { lpid_t root_pid(stid(), _iref.indirect_root); lgindex_p root; W_DO( root.fix(root_pid, LATCH_EX) ); w_assert1(root.is_fixed()); // first deallocate the indirect pages w_assert9(root.pid_count() == _page_cnt/lgindex_p::max_pids + 1); first_dealloc = root.pid_count()-indirect_rm_count; last_dealloc = root.pid_count()-1; for (i = first_dealloc; i <= last_dealloc; i++) { lpid_t pid_to_free(stid(), root.pids(i)); W_DO(smlevel_0::io->free_page(pid_to_free)); } // if will be only one indirect page left, then remember // the ID of this page /* shpid_t new_indirect_root; if (indirect_type(_page_cnt-num_pages) == t_large_1) { new_indirect_root = root->pids(0); } */ W_DO(root.truncate(indirect_rm_count)); // if there is only one indirect page left, then switch to // a single level tree if (indirect_type(_page_cnt-num_pages) == t_large_1) { w_assert9( ((_page_cnt-1)/lgindex_p::max_pids+1) - indirect_rm_count == 0); if (root.pid_count() > 0) { // there is at least one page left in the record, // the the first page in the root becomes the new root _iref.indirect_root = root.pids(0); } else { // all pages have been removed, so there is no root _iref.indirect_root = 0; } root.unfix(); W_DO(smlevel_0::io->free_page(root_pid)); } } // if we have not removed all pages, we must truncate pids // from the last indirect page if (_page_cnt > num_pages) { // get the pid for the last indirect page before truncate point // temporarily lower _page_cnt _page_cnt -= num_pages; lpid_t last_index_pid(stid(), _last_indirect()); _page_cnt += num_pages; lgindex_p last_index; W_DO( last_index.fix(last_index_pid, LATCH_EX) ); w_assert1(last_index.is_fixed()); W_DO(last_index.truncate(pids_to_rm)); } else { w_assert9(_page_cnt == num_pages); // we have removed all data pages, so remove the root // (assuming it is not 0 meaning it has already been removed) if (_iref.indirect_root != 0) { lpid_t root_pid(stid(), _iref.indirect_root); W_DO(smlevel_0::io->free_page(root_pid)); _iref.indirect_root = 0; // mark that there is no root } } return RCOK; }