Exemplo n.º 1
0
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++;
}
Exemplo n.º 2
0
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);
    }
}
Exemplo n.º 3
0
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++;
        }
    }
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
    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++;
        }
    }
Exemplo n.º 7
0
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;
        }
    }
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
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);
}
Exemplo n.º 10
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;
}
Exemplo n.º 11
0
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;
}
Exemplo n.º 12
0
/*
 * 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
}
Exemplo n.º 13
0
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);
    }
}
Exemplo n.º 14
0
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++;
        }
    }
}
Exemplo n.º 15
0
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");
    }
Exemplo n.º 16
0
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;
}
Exemplo n.º 17
0
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());
}
Exemplo n.º 18
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);
}
Exemplo n.º 19
0
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);
}
Exemplo n.º 20
0
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;
}
Exemplo n.º 21
0
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;
    }
}
Exemplo n.º 22
0
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;
}
Exemplo n.º 23
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;
    }
Exemplo n.º 24
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);
}
Exemplo n.º 25
0
// 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();
}
Exemplo n.º 26
0
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;
}
Exemplo n.º 27
0
/*********************************************************************
*
*  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();
}
Exemplo n.º 28
0
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);
}
Exemplo n.º 29
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;
}