| 3 | | |
|---|
| 4 | | BEGIN { |
|---|
| 5 | | begin |
|---|
| 6 | | require 'fastthread' |
|---|
| 7 | | require 'thread' |
|---|
| 8 | | puts 'Using FastThread' |
|---|
| 9 | | rescue LoadError |
|---|
| 10 | | puts "not using FastThread" |
|---|
| 11 | | end |
|---|
| 12 | | } |
|---|
| 13 | | begin |
|---|
| 14 | | require 'fjson' |
|---|
| 15 | | puts "using fjson" |
|---|
| 16 | | rescue LoadError |
|---|
| 17 | | require 'json' |
|---|
| 18 | | end |
|---|
| 19 | | require 'optparse' |
|---|
| 20 | | require 'ostruct' |
|---|
| 21 | | require 'fileutils' |
|---|
| 22 | | require 'yaml' |
|---|
| 23 | | require 'erubis' |
|---|
| 24 | | |
|---|
| 25 | | module Erubis |
|---|
| 26 | | class MEruby < Erubis::Eruby |
|---|
| 27 | | include PercentLineEnhancer |
|---|
| 28 | | include StringBufferEnhancer |
|---|
| 29 | | end |
|---|
| 30 | | end |
|---|
| 31 | | |
|---|
| 32 | | module Merb; end |
|---|
| 33 | | |
|---|
| 34 | | class Merb::Config |
|---|
| 35 | | def self.setup |
|---|
| 36 | | defaults = { |
|---|
| 37 | | :host => "0.0.0.0", |
|---|
| 38 | | :port => "4000", |
|---|
| 39 | | :allow_reloading => true, |
|---|
| 40 | | :merb_root => Dir.pwd, |
|---|
| 41 | | :template_ext => {:html => :herb, :js => :jerb, :xml => :xerb} |
|---|
| 42 | | } |
|---|
| 43 | | begin |
|---|
| 44 | | options = defaults.merge(YAML.load(Erubis::MEruby.new(IO.read("#{defaults[:merb_root]}/dist/conf/merb.yml")).result)) |
|---|
| 45 | | rescue |
|---|
| 46 | | options = defaults |
|---|
| 47 | | end |
|---|
| 48 | | |
|---|
| 49 | | options |
|---|
| 50 | | end |
|---|
| 51 | | end |
|---|
| 52 | | |
|---|
| 53 | | class Merb::Server |
|---|
| 54 | | |
|---|
| 55 | | def self.merb_config |
|---|
| 56 | | options = Merb::Config.setup |
|---|
| 57 | | |
|---|
| 58 | | opts = OptionParser.new do |opts| |
|---|
| 59 | | opts.banner = "Usage: merb [fdcphmisl] [argument]" |
|---|
| 60 | | opts.define_head "Merb Mongrel+ Erb. Lightweight replacement for ActionPack" |
|---|
| 61 | | opts.separator '*'*80 |
|---|
| 62 | | opts.separator 'If no flags are given, Merb starts in the foreground on port 4000' |
|---|
| 63 | | opts.separator '*'*80 |
|---|
| 64 | | |
|---|
| 65 | | opts.on("-f", "--config-file FILENAME", "This flag is for adding extra config files for things like the upload progress module") do |config| |
|---|
| 66 | | options[:config] = config |
|---|
| 67 | | end |
|---|
| 68 | | |
|---|
| 69 | | opts.on("-d", "--daemonize", "This will run a single merb in the background") do |config| |
|---|
| 70 | | options[:daemonize] = true |
|---|
| 71 | | end |
|---|
| 72 | | |
|---|
| 73 | | opts.on("-c", "--cluster-nodes NUM_MERBS", "Number of merb daemons to run") do |nodes| |
|---|
| 74 | | options[:cluster] = nodes |
|---|
| 75 | | end |
|---|
| 76 | | |
|---|
| 77 | | opts.on("-p", "--port PORTNUM", "Port to run merb on, defaults to 4000") do |port| |
|---|
| 78 | | options[:port] = port |
|---|
| 79 | | end |
|---|
| 80 | | |
|---|
| 81 | | opts.on("-h", "--host HOSTNAME", "Host to bind to(default is all IP's)") do |host| |
|---|
| 82 | | options[:host] = host |
|---|
| 83 | | end |
|---|
| 84 | | |
|---|
| 85 | | opts.on("-m", "--merb-root MERB_ROOT", "the path to the MERB_ROOT for the app you want to run") do |merb_root| |
|---|
| 86 | | options[:merb_root] = File.expand_path(merb_root) |
|---|
| 87 | | end |
|---|
| 88 | | |
|---|
| 89 | | opts.on("-i", "--irb-console", "This flag will start merb in irb console mode. All your models and other classes will be available for you in an irb session.") do |console| |
|---|
| 90 | | options[:console] = true |
|---|
| 91 | | end |
|---|
| 92 | | |
|---|
| 93 | | opts.on("-s", "--server-drb-port PORTNUM", "This is the port number to run the drb daemon on for sessions and uplod progress monitoring.") do |drb_port| |
|---|
| 94 | | options[:server_drb_port] = drb_port |
|---|
| 95 | | end |
|---|
| 96 | | |
|---|
| 97 | | opts.on("-l", "--log-level LEVEL", "Log levels can be set to any of these options: DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN") do |loglevel| |
|---|
| 98 | | options[:log_level] = loglevel |
|---|
| 99 | | end |
|---|
| 100 | | |
|---|
| 101 | | opts.on("-?", "--help", "Show this help message") do |
|---|
| 102 | | puts opts |
|---|
| 103 | | exit |
|---|
| 104 | | end |
|---|
| 105 | | |
|---|
| 106 | | end |
|---|
| 107 | | |
|---|
| 108 | | opts.parse!(@@merb_raw_opts) |
|---|
| 109 | | |
|---|
| 110 | | |
|---|
| 111 | | @@merb_opts = options |
|---|
| 112 | | puts %{Merb started with these options:} |
|---|
| 113 | | puts @@merb_opts.to_yaml; puts |
|---|
| 114 | | end |
|---|
| 115 | | |
|---|
| 116 | | def self.initialize_merb |
|---|
| 117 | | require 'merb' |
|---|
| 118 | | require @@merb_opts[:merb_root]+'/dist/conf/router.rb' |
|---|
| 119 | | require @@merb_opts[:merb_root]+'/dist/conf/merb_init.rb' |
|---|
| 120 | | end |
|---|
| 121 | | |
|---|
| 122 | | def self.run |
|---|
| 123 | | @@merb_raw_opts = ARGV |
|---|
| 124 | | merb_config |
|---|
| 125 | | |
|---|
| 126 | | @@merb_opts[:dist_root] = @@merb_opts[:merb_root]+'/dist' |
|---|
| 127 | | $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/app/controllers') ) |
|---|
| 128 | | $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/app/models') ) |
|---|
| 129 | | $LOAD_PATH.unshift( File.join(@@merb_opts[:dist_root] , '/lib') ) |
|---|
| 130 | | |
|---|
| 131 | | if @@merb_opts[:console] |
|---|
| 132 | | initialize_merb |
|---|
| 133 | | ARGV.clear # Avoid passing args to IRB |
|---|
| 134 | | require 'irb' |
|---|
| 135 | | require 'irb/completion' |
|---|
| 136 | | def exit |
|---|
| 137 | | exit! |
|---|
| 138 | | end |
|---|
| 139 | | if File.exists? ".irbrc" |
|---|
| 140 | | ENV['IRBRC'] = ".irbrc" |
|---|
| 141 | | end |
|---|
| 142 | | IRB.start |
|---|
| 143 | | exit! |
|---|
| 144 | | end |
|---|
| 145 | | |
|---|
| 146 | | if @@merb_opts[:server_drb_port] |
|---|
| 147 | | start(@@merb_opts[:server_drb_port], :drbserver_start) |
|---|
| 148 | | end |
|---|
| 149 | | |
|---|
| 150 | | if @@merb_opts[:cluster] |
|---|
| 151 | | delete_pidfiles |
|---|
| 152 | | @@merb_opts[:port].to_i.upto(@@merb_opts[:port].to_i+@@merb_opts[:cluster].to_i-1) do |port| |
|---|
| 153 | | puts "Starting merb server on port: #{port}" |
|---|
| 154 | | start(port) |
|---|
| 155 | | end |
|---|
| 156 | | elsif @@merb_opts[:daemonize] |
|---|
| 157 | | delete_pidfiles(@@merb_opts[:port]) |
|---|
| 158 | | start(@@merb_opts[:port]) |
|---|
| 159 | | else |
|---|
| 160 | | initialize_merb |
|---|
| 161 | | trap('TERM') { exit } |
|---|
| 162 | | mongrel_start(@@merb_opts[:port]) |
|---|
| 163 | | end |
|---|
| 164 | | |
|---|
| 165 | | end |
|---|
| 166 | | |
|---|
| 167 | | def self.store_pid(pid,port) |
|---|
| 168 | | File.open("#{@@merb_opts[:merb_root]}/log/merb.#{port}.pid", 'w'){|f| f.write("#{Process.pid}\n")} |
|---|
| 169 | | end |
|---|
| 170 | | |
|---|
| 171 | | def self.start(port,what=:mongrel_start) |
|---|
| 172 | | fork do |
|---|
| 173 | | Process.setsid |
|---|
| 174 | | exit if fork |
|---|
| 175 | | if what == :mongrel_start |
|---|
| 176 | | store_pid(Process.pid, port) |
|---|
| 177 | | else |
|---|
| 178 | | store_pid(Process.pid, "drb.#{port}") |
|---|
| 179 | | end |
|---|
| 180 | | Dir.chdir @@merb_opts[:merb_root] |
|---|
| 181 | | File.umask 0000 |
|---|
| 182 | | STDIN.reopen "/dev/null" |
|---|
| 183 | | STDOUT.reopen "/dev/null", "a" |
|---|
| 184 | | STDERR.reopen STDOUT |
|---|
| 185 | | trap("TERM") { exit } |
|---|
| 186 | | send(what, port) |
|---|
| 187 | | end |
|---|
| 188 | | end |
|---|
| 189 | | |
|---|
| 190 | | def self.delete_pidfiles(portor_star='*') |
|---|
| 191 | | Dir["#{@@merb_opts[:merb_root]}/log/merb.#{portor_star}.pid"].each do |pid| |
|---|
| 192 | | FileUtils.rm(pid) rescue nil |
|---|
| 193 | | end |
|---|
| 194 | | end |
|---|
| 195 | | |
|---|
| 196 | | def self.drbserver_start(port) |
|---|
| 197 | | puts "Starting merb drb server on port: #{port}" |
|---|
| 198 | | require 'merb/merb_drb_server' |
|---|
| 199 | | DRb.start_service("druby://#{@@merb_opts[:host]}:#{port}", Merb::DrbServiceProvider) |
|---|
| 200 | | DRb.thread.join |
|---|
| 201 | | end |
|---|
| 202 | | |
|---|
| 203 | | def self.mongrel_start(port) |
|---|
| 204 | | @@merb_opts[:port] = port |
|---|
| 205 | | initialize_merb |
|---|
| 206 | | |
|---|
| 207 | | config = Mongrel::Configurator.new :host => (@@merb_opts[:host]||"0.0.0.0"), :port => (port ||4000) do |
|---|
| 208 | | config = YAML.load(Erubis::Eruby.new(IO.read(File.expand_path(@@merb_opts[:config]))).result) if @@merb_opts[:config] |
|---|
| 209 | | listener do |
|---|
| 210 | | uri( "/", :handler => MerbUploadHandler.new(config), :in_front => true) if @@merb_opts[:config] |
|---|
| 211 | | uri "/", :handler => MerbHandler.new(@@merb_opts[:dist_root]+'/public') |
|---|
| 212 | | uri "/favicon.ico", :handler => Mongrel::Error404Handler.new("") |
|---|
| 213 | | end |
|---|
| 214 | | |
|---|
| 215 | | trap("INT") { stop } |
|---|
| 216 | | run |
|---|
| 217 | | end |
|---|
| 218 | | config.join |
|---|
| 219 | | end |
|---|
| 220 | | |
|---|
| 221 | | def self.config |
|---|
| 222 | | @@merb_opts |
|---|
| 223 | | end |
|---|
| 224 | | |
|---|
| 225 | | end |
|---|
| 226 | | |
|---|
| | 4 | require 'merb/merb_server' |
|---|