예제 #1
0
    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;
    }
예제 #2
0
파일: verifylog.cpp 프로젝트: iMax3060/zero
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);
}
예제 #3
0
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;
            }
        }
예제 #4
0
파일: log_core.cpp 프로젝트: iMax3060/zero
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
예제 #5
0
파일: lsn.cpp 프로젝트: iMax3060/zero
// to use in gdb
void print_lsn(lsn_t lsn)
{
    std::cout << lsn.file() << "." << lsn.rba() << std::endl;
}