00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 #ifndef XCT_H
00054 #define XCT_H
00055
00056 #include "w_defines.h"
00057
00058
00059
00060 #ifdef __GNUG__
00061 #pragma interface
00062 #endif
00063
00064 #if W_DEBUG_LEVEL > 4
00065
00066
00067
00068
00069 #define X_LOG_COMMENT_ON 1
00070 #define ADD_LOG_COMMENT_SIG ,const char *debugmsg
00071 #define ADD_LOG_COMMENT_USE ,debugmsg
00072 #define LOG_COMMENT_USE(x) ,x
00073
00074 #else
00075
00076 #define X_LOG_COMMENT_ON 0
00077 #define ADD_LOG_COMMENT_SIG
00078 #define ADD_LOG_COMMENT_USE
00079 #define LOG_COMMENT_USE(x)
00080 #endif
00081
00082 class xct_dependent_t;
00083
00084
00085
00086
00087
00088
00089
00090 class xct_log_t : public smlevel_1 {
00091 private:
00092
00093 bool _xct_log_off;
00094 public:
00095 NORET xct_log_t(): _xct_log_off(false) {};
00096 bool xct_log_is_off() { return _xct_log_off; }
00097 void set_xct_log_off() { _xct_log_off = true; }
00098 void set_xct_log_on() { _xct_log_off = false; }
00099 };
00100
00101
00102 class lockid_t;
00103 class sdesc_cache_t;
00104 class xct_i;
00105 class restart_m;
00106 class lock_m;
00107 class lock_core_m;
00108 class lock_request_t;
00109 class xct_log_switch_t;
00110 class xct_lock_info_t;
00111 class xct_prepare_alk_log;
00112 class xct_prepare_fi_log;
00113 class xct_prepare_lk_log;
00114 class sm_quark_t;
00115 class smthread_t;
00116
00117 class logrec_t;
00118 class page_p;
00119
00120
00121
00122
00123
00124
00125 class stid_list_elem_t {
00126 public:
00127 stid_t stid;
00128 w_link_t _link;
00129
00130 stid_list_elem_t(const stid_t& theStid)
00131 : stid(theStid)
00132 {};
00133 ~stid_list_elem_t()
00134 {
00135 if (_link.member_of() != NULL)
00136 _link.detach();
00137 }
00138 static w_base_t::uint4_t link_offset()
00139 {
00140 return W_LIST_ARG(stid_list_elem_t, _link);
00141 }
00142 };
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154 class xct_t : public smlevel_1 {
00155
00156 #if USE_BLOCK_ALLOC_FOR_LOGREC
00157 friend class block_alloc<xct_t>;
00158 #endif
00159 friend class xct_i;
00160 friend class smthread_t;
00161 friend class restart_m;
00162 friend class lock_m;
00163 friend class lock_core_m;
00164 friend class lock_request_t;
00165 friend class xct_log_switch_t;
00166 friend class xct_prepare_alk_log;
00167 friend class xct_prepare_fi_log;
00168 friend class xct_prepare_lk_log;
00169 friend class sm_quark_t;
00170
00171 protected:
00172 enum commit_t { t_normal = 0, t_lazy = 1, t_chain = 2 };
00173
00174
00175
00176 public:
00177 typedef xct_state_t state_t;
00178
00179 static
00180 xct_t* new_xct(
00181 sm_stats_info_t* stats = 0,
00182 timeout_in_ms timeout = WAIT_SPECIFIED_BY_THREAD);
00183
00184 static
00185 xct_t* new_xct(
00186 const tid_t& tid,
00187 state_t s,
00188 const lsn_t& last_lsn,
00189 const lsn_t& undo_nxt,
00190 timeout_in_ms timeout = WAIT_SPECIFIED_BY_THREAD);
00191 static
00192 void destroy_xct(xct_t* xd);
00193
00194 private:
00195 struct xct_core;
00196 NORET xct_t(
00197 xct_core* core,
00198 sm_stats_info_t* stats,
00199 const lsn_t& last_lsn,
00200 const lsn_t& undo_nxt);
00201 NORET ~xct_t();
00202
00203 public:
00204
00205 friend ostream& operator<<(ostream&, const xct_t&);
00206
00207 static int collect(vtable_t&, bool names_too);
00208 void vtable_collect(vtable_row_t &);
00209 static void vtable_collect_names(vtable_row_t &);
00210
00211 state_t state() const;
00212 void set_timeout(timeout_in_ms t) ;
00213
00214 timeout_in_ms timeout_c() const;
00215
00216
00217
00218
00219 public:
00220 void force_readonly();
00221 bool forced_readonly() const;
00222
00223 vote_t vote() const;
00224 bool is_extern2pc() const;
00225 rc_t enter2pc(const gtid_t &g);
00226 const gtid_t* gtid() const;
00227 const server_handle_t& get_coordinator()const;
00228 void set_coordinator(const server_handle_t &);
00229 static rc_t recover2pc(const gtid_t &g,
00230 bool mayblock, xct_t *&);
00231 static rc_t query_prepared(int &numtids);
00232 static rc_t query_prepared(int numtids, gtid_t l[]);
00233
00234 rc_t prepare();
00235 rc_t log_prepared(bool in_chkpt=false);
00236
00237
00238
00239
00240 public:
00241 static void dump(ostream &o);
00242 static int cleanup(bool dispose_prepared=false);
00243
00244
00245
00246 bool is_instrumented() {
00247 return (__stats != 0);
00248 }
00249 void give_stats(sm_stats_info_t* s) {
00250 w_assert1(__stats == 0);
00251 __stats = s;
00252 }
00253 void clear_stats() {
00254 memset(__stats,0, sizeof(*__stats));
00255 }
00256 sm_stats_info_t* steal_stats() {
00257 sm_stats_info_t*s = __stats;
00258 __stats = 0;
00259 return s;
00260 }
00261 const sm_stats_info_t& const_stats_ref() { return *__stats; }
00262 rc_t commit(bool lazy = false, lsn_t* plastlsn=NULL);
00263 rc_t rollback(const lsn_t &save_pt);
00264 rc_t save_point(lsn_t& lsn);
00265 rc_t chain(bool lazy = false);
00266 rc_t abort(bool save_stats = false);
00267
00268
00269 protected:
00270 sm_stats_info_t& stats_ref() { return *__stats; }
00271 rc_t dispose();
00272 void change_state(state_t new_state);
00273 void set_first_lsn(const lsn_t &) ;
00274 void set_last_lsn(const lsn_t &) ;
00275 void set_undo_nxt(const lsn_t &) ;
00276 void prepare_restore_log_resv(int, int, int, int);
00277
00278
00279 public:
00280
00281
00282 const lsn_t& last_lsn() const;
00283 const lsn_t& first_lsn() const;
00284 const lsn_t& undo_nxt() const;
00285 const logrec_t* last_log() const;
00286 fileoff_t get_log_space_used() const;
00287 rc_t wait_for_log_space(fileoff_t amt);
00288
00289
00290 static xct_t* look_up(const tid_t& tid);
00291 static tid_t oldest_tid();
00292 static tid_t youngest_tid();
00293
00294 static void update_youngest_tid(const tid_t &);
00295
00296
00297
00298 static w_base_t::uint4_t num_active_xcts();
00299
00300
00301
00302 const lsn_t& anchor(bool grabit = true);
00303 void release_anchor(bool compensate
00304 ADD_LOG_COMMENT_SIG
00305 );
00306 int compensated_op_depth() const ;
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 void start_crit() { (void) anchor(false); }
00320
00321
00322
00323
00324
00325 void stop_crit() {(void) release_anchor(false
00326 LOG_COMMENT_USE( "stopcrit"));}
00327
00328
00329 void compensate(const lsn_t&,
00330 bool undoable
00331 ADD_LOG_COMMENT_SIG
00332 );
00333
00334 void compensate_undo(const lsn_t&);
00335
00336
00337
00338
00339
00340
00341
00342 void log_warn_disable();
00343 void log_warn_resume();
00344 bool log_warn_is_on() const;
00345
00346
00347
00348 public:
00349
00350 rc_t add_dependent(xct_dependent_t* dependent);
00351 rc_t remove_dependent(xct_dependent_t* dependent);
00352 bool find_dependent(xct_dependent_t* dependent);
00353
00354
00355
00356
00357 bool is_log_on() const;
00358 rc_t get_logbuf(logrec_t*&, const page_p *p = 0);
00359 rc_t give_logbuf(logrec_t*, const page_p *p = 0);
00360
00361
00362
00363
00364 void AddStoreToFree(const stid_t& stid);
00365 void AddLoadStore(const stid_t& stid);
00366
00367 void set_alloced() { }
00368
00369 void num_extents_marked_for_deletion(
00370 base_stat_t &num);
00371 public:
00372
00373 void GetEscalationThresholds(
00374 w_base_t::int4_t &toPage,
00375 w_base_t::int4_t &toStore,
00376 w_base_t::int4_t &toVolume);
00377 void SetEscalationThresholds(
00378 w_base_t::int4_t toPage,
00379 w_base_t::int4_t toStore,
00380 w_base_t::int4_t toVolume);
00381 bool set_lock_cache_enable(bool enable);
00382 bool lock_cache_enabled();
00383
00384 protected:
00385
00386
00387
00388
00389 static lockid_t* new_lock_hierarchy();
00390 static sdesc_cache_t* new_sdesc_cache_t();
00391 static xct_log_t* new_xct_log_t();
00392 void steal(lockid_t*&, sdesc_cache_t*&, xct_log_t*&);
00393 void stash(lockid_t*&, sdesc_cache_t*&, xct_log_t*&);
00394
00395 void attach_thread();
00396 void detach_thread();
00397
00398
00399
00400 lockid_t* lock_info_hierarchy() const {
00401 return me()->lock_hierarchy();
00402 }
00403 public:
00404
00405 sdesc_cache_t* sdesc_cache() const;
00406
00407 protected:
00408
00409
00410 switch_t set_log_state(switch_t s);
00411
00412 void restore_log_state(switch_t s);
00413
00414
00415 public:
00416 concurrency_t get_lock_level();
00417 void lock_level(concurrency_t l);
00418
00419 int num_threads();
00420 rc_t check_one_thread_attached() const;
00421 void attach_update_thread();
00422 void detach_update_thread();
00423 int update_threads() const;
00424
00425 protected:
00426
00427 w_rc_t lockblock(timeout_in_ms timeout);
00428 void lockunblock();
00429 const w_base_t::int4_t* GetEscalationThresholdsArray();
00430
00431 rc_t check_lock_totals(int nex,
00432 int nix, int nsix, int ) const;
00433 rc_t obtain_locks(lock_mode_t mode,
00434 int nlks, const lockid_t *l);
00435 rc_t obtain_one_lock(lock_mode_t mode,
00436 const lockid_t &l);
00437
00438 xct_lock_info_t* lock_info() const;
00439
00440 public:
00441
00442
00443
00444 static w_rc_t acquire_xlist_mutex();
00445 static void release_xlist_mutex();
00446 static void assert_xlist_mutex_not_mine();
00447 static void assert_xlist_mutex_is_mine();
00448 static bool xlist_mutex_is_mine();
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463 void force_nonblocking();
00464
00465
00466
00467
00468
00469 protected:
00470
00471 w_link_t _xlink;
00472 static w_descend_list_t<xct_t, queue_based_lock_t, tid_t> _xlist;
00473 void put_in_order();
00474 private:
00475 static queue_based_lock_t _xlist_mutex;
00476
00477 sm_stats_info_t* __stats;
00478 lockid_t* __saved_lockid_t;
00479 sdesc_cache_t* __saved_sdesc_cache_t;
00480 xct_log_t* __saved_xct_log_t;
00481
00482 static tid_t _nxt_tid;
00483
00484 static tid_t _oldest_tid;
00485
00486
00487
00488 tid_t _tid;
00489
00490 public:
00491 void acquire_1thread_xct_mutex() const;
00492 void release_1thread_xct_mutex() const;
00493 bool is_1thread_log_mutex_mine() const;
00494
00495
00496 private:
00497 void acquire_1thread_log_mutex();
00498 void release_1thread_log_mutex();
00499 void assert_1thread_log_mutex_free()const;
00500 private:
00501 bool is_1thread_xct_mutex_mine() const;
00502 void assert_1thread_xct_mutex_free()const;
00503
00504 rc_t _abort();
00505 rc_t _commit(w_base_t::uint4_t flags,
00506 lsn_t* plastlsn=NULL);
00507
00508 protected:
00509
00510 switch_t set_log_state(switch_t s, bool &nested);
00511 void restore_log_state(switch_t s, bool nested);
00512
00513 private:
00514 bool one_thread_attached() const;
00515
00516 void _compensate(const lsn_t&, bool undoable = false);
00517
00518 w_base_t::int4_t escalationThresholds[lockid_t::NUMLEVELS-1];
00519 public:
00520 void SetDefaultEscalationThresholds();
00521
00522 void ClearAllStoresToFree();
00523 void FreeAllStoresToFree();
00524 rc_t PrepareLogAllStoresToFree();
00525 void DumpStoresToFree();
00526 rc_t ConvertAllLoadStoresToRegularStores();
00527 void ClearAllLoadStores();
00528
00529 ostream & dump_locks(ostream &) const;
00530
00531
00532 private:
00533
00534
00535
00536
00537
00538 static void xct_stats(
00539 u_long& begins,
00540 u_long& commits,
00541 u_long& aborts,
00542 bool reset);
00543
00544 w_rc_t _flush_logbuf();
00545 w_rc_t _sync_logbuf(bool block=true);
00546 void _teardown(bool is_chaining);
00547
00548 private:
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560 struct xct_core
00561 {
00562 xct_core(tid_t const &t, state_t s, timeout_in_ms timeout);
00563 ~xct_core();
00564
00565
00566 tid_t _tid;
00567 timeout_in_ms _timeout;
00568 bool _warn_on;
00569 xct_lock_info_t* _lock_info;
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 bool _lock_cache_enable;
00580
00581
00582
00583
00584 queue_based_lock_t _1thread_xct;
00585
00586
00587
00588 volatile int _updating_operations;
00589
00590
00591 volatile int _threads_attached;
00592
00593
00594 pthread_cond_t _waiters_cond;
00595 mutable pthread_mutex_t _waiters_mutex;
00596
00597 state_t _state;
00598 bool _forced_readonly;
00599 vote_t _vote;
00600 gtid_t * _global_tid;
00601 server_handle_t* _coord_handle;
00602 bool _read_only;
00603
00604
00605
00606
00607
00608 w_list_t<stid_list_elem_t,queue_based_lock_t> _storesToFree;
00609
00610
00611
00612
00613
00614 w_list_t<stid_list_elem_t,queue_based_lock_t> _loadStores;
00615
00616 volatile int _xct_ended;
00617 };
00618
00619 private:
00620
00621
00622
00623
00624
00625
00626 mutable queue_based_lock_t _1thread_log;
00627
00628 lsn_t _first_lsn;
00629 lsn_t _last_lsn;
00630 lsn_t _undo_nxt;
00631
00632
00633
00634 w_list_t<xct_dependent_t,queue_based_lock_t> _dependent_list;
00635
00636
00637
00638
00639 static lockid_t::name_space_t convert(concurrency_t cc);
00640 static concurrency_t convert(lockid_t::name_space_t n);
00641
00642
00643
00644
00645 logrec_t* _last_log;
00646 logrec_t* _log_buf;
00647
00648
00649
00650
00651 fileoff_t _log_bytes_rsvd;
00652 fileoff_t _log_bytes_ready;
00653 fileoff_t _log_bytes_used;
00654 fileoff_t _log_bytes_reserved_space;
00655
00656 bool _rolling_back;
00657
00658
00659
00660 #if CHECK_NESTING_VARIABLES
00661
00662 volatile int _acquire_1thread_log_depth;
00663 public:
00664 void inc_acquire_1thread_log_depth() { _acquire_1thread_log_depth ++; }
00665 void dec_acquire_1thread_log_depth() { -- _acquire_1thread_log_depth; }
00666 int acquire_1thread_log_depth() const { return
00667 _acquire_1thread_log_depth; }
00668 #else
00669 public:
00670 void inc_acquire_1thread_log_depth() { }
00671 void dec_acquire_1thread_log_depth() { }
00672 int acquire_1thread_log_depth() const { return 0; }
00673 #endif
00674 private:
00675
00676 volatile int _in_compensated_op;
00677
00678
00679 lsn_t _anchor;
00680
00681
00682 xct_core* _core;
00683
00684 public:
00685 tid_t tid() const {
00686 w_assert1(_tid == _core->_tid);
00687 return _tid; }
00688 };
00689
00690
00691 class auto_release_anchor_t {
00692 private:
00693 xct_t* _xd;
00694 lsn_t _anchor;
00695 bool _and_compensate;
00696 int _line;
00697
00698 operator lsn_t const&() const { return _anchor; }
00699 public:
00700
00701 auto_release_anchor_t(bool and_compensate, int line)
00702 : _xd(xct()), _and_compensate(and_compensate), _line(line)
00703 {
00704 if(_xd)
00705 _anchor = _xd->anchor(_and_compensate);
00706 }
00707 void compensate() {
00708 if(_xd)
00709 _xd->compensate(_anchor, false
00710 LOG_COMMENT_USE("auto_release_anchor_t")
00711 );
00712 _xd = 0;
00713 }
00714 ~auto_release_anchor_t();
00715 };
00716
00717
00718
00719
00720
00721 #if X_LOG_COMMENT_ON
00722 #define X_DO1(x,anchor,line) \
00723 { \
00724 w_rc_t __e = (x); \
00725 if (__e.is_error()) { \
00726 w_assert3(xct()); \
00727 W_COERCE(xct()->rollback(anchor)); \
00728 xct()->release_anchor(true, line ); \
00729 return RC_AUGMENT(__e); \
00730 } \
00731 }
00732 #define to_string(x) # x
00733 #define X_DO(x,anchor) X_DO1(x,anchor, to_string(x))
00734
00735 #else
00736
00737 #define X_DO(x,anchor) \
00738 { \
00739 w_rc_t __e = (x); \
00740 if (__e.is_error()) { \
00741 w_assert3(xct()); \
00742 W_COERCE(xct()->rollback(anchor)); \
00743 xct()->release_anchor(true); \
00744 return RC_AUGMENT(__e); \
00745 } \
00746 }
00747 #endif
00748
00749
00750 class xct_log_switch_t : public smlevel_0 {
00751
00752
00753
00754
00755
00756
00757
00758 switch_t old_state;
00759 public:
00760
00761 NORET xct_log_switch_t(switch_t s) : old_state(OFF)
00762 {
00763 if(smlevel_1::log) {
00764 INC_TSTAT(log_switches);
00765 if (xct()) {
00766 old_state = xct()->set_log_state(s);
00767 }
00768 }
00769 }
00770
00771 NORET
00772 ~xct_log_switch_t() {
00773 if(smlevel_1::log) {
00774 if (xct()) {
00775 xct()->restore_log_state(old_state);
00776 }
00777 }
00778 }
00779 };
00780
00781 inline
00782 bool xct_t::is_log_on() const {
00783 return (me()->xct_log()->xct_log_is_off() == false);
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 class xct_i {
00798 public:
00799
00800
00801
00802
00803
00804
00805
00806 bool locked_by_me() const {
00807 if(xct_t::xlist_mutex_is_mine()) {
00808 W_IFDEBUG1(if(_may_check) w_assert1(_locked);)
00809 return true;
00810 }
00811 return false;
00812 }
00813
00814
00815 void never_mind() {
00816
00817
00818 if(_locked && locked_by_me()) {
00819 *(const_cast<bool *>(&_locked)) = false;
00820 xct_t::release_xlist_mutex();
00821 }
00822 }
00823
00824 xct_t* curr() const { return unsafe_iterator.curr(); }
00825
00826 xct_t* next() { return unsafe_iterator.next(); }
00827
00828
00829
00830 static bool init_locked(bool lockit)
00831 {
00832 if(lockit) {
00833 W_COERCE(xct_t::acquire_xlist_mutex());
00834 }
00835 return lockit;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844
00845 NORET xct_i(bool locked_accesses)
00846 : _locked(init_locked(locked_accesses)),
00847 _may_check(locked_accesses),
00848 unsafe_iterator(xct_t::_xlist)
00849 {
00850 w_assert1(_locked == locked_accesses);
00851 _check(_locked);
00852 }
00853
00854
00855 NORET ~xct_i() {
00856 if(locked_by_me()) {
00857 _check(true);
00858 never_mind();
00859 _check(false);
00860 }
00861 }
00862
00863 private:
00864 void _check(bool b) const {
00865 if(!_may_check) return;
00866 if(b) xct_t::assert_xlist_mutex_is_mine();
00867 else xct_t::assert_xlist_mutex_not_mine();
00868 }
00869
00870 const bool _locked;
00871 const bool _may_check;
00872 w_list_i<xct_t,queue_based_lock_t> unsafe_iterator;
00873
00874
00875 xct_i(const xct_i&);
00876 xct_i& operator=(const xct_i&);
00877 };
00878
00879
00880
00881
00882
00883
00884 class xct_auto_abort_t : public smlevel_1 {
00885 public:
00886 xct_auto_abort_t() : _xct(xct_t::new_xct()) {}
00887 ~xct_auto_abort_t() {
00888 switch(_xct->state()) {
00889 case smlevel_1::xct_ended:
00890
00891 break;
00892 case smlevel_1::xct_active:
00893 W_COERCE(_xct->abort());
00894 break;
00895 default:
00896 W_FATAL(eINTERNAL);
00897 }
00898 xct_t::destroy_xct(_xct);
00899 }
00900 rc_t commit() {
00901
00902
00903 W_DO(_xct->commit());
00904 return RCOK;
00905 }
00906 rc_t abort() {W_DO(_xct->abort()); return RCOK;}
00907
00908 private:
00909 xct_t* _xct;
00910 };
00911
00912 inline
00913 xct_t::state_t
00914 xct_t::state() const
00915 {
00916 return _core->_state;
00917 }
00918
00919
00920 inline
00921 bool
00922 operator>(const xct_t& x1, const xct_t& x2)
00923 {
00924 return (x1.tid() > x2.tid());
00925 }
00926
00927 inline void
00928 xct_t::SetEscalationThresholds(w_base_t::int4_t toPage,
00929 w_base_t::int4_t toStore,
00930 w_base_t::int4_t toVolume)
00931 {
00932 if (toPage != dontModifyThreshold)
00933 escalationThresholds[2] = toPage;
00934
00935 if (toStore != dontModifyThreshold)
00936 escalationThresholds[1] = toStore;
00937
00938 if (toVolume != dontModifyThreshold)
00939 escalationThresholds[0] = toVolume;
00940 }
00941
00942 inline void
00943 xct_t::SetDefaultEscalationThresholds()
00944 {
00945 SetEscalationThresholds(smlevel_0::defaultLockEscalateToPageThreshold,
00946 smlevel_0::defaultLockEscalateToStoreThreshold,
00947 smlevel_0::defaultLockEscalateToVolumeThreshold);
00948 }
00949
00950 inline void
00951 xct_t::GetEscalationThresholds(w_base_t::int4_t &toPage,
00952 w_base_t::int4_t &toStore,
00953 w_base_t::int4_t &toVolume)
00954 {
00955 toPage = escalationThresholds[2];
00956 toStore = escalationThresholds[1];
00957 toVolume = escalationThresholds[0];
00958 }
00959
00960 inline const w_base_t::int4_t *
00961 xct_t::GetEscalationThresholdsArray()
00962 {
00963 return escalationThresholds;
00964 }
00965
00966 inline
00967 xct_t::vote_t
00968 xct_t::vote() const
00969 {
00970 return _core->_vote;
00971 }
00972
00973 inline
00974 const lsn_t&
00975 xct_t::last_lsn() const
00976 {
00977 return _last_lsn;
00978 }
00979
00980 inline
00981 void
00982 xct_t::set_last_lsn( const lsn_t&l)
00983 {
00984 _last_lsn = l;
00985 }
00986
00987 inline
00988 const lsn_t&
00989 xct_t::first_lsn() const
00990 {
00991 return _first_lsn;
00992 }
00993
00994 inline
00995 void
00996 xct_t::set_first_lsn(const lsn_t &l)
00997 {
00998 _first_lsn = l;
00999 }
01000
01001 inline
01002 const lsn_t&
01003 xct_t::undo_nxt() const
01004 {
01005 return _undo_nxt;
01006 }
01007
01008 inline
01009 void
01010 xct_t::set_undo_nxt(const lsn_t &l)
01011 {
01012 _undo_nxt = l;
01013 }
01014
01015 inline
01016 const logrec_t*
01017 xct_t::last_log() const
01018 {
01019 return _last_log;
01020 }
01021
01022 inline
01023 bool
01024 xct_t::forced_readonly() const
01025 {
01026 return _core->_forced_readonly;
01027 }
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038 inline bool
01039 xct_t::is_extern2pc()
01040 const
01041 {
01042
01043 return _core->_global_tid != 0;
01044 }
01045
01046
01047 inline
01048 const gtid_t*
01049 xct_t::gtid() const
01050 {
01051 return _core->_global_tid;
01052 }
01053
01054
01055
01056
01057
01058 #endif