module EY module Backup module Splitter extend Spawner extend Logging extend self CHUNK_SIZE = 1024 * 64 MAX_FILE_SIZE = (4.5*1024*1024*1024).to_i #4.5GB def load(backup) if backup.files.size > 1 backup.files = join(backup.files) end backup end def dump(command, files) if files.size != 1 fatal "Can't split multiple files." end end def dump(backup) output_files = backup.files.map do |file| if File.size(file) >= split_size split(file) else file end end.flatten backup.files = output_files backup end def join(input_files) filename = input_files.first.sub(/\.part\d+$/, '') File.open(filename, 'w') do |output| sort(input_files).each do |input| File.open(input, 'r') do |i| while chunk = i.read(CHUNK_SIZE) output << chunk end end FileUtils.rm(input) end end [filename] end def sort(input_files) input_files.sort {|a,b| part_number(a) <=> part_number(b) } end def part_number(file) file[/\.part(\d+)/, 1].to_i end def split(file) total_size, part = 0, 0 files = [] File.open(file, 'r') do |i| until total_size == File.size(file) part += 1 part_size = 0 filename = "#{file}.part#{part}" File.open(filename, 'w') do |o| while part_size < split_size && (chunk = i.read([split_size - part_size, CHUNK_SIZE].min)) part_size += chunk.size o << chunk end end total_size += part_size files << filename end end FileUtils.rm(file) files end def split_size EY::Backup.config.split_size || MAX_FILE_SIZE end end end end