class Object
Constants
- MAX_SIZE
Public Instance Methods
collect_hostlist(hosts, silently_discard_bad = false)
click to toggle source
Collect a hostlist string from a list of hosts
# File lib/hostlist_expand_collect.rb, line 122 def collect_hostlist(hosts, silently_discard_bad = false) left_right = [] hosts.each do |host| # Remove leading and trailing whitespace first, and skip empty lines host = host.strip next if host.empty? # We cannot accept a host containing any of the three special # characters in the hostlist syntax (comma and flat brackets) unless host.scan(/[\[\]\,]/).empty? next if silently_discard_bad raise 'Error! Forbidden character!' end left_right.push [host, ""] end # Call the iterative function until it syas it's done looping = true while looping left_right, looping = collect_hostlist_1 left_right end return (left_right.collect { |left, right| left + right }).join(",") end
collect_hostlist_1(left_right, silently_discard_bad = false)
click to toggle source
Collect a hostlist string from a list of hosts (left + right)
# File lib/hostlist_expand_collect.rb, line 162 def collect_hostlist_1(left_right, silently_discard_bad = false) # Scan a list of hosts (left+right) and build two things: # 1) a set of all hosts seen (used later) # 2) a list where each host entry is preprocessed for correct sorting sortlist = [] remeaning = Set.new left_right.each do |left, right| host = left + right remeaning.add host m = /^(.*?)([0-9]+)?([^0-9]*)$/.match left prefix, num_str, suffix = m[1], m[2], m[3] suffix = suffix + right unless num_str throw 'Error! Prefix is not empty' unless prefix.empty? sortlist.push [[host, nil], nil, nil, host] else num_int = num_str.to_i sortlist.push [[prefix, suffix], num_int, num_str.length, host] end end sortlist.sort! results = [] need_another_loop = false sortlist.group_by { |x| x[0] }.each do |prefix_suffix, group| prefix, suffix = prefix_suffix unless suffix # Special case: a host with no numeric part results.push ["", prefix] remeaning.delete prefix else # General case range_list = [] group.each do |prefix_suffix_2, num_int, num_width, host| prefix_2, suffix_2 = prefix_suffix_2 next unless remeaning.include? host raise 'Error! num_int is nil' unless num_int # Scan for a range starting at the current host low = num_int while true host = "#{prefix}%0#{num_width}d#{suffix}" % num_int if remeaning.include? host remeaning.delete host num_int += 1 else break end end high = num_int - 1 raise 'Error! High < Low' if high < low range_list.push [low, high, num_width] end need_another_loop = true if range_list.length == 1 and range_list[0][0] == range_list[0][1] results.push [prefix, "%0#{range_list[0][2]}d#{suffix}" % range_list[0][0]] else results.push [prefix, "[" + range_list.map { |l, h, w| format_range(l, h, w)}.join(',') + "]" + suffix] end end end raise 'Error! Remeaning is not empty' unless remeaning.empty? return results, need_another_loop end
expand_hostlist(hostlist, allow_duplicates=false)
click to toggle source
Expand a hostlist expression string to list
Example: expand_hostlist(“n,d”) ==>
['n9', 'n10', 'n11', 'd01', 'd02']
# File lib/hostlist_expand_collect.rb, line 84 def expand_hostlist(hostlist, allow_duplicates=false) results = [] bracket_level = 0 part = '' (hostlist + ',').each_char do |c| if c == ',' and bracket_level == 0 if part results.concat(expand_part part) end part = '' bad_part = false else part += c end bracket_level += 1 if c == '[' bracket_level -= 1 if c == ']' if bracket_level > 1 raise 'Error! Bad hostlist (nested brackets)' elsif bracket_level < 0 raise 'Error! Bad hostlist (unbalanced brackets)' end end if bracket_level > 0 raise 'Error! Bad hostlist (unbalanced brackets)' end return remove_duplicates(results) unless allow_duplicates results end
expand_part(s)
click to toggle source
Expand a part (e.g. “x[1-2]y[1-3] (no outer level commas)”)
# File lib/hostlist_expand_collect.rb, line 42 def expand_part(s) # Базовый случай - пустая часть развернётся в список с "" return [""] if s == '' # Разбить на: # 1) Строку префикс (может быть пустой) # 2) Rangelist в скобках (может быть пропущен) # 3) Остальное m = /([^,\[]*)(\[[^\]]*\])?(.*)/.match s prefix, rangelist, rest = m[1], m[2], m[3] # Развернём остаток rest_expanded = expand_part rest # Развернём собственную часть unless rangelist us_expanded = [prefix] else us_expanded = expand_rangelist(prefix, rangelist[1..-2]) end # Комбинируем список со списком if us_expanded.length * rest_expanded.length > MAX_SIZE raise 'Error! Bad hostlist (results too large)' end us_expanded.product(rest_expanded).collect { |x, y| x + y } end
expand_range(prefix, r)
click to toggle source
Expand a range (e.g/ 1-10 or 14), putting a prefix before
# File lib/hostlist_expand_collect.rb, line 7 def expand_range(prefix, r) return ["#{prefix}#{r}"] if /^[0-9]+$/.match r m = /^([0-9]+)-([0-9]+)$/.match r raise 'Error! Bad hostlist (bad range)' unless m s_low, s_high = m[1], m[2] low = s_low.to_i high = s_high.to_i raise 'Error! Start > Stop' if high < low raise 'Error! Range too large' if high - low > MAX_SIZE result = [] (low..high).each { |v| result.push "#{prefix}%0#{s_low.length}d" % v } result end
expand_rangelist(prefix, rangelist)
click to toggle source
Expand a rangelist (e.g “1-10,14”), putting a prefix before.
# File lib/hostlist_expand_collect.rb, line 30 def expand_rangelist(prefix, rangelist) result = [] rangelist.split(",").each do |r| result.concat(expand_range(prefix, r)) end result end
format_range(low, high, width)
click to toggle source
Format a range from low to high inclusively, with a certain width
# File lib/hostlist_expand_collect.rb, line 154 def format_range(low, high, width) return "%0#{width}d" % low if low == high "%0#{width}d-" % low + "%0#{width}d" % high end
remove_duplicates(l)
click to toggle source
Удалить дубликаты из списка
# File lib/hostlist_expand_collect.rb, line 75 def remove_duplicates(l) l.to_set.to_a end