class Arv::Collection::LocatorList

Public Class Methods

new(locators) click to toggle source

LocatorList efficiently builds LocatorSegments from a stream manifest.

# File lib/arvados/collection.rb, line 176
def initialize(locators)
  next_start = 0
  @ranges = locators.map do |loc_s|
    new_range = LocatorRange.new(loc_s, next_start)
    next_start = new_range.end
    new_range
  end
end

Public Instance Methods

segment(start_pos, length) click to toggle source
# File lib/arvados/collection.rb, line 185
def segment(start_pos, length)
  # Return a LocatorSegment that captures `length` bytes from `start_pos`.
  start_index = search_for_byte(start_pos)
  if length == 0
    end_index = start_index
  else
    end_index = search_for_byte(start_pos + length - 1, start_index)
  end
  seg_ranges = @ranges[start_index..end_index]
  Struct::LocatorSegment.new(seg_ranges.map(&:locator),
                             start_pos - seg_ranges.first.begin,
                             length)
end

Private Instance Methods

search_for_byte(target, start_index=0) click to toggle source
# File lib/arvados/collection.rb, line 201
def search_for_byte(target, start_index=0)
  # Do a binary search for byte `target` in the list of locators,
  # starting from `start_index`.  Return the index of the range in
  # @ranges that contains the byte.
  lo = start_index
  hi = @ranges.size
  loop do
    ii = (lo + hi) / 2
    range = @ranges[ii]
    if range.include?(target) && (target < range.end || ii == hi-1)
      return ii
    elsif ii == lo
      raise RangeError.new("%i not in segment" % target)
    elsif target < range.begin
      hi = ii
    else
      lo = ii
    end
  end
end