distributed_mutex 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.2
1
+ 1.1.0
@@ -1,4 +1,5 @@
1
1
  require 'mutex_lock_timeout'
2
+ require 'mutex_lock_release_failure'
2
3
 
3
4
  class DistributedMutex < Mutex
4
5
 
@@ -16,7 +17,8 @@ class DistributedMutex < Mutex
16
17
  end
17
18
 
18
19
  def lock
19
- if @locked = get_lock
20
+ @locked = get_lock
21
+ if true == @locked
20
22
  true
21
23
  else
22
24
  if @exception_on_timeout
@@ -56,12 +58,12 @@ class DistributedMutex < Mutex
56
58
  end
57
59
 
58
60
  def unlock
59
- if @locked
61
+ if locked?
60
62
  if release_lock
61
63
  @locked = false
62
64
  true
63
65
  else
64
- false
66
+ raise MutexLockReleaseFailure
65
67
  end
66
68
  else
67
69
  false
@@ -0,0 +1,6 @@
1
+ class MutexLockReleaseFailure < StandardError
2
+
3
+ def message
4
+ 'Failed to release Mutex lock. This should be regarded as a system bug.'
5
+ end
6
+ end
data/lib/mysql_mutex.rb CHANGED
@@ -3,40 +3,82 @@ require 'distributed_mutex'
3
3
 
4
4
  class MySQLMutex < DistributedMutex
5
5
 
6
- @active_locks = Hash.new
6
+ @@thread_locks = Hash.new { |h,k| h[k] = Hash.new(0) } # Accounting for nested locks.
7
7
 
8
8
  def initialize(key, timeout = DEFAULT_TIMEOUT, exception_on_timeout = DEFAULT_EXCEPTION_ON_TIMEOUT, connection = ActiveRecord::Base.connection)
9
+ super(key, timeout, exception_on_timeout)
9
10
  @connection = connection
10
- @lock_was_free = false
11
- @get_sql = ActiveRecord::Base.send(:sanitize_sql_array,["SELECT IS_FREE_LOCK(?), GET_LOCK(?,?)", key, key, timeout])
11
+ @connection_id = connection.show_variable('pseudo_thread_id')
12
+ @get_sql = ActiveRecord::Base.send(:sanitize_sql_array,["SELECT GET_LOCK(?,?)", key, timeout])
12
13
  @release_sql = ActiveRecord::Base.send(:sanitize_sql_array,["SELECT RELEASE_LOCK(?)", key])
13
- super(key, timeout, exception_on_timeout)
14
- end
15
-
16
- def self.active_locks
17
- @active_locks
18
14
  end
19
15
 
20
16
  def self.synchronize(key, timeout = DEFAULT_TIMEOUT, exception_on_timeout = DEFAULT_TIMEOUT, con = ActiveRecord::Base.connection, &block)
21
17
  mutex = new(key, timeout, exception_on_timeout, con)
22
- @active_locks[key] = timeout
23
18
  mutex.synchronize(&block)
24
- @active_locks.delete(key)
19
+ end
20
+
21
+ def self.active_locks
22
+ @@thread_locks
25
23
  end
26
24
 
27
25
  private
28
26
 
29
27
  def get_lock
30
- is_free_lock, get_lock = @connection.select_rows(@get_sql).first
31
- @lock_was_free = ('1' == is_free_lock)
32
- '1' == get_lock
28
+ if thread_lock_count > 0
29
+ increment_thread_lock_count
30
+ true
31
+ else
32
+ get_lock = @connection.select_value(@get_sql)
33
+
34
+ if defined?(Rails)
35
+ Rails.logger.debug("MySQLMutex: GET_LOCK=#{get_lock}")
36
+ end
37
+
38
+ if '1' == get_lock
39
+ increment_thread_lock_count
40
+ true
41
+ else
42
+ false
43
+ end
44
+ end
33
45
  end
34
46
 
35
47
  def release_lock
36
- if @lock_was_free
37
- '1' == @connection.select_value(@release_sql)
38
- else
48
+ if thread_lock_count > 1
49
+ decrement_thread_lock_count
39
50
  true
51
+ elsif thread_lock_count > 0
52
+ lock_release = @connection.select_value(@release_sql)
53
+
54
+ if defined?(Rails)
55
+ Rails.logger.debug("MySQLMutex: RELEASE_LOCK=#{lock_release}")
56
+ end
57
+
58
+ if '1' == lock_release
59
+ decrement_thread_lock_count
60
+ true
61
+ else
62
+ false
63
+ end
64
+ else
65
+ false
66
+ end
67
+ end
68
+
69
+ def thread_lock_count
70
+ @@thread_locks[@connection_id][self.key]
71
+ end
72
+
73
+ def increment_thread_lock_count
74
+ @@thread_locks[@connection_id][self.key] += 1
75
+ end
76
+
77
+ def decrement_thread_lock_count
78
+ @@thread_locks[@connection_id][self.key] -= 1
79
+
80
+ if 0 == @@thread_locks[@connection_id][self.key]
81
+ @@thread_locks[@connection_id].delete(self.key)
40
82
  end
41
83
  end
42
84
 
@@ -44,6 +86,10 @@ end
44
86
 
45
87
  at_exit do
46
88
  locks = MySQLMutex.active_locks
89
+ locks.delete_if do |k, v|
90
+ v.empty?
91
+ end
92
+
47
93
  if locks.size > 0
48
94
  if defined?(Rails)
49
95
  Rails.logger.error("MySQLMutex: Locks still active! - #{locks.inspect}")
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 2
9
- version: 1.0.2
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Birkir A. Barkarson
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-12-06 00:00:00 +09:00
17
+ date: 2010-12-10 00:00:00 +09:00
18
18
  default_executable:
19
19
  dependencies: []
20
20
 
@@ -33,6 +33,7 @@ files:
33
33
  - init.rb
34
34
  - lib/distributed_mutex.rb
35
35
  - lib/global_mutex.rb
36
+ - lib/mutex_lock_release_failure.rb
36
37
  - lib/mutex_lock_timeout.rb
37
38
  - lib/mysql_mutex.rb
38
39
  - rails/init.rb