void Journallable::apply_restored(const Operation &op) { TRACEPX(PCOMN_Journal, DBGL_MIDLEV, "Applying restored " << op << " to " << *this) ; NOXCHECK(state() == ST_RESTORING) ; NOXCHECK(is_op_compatible(op)) ; try { // Needn't lock, needn't store op.apply(*this) ; atomic_op::preinc(&_changecnt) ; } catch (const std::runtime_error &x) { // We may choose to ignore an exception: when an operation is being stored into // the journal, it is written _before_ applying; so, although do_lock_target // (which is called _before_ storing the operation) can check whether the // operation is applicable, such check may be noncomprehensive, e.g. due to // performance/locking issues. As a result, the operation may fail after having // been saved (though leaving the Journallable in consistent state). // Such operation will also inevitably fail while being restored but failure may // (and should!) be ignored. if (!op.is_ignorable_exception(x)) { LOGPXERR(PCOMN_Journal, "Non-ignorable exception restoring " << op << " to " << *this << ": " << STDEXCEPTOUT(x)) ; throw ; } LOGINFO("Ignorable exception restoring " << op << " to " << *this << ": " << STDEXCEPTOUT(x)) ; } TRACEPX(PCOMN_Journal, DBGL_MIDLEV, "OK applied restored " << op) ; }
void apply(int number, char op) { Operation newOperation(number, op); int i = opStack.size() - 1; while (i >= 0) { Operation next = opStack[i--]; if (Operators::rank(next.op) >= Operators::rank(op)) { newOperation.number = next.apply(newOperation.number); opStack.pop_back(); } else { break; } } opStack.push_back(newOperation); }
void Journallable::apply_created(const Operation &op) { TRACEPX(PCOMN_Journal, DBGL_MIDLEV, "Applying new " << op << " to " << *this) ; NOXCHECK((pcomn::one_of<ST_RESTORED, ST_ACTIVE, ST_CHECKPOINT>::is(state()))) ; NOXCHECK(is_op_compatible(op)) ; op.lock_target(*this, true) ; try { if (state() != ST_RESTORED) { TRACEPX(PCOMN_Journal, DBGL_LOWLEV, "Storing " << op << " to " << *unlocked_journal()) ; unlocked_journal()->store_operation(op) ; } TRACEPX(PCOMN_Journal, DBGL_VERBOSE, "Actually applying " << op) ; op.apply(*this) ; atomic_op::preinc(&_changecnt) ; } catch (const std::exception &x) { LOGPXERR_CALL(PCOMN_FAIL, PCOMN_Journal, STDEXCEPTOUT(x) << "\nwhile applying " << op << "\nto " << *unlocked_journal() << ".\nThe operation is NOT applied") ; return ; } catch (...) { LOGPXERR_CALL(PCOMN_FAIL, PCOMN_Journal, "Unknown exception while applying " << op << "\nto " << *unlocked_journal() << ".\nThe operation is NOT applied") ; return ; } op.lock_target(*this, false) ; TRACEPX(PCOMN_Journal, DBGL_MIDLEV, "OK applied new " << op) ; }