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 CHANGED
@@ -4,7 +4,7 @@
4
4
  #
5
5
  module Mongoid
6
6
  class Bolt
7
- const_set :Version, '1.0.0'
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
- ::Mongoid::Bolt.alive?(ppid, pid)
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!(conditions = {}, update = {})
163
- conditions.to_options!
164
- update.to_options!
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 if _lock.owner?
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.alive?(*pids)
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.0.0"
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
@@ -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.0.0
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-24 00:00:00.000000000 Z
12
+ date: 2012-07-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: mongoid