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 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