Class: Ballad::Cli

Inherits:
Object
  • Object
show all
Defined in:
lib/ballad/cli.rb

Defined Under Namespace

Classes: Option

Instance Method Summary collapse

Constructor Details

#initializeCli

Returns a new instance of Cli.



10
11
12
13
14
15
# File 'lib/ballad/cli.rb', line 10

def initialize
  @opt = Ballad::Cli::Option.new
  @i_p_q = Queue.new
  @i_r_q = Queue.new
  @p_r_q = Queue.new
end

Instance Method Details

#edit(res) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ballad/cli.rb', line 111

def edit(res)
  if res.nil?
    return "???"
  end
  outputs = []
  @opt.args.each do |arg|
    case arg
    when :status
      outputs << res.code
    end
  end
  outputs.join("\t")
end

#fetch(url) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/ballad/cli.rb', line 125

def fetch(url)
  uri = URI.parse(url)
  klass = Net::HTTP.const_get(@opt.http_method.capitalize.to_sym)
  req = klass.new(uri.path)
  Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == "https") do |http|
    http.open_timeout = 10
    http.read_timeout = 10
    http.request req
  end
rescue
  return nil
end

#optionObject



107
108
109
# File 'lib/ballad/cli.rb', line 107

def option
  @opt
end

#parseObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/ballad/cli.rb', line 17

def parse
  # default settings
  @opt.args = [:status]
  @opt.concurrency = Etc.respond_to?(:nprocessors) ? Etc.nprocessors : 8
  @opt.http_method = :head

  parser = OptionParser.new do |o|
    o.on '-s', 'edit by HTTP response status code (default on)' do |arg|
      @opt.args << :status unless opt.args.index(:status)
    end
    o.on '-j=num', 'number of concurrent (default is cpu count)' do |arg|
      raise "number of concurrent should be over 1" unless 0 < arg.to_i
      @opt.concurrency = arg.to_i
    end
    o.on '-m=name', 'request http method (default head)' do |arg|
      @opt.http_method = arg
    end
  end
  parser.parse!(ARGV)

  self
end

#runObject

Thread design

| input | -> | pool | -> | | -> | output |

|                    | results |
+------------------->|         |


45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/ballad/cli.rb', line 45

def run
  in_count = 0
  out_count = 0
  quit = false
  m = Mutex.new
  pool = Array.new(@opt.concurrency) {
    Thread.start {
      while true
        url = @i_p_q.pop
        res = fetch(url)
        @p_r_q.push [edit(res), url]
      end
    }
  }
  IO.pipe do |r, w|
    result_thread = Thread.start {
      stock = []
      check = -> {
        if quit && in_count == out_count
          w.write "q"
          w.close
          Thread.exit
        end
      }
      out_proc = -> (set) {
        print "#{set[0]}\t#{set[1]}\n"
        out_count += 1
        stock.delete(set)
        check.call
      }
      while input = @i_r_q.pop
        found = false
        while st = stock.rassoc(input)
          out_proc.call(st)
          found = true
        end

        next if found
        check.call
        while res = @p_r_q.pop
          if res[1] == input
            out_proc.call(res)
            break
          else
            stock << res
          end
        end
      end
    }
    while line = $stdin.gets
      in_count += 1
      url = line.chomp
      @i_p_q.push url
      @i_r_q.push url
    end
    quit = true
    r.read(1) # wait for all task
    pool.each(&:kill)
    result_thread.kill
  end
end