mongoid-bolt 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|