Class: Vmit::RefcountedResource

Inherits:
Object
  • Object
show all
Defined in:
lib/vmit/refcounted_resource.rb

Overview

This class allows to bring a resource represented by a shared lock file only once by the the first process using it, and down when the last process finishes.

Think of it as the first one that enters the room turn the lights on, and the last one that exits, turns the lights off.

Call:

on_up : will bring the resource up if needed on_down: will bring tthe resource down if no more users on_acquire: will start using the resource on_release: will stop using the resource

Then use the class like this:

YourRefCountedResource.auto(‘name’) do

# do something

end

Direct Known Subclasses

Network

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ RefcountedResource

Returns a new instance of RefcountedResource.



68
69
70
71
72
73
74
75
# File 'lib/vmit/refcounted_resource.rb', line 68

def initialize(name)
  @name = name
  # Allow the testcases to run as not root
  resource_dir = File.join(Vmit::RUN_DIR, 'resources')
  @lockfile_dir = File.join(resource_dir, resource_class, name)
  FileUtils.mkdir_p @lockfile_dir
  @lockfile_path = File.join(@lockfile_dir, 'lock')
end

Instance Attribute Details

#lockfile_dirObject (readonly)

Returns the value of attribute lockfile_dir.



52
53
54
# File 'lib/vmit/refcounted_resource.rb', line 52

def lockfile_dir
  @lockfile_dir
end

#lockfile_pathObject (readonly)

Returns the value of attribute lockfile_path.



51
52
53
# File 'lib/vmit/refcounted_resource.rb', line 51

def lockfile_path
  @lockfile_path
end

#nameObject (readonly)

Returns the value of attribute name.



50
51
52
# File 'lib/vmit/refcounted_resource.rb', line 50

def name
  @name
end

Class Method Details

.make_tempRefcountedResource

Creates a temporary resource with a random name

Returns:



79
80
81
82
83
# File 'lib/vmit/refcounted_resource.rb', line 79

def self.make_temp
  name = File.basename(Dir::Tmpname.make_tmpname([resource_class, 'tmp'],
    File.join(resource_dir, resource_class)))
  self.new(name)
end

Instance Method Details

#auto { ... } ⇒ Object

Executes the given block.

Yields:

  • calling before on_up once per group of processes using the same resurce, and on_acquire before executing the block. It will execute on_release after executing the block and the last process using the reource will call on_down



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/vmit/refcounted_resource.rb', line 98

def auto
  begin
    Vmit.logger.debug "Using resource lock #{lockfile_path}"
    File.open(lockfile_path, File::WRONLY | File::CREAT, 0666) do |f|
      begin
        if f.flock File::LOCK_EX | File::LOCK_NB
          # we are the first ones, bring the resource up
          self.on_up
        end

        if f.flock File::LOCK_SH
          self.on_acquire
        end

        yield if block_given?
      rescue Exception => e
        Vmit.logger.error e.message
        raise e
      ensure
        if f.flock File::LOCK_EX | File::LOCK_NB
            self.on_down
        end
        on_release
        f.flock File::LOCK_UN
      end
    end
  rescue Exception => e
    Vmit.logger.error e.message
    raise e
  ensure
    File.unlink(lockfile_path)
  end
end

#resource_classObject

The resource class. Resources with the same class and name are considered to be the same resource by the locking and refcounting mechanism.

For example, you may subclass RefcountedResource as Network, and then have multiple Network subclasses, but you can reimplement resource_class once in Network so that all Network subclasses have the same resource class.



64
65
66
# File 'lib/vmit/refcounted_resource.rb', line 64

def resource_class
  (self.class.name.split('::').last || '').downcase
end