Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

create new redis client in lock refresh thread

Change-Id: I73f4efff1a7fda8bdc05b29eb216031137622fa8
  • Loading branch information...
commit 554be907a098a9695116c6f1ecbf4acf083b203d 1 parent 1d5dafe
Andrew Liu authored April 10, 2012
BIN  atmos/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
41  base/lib/base/job/lock.rb
@@ -20,6 +20,7 @@ def initialize(name, opts={})
20 20
       config = Config.redis_config
21 21
       raise "Can't find configuration of redis." unless config
22 22
       @redis = ::Redis.new(config)
  23
+      @released_thread = {}
23 24
     end
24 25
 
25 26
     def make_logger
@@ -36,7 +37,7 @@ def lock
36 37
         existing_lock = @redis.get(@name)
37 38
         if existing_lock.to_f < Time.now.to_f
38 39
           @logger.debug("Lock #{@name} is expired, trying to acquire it.")
39  
-          break if watch_and_update(expiration)
  40
+          break if watch_and_update(@redis, expiration)
40 41
         end
41 42
 
42 43
         raise ServiceError.new(ServiceError::JOB_QUEUE_TIMEOUT, @timeout)if Time.now.to_f - started > @timeout
@@ -53,15 +54,15 @@ def lock
53 54
       begin
54 55
         yield if block_given?
55 56
       ensure
56  
-        refresh_thread.exit
  57
+        release_thread(refresh_thread) if refresh_thread
57 58
         delete
58 59
       end
59 60
     end
60 61
 
61  
-    def watch_and_update(expiration)
62  
-      @redis.watch(@name)
63  
-      res = @redis.multi do
64  
-        @redis.set(@name, expiration)
  62
+    def watch_and_update(redis, expiration)
  63
+      redis.watch(@name)
  64
+      res = redis.multi do
  65
+        redis.set(@name, expiration)
65 66
       end
66 67
       if res
67 68
         @logger.debug("Lock #{@name} is renewed and acquired.")
@@ -71,27 +72,41 @@ def watch_and_update(expiration)
71 72
       res
72 73
     end
73 74
 
  75
+    def release_thread t
  76
+      @released_thread[t.object_id] = true
  77
+    end
  78
+
  79
+    def released?
  80
+      @released_thread[Thread.current.object_id]
  81
+    end
  82
+
74 83
     def setup_refresh_thread
75 84
       t = Thread.new do
  85
+        redis = ::Redis.new(Config.redis_config)
76 86
         sleep_interval = [1.0, @expiration/2].max
77 87
         begin
78 88
           loop do
  89
+            break if released?
79 90
             @logger.debug("Renewing lock #{@name}")
80  
-            @redis.watch(@name)
81  
-            existing_lock = @redis.get(@name)
  91
+            redis.watch(@name)
  92
+            existing_lock = redis.get(@name)
82 93
 
83 94
             break if existing_lock.to_f > @lock_expiration # lock has been updated by others
84 95
             expiration = Time.now.to_f + @expiration + 1
85  
-            break unless watch_and_update(expiration)
  96
+            break unless watch_and_update(redis, expiration)
86 97
             @lock_expiration = expiration
87  
-
88  
-            sleep(sleep_interval)
  98
+            sleep sleep_interval
89 99
           end
90 100
         rescue => e
91 101
           @logger.error("Can't renew lock #{@name}, #{e}")
92 102
         ensure
93  
-          @logger.debug("Lock renew thread for #{@name} exited.")
94  
-          @redis.quit
  103
+          begin
  104
+            @logger.debug("Lock renew thread for #{@name} exited.")
  105
+            redis.quit
  106
+          rescue => e
  107
+            # just logging, ignore error
  108
+            @logger.debug("Ignore error when quit: #{e}")
  109
+          end
95 110
         end
96 111
       end
97 112
       t
17  base/spec/job_spec.rb
@@ -85,4 +85,21 @@
85 85
     ran_once.should be_true
86 86
     (@stored_value == start - 1).should_not be_true
87 87
   end
  88
+
  89
+  it "should not update expiration time after the lock is released" do
  90
+    start = Time.now.to_f
  91
+
  92
+    @redis.should_receive(:watch).with(@name).any_number_of_times
  93
+    @redis.should_receive(:multi).any_number_of_times.and_yield
  94
+
  95
+    expiration = 0.5
  96
+    lock = VCAP::Services::Base::AsyncJob::Lock.new(@name,:timeout => @timeout, :expiration => expiration, :logger => @logger)
  97
+
  98
+    ran_once = false
  99
+    lock.lock{ran_once = true; sleep expiration *2 }
  100
+
  101
+    current_value = @stored_value
  102
+    sleep expiration * 2
  103
+    current_value.should == @stored_value
  104
+  end
88 105
 end
BIN  filesystem/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  mongodb/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  mysql/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  neo4j/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  postgresql/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  rabbit/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  redis/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  service_broker/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  tools/backup/manager/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown
BIN  vblob/vendor/cache/vcap_services_base-0.1.9.gem
Binary file not shown

Git Notes

review

Code-Review+2: Nicholas Kushmerick <nicholask@vmware.com>
Code-Review+1: Figo Feng <ffeng@vmware.com>
Verified+1: Figo Feng <ffeng@vmware.com>
Submitted-by: Andrew Liu <aliu@vmware.com>
Submitted-at: Fri, 13 Apr 2012 03:18:58 +0000
Reviewed-on: http://reviews.cloudfoundry.org/4902
Project: vcap-services
Branch: refs/heads/services-r10

0 notes on commit 554be90

Please sign in to comment.
Something went wrong with that request. Please try again.