Class: TrustedSandbox::UidPool

Inherits:
Object
  • Object
show all
Defined in:
lib/trusted_sandbox/uid_pool.rb

Overview

Offers intra-server inter-process pool of Uids. In other words:

- Every server has its own pool. Since Docker containers live within a server, this is what we want.
- Processes within the same server share the pool.

Usage:

The following will behave the same when different processes try to perform #lock and #release.

pool = UidPool.new 100, 101
pool.lock
# => 100

pool.lock
# => 101

pool.lock
# => RuntimeError: No available UIDs in the pool. Please try again later.

pool.release(100)
# => 100

pool.lock
# => 100

pool.release_all

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lock_dir, lower, upper, options = {}) ⇒ UidPool

Returns a new instance of UidPool.

Parameters:

  • lower (Integer)

    lower bound of the pool

  • upper (Integer)

    upper bound of the pool

  • timeout (Hash)

    a customizable set of options

  • retries (Hash)

    a customizable set of options

  • delay (Hash)

    a customizable set of options



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/trusted_sandbox/uid_pool.rb', line 37

def initialize(lock_dir, lower, upper, options={})
  @lock_dir = lock_dir
  FileUtils.mkdir_p(lock_dir)

  @master_lock_file = lock_file_path_for('master')
  @lower = lower
  @upper = upper
  @timeout = options[:timeout] || options['timeout'] || 3
  @retries = options[:retries] || options['retries'] || 5
  @delay = options[:delay] || options['delay'] || 0.5
end

Instance Attribute Details

#delayObject (readonly)

Returns the value of attribute delay.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def delay
  @delay
end

#lock_dirObject (readonly)

Returns the value of attribute lock_dir.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def lock_dir
  @lock_dir
end

#lowerObject (readonly)

Returns the value of attribute lower.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def lower
  @lower
end

#master_lock_fileObject (readonly)

Returns the value of attribute master_lock_file.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def master_lock_file
  @master_lock_file
end

#retriesObject (readonly)

Returns the value of attribute retries.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def retries
  @retries
end

#timeoutObject (readonly)

Returns the value of attribute timeout.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def timeout
  @timeout
end

#upperObject (readonly)

Returns the value of attribute upper.



30
31
32
# File 'lib/trusted_sandbox/uid_pool.rb', line 30

def upper
  @upper
end

Instance Method Details

#availableInteger

Returns number of availabld UIDs.

Returns:

  • (Integer)

    number of availabld UIDs



94
95
96
# File 'lib/trusted_sandbox/uid_pool.rb', line 94

def available
  available_uids.length
end

#available_uidsArray<Integer>

Returns all non taken uids.

Returns:

  • (Array<Integer>)

    all non taken uids



105
106
107
# File 'lib/trusted_sandbox/uid_pool.rb', line 105

def available_uids
  all_uids - used_uids
end

#inspectObject



49
50
51
# File 'lib/trusted_sandbox/uid_pool.rb', line 49

def inspect
  "#<TrustedSandbox::UidPool used: #{used}, available: #{available}, used_uids: #{used_uids}>"
end

#lockInteger

Locks one UID from the pool, in a cross-process atomic manner

Returns:

  • (Integer)

Raises:



56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/trusted_sandbox/uid_pool.rb', line 56

def lock
  retries.times do
    atomically(timeout) do
      uid = available_uid
      if uid
        lock_uid uid
        return uid.to_i
      end
    end
    sleep(delay)
  end
  raise PoolTimeoutError.new('No available UIDs in the pool. Please try again later.')
end

#release(uid) ⇒ Integer

Releases one UID

Parameters:

  • uid (Integer)

Returns:

  • (Integer)

    UID removed



82
83
84
85
86
# File 'lib/trusted_sandbox/uid_pool.rb', line 82

def release(uid)
  atomically(timeout) do
    release_uid uid
  end
end

#release_allUidPool

Releases all UIDs

Returns:



72
73
74
75
76
77
# File 'lib/trusted_sandbox/uid_pool.rb', line 72

def release_all
  all_uids.each do |uid|
    release uid
  end
  self
end

#usedInteger

Returns number of used UIDs.

Returns:

  • (Integer)

    number of used UIDs



89
90
91
# File 'lib/trusted_sandbox/uid_pool.rb', line 89

def used
  used_uids.length
end

#used_uidsArray<Integer>

Returns all taken uids.

Returns:

  • (Array<Integer>)

    all taken uids



99
100
101
102
# File 'lib/trusted_sandbox/uid_pool.rb', line 99

def used_uids
  uids = Dir.entries(lock_dir) - %w(. .. master)
  uids.map(&:to_i)
end