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; }
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); }
void lil_global_table_base::release_locks(bool *lock_taken, bool read_lock_only, lsn_t commit_lsn) { bool broadcast = false; { tataslock_critical_section cs (&_spin_lock); // CRITICAL_SECTION(cs, _spin_lock); ++_release_version; // to let waiting threads that something really happened if (lock_taken[LIL_IS]) { w_assert1(_IS_count > 0); --_IS_count; if (_IS_count == 0 && _waiting_X != 0) { broadcast = true; } } if (lock_taken[LIL_IX] && !read_lock_only) { w_assert1(_IX_count > 0); --_IX_count; if (_IX_count == 0 && (_waiting_S != 0 || _waiting_X != 0)) { broadcast = true; } } if (lock_taken[LIL_S]) { w_assert1(_S_count > 0); --_S_count; broadcast = true; } if (lock_taken[LIL_X] && !read_lock_only) { w_assert1(_X_taken); _X_taken = false; broadcast = true; // only when we release X lock, we update the tag for safe SX-ELR. // IX doesn't matter because the lower level will do the job. if (commit_lsn.valid() && commit_lsn > _x_lock_tag) { DBGOUT1(<<"LIL: tag for Safe SX-ELR updated to " << commit_lsn); _x_lock_tag = commit_lsn; } }
rc_t log_core::fetch(lsn_t& ll, void* buf, lsn_t* nxt, const bool forward) { INC_TSTAT(log_fetches); lintel::atomic_thread_fence(lintel::memory_order_acquire); if (ll < _fetch_buf_end && ll >= _fetch_buf_begin) { // log record can be found in fetch buffer -- no I/O size_t i = ll.hi() - _fetch_buf_first; if (_fetch_buffers[i]) { logrec_t* rp = (logrec_t*) (_fetch_buffers[i] + ll.lo()); w_assert1(rp->valid_header(ll)); if (rp->type() == logrec_t::t_skip) { if (forward) { ll = lsn_t(ll.hi() + 1, 0); return fetch(ll, buf, nxt, forward); } else { // backward scan ll = *((lsn_t*) (_fetch_buffers[i] + ll.lo() - sizeof(lsn_t))); } rp = (logrec_t*) (_fetch_buffers[i] + ll.lo()); w_assert1(rp->valid_header(ll)); } if (nxt) { if (!forward && ll.lo() == 0) { auto p = _storage->get_partition(ll.hi() - 1); *nxt = p ? lsn_t(p->num(), p->get_size()) : lsn_t::null; } else { if (forward) { *nxt = ll; nxt->advance(rp->length()); } else { memcpy(nxt, (char*) rp - sizeof(lsn_t), sizeof(lsn_t)); } } } memcpy(buf, rp, rp->length()); INC_TSTAT(log_buffer_hit); return RCOK; } } if (forward && ll >= durable_lsn()) { w_assert1(ll == durable_lsn()); // reading the durable_lsn during recovery yields a skip log record, return RC(eEOF); } if (!forward && ll == lsn_t::null) { // for a backward scan, nxt pointer is set to null // when the first log record in the first partition is set return RC(eEOF); } auto p = _storage->get_partition(ll.hi()); if(!p) { return RC(eEOF); } W_DO(p->open_for_read()); logrec_t* rp; lsn_t prev_lsn = lsn_t::null; DBGOUT3(<< "fetch @ lsn: " << ll); W_COERCE(p->read(rp, ll, forward ? nullptr : &prev_lsn)); w_assert1(rp->valid_header(ll)); // handle skip log record if (rp->type() == logrec_t::t_skip) { p->release_read(); if (forward) { DBGTHRD(<<"seeked to skip" << ll ); DBGTHRD(<<"getting next partition."); ll = lsn_t(ll.hi() + 1, 0); p = _storage->get_partition(ll.hi()); if(!p) { return RC(eEOF); } // re-read DBGOUT3(<< "fetch @ lsn: " << ll); W_DO(p->open_for_read()); W_COERCE(p->read(rp, ll)); w_assert1(rp->valid_header(ll)); } else { // backward scan
// to use in gdb void print_lsn(lsn_t lsn) { std::cout << lsn.file() << "." << lsn.rba() << std::endl; }