mongoid-bolt 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/mongoid-bolt.rb +48 -16
- data/mongoid-bolt.gemspec +1 -1
- data/test/helper.rb +49 -0
- data/test/mongoid-bolt_test.rb +29 -0
- metadata +2 -2
data/lib/mongoid-bolt.rb
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
module Mongoid
|
6
6
|
class Bolt
|
7
|
-
const_set :Version, '1.
|
7
|
+
const_set :Version, '1.1.0'
|
8
8
|
|
9
9
|
class << Bolt
|
10
10
|
def version
|
@@ -81,6 +81,7 @@ end
|
|
81
81
|
field(:hostname, :default => proc{ ::Mongoid::Bolt.hostname })
|
82
82
|
field(:ppid, :default => proc{ ::Mongoid::Bolt.ppid })
|
83
83
|
field(:pid, :default => proc{ ::Mongoid::Bolt.pid })
|
84
|
+
field(:tid, :default => proc{ ::Mongoid::Bolt.tid })
|
84
85
|
|
85
86
|
attr_accessor :stolen
|
86
87
|
alias_method :stolen?, :stolen
|
@@ -100,7 +101,24 @@ end
|
|
100
101
|
|
101
102
|
def alive?
|
102
103
|
return true unless localhost?
|
103
|
-
|
104
|
+
|
105
|
+
process_alive = ::Mongoid::Bolt.process_alive?(ppid, pid)
|
106
|
+
|
107
|
+
same_process = ::Mongoid::Bolt.pid == pid
|
108
|
+
|
109
|
+
if process_alive
|
110
|
+
if same_process
|
111
|
+
::Mongoid::Bolt.thread_alive?(tid)
|
112
|
+
else
|
113
|
+
false
|
114
|
+
end
|
115
|
+
else
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def stale?
|
121
|
+
not alive?
|
104
122
|
end
|
105
123
|
|
106
124
|
def relock!
|
@@ -110,7 +128,8 @@ end
|
|
110
128
|
'_lock._id' => id,
|
111
129
|
'_lock.hostname' => hostname,
|
112
130
|
'_lock.ppid' => ppid,
|
113
|
-
'_lock.pid' => pid
|
131
|
+
'_lock.pid' => pid,
|
132
|
+
'_lock.tid' => tid
|
114
133
|
}
|
115
134
|
|
116
135
|
update = {
|
@@ -118,6 +137,7 @@ end
|
|
118
137
|
'_lock.hostname' => ::Mongoid::Bolt.hostname,
|
119
138
|
'_lock.ppid' => ::Mongoid::Bolt.ppid,
|
120
139
|
'_lock.pid' => ::Mongoid::Bolt.pid,
|
140
|
+
'_lock.tid' => ::Mongoid::Bolt.tid,
|
121
141
|
'_lock.updated_at' => Time.now.utc
|
122
142
|
}
|
123
143
|
}
|
@@ -136,16 +156,12 @@ end
|
|
136
156
|
self.stolen = !!relock!
|
137
157
|
end
|
138
158
|
|
139
|
-
def stale?
|
140
|
-
localhost? and not alive?
|
141
|
-
end
|
142
|
-
|
143
159
|
def owner?
|
144
160
|
::Mongoid::Bolt.identifier == identifier
|
145
161
|
end
|
146
162
|
|
147
163
|
def identifier
|
148
|
-
{:hostname => hostname, :ppid => ppid, :pid => pid}
|
164
|
+
{:hostname => hostname, :ppid => ppid, :pid => pid, :tid => tid}
|
149
165
|
end
|
150
166
|
end
|
151
167
|
|
@@ -159,9 +175,11 @@ end
|
|
159
175
|
|
160
176
|
## locking methods
|
161
177
|
#
|
162
|
-
def target_class.lock!(
|
163
|
-
|
164
|
-
|
178
|
+
def target_class.lock!(options = {})
|
179
|
+
options.to_options!
|
180
|
+
|
181
|
+
conditions = (options[:conditions] || {}).to_options!
|
182
|
+
update = (options[:update] || {}).to_options!
|
165
183
|
|
166
184
|
conditions[:_lock] = nil
|
167
185
|
|
@@ -172,6 +190,10 @@ end
|
|
172
190
|
find_and_modify(update, new: true)
|
173
191
|
end
|
174
192
|
|
193
|
+
def target_class.reserve!(options = {})
|
194
|
+
target_class.lock!(options = {})
|
195
|
+
end
|
196
|
+
|
175
197
|
def lock!(conditions = {})
|
176
198
|
conditions.to_options!
|
177
199
|
|
@@ -201,9 +223,9 @@ end
|
|
201
223
|
def unlock!
|
202
224
|
unlocked = false
|
203
225
|
|
204
|
-
if _lock
|
226
|
+
if _lock and _lock.owner?
|
205
227
|
begin
|
206
|
-
_lock.destroy
|
228
|
+
_lock.destroy
|
207
229
|
@locked = false
|
208
230
|
unlocked = true
|
209
231
|
rescue
|
@@ -315,7 +337,7 @@ end
|
|
315
337
|
##
|
316
338
|
#
|
317
339
|
def Bolt.hostname
|
318
|
-
Socket.gethostname
|
340
|
+
@hostname ||= Socket.gethostname
|
319
341
|
end
|
320
342
|
|
321
343
|
def Bolt.ppid
|
@@ -326,11 +348,15 @@ end
|
|
326
348
|
Process.pid
|
327
349
|
end
|
328
350
|
|
351
|
+
def Bolt.tid
|
352
|
+
Thread.current.object_id
|
353
|
+
end
|
354
|
+
|
329
355
|
def Bolt.identifier
|
330
|
-
{:hostname => hostname, :ppid => ppid, :pid => pid}
|
356
|
+
{:hostname => hostname, :ppid => ppid, :pid => pid, :tid => tid}
|
331
357
|
end
|
332
358
|
|
333
|
-
def Bolt.
|
359
|
+
def Bolt.process_alive?(*pids)
|
334
360
|
pids.flatten.compact.all? do |pid|
|
335
361
|
begin
|
336
362
|
Process.kill(0, Integer(pid))
|
@@ -341,6 +367,12 @@ end
|
|
341
367
|
end
|
342
368
|
end
|
343
369
|
|
370
|
+
def Bolt.thread_alive?(*tids)
|
371
|
+
tids.flatten.compact.all? do |tid|
|
372
|
+
Thread.list.detect{|thread| thread.object_id == tid}
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
344
376
|
##
|
345
377
|
#
|
346
378
|
include Bolt.ability
|
data/mongoid-bolt.gemspec
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
|
4
4
|
Gem::Specification::new do |spec|
|
5
5
|
spec.name = "mongoid-bolt"
|
6
|
-
spec.version = "1.
|
6
|
+
spec.version = "1.1.0"
|
7
7
|
spec.platform = Gem::Platform::RUBY
|
8
8
|
spec.summary = "mongoid-bolt"
|
9
9
|
spec.description = "a mongoid 3/moped compatible lock implementation and mixin"
|
data/test/helper.rb
CHANGED
@@ -1,7 +1,56 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
|
+
|
2
3
|
require_relative 'testing'
|
3
4
|
require_relative '../lib/mongoid-bolt.rb'
|
4
5
|
|
5
6
|
Mongoid.configure do |config|
|
6
7
|
config.connect_to('mongoid-bolt_test')
|
7
8
|
end
|
9
|
+
|
10
|
+
require 'thread'
|
11
|
+
|
12
|
+
class Thread
|
13
|
+
class Pipe
|
14
|
+
class Queue < ::Queue
|
15
|
+
attr_accessor :thread_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@queues = [Queue.new, Queue.new]
|
20
|
+
end
|
21
|
+
|
22
|
+
def thread_id
|
23
|
+
Thread.current.object_id
|
24
|
+
end
|
25
|
+
|
26
|
+
def reserve_write_queue!
|
27
|
+
Thread.exclusive do
|
28
|
+
@queues.each do |queue|
|
29
|
+
next if queue.thread_id
|
30
|
+
queue.thread_id = thread_id
|
31
|
+
return queue
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def write_queue
|
37
|
+
@queues.detect{|q| q.thread_id == thread_id} || reserve_write_queue!
|
38
|
+
end
|
39
|
+
|
40
|
+
def read_queue
|
41
|
+
@queues.detect{|q| q != write_queue}
|
42
|
+
end
|
43
|
+
|
44
|
+
def write(object)
|
45
|
+
write_queue.push(object)
|
46
|
+
end
|
47
|
+
|
48
|
+
alias_method('push', 'write')
|
49
|
+
|
50
|
+
def read
|
51
|
+
read_queue.pop
|
52
|
+
end
|
53
|
+
|
54
|
+
alias_method('pop', 'read')
|
55
|
+
end
|
56
|
+
end
|
data/test/mongoid-bolt_test.rb
CHANGED
@@ -67,4 +67,33 @@ Testing Mongoid::Bolt do
|
|
67
67
|
assert{ A.create.lock{ locked = true } }
|
68
68
|
assert{ locked }
|
69
69
|
end
|
70
|
+
|
71
|
+
test 'that two threads cannot obtain the same lock' do
|
72
|
+
pa = Thread::Pipe.new
|
73
|
+
pb = Thread::Pipe.new
|
74
|
+
|
75
|
+
lock = assert{ Bolt.for(:shared_resource) }
|
76
|
+
|
77
|
+
a = Thread.new do
|
78
|
+
Thread.current.abort_on_exception = true
|
79
|
+
|
80
|
+
pa.pop
|
81
|
+
pa.push(lock.lock! ? :locked : :not_locked)
|
82
|
+
sleep
|
83
|
+
end
|
84
|
+
|
85
|
+
b = Thread.new do
|
86
|
+
Thread.current.abort_on_exception = true
|
87
|
+
|
88
|
+
pb.pop
|
89
|
+
pb.push(lock.lock! ? :locked : :not_locked)
|
90
|
+
sleep
|
91
|
+
end
|
92
|
+
|
93
|
+
pa.push :go
|
94
|
+
assert{ pa.pop == :locked }
|
95
|
+
|
96
|
+
pb.push :go
|
97
|
+
assert{ pb.pop != :locked }
|
98
|
+
end
|
70
99
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongoid-bolt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-07-
|
12
|
+
date: 2012-07-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mongoid
|