File Coverage

blib/lib/XAS/Lib/Lockmgr.pm
Criterion Covered Total %
statement 12 56 21.4
branch 0 10 0.0
condition n/a
subroutine 4 10 40.0
pod 6 6 100.0
total 22 82 26.8


line stmt bran cond sub pod time code
1             package XAS::Lib::Lockmgr;
2              
3             our $VERSION = '0.03';
4              
5 1     1   2240 use DateTime;
  1         1  
  1         25  
6 1     1   426 use DateTime::Span;
  1         30718  
  1         26  
7 1     1   453 use Try::Tiny::Retry ':all';
  1         916  
  1         193  
8              
9             use XAS::Class
10 1         18 debug => 0,
11             version => $VERSION,
12             base => 'XAS::Singleton',
13             mixin => 'XAS::Lib::Mixins::Process XAS::Lib::Mixins::Handlers',
14             utils => ':validation dotid load_module',
15             accessors => 'lockers',
16             constants => 'LOCK_DRIVERS TRUE FALSE HASHREF',
17             vars => {
18             PARAMS => {
19             -deadlocked => { optional => 1, default => 1800 },
20             -breaklock => { optional => 1, default => 0 },
21             -timeout => { optional => 1, default => 30 },
22             -attempts => { optional => 1, default => 30 },
23             }
24             }
25 1     1   5 ;
  1         2  
26              
27             #use Data::Dumper;
28              
29             # ----------------------------------------------------------------------
30             # Public Methods
31             # ----------------------------------------------------------------------
32              
33             sub add {
34 0     0 1   my $self = shift;
35 0           my $p = validate_params(\@_, {
36             -key => 1,
37             -args => { optional => 1, default => {}, type => HASHREF },
38             -driver => { optional => 1, default => 'Filesystem', regex => LOCK_DRIVERS },
39             });
40              
41 0           my $stat = FALSE;
42 0           my $key = $p->{'key'};
43 0           my $args = $p->{'args'};
44 0           my $module = 'XAS::Lib::Lockmgr::' . $p->{'driver'};
45              
46 0 0         unless (defined($self->lockers->{$key})) {
47              
48 0           load_module($module);
49              
50 0           $self->lockers->{$key} = $module->new(-key => $key, -args => $args);
51 0           $stat = TRUE;
52              
53             }
54              
55 0           return $stat;
56              
57             }
58              
59             sub remove {
60 0     0 1   my $self = shift;
61 0           my ($key) = validate_params(\@_, [1]);
62              
63 0           my $stat = FALSE;
64              
65 0 0         if (my $locker = $self->lockers->{$key}) {
66              
67 0           $stat = $locker->destroy();
68 0           delete $self->lockers->{$key};
69              
70             } else {
71              
72 0           $self->throw_msg(
73             dotid($self->class) . '.remove.nokey',
74             'lock_nokey',
75             $key
76             );
77              
78             }
79              
80 0           return $stat;
81              
82             }
83              
84             sub lock {
85 0     0 1   my $self = shift;
86 0           my ($key) = validate_params(\@_, [1]);
87              
88 0           my $stat = FALSE;
89              
90 0 0         if (my $locker = $self->lockers->{$key}) {
91              
92 0           $stat = $locker->lock();
93              
94             } else {
95              
96 0           $self->throw_msg(
97             dotid($self->class) . '.lock.nokey',
98             'lock_nokey',
99             $key
100             );
101              
102             }
103              
104 0           return $stat;
105              
106             }
107              
108             sub unlock {
109 0     0 1   my $self = shift;
110 0           my ($key) = validate_params(\@_, [1]);
111              
112 0           my $stat = FALSE;
113              
114 0 0         if (my $locker = $self->lockers->{$key}) {
115              
116 0           $stat = $locker->unlock();
117              
118             } else {
119              
120 0           $self->throw_msg(
121             dotid($self->class) . '.unlock.nokey',
122             'lock_nokey',
123             $key
124             );
125              
126             }
127              
128 0           return $stat;
129              
130             }
131              
132             sub try_lock {
133 0     0 1   my $self = shift;
134 0           my ($key) = validate_params(\@_, [1]);
135              
136 0           my $stat = FALSE;
137              
138 0 0         if (my $locker = $self->lockers->{$key}) {
139              
140 0           $stat = $locker->try_lock();
141              
142             } else {
143              
144 0           $self->throw_msg(
145             dotid($self->class) . '.try_lock.nokey',
146             'lock_nokey',
147             $key
148             );
149              
150             }
151              
152 0           return $stat;
153              
154             }
155              
156             # ----------------------------------------------------------------------
157             # Private Methods
158             # ----------------------------------------------------------------------
159              
160             sub init {
161 0     0 1   my $class = shift;
162              
163 0           my $self = $class->SUPER::init(@_);
164              
165 0           $self->{'lockers'} = {};
166              
167 0           return $self;
168              
169             }
170              
171             1;
172              
173             __END__
174              
175             =head1 NAME
176              
177             XAS::Lib::Lockmgr - The base class for locking within XAS
178              
179             =head1 SYNOPSIS
180              
181             my $lock = 'testing';
182             my $lockmgr = XAS::Lib::Lockmgr->new();
183              
184             $lockmgr->add(-key => $lock);
185              
186             if ($lockmgr->try_lock($lock)) {
187              
188             if ($lockmgr->lock($lock)) {
189              
190             ....
191              
192             $lockmgr->unlock($lock);
193              
194             }
195              
196             }
197              
198             =head1 DESCRIPTION
199              
200             This module provides a general purpose locking mechanism to protect shared
201             resources. It is rather interesting to ask a developer how they protect
202             global shared data. They usually answer, "what do you mean by "global shared
203             data" ?". Well, for those who understand the need, this module provides it
204             for XAS.
205              
206             =head1 METHODS
207              
208             =head2 new
209              
210             This method initializes the module. It takes the following parameters:
211              
212             =over 4
213              
214             =item B<-deadlock>
215              
216             The number of minutes before a lock is considered deadlocked. At which point
217             an attempt will be made to remove the lock. Defaults to 5.
218              
219             =item B<-breaklock>
220              
221             After a deadlock has been detected, break the lock, irregardless of who
222             owns the lock. Defaults to false. The default will also throw an exception
223             instead of breaking the lock.
224              
225             =item B<-attempts>
226              
227             The number of attempts to aquire the lock. Default to 30.
228              
229             =item B<-timeout>
230              
231             The number of seconds to wait between each lock attempt. Defaults to 30.
232              
233             =back
234              
235             =head2 add(...)
236              
237             This method adds a key and defines the module that is used to manage that key.
238             It takes the following named parameters:
239              
240             =over 4
241              
242             =item B<-key>
243              
244             The name of the key. This parameter is required.
245              
246             =item B<-driver>
247              
248             The module that will manage the lock. The default is 'Filesystem'. Which will
249             load L<XAS::Lib::Lockmgr::Filesystem|XAS::Lib::Lockmgr::Filesystem>.
250              
251             =item B<-args>
252              
253             An optional hash reference of arguments to pass to the driver.
254              
255             =back
256              
257             =head2 remove($key)
258              
259             This method will remove the key from management. This will call the destroy
260             method of the managing module.
261              
262             =over 4
263              
264             =item B<$key>
265              
266             The name of the managed key.
267              
268             =back
269              
270             =head2 lock($key)
271              
272             Aquires a lock, returns true if successful.
273              
274             =over 4
275              
276             =item B<$key>
277              
278             The name of the managed key.
279              
280             =back
281              
282             =head2 unlock($key)
283              
284             Releases the lock. Returns true if successful.
285              
286             =over 4
287              
288             =item B<$key>
289              
290             The name of the managed key.
291              
292             =back
293              
294             =head2 try_lock($key)
295              
296             Tests to see if the lock is available, returns true if the lock is available.
297              
298             =over 4
299              
300             =item B<$key>
301              
302             The name of the managed key.
303              
304             =back
305              
306             =head1 SEE ALSO
307              
308             =over 4
309              
310             =item L<XAS::Lib::Lockmgr::Filesystem|XAS::Lib::Lockmgr::Filesystem>
311              
312             =item L<XAS|XAS>
313              
314             =back
315              
316             =head1 AUTHOR
317              
318             Kevin L. Esteb, E<lt>kevin@kesteb.usE<gt>
319              
320             =head1 COPYRIGHT AND LICENSE
321              
322             Copyright (c) 2012-2016 Kevin L. Esteb
323              
324             This is free software; you can redistribute it and/or modify it under
325             the terms of the Artistic License 2.0. For details, see the full text
326             of the license at http://www.perlfoundation.org/artistic_license_2_0.
327              
328             =cut