File Coverage

lib/Mysql/NameLocker.pm
Criterion Covered Total %
statement 6 36 16.6
branch 0 12 0.0
condition 0 12 0.0
subroutine 2 4 50.0
pod 1 1 100.0
total 9 65 13.8


line stmt bran cond sub pod time code
1             package Mysql::NameLocker;
2 1     1   497 use strict;
  1         2  
  1         38  
3 1     1   6 use Carp;
  1         2  
  1         417  
4             our $VERSION = '1.00';
5              
6             =head1 NAME
7              
8             Mysql::NameLocker - Safe way of locking and unlocking MySQL tables using named locks.
9              
10             =head1 SYNOPSIS
11              
12             use Mysql::NameLocker;
13              
14             # Simulate a record lock
15             my $tablename = 'category'
16             my $id = 123;
17             my $lockname = "$tablename_$id";
18             my $timeout = 10;
19             my $locker = new Mysql::NameLocker($dbh,$lockname,$timeout);
20              
21             # Execute some tricky statements here...
22              
23             # Locks are automically released when $locker goes out of scope.
24             undef($locker);
25              
26             =head1 DESCRIPTION
27              
28             Mysql::NameLocker is a simple class for safely using MySQL named locks.
29             A locks is created when you instantiate the class and is automatically
30             released when the object goes out of scope (or when you call undef on the
31             object). One situation where this class is useful is when you have
32             persistent database connections such as in some mod_perl scripts and you
33             want to be sure that locks are always released even when a script dies
34             somewhere unexpectedly.
35              
36             =head1 CLASS METHODS
37              
38             =head2 new ($dbh,$lockname,$timeout)
39              
40             Attempts to acquire a named lock and returns a Mysql::NameLocker object
41             that encapsulates this lock. If a timeout occurs, then undef is returned.
42             If an error occurs (The MySQL statement GET_LOCK() returns NULL) then this
43             constructor croaks.
44              
45             Parameters:
46              
47             =over 4
48              
49             =item 1. DBI database handle object.
50              
51             =item 2. Lock name.
52              
53             =item 3. Timeout in seconds.
54              
55             =back
56              
57             Returns: Mysql::NameLocker object or undef if failed to acquire lock.
58              
59             =cut
60              
61             sub new {
62 0     0 1   my $proto = shift;
63 0           my $dbh = shift;
64 0           my $lockname = shift;
65 0           my $timeout = shift;
66 0 0 0       unless(defined($dbh) && defined($lockname) && length($lockname) && defined($timeout)) {
      0        
      0        
67 0           croak('Invalid parameters for ' . __PACKAGE__ . '->new() constructor!');
68             }
69 0           my $sth = $dbh->prepare('SELECT GET_LOCK(?,?)');
70 0 0         unless(defined($sth)) {
71 0           croak($dbh->errstr());
72             }
73 0           $sth->bind_param(1,$lockname);
74 0           $sth->bind_param(2,$timeout);
75 0 0         unless($sth->execute()) {
76 0           croak($sth->errstr());
77             }
78 0           my ($result) = $sth->fetchrow_array();
79 0           $sth->finish();
80 0 0         unless(defined($result)) {
81 0           croak("Error trying to acquire named lock.\n");
82             }
83 0 0         unless($result) {
84 0           return undef;
85             }
86 0           my $self = {'_dbh' => $dbh,
87             '_lockname' => $lockname};
88 0   0       my $class = ref($proto) || $proto;
89 0           bless $self,$class;
90 0           return $self;
91             }
92              
93              
94              
95              
96              
97              
98             =head2 DESTROY
99              
100             Destructor called implicitly by perl when object is destroyed. The acquired
101             lock is released here if the DBI database handle is still connected.
102              
103             =cut
104              
105             sub DESTROY {
106 0     0     my $self = shift;
107 0           my $dbh = $self->{'_dbh'};
108 0 0         if ($dbh->ping()) {
109 0           my $sth = $dbh->prepare('SELECT RELEASE_LOCK(?)');
110 0           $sth->bind_param(1,$self->{'_lockname'});
111 0           $sth->execute();
112 0           $sth->finish();
113             }
114             }
115              
116              
117              
118              
119             1;
120              
121              
122             __END__