class CrapServer::Application

Example:

Crap::Application.run! do |data|

if data =~ /^GET/i
  write SomeDatabase.get('column')
elsif data =~/SET/
  SomeDatabase.set('column', data.split(' ')[1])
else
  write 'Error. Invalid action.'
end

end

Public Class Methods

configure(&block) click to toggle source
# File lib/crap_server/application.rb, line 20
def configure(&block)
  @config ||= CrapServer::Configure.new
  block.yield @config
end
per_process(&block) click to toggle source
# File lib/crap_server/application.rb, line 25
def per_process(&block)
  @per_process_block = block
end
run!(&block) click to toggle source

Main method. This setup all the connections and make the logic of the app

# File lib/crap_server/application.rb, line 30
def run!(&block)
  begin
    logger.info 'Initializing Crap Server'
    # Bup the maximum opened file to the maximum allowed by the system
    Process.setrlimit(:NOFILE, Process.getrlimit(:NOFILE)[1])

    # Start IPv4 and IPv6 connection for the current port
    open_connections


    # Some log info to the user :)
    logger.info "Listening 0.0.0.0:#{config.port}"
    logger.debug "Maximum allowed waiting connections: #{Socket::SOMAXCONN}"
    logger.debug "Maximum number of allowed connections: #{Process.getrlimit(:NOFILE)[1]}" # Same as maximum of opened files
    logger.debug "Number of threads per core: #{config.pool_size}"
    logger.info 'Everything is ready. Have fun!'
    logger.info ''

    # Prefork and handle the connections in each process.
    forker = CrapServer::Forker.new([socket_ipv4, socket_ipv6])
    # Run loop. (basically, waiting until Ctrl+C)
    forker.run &block

  # If any kind of error happens, we MUST close the sockets
  rescue => e
    logger.error "Error: #{e.message}"
    e.backtrace.each do |line|
      logger.error line
    end
  # We don't need to close the socket, because are closed automatically by ruby

  rescue Interrupt
    # We don't need to close the socket, because are closed automatically by ruby
    # Leaved in black only to prevent error backtrace.
    # The process are killed by CrapServer::Forker
  end
end

Protected Class Methods

config() click to toggle source

Main configuration. See Crap::Configure

# File lib/crap_server/application.rb, line 128
def config
  @config ||= CrapServer::Configure.new
end
logger() click to toggle source
# File lib/crap_server/application.rb, line 136
def logger
  if not @logger
    @logger = Logger.new(config.log_file)
    @logger.level = config.log_level
  end
  @logger
end
logger=(value) click to toggle source
# File lib/crap_server/application.rb, line 132
def logger=(value)
  @logger = value
end
open_connections() click to toggle source

Open TCP connection (IPv4 and IPv6)

# File lib/crap_server/application.rb, line 75
def open_connections
  start_ipv4_socket
  start_ipv6_socket
end
per_process_block() click to toggle source
# File lib/crap_server/application.rb, line 70
def per_process_block
  @per_process_block
end
socket_ipv4() click to toggle source
# File lib/crap_server/application.rb, line 118
def socket_ipv4
  @socket4
end
socket_ipv4=(value) click to toggle source
# File lib/crap_server/application.rb, line 122
def socket_ipv4=(value)
  @socket4 = value
end
socket_ipv6() click to toggle source
# File lib/crap_server/application.rb, line 110
def socket_ipv6
  @socket6
end
socket_ipv6=(value) click to toggle source
# File lib/crap_server/application.rb, line 114
def socket_ipv6=(value)
  @socket6 = value
end
start_ipv4_socket() click to toggle source
# File lib/crap_server/application.rb, line 86
def start_ipv4_socket
  # :INET is to open an IPv4 connection
  # :STREAM is to open a TCP socket
  @socket4 = start_socket :INET, :STREAM, '0.0.0.0'
end
start_ipv6_socket() click to toggle source
# File lib/crap_server/application.rb, line 80
def start_ipv6_socket
  # :INET6 is to open an IPv6 connection
  # :STREAM is to open a TCP socket
  @socket6 = start_socket :INET6, :STREAM, '::1'
end
start_socket(version, type, loopback) click to toggle source
# File lib/crap_server/application.rb, line 92
def start_socket(version, type, loopback)
  socket = Socket.new(version, type)

  begin
    # Now, bind the port.
    socket.bind(Socket.pack_sockaddr_in(config.port, loopback))
  rescue Errno::EADDRINUSE
    socket.close
    raise ConnectionError.new "Unable to bind #{config.port} port."
  end

  socket.listen(config.max_pending_connections)
  # Tell to the Kernel that is ok to rebind the port if is in TIME_WAIT state (after close the connection
  # and the Kernel wait for client acknowledgement)
  socket.setsockopt(:SOCKET, :REUSEADDR, true)
  socket
end