X-Git-Url: http://git.sourceforge.jp/view?p=shogi-server%2Fshogi-server.git;a=blobdiff_plain;f=shogi-server;h=d79f1657836dba993c41c781472d875e5e92a3c3;hp=1058135f6706f9d6a82c91b8f841e8a243df015f;hb=42fea02e19112ca25966e705ee98cd45cfc70155;hpb=179c06c16511e021caeac33b70c4cd88e04b6df5;ds=inline diff --git a/shogi-server b/shogi-server index 1058135..d79f165 100755 --- a/shogi-server +++ b/shogi-server @@ -1,4 +1,4 @@ -#! /usr/bin/env ruby +#! /usr/bin/ruby1.9.1 # $Id$ # # Author:: NABEYA Kenichi, Daigo Moriwaki @@ -33,6 +33,7 @@ $:.unshift File.dirname(__FILE__) require 'shogi_server' require 'shogi_server/config' require 'shogi_server/util' +require 'shogi_server/league/floodgate_thread.rb' require 'tempfile' ################################################# @@ -41,6 +42,12 @@ require 'tempfile' ShogiServer.reload +# Return +# - a received string +# - :timeout +# - :exception +# - nil when a socket is closed +# def gets_safe(socket, timeout=nil) if r = select([socket], nil, nil, timeout) return r[0].first.gets @@ -55,33 +62,92 @@ end def usage print <.conf". The file will be re-read once just after a + game starts. + + For example, a floodgate-3600-30 game group requires + floodgate-3600-30.conf. However, for floodgate-900-0 and + floodgate-3600-0, which were default enabled in previous + versions, configuration files are optional if you are happy with + default time settings. + File format is: + Line format: + # This is a comment line + DoW Time + ... + where + DoW := "Sun" | "Mon" | "Tue" | "Wed" | "Thu" | "Fri" | "Sat" | + "Sunday" | "Monday" | "Tuesday" | "Wednesday" | "Thursday" | + "Friday" | "Saturday" + Time := HH:MM + + For example, + Sat 13:00 + Sat 22:00 + Sun 13:00 + LICENSE - GPL versoin 2 or later + GPL versoin 2 or later SEE ALSO RELEASE - #{ShogiServer::Release} + #{ShogiServer::Release} REVISION - #{ShogiServer::Revision} + #{ShogiServer::Revision} EOM end @@ -115,6 +181,7 @@ def parse_command_line options = Hash::new parser = GetoptLong.new( ["--daemon", GetoptLong::REQUIRED_ARGUMENT], + ["--floodgate-games", GetoptLong::REQUIRED_ARGUMENT], ["--pid-file", GetoptLong::REQUIRED_ARGUMENT], ["--player-log-dir", GetoptLong::REQUIRED_ARGUMENT]) parser.quiet = true @@ -168,6 +235,19 @@ def check_command_line end end + if $options["floodgate-games"] + names = $options["floodgate-games"].split(",") + new_names = + names.select do |name| + ShogiServer::League::Floodgate::game_name?(name) + end + if names.size != new_names.size + $stderr.puts "Found a wrong Floodgate game: %s" % [names.join(",")] + exit 6 + end + $options["floodgate-games"] = new_names + end + if $options["floodgate-history"] $stderr.puts "WARNING: --floodgate-history has been deprecated." $options["floodgate-history"] = nil @@ -278,73 +358,6 @@ def setup_watchdog_for_giant_lock end end -def floodgate_reload_log(leagues) - floodgate = leagues.min {|a,b| a.next_time <=> b.next_time} - diff = floodgate.next_time - Time.now - log_message("Floodgate reloaded. The next match will start at %s in %d seconds" % - [floodgate.next_time, diff]) -end - -def setup_floodgate(game_names) - return Thread.start(game_names) do |game_names| - Thread.pass - leagues = game_names.collect do |game_name| - ShogiServer::League::Floodgate.new($league, - {:game_name => game_name}) - end - leagues.delete_if do |floodgate| - ret = false - unless floodgate.next_time - log_error("Unsupported game name: %s" % floodgate.game_name) - ret = true - end - ret - end - if leagues.empty? - log_error("No valid Floodgate game names found") - return # exit from this thread - end - floodgate_reload_log(leagues) - - while (true) - begin - floodgate = leagues.min {|a,b| a.next_time <=> b.next_time} - diff = floodgate.next_time - Time.now - if diff > 0 - floodgate_reload_log(leagues) if $DEBUG - sleep(diff/2) - next - end - next_array = leagues.collect do |floodgate| - if (floodgate.next_time - Time.now) > 0 - [floodgate.game_name, floodgate.next_time] - else - log_message("Starting Floodgate games...: %s" % [floodgate.game_name]) - $league.reload - floodgate.match_game - floodgate.charge - [floodgate.game_name, floodgate.next_time] # next_time has been updated - end - end - $mutex.synchronize do - log_message("Reloading source...") - ShogiServer.reload - end - # Regenerate floodgate instances after ShogiServer.realod - leagues = next_array.collect do |game_name, next_time| - floodgate = ShogiServer::League::Floodgate.new($league, - {:game_name => game_name, - :next_time => next_time}) - end - floodgate_reload_log(leagues) - rescue Exception => ex - # ignore errors - log_error("[in Floodgate's thread] #{ex} #{ex.backtrace}") - end - end - end -end - def main $options = parse_command_line @@ -366,7 +379,7 @@ def main config[:ServerType] = WEBrick::Daemon if $options["daemon"] config[:Logger] = $logger - fg_thread = nil + setup_floodgate = nil config[:StartCallback] = Proc.new do srand @@ -375,7 +388,8 @@ def main end setup_watchdog_for_giant_lock $league.setup_players_database - fg_thread = setup_floodgate(["floodgate-900-0", "floodgate-3600-0"]) + setup_floodgate = ShogiServer::SetupFloodgate.new($options["floodgate-games"]) + setup_floodgate.start end config[:StopCallback] = Proc.new do @@ -389,7 +403,7 @@ def main ["INT", "TERM"].each do |signal| trap(signal) do server.shutdown - fg_thread.kill if fg_thread + setup_floodgate.kill end end unless (RUBY_PLATFORM.downcase =~ /mswin|mingw|cygwin|bccwin/) @@ -401,11 +415,15 @@ def main log_message("server started [Revision: #{ShogiServer::Revision}]") server.start do |client| + begin # client.sync = true # this is already set in WEBrick client.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, true) # Keepalive time can be set by /proc/sys/net/ipv4/tcp_keepalive_time player, login = login_loop(client) # loop - next unless player + unless player + log_error("Detected a timed out login attempt") + next + end log_message(sprintf("user %s login", player.name)) login.process @@ -416,12 +434,16 @@ def main if (player.game) player.game.kill(player) end - player.finish # socket has been closed + player.finish $league.delete(player) log_message(sprintf("user %s logout", player.name)) ensure $mutex.unlock end + player.wait_write_thread_finish(1000) # milliseconds + rescue Exception => ex + log_error("server.start: #{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}") + end end end