void VerifyHandler::invoke(logrec_t& r) { w_assert0(r.valid_header()); lsn_t lsn = r.lsn(); PageID pid = r.pid(); if (r.is_redo()) { checkRedo(r, pid, lsn, r.page_prev_lsn()); if (r.is_multi_page()) { checkRedo(r, r.pid2(), lsn, r.page2_prev_lsn()); } if (alloc_cache_t::is_alloc_pid(pid)) { // checkAlloc(r); } } if (merge) { w_assert0(pid >= lastPID); if (pid == lastPID) { w_assert0(lsn > lastLSN); } w_assert0(merge || lsn >= minLSN); w_assert0(merge || lsn <= maxLSN); } lastLSN = lsn; lastPID = pid; count++; }
void VerifyHandler::checkAlloc(logrec_t& r) { auto lsn = r.lsn(); PageID pid = *((PageID*) (r.data_ssx())); if (r.type() == logrec_t::t_alloc_page) { if (allocatedPages.find(pid) != allocatedPages.end()) { std::cout << "on " << lsn << " alloc_page of pid " << pid << " which is already allocated" << std::endl; w_assert0(false); } allocatedPages.insert(pid); } else if (r.type() == logrec_t::t_dealloc_page) { if (allocatedPages.find(pid) == allocatedPages.end()) { std::cout << "on " << lsn << " dealloc_page of pid " << pid << " which is not allocated" << std::endl; w_assert0(false); } allocatedPages.erase(pid); } else { std::cout << "on " << lsn << " update on alloc pid " << r.pid() << " but invalid logrec type " << r.type_str() << std::endl; w_assert0(false); } }
void RestoreBitmap::serialize(char* buf, size_t from, size_t to) { spinlock_read_critical_section cs(&mutex); w_assert0(from < to); w_assert0(to <= bits.size()); /* * vector<bool> does not provide access to the internal bitmap structure, * so we stick with this non-efficient loop mechanism. If this becomes a * performance concern, the options are: * 1) Implement our own bitmap * 2) Reuse a bitmap with serialization support (e.g., Boost) * 3) In C++11, there is a data() method that returns the underlying array. * Maybe that would work here. */ size_t byte = 0, j = 0; for (size_t i = from; i < to; i++) { // set bit j on current byte // C++ guarantees that "true" expands to the integer 1 buf[byte] |= (bits[i] << j++); // wrap around next byte if (j == 8) { j = 0; byte++; } } }
bfcb_t* htab_insert(bf_core_m *core, bfpid_t const &pid, bf_core_m::Tstats &s) { // avoid double-insertions w/o a removal. bool already_there(false); bfcb_t *ret = core->_htab->lookup(pid); if(ret) { already_there = true; htab_remove(core, pid, s); } bfcb_t *ret2 = core->_htab->lookup(pid); w_assert0(ret2 == NULL); bfcb_t *cb ; if(already_there) { cb = ret; } else { ret = NULL; cb = core->replacement(); w_assert0(cb->latch.is_mine()); cb->latch.latch_release(); } if(cb == NULL) { cerr << " htab_insert could not get a replacement frame " << endl; } if(cb) { if(cb->old_pid_valid()) { // it's a replacement // ... obsolete check removed.. } cb->set_pid(pid); cb->zero_pin_cnt(); ret = core->_htab->insert(cb); s = me()->TL_stats().bfht; } #if W_DEBUG_LEVEL > 1 int sz= core->_htab->_size; for(int i=0; i < sz; i++) { bf_core_m::htab::bucket &b = core->_htab->_table[i]; w_assert2(b._lock.is_mine()==false); } #endif return ret; }
int get_wh(int sf, int specificWH, int tspread) { int wh = _change_load ? w_skewer.get_input() : URand(1, sf); if (specificWH > 0) { w_assert0(tspread > 0); w_assert0(specificWH <= tspread); wh = (wh / tspread) * tspread + specificWH; if (wh > sf) { wh -= tspread; } w_assert0(wh <= sf); w_assert0(wh > 0); } return wh; }
virtual void invoke(logrec_t& r) { // Dump stats on each tick log record if (r.type() == logrec_t::t_tick_sec || r.type() == logrec_t::t_tick_msec) { dumpStats(r.lsn()); return; } // Code copied from chkpt_t::scan_log if (r.is_redo()) { // Ignore metadata pages if (r.pid() % alloc_cache_t::extent_size == 0 || r.pid() == stnode_page::stpid) { return; } lsn_t lsn = r.lsn(); w_assert0(r.is_redo()); chkpt.mark_page_dirty(r.pid(), lsn, lsn); if (r.is_multi_page()) { w_assert0(r.pid2() != 0); chkpt.mark_page_dirty(r.pid2(), lsn, lsn); } updates++; } else if (r.type() == logrec_t::t_page_write) { char* pos = r.data(); PageID pid = *((PageID*) pos); pos += sizeof(PageID); lsn_t clean_lsn = *((lsn_t*) pos); pos += sizeof(lsn_t); uint32_t count = *((uint32_t*) pos); PageID end = pid + count; while (pid < end) { chkpt.mark_page_clean(pid, clean_lsn); pid++; } page_writes += count; } else if (r.type() == logrec_t::t_xct_end) { commits++; } }
void sm_stats_t::compute() { latch_uncondl_waits = need_latch_uncondl - latch_uncondl_nowaits; await_vol_lock_r = need_vol_lock_r - nowait_vol_lock_r; await_vol_lock_w = need_vol_lock_w - nowait_vol_lock_w; if(log_bytes_written > 0) { // skip-log and padding bytes -- actually, // anything flushed more than once, although inserted // bytes not yet flushed will tend to warp this number // if the log wasn't recently flushed. log_bytes_rewritten = log_bytes_written - log_bytes_generated; } if(log_bytes_generated_rb > 0) { // get the # bytes generated during forward processing. double z = log_bytes_generated; double y = log_bytes_generated_rb; double x = z - y; w_assert0(x >= 0.0); // should always be > 0, since the log_bytes_generated is // the total of fwd and rollback bytes. if(x>0.0) { log_bytes_rbfwd_ratio = double(log_bytes_generated_rb) / x; }else { log_bytes_rbfwd_ratio = 0.0; } } }
bool htab_remove(bf_core_m *core, bfpid_t const &pid, bf_core_m::Tstats &s) { bool ret(false); bfcb_t *cb = core->_htab->lookup(pid); if(cb) { // find the bucket so we can acquire the lock, // necessary for removal. // also ensure pin count is zero. int idx = core->_htab->hash(cb->hash_func(), pid); bf_core_m::htab::bucket &b = core->_htab->_table[idx]; cb->zero_pin_cnt(); CRITICAL_SECTION(cs, b._lock); bool bull = core->_htab->remove(cb); w_assert0(bull); w_assert1(cb->pin_cnt() == 0); } // It's possible that it couldn't remove the item // because the lock is not held or the pin count is > 0 if(ret) { w_assert2(cb->hash_func() == bf_core_m::htab::HASH_COUNT); } s = me()->TL_stats().bfht; return ret; }
int ShoreTPCCEnv::post_init() { conf(); // If the database is set to be padded if (get_pd() == PD_PADDED) { // CS: not supported // We should probably pad it by default at creation (TODO) w_assert0(false); TRACE( TRACE_ALWAYS, "Checking for WH record padding...\n"); // W_COERCE(db()->begin_xct()); // w_rc_t rc = _post_init_impl(); // if(rc.is_error()) { // cerr << "-> WH padding failed with: " << rc << endl; // rc = db()->abort_xct(); // return (rc.err_num()); // } // else { // TRACE( TRACE_ALWAYS, "-> Done\n"); // rc = db()->commit_xct(); // return (0); // } } return (0); }
w_rc_t table_man_t<T>::print_index(unsigned ind, ostream& os, int num_lines, bool need_tuple) { table_row_t* row = get_tuple(); rep_row_t rep(ts()); rep_row_t repkey(ts()); rep.set(table()->maxsize()); repkey.set(table()->maxsize()); row->_rep = &rep; row->_rep_key = &repkey; index_desc_t* pindex = table()->get_indexes()[ind]; w_assert0(pindex); index_scan_iter_impl<T> scanner(pindex, this, need_tuple); scanner.open_scan(); bool eof = false; size_t i = 0; while (true) { scanner.next(eof, *row); if (eof) break; if (num_lines > 0 && i++ > num_lines) break; row->print_values(os); } give_tuple(row); return RCOK; }
rc_t btree_impl::_ux_adopt_foster_core (btree_page_h &parent, btree_page_h &child, const w_keystr_t &new_child_key) { w_assert1 (g_xct()->is_single_log_sys_xct()); w_assert1 (parent.is_fixed()); w_assert1 (parent.latch_mode() == LATCH_EX); w_assert1 (parent.is_node()); w_assert1 (child.is_fixed()); w_assert1 (child.latch_mode() == LATCH_EX); w_assert0 (child.get_foster() != 0); PageID new_child_pid = child.get_foster(); if (smlevel_0::bf->is_swizzled_pointer(new_child_pid)) { smlevel_0::bf->unswizzle(parent.get_generic_page(), GeneralRecordIds::FOSTER_CHILD, true, &new_child_pid); } w_assert1(!smlevel_0::bf->is_swizzled_pointer(new_child_pid)); lsn_t child_emlsn = child.get_foster_emlsn(); W_DO(log_btree_foster_adopt (parent, child, new_child_pid, child_emlsn, new_child_key)); _ux_adopt_foster_apply_parent (parent, new_child_pid, child_emlsn, new_child_key); _ux_adopt_foster_apply_child (child); // Switch parent of newly adopted child // CS TODO: I'm not sure we can do this because we don't hold a latch on new_child_pid smlevel_0::bf->switch_parent(new_child_pid, parent.get_generic_page()); w_assert3(parent.is_consistent(true, true)); w_assert3(child.is_consistent(true, true)); return RCOK; }
/* * replacement for solaris gethrtime(), which is based in any case * on this clock: */ int64_t gethrtime() { struct timespec tsp; long e = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tsp); w_assert0(e == 0); // tsp.tv_sec is time_t return (tsp.tv_sec * 1000* 1000 * 1000) + tsp.tv_nsec; // nanosecs }
ConsolidationArray::~ConsolidationArray() { delete[] _active_slots; // Check all slots are freed for (int i = 0; i < ALL_SLOT_COUNT; ++i) { w_assert0(_all_slots[i].count == SLOT_UNUSED || _all_slots[i].count == SLOT_AVAILABLE); } }
void RestoreBitmap::deserialize(char* buf, size_t from, size_t to) { spinlock_write_critical_section cs(&mutex); w_assert0(from < to); w_assert0(to <= bits.size()); size_t byte = 0, j = 0; for (size_t i = from; i < to; i++) { // set if bit on position j is a one bits[i] = buf[byte] & (1 << j++); // wrap around next byte if (j == 8) { j = 0; byte++; } } }
RestoreMgr::RestoreMgr(const sm_options& options, LogArchiver::ArchiveDirectory* archive, vol_t* volume, bool useBackup, bool takeBackup) : smthread_t(t_regular, "Restore Manager"), archive(archive), volume(volume), numRestoredPages(0), useBackup(useBackup), takeBackup(takeBackup), failureLSN(lsn_t::null), pinCount(0) { w_assert0(archive); w_assert0(volume); instantRestore = options.get_bool_option("sm_restore_instant", true); preemptive = options.get_bool_option("sm_restore_preemptive", false); segmentSize = options.get_int_option("sm_restore_segsize", 1024); if (segmentSize <= 0) { W_FATAL_MSG(fcINTERNAL, << "Restore segment size must be a positive number"); }
w_rc_t table_desc_t::load_stids() { w_assert0(_db); stid_t cat_stid = get_catalog_stid(); W_DO(_primary_idx->load_stid(_db, cat_stid)); for (size_t i = 0; i < _indexes.size(); i++) { W_DO(_indexes[i]->load_stid(_db, cat_stid)); } return RCOK; }
void RestoreBitmap::getBoundaries(size_t& lowestFalse, size_t& highestTrue) { spinlock_read_critical_section cs(&mutex); lowestFalse = 0; highestTrue = 0; bool allTrueSoFar = true; for (size_t i = 0; i < bits.size(); i++) { if (bits[i]) highestTrue = i; if (allTrueSoFar && bits[i]) { lowestFalse = i + 1; } else { allTrueSoFar = false; } } w_assert0(lowestFalse <= bits.size()); w_assert0(highestTrue < bits.size()); }
void checkLSN(lsn_t lsn, lsn_t current, lsn_t expected) { if (current.is_null()) { return; } if(expected != current) { std::cout << "on " << lsn << " current is " << current << " but should be " << expected << std::endl; } w_assert0(expected == current); }
w_rc_t table_desc_t::create_physical_table(ss_m* db) { assert (db); _db = db; W_DO(create_physical_index(db, _primary_idx)); w_assert0(_primary_idx); for (size_t i = 0; i < _indexes.size(); i++) { W_DO(create_physical_index(db, _indexes[i])); } return (RCOK); }
rc_t vol_t::open_backup() { // mutex held by caller -- no concurrent backup being added string backupFile = _backups.back(); // Using direct I/O int open_flags = smthread_t::OPEN_RDONLY | smthread_t::OPEN_SYNC; if (_use_o_direct) { open_flags |= smthread_t::OPEN_DIRECT; } W_DO(me()->open(backupFile.c_str(), open_flags, 0666, _backup_fd)); w_assert0(_backup_fd > 0); _current_backup_lsn = _backup_lsns.back(); return RCOK; }
RestoreScheduler::RestoreScheduler(const sm_options& options, RestoreMgr* restore) : restore(restore) { w_assert0(restore); firstNotRestored = PageID(0); lastUsedPid = restore->getLastUsedPid(); trySinglePass = options.get_bool_option("sm_restore_sched_singlepass", true); onDemand = options.get_bool_option("sm_restore_sched_ondemand", true); if (!onDemand) { // override single-pass option trySinglePass = true; } }
bool RestoreScheduler::next(PageID& next, bool peek) { spinlock_write_critical_section cs(&mutex); next = firstNotRestored; if (onDemand && queue.size() > 0) { next = queue.front(); if (!peek) { queue.pop(); INC_TSTAT(restore_sched_queued); } } else if (trySinglePass) { // if queue is empty, find the first not-yet-restored PID while (next <= lastUsedPid && restore->isRestored(next)) { // if next pid is already restored, then the whole segment is next = next + restore->getSegmentSize(); } if (!peek) { firstNotRestored = next + restore->getSegmentSize(); } if (next > lastUsedPid) { next = 0; } if (!peek) { INC_TSTAT(restore_sched_seq); } } else { w_assert0(onDemand); return false; } /* * CS: there is no guarantee (from the scheduler) that next is indeed not * restored yet, because we do not control the bitmap from here. The only * guarantee is that only one thread will be executing the restore loop (or * that multiple threads will restore disjunct segment sets). In the * current implementation, it turns out that the scheduler is only invoked * from the restore loop, which means that a page returned by the scheduler * is guaranteed to not be restored when is is picked up by the restore * loop, but that may change in the future. */ return true; }
void dumpStats(lsn_t lsn) { // A checkpoint taken with a forward scan does not update rec_lsn // correctly, so it will always be the first update on each page. We // take min_clean_lsn here since it should be a good approximation lsn_t rec_lsn = lsn_t::max; for(buf_tab_t::const_iterator it = chkpt.buf_tab.begin(); it != chkpt.buf_tab.end(); ++it) { if (it->second.clean_lsn != lsn_t::null && it->second.clean_lsn < rec_lsn) { rec_lsn = it->second.clean_lsn; } } if (rec_lsn == lsn_t::max) { rec_lsn = lsn_t::null; } size_t redo_length = 0; if (rec_lsn.hi() == lsn.hi()) { redo_length = lsn.lo() - rec_lsn.lo(); } else if (rec_lsn != lsn_t::null) { w_assert0(lsn > rec_lsn); size_t rest = lsn.lo() + psize - rec_lsn.lo(); redo_length = psize * (lsn.hi() - rec_lsn.hi()) + rest; } ERROUT(<< "min_rec_lsn: " << rec_lsn); size_t dirty_page_count = 0; for (auto e : chkpt.buf_tab) { if (e.second.is_dirty()) { dirty_page_count++; } } out() << "" << dirty_page_count << " " << redo_length / 1048576 << " " << page_writes << " " << commits << " " << updates << endl; page_writes = 0; commits = 0; updates = 0; }
w_rc_t table_desc_t::create_physical_index(ss_m* db, index_desc_t* index) { // Create all the indexes of the table stid_t stid = stid_t::null; W_DO(db->create_index(_vid, stid)); w_assert0(index); index->set_stid(stid); // Add entry on catalog w_keystr_t kstr; kstr.construct_regularkey(index->name().c_str(), index->name().length()); W_DO(db->create_assoc(get_catalog_stid(), kstr, vec_t(&stid, sizeof(stid_t)))); // Print info TRACE( TRACE_STATISTICS, "%s %d (%s) (%s) (%s)\n", index->name().c_str(), stid.store, (index->is_latchless() ? "no latch" : "latch"), (index->is_relaxed() ? "relaxed" : "no relaxed"), (index->is_unique() ? "unique" : "no unique")); return (RCOK); }
// Returns the stid of the primary index. If no primary index exists it // returns the stid of the table stid_t table_desc_t::get_primary_stid() { w_assert0(_primary_idx); return _primary_idx->stid(); }
rc_t btree_impl::_sx_split_foster(btree_page_h& page, PageID& new_page_id, const w_keystr_t& triggering_key) { sys_xct_section_t sxs(true); W_DO(sxs.check_error_on_start()); w_assert1 (page.latch_mode() == LATCH_EX); // DBG(<< "SPLITTING " << page); /* * Step 1: Allocate a new page for the foster child */ W_DO(smlevel_0::vol->alloc_a_page(new_page_id)); /* * Step 2: Create new foster child and move records into it, logging its * raw contents as a page_img_format operation */ btree_page_h new_page; rc_t rc = new_page.fix_nonroot(page, new_page_id, LATCH_EX, false, true); if (rc.is_error()) { W_DO(smlevel_0::vol ->deallocate_page(new_page_id)); return rc; } // assure foster-child page has an entry same as fence-low for locking correctness. // See jira ticket:84 "Key Range Locking" (originally trac ticket:86). // CS TODO - why is this required // There may be a bug, since error happens if we uncomment this // W_DO(_ux_assure_fence_low_entry(new_page)); // this might be another SSX int move_count = 0; w_keystr_t split_key; W_DO(new_page.format_foster_child(page, new_page_id, triggering_key, split_key, move_count)); w_assert0(move_count > 0); // DBG5(<< "NEW FOSTER CHILD " << new_page); /* * Step 3: Delete moved records and update foster child pointer and high * fence on overflowing page. Foster parent is not recompressed after * moving records (CS TODO) */ page.delete_range(page.nrecs() - move_count, page.nrecs()); // DBG5(<< "AFTER RANGE DELETE " << page); w_keystr_t new_chain; new_page.copy_chain_fence_high_key(new_chain); bool foster_set = page.set_foster_child(new_page_id, split_key, new_chain); w_assert0(foster_set); /* * Step 4: Update parent pointers of the moved records. The new foster * child will have the correct parent set by the fix call above. This is * only required because of swizzling. */ // set parent pointer on hash table // smlevel_0::bf->switch_parent(new_page_id, page.get_generic_page()); // set parent pointer for children that moved to new page int max_slot = new_page.max_child_slot(); for (general_recordid_t i = GeneralRecordIds::FOSTER_CHILD; i <= max_slot; ++i) { // CS TODO: Slot 1 (which is actually 0 in the internal page // representation) is not used when inserting into an empty node (see // my comment on btree_page_h.cpp::insert_nonghost), so in *some* // cases, the slot i=1 will yield and invalid page in switch_parent // below. Because of this great design feature, switch_parent has to // cope with an invalid page. smlevel_0::bf->switch_parent(*new_page.child_slot_address(i), new_page.get_generic_page()); } /* * Step 5: Log bulk deletion and foster update on parent */ W_DO(log_btree_split(new_page, page, move_count, split_key, new_chain)); w_assert1(new_page.get_page_lsn() != lsn_t::null); // hint for subsequent accesses increase_forster_child(page.pid()); W_DO (sxs.end_sys_xct (RCOK)); DBG1(<< "Split page " << page.pid() << " into " << new_page_id); return RCOK; }
/********************************************************************* * * chkpt_m::backward_scan_log(lock_heap) * * Scans the log backwards, starting from _lsn until the t_chkpt_begin log record * corresponding to the latest completed checkpoint. * *********************************************************************/ void chkpt_t::scan_log() { init(); lsn_t scan_start = smlevel_0::log->durable_lsn(); if (scan_start == lsn_t(1,0)) { return; } log_i scan(*smlevel_0::log, scan_start, false); // false == backward scan logrec_t r; lsn_t lsn = lsn_t::max; // LSN of the retrieved log record // Set when scan finds begin of previous checkpoint lsn_t scan_stop = lsn_t(1,0); // CS TODO: not needed with file serialization // bool insideChkpt = false; while (lsn > scan_stop && scan.xct_next(lsn, r)) { if (r.is_skip() || r.type() == logrec_t::t_comment) { continue; } if (!r.tid().is_null()) { if (r.tid() > get_highest_tid()) { set_highest_tid(r.tid()); } if (r.is_page_update() || r.is_cpsn()) { mark_xct_active(r.tid(), lsn, lsn); if (is_xct_active(r.tid())) { if (!r.is_cpsn()) { acquire_lock(r); } } else if (r.xid_prev().is_null()) { // We won't see this xct again -- delete it delete_xct(r.tid()); } } } if (r.is_page_update()) { w_assert0(r.is_redo()); mark_page_dirty(r.pid(), lsn, lsn); if (r.is_multi_page()) { w_assert0(r.pid2() != 0); mark_page_dirty(r.pid2(), lsn, lsn); } } switch (r.type()) { case logrec_t::t_chkpt_begin: // CS TODO: not needed with file serialization // if (insideChkpt) { // // Signal to stop backward log scan loop now // scan_stop = lsn; // } { fs::path fpath = smlevel_0::log->get_storage()->make_chkpt_path(lsn); if (fs::exists(fpath)) { ifstream ifs(fpath.string(), ios::binary); deserialize_binary(ifs); ifs.close(); scan_stop = lsn; } } break; case logrec_t::t_chkpt_bf_tab: // CS TODO: not needed with file serialization // if (insideChkpt) { // const chkpt_bf_tab_t* dp = (chkpt_bf_tab_t*) r.data(); // for (uint i = 0; i < dp->count; i++) { // mark_page_dirty(dp->brec[i].pid, dp->brec[i].page_lsn, // dp->brec[i].rec_lsn); // } // } break; case logrec_t::t_chkpt_xct_lock: // CS TODO: not needed with file serialization // if (insideChkpt) { // const chkpt_xct_lock_t* dp = (chkpt_xct_lock_t*) r.data(); // if (is_xct_active(dp->tid)) { // for (uint i = 0; i < dp->count; i++) { // add_lock(dp->tid, dp->xrec[i].lock_mode, // dp->xrec[i].lock_hash); // } // } // } break; case logrec_t::t_chkpt_xct_tab: // CS TODO: not needed with file serialization // if (insideChkpt) { // const chkpt_xct_tab_t* dp = (chkpt_xct_tab_t*) r.data(); // for (size_t i = 0; i < dp->count; ++i) { // tid_t tid = dp->xrec[i].tid; // w_assert1(!tid.is_null()); // mark_xct_active(tid, dp->xrec[i].first_lsn, // dp->xrec[i].last_lsn); // } // } break; // CS TODO: not needed with file serialization // case logrec_t::t_chkpt_end: // checkpoints should not run concurrently // w_assert0(!insideChkpt); // insideChkpt = true; break; // CS TODO: why do we need this? Isn't it related to 2PC? // case logrec_t::t_xct_freeing_space: case logrec_t::t_xct_end: case logrec_t::t_xct_abort: mark_xct_ended(r.tid()); break; case logrec_t::t_xct_end_group: { // CS TODO: is this type of group commit still used? w_assert0(false); const xct_list_t* list = (xct_list_t*) r.data(); uint listlen = list->count; for(uint i=0; i<listlen; i++) { tid_t tid = list->xrec[i].tid; mark_xct_ended(tid); } } break; case logrec_t::t_page_write: { char* pos = r.data(); PageID pid = *((PageID*) pos); pos += sizeof(PageID); lsn_t clean_lsn = *((lsn_t*) pos); pos += sizeof(lsn_t); uint32_t count = *((uint32_t*) pos); PageID end = pid + count; while (pid < end) { mark_page_clean(pid, clean_lsn); pid++; } } break; case logrec_t::t_add_backup: { const char* dev = (const char*)(r.data_ssx()); add_backup(dev); } break; case logrec_t::t_chkpt_backup_tab: // CS TODO break; case logrec_t::t_restore_begin: case logrec_t::t_restore_end: case logrec_t::t_restore_segment: case logrec_t::t_chkpt_restore_tab: // CS TODO - IMPLEMENT! break; default: break; } //switch } //while w_assert0(lsn == scan_stop); cleanup(); }
void assert_failed(const char *desc, const char *f, int l) { fprintf(stdout, "Assertion failed: %s at line %d file %s ", desc, l,f); w_assert0(0); }
void chkpt_t::acquire_lock(logrec_t& r) { w_assert1(is_xct_active(r.tid())); w_assert1(!r.is_single_sys_xct()); w_assert1(!r.is_multi_page()); w_assert1(!r.is_cpsn()); w_assert1(r.is_page_update()); switch (r.type()) { case logrec_t::t_btree_insert: case logrec_t::t_btree_insert_nonghost: { btree_insert_t* dp = (btree_insert_t*) r.data(); w_keystr_t key; key.construct_from_keystr(dp->data, dp->klen); okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key); lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(), key.get_length_as_keystr()); add_lock(r.tid(), mode, lid.hash()); } break; case logrec_t::t_btree_update: { btree_update_t* dp = (btree_update_t*) r.data(); w_keystr_t key; key.construct_from_keystr(dp->_data, dp->_klen); okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key); lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(), key.get_length_as_keystr()); add_lock(r.tid(), mode, lid.hash()); } break; case logrec_t::t_btree_overwrite: { btree_overwrite_t* dp = (btree_overwrite_t*) r.data(); w_keystr_t key; key.construct_from_keystr(dp->_data, dp->_klen); okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key); lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(), key.get_length_as_keystr()); add_lock(r.tid(), mode, lid.hash()); } break; case logrec_t::t_btree_ghost_mark: { btree_ghost_t* dp = (btree_ghost_t*) r.data(); for (size_t i = 0; i < dp->cnt; ++i) { w_keystr_t key (dp->get_key(i)); okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key); lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(), key.get_length_as_keystr()); add_lock(r.tid(), mode, lid.hash()); } } break; case logrec_t::t_btree_ghost_reserve: { btree_ghost_reserve_t* dp = (btree_ghost_reserve_t*) r.data(); w_keystr_t key; key.construct_from_keystr(dp->data, dp->klen); okvl_mode mode = btree_impl::create_part_okvl(okvl_mode::X, key); lockid_t lid (r.stid(), (const unsigned char*) key.buffer_as_keystr(), key.get_length_as_keystr()); add_lock(r.tid(), mode, lid.hash()); } break; default: w_assert0(r.type() == logrec_t::t_page_img_format); break; } return; }