Class: OsCtld::IdRange

Inherits:
Object
  • Object
show all
Includes:
Assets::Definition, Lockable, Manipulable
Defined in:
lib/osctld/id_range.rb

Defined Under Namespace

Classes: AllocationError, AllocationTable

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Assets::Definition

#define_assets

Methods included from Manipulable

#acquire_manipulation_lock, #init_manipulable, #is_being_manipulated?, #manipulate, #manipulated_by, #release_manipulation_lock

Methods included from Lockable

#exclusively, included, #inclusively, #init_lock, #lock, #unlock

Constructor Details

#initialize(pool, name, load: true) ⇒ IdRange

Returns a new instance of IdRange.



16
17
18
19
20
21
22
23
# File 'lib/osctld/id_range.rb', line 16

def initialize(pool, name, load: true)
  init_lock
  init_manipulable
  @pool = pool
  @name = name
  @attrs = Attributes.new
  load_config if load
end

Instance Attribute Details

#allocationsObject (readonly, protected)

Returns the value of attribute allocations.



184
185
186
# File 'lib/osctld/id_range.rb', line 184

def allocations
  @allocations
end

#attrsObject (readonly)

Returns the value of attribute attrs.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def attrs
  @attrs
end

#block_countObject (readonly)

Returns the value of attribute block_count.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def block_count
  @block_count
end

#block_sizeObject (readonly)

Returns the value of attribute block_size.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def block_size
  @block_size
end

#nameObject (readonly)

Returns the value of attribute name.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def name
  @name
end

#poolObject (readonly)

Returns the value of attribute pool.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def pool
  @pool
end

#start_idObject (readonly)

Returns the value of attribute start_id.



14
15
16
# File 'lib/osctld/id_range.rb', line 14

def start_id
  @start_id
end

Instance Method Details

#add_block_ids(block) ⇒ Object (protected)



186
187
188
189
190
191
192
193
# File 'lib/osctld/id_range.rb', line 186

def add_block_ids(block)
  first_id = start_id + block[:block_index] * block_size
  block.merge(
    first_id: first_id,
    last_id: first_id + block_size * block[:block_count] - 1,
    id_count: block_size * block[:block_count],
  )
end

#allocate(block_count, opts = {}) ⇒ Hash

Parameters:

  • block_count (Integer)

    number of blocks to allocate

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :block_index (Integer)

    optional starting block_index

  • :owner (String)

Returns:

  • (Hash)


44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/osctld/id_range.rb', line 44

def allocate(block_count, opts = {})
  ret = nil

  exclusively do
    if opts[:block_index]
      begin
        ret = allocations.allocate_at(opts[:block_index], block_count, opts[:owner])
      rescue ArgumentError => e
        raise AllocationError, e.message
      end
    else
      unless ret = allocations.allocate(block_count, opts[:owner])
        raise AllocationError, 'no free space found'
      end
    end
    save_config
  end

  add_block_ids(ret)
end

#assetsObject



87
88
89
90
91
92
93
94
95
96
97
# File 'lib/osctld/id_range.rb', line 87

def assets
  define_assets do |add|
    add.file(
      config_path,
      desc: 'Configuration file',
      user: 0,
      group: 0,
      mode: 0400
    )
  end
end

#can_delete?Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/osctld/id_range.rb', line 83

def can_delete?
  allocations.empty?
end

#config_pathObject



175
176
177
# File 'lib/osctld/id_range.rb', line 175

def config_path
  File.join(pool.conf_path, 'id-range', "#{name}.yml")
end

#configure(start_id, block_size, block_count) ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/osctld/id_range.rb', line 29

def configure(start_id, block_size, block_count)
  exclusively do
    @start_id = start_id
    @block_size = block_size
    @block_count = block_count
    @allocations = AllocationTable.new(block_count)
    save_config
  end
end

#exportObject



135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/osctld/id_range.rb', line 135

def export
  inclusively do
    {
      pool: pool.name,
      name: name,
      start_id: start_id,
      last_id: last_id,
      block_size: block_size,
      block_count: block_count,
      allocated: allocations.count_allocated_blocks,
      free: allocations.count_free_blocks,
    }.merge!(attrs.export)
  end
end

#export_allObject



150
151
152
153
154
# File 'lib/osctld/id_range.rb', line 150

def export_all
  inclusively do
    allocations.export_all.map { |v| add_block_ids(v)}
  end
end

#export_allocatedObject



156
157
158
159
160
# File 'lib/osctld/id_range.rb', line 156

def export_allocated
  inclusively do
    allocations.export_allocated.map { |v| add_block_ids(v)}
  end
end

#export_at(block_index) ⇒ Object

Parameters:

  • block_index (Integer)


169
170
171
172
173
# File 'lib/osctld/id_range.rb', line 169

def export_at(block_index)
  inclusively do
    add_block_ids(allocations.export_at(block_index))
  end
end

#export_freeObject



162
163
164
165
166
# File 'lib/osctld/id_range.rb', line 162

def export_free
  inclusively do
    allocations.export_free.map { |v| add_block_ids(v) }
  end
end

#free_at(block_index) ⇒ Object

Parameters:

  • block_index (Integer)


66
67
68
69
70
71
72
73
# File 'lib/osctld/id_range.rb', line 66

def free_at(block_index)
  exclusively do
    unless allocations.free_at(block_index)
      raise AllocationError, "block at index #{block_index} not found"
    end
    save_config
  end
end

#free_by(owner) ⇒ Object

Parameters:

  • owner (String)


76
77
78
79
80
81
# File 'lib/osctld/id_range.rb', line 76

def free_by(owner)
  exclusively do
    allocations.free_by(owner)
    save_config
  end
end

#idObject



25
26
27
# File 'lib/osctld/id_range.rb', line 25

def id
  name
end

#last_idObject



131
132
133
# File 'lib/osctld/id_range.rb', line 131

def last_id
  start_id + block_size * block_count - 1
end

#load_configObject (protected)



195
196
197
198
199
200
201
202
203
# File 'lib/osctld/id_range.rb', line 195

def load_config
  cfg = YAML.load_file(config_path)

  @start_id = cfg['start_id']
  @block_size = cfg['block_size']
  @block_count = cfg['block_count']
  @allocations = AllocationTable.load(block_count, cfg['allocations'])
  @attrs = Attributes.load(cfg['attrs'] || {})
end

#manipulation_resourceObject



179
180
181
# File 'lib/osctld/id_range.rb', line 179

def manipulation_resource
  ['id-range', "#{pool.name}:#{name}"]
end

#save_configObject (protected)



205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/osctld/id_range.rb', line 205

def save_config
  File.open(config_path, 'w', 0400) do |f|
    f.write(YAML.dump({
      'start_id' => start_id,
      'block_size' => block_size,
      'block_count' => block_count,
      'allocations' => allocations.dump,
      'attrs' => attrs.dump,
    }))
  end

  File.chown(0, 0, config_path)
end

#set(opts) ⇒ Object

Parameters:

  • opts (Hash)

Options Hash (opts):

  • :attrs (Hash)


101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/osctld/id_range.rb', line 101

def set(opts)
  opts.each do |k, v|
    case k
    when :attrs
      attrs.update(v)

    else
      fail "unsupported option '#{k}'"
    end
  end

  save_config
end

#unset(opts) ⇒ Object

Parameters:

  • opts (Hash)

Options Hash (opts):

  • :attrs (Array<String>)


117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/osctld/id_range.rb', line 117

def unset(opts)
  opts.each do |k, v|
    case k
    when :attrs
      v.each { |attr| attrs.unset(attr) }

    else
      fail "unsupported option '#{k}'"
    end
  end

  save_config
end