| Filename | /usr/share/perl5/DBIx/Class/Storage/TxnScopeGuard.pm |
| Statements | Executed 17 statements in 1.60ms |
| Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine |
|---|---|---|---|---|---|
| 1 | 1 | 1 | 19µs | 19µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@7 |
| 1 | 1 | 1 | 17µs | 29µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@3 |
| 1 | 1 | 1 | 15µs | 294µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@10 |
| 1 | 1 | 1 | 13µs | 31µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@6 |
| 1 | 1 | 1 | 12µs | 69µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@9 |
| 1 | 1 | 1 | 9µs | 32µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@5 |
| 1 | 1 | 1 | 9µs | 18µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@4 |
| 1 | 1 | 1 | 8µs | 24µs | DBIx::Class::Storage::TxnScopeGuard::BEGIN@8 |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::DESTROY |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::__ANON__[:80] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::__ANON__[:81] |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::commit |
| 0 | 0 | 0 | 0s | 0s | DBIx::Class::Storage::TxnScopeGuard::new |
| Line | State ments |
Time on line |
Calls | Time in subs |
Code |
|---|---|---|---|---|---|
| 1 | package DBIx::Class::Storage::TxnScopeGuard; | ||||
| 2 | |||||
| 3 | 2 | 44µs | 2 | 41µs | # spent 29µs (17+12) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@3 which was called:
# once (17µs+12µs) by DBIx::Class::Storage::BEGIN@18 at line 3 # spent 29µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@3
# spent 12µs making 1 call to strict::import |
| 4 | 2 | 34µs | 2 | 26µs | # spent 18µs (9+9) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@4 which was called:
# once (9µs+9µs) by DBIx::Class::Storage::BEGIN@18 at line 4 # spent 18µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@4
# spent 9µs making 1 call to warnings::import |
| 5 | 2 | 54µs | 2 | 55µs | # spent 32µs (9+23) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@5 which was called:
# once (9µs+23µs) by DBIx::Class::Storage::BEGIN@18 at line 5 # spent 32µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@5
# spent 23µs making 1 call to Exporter::import |
| 6 | 2 | 49µs | 2 | 49µs | # spent 31µs (13+18) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@6 which was called:
# once (13µs+18µs) by DBIx::Class::Storage::BEGIN@18 at line 6 # spent 31µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@6
# spent 18µs making 1 call to Exporter::import |
| 7 | 2 | 39µs | 1 | 19µs | # spent 19µs within DBIx::Class::Storage::TxnScopeGuard::BEGIN@7 which was called:
# once (19µs+0s) by DBIx::Class::Storage::BEGIN@18 at line 7 # spent 19µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@7 |
| 8 | 2 | 50µs | 2 | 39µs | # spent 24µs (8+15) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@8 which was called:
# once (8µs+15µs) by DBIx::Class::Storage::BEGIN@18 at line 8 # spent 24µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@8
# spent 15µs making 1 call to Exporter::import |
| 9 | 2 | 45µs | 2 | 126µs | # spent 69µs (12+57) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@9 which was called:
# once (12µs+57µs) by DBIx::Class::Storage::BEGIN@18 at line 9 # spent 69µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@9
# spent 57µs making 1 call to DBIx::Class::Carp::import |
| 10 | 2 | 1.28ms | 2 | 573µs | # spent 294µs (15+279) within DBIx::Class::Storage::TxnScopeGuard::BEGIN@10 which was called:
# once (15µs+279µs) by DBIx::Class::Storage::BEGIN@18 at line 10 # spent 294µs making 1 call to DBIx::Class::Storage::TxnScopeGuard::BEGIN@10
# spent 279µs making 1 call to namespace::clean::import |
| 11 | |||||
| 12 | sub new { | ||||
| 13 | my ($class, $storage) = @_; | ||||
| 14 | |||||
| 15 | my $guard = { | ||||
| 16 | inactivated => 0, | ||||
| 17 | storage => $storage, | ||||
| 18 | }; | ||||
| 19 | |||||
| 20 | # we are starting with an already set $@ - in order for things to work we need to | ||||
| 21 | # be able to recognize it upon destruction - store its weakref | ||||
| 22 | # recording it before doing the txn_begin stuff | ||||
| 23 | # | ||||
| 24 | # FIXME FRAGILE - any eval that fails but *does not* rethrow between here | ||||
| 25 | # and the unwind will trample over $@ and invalidate the entire mechanism | ||||
| 26 | # There got to be a saner way of doing this... | ||||
| 27 | if (is_exception $@) { | ||||
| 28 | weaken( | ||||
| 29 | $guard->{existing_exception_ref} = (ref($@) eq '') ? \$@ : $@ | ||||
| 30 | ); | ||||
| 31 | } | ||||
| 32 | |||||
| 33 | $storage->txn_begin; | ||||
| 34 | |||||
| 35 | weaken( $guard->{dbh} = $storage->_dbh ); | ||||
| 36 | |||||
| 37 | bless $guard, ref $class || $class; | ||||
| 38 | |||||
| 39 | $guard; | ||||
| 40 | } | ||||
| 41 | |||||
| 42 | sub commit { | ||||
| 43 | my $self = shift; | ||||
| 44 | |||||
| 45 | $self->{storage}->throw_exception("Refusing to execute multiple commits on scope guard $self") | ||||
| 46 | if $self->{inactivated}; | ||||
| 47 | |||||
| 48 | $self->{storage}->txn_commit; | ||||
| 49 | $self->{inactivated} = 1; | ||||
| 50 | } | ||||
| 51 | |||||
| 52 | sub DESTROY { | ||||
| 53 | my $self = shift; | ||||
| 54 | |||||
| 55 | return if $self->{inactivated}; | ||||
| 56 | |||||
| 57 | # if our dbh is not ours anymore, the $dbh weakref will go undef | ||||
| 58 | $self->{storage}->_verify_pid unless DBIx::Class::_ENV_::BROKEN_FORK; | ||||
| 59 | return unless $self->{dbh}; | ||||
| 60 | |||||
| 61 | my $exception = $@ if ( | ||||
| 62 | is_exception $@ | ||||
| 63 | and | ||||
| 64 | ( | ||||
| 65 | ! defined $self->{existing_exception_ref} | ||||
| 66 | or | ||||
| 67 | refaddr( ref($@) eq '' ? \$@ : $@ ) != refaddr($self->{existing_exception_ref}) | ||||
| 68 | ) | ||||
| 69 | ); | ||||
| 70 | |||||
| 71 | { | ||||
| 72 | local $@; | ||||
| 73 | |||||
| 74 | carp 'A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back.' | ||||
| 75 | unless defined $exception; | ||||
| 76 | |||||
| 77 | my $rollback_exception; | ||||
| 78 | # do minimal connectivity check due to weird shit like | ||||
| 79 | # https://rt.cpan.org/Public/Bug/Display.html?id=62370 | ||||
| 80 | try { $self->{storage}->_seems_connected && $self->{storage}->txn_rollback } | ||||
| 81 | catch { $rollback_exception = shift }; | ||||
| 82 | |||||
| 83 | if ( $rollback_exception and ( | ||||
| 84 | ! defined blessed $rollback_exception | ||||
| 85 | or | ||||
| 86 | ! $rollback_exception->isa('DBIx::Class::Storage::NESTED_ROLLBACK_EXCEPTION') | ||||
| 87 | ) ) { | ||||
| 88 | # append our text - THIS IS A TEMPORARY FIXUP! | ||||
| 89 | # a real stackable exception object is in the works | ||||
| 90 | if (ref $exception eq 'DBIx::Class::Exception') { | ||||
| 91 | $exception->{msg} = "Transaction aborted: $exception->{msg} " | ||||
| 92 | ."Rollback failed: ${rollback_exception}"; | ||||
| 93 | } | ||||
| 94 | elsif ($exception) { | ||||
| 95 | $exception = "Transaction aborted: ${exception} " | ||||
| 96 | ."Rollback failed: ${rollback_exception}"; | ||||
| 97 | } | ||||
| 98 | else { | ||||
| 99 | carp (join ' ', | ||||
| 100 | "********************* ROLLBACK FAILED!!! ********************", | ||||
| 101 | "\nA rollback operation failed after the guard went out of scope.", | ||||
| 102 | 'This is potentially a disastrous situation, check your data for', | ||||
| 103 | "consistency: $rollback_exception" | ||||
| 104 | ); | ||||
| 105 | } | ||||
| 106 | } | ||||
| 107 | } | ||||
| 108 | |||||
| 109 | $@ = $exception; | ||||
| 110 | } | ||||
| 111 | |||||
| 112 | 1 | 2µs | 1; | ||
| 113 | |||||
| 114 | 1 | 249µs | __END__ # spent 249µs making 1 call to B::Hooks::EndOfScope::XS::__ANON__ |