* Debugged write thread termination.
$:.unshift File.dirname(__FILE__)
require 'shogi_server'
-require 'shogi_server/board' # not autoloaded
-require 'shogi_server/player'
-require 'shogi_server/game'
#################################################
# MAIN
#
+ShogiServer.reload
+
def gets_safe(socket, timeout=nil)
if r = select([socket], nil, nil, timeout)
return r[0].first.gets
end
def setup_floodgate
- Thread.start do
+ return Thread.start do
Thread.pass
floodgate = ShogiServer::League::Floodgate.new(LEAGUE)
log_message("Flooddgate reloaded. The next match will start at %s." %
while (true)
begin
- sleep(10)
- next if Time.now < floodgate.next_time
+ diff = floodgate.next_time - Time.now
+ if diff > 0
+ sleep(diff/2)
+ next
+ end
LEAGUE.reload
floodgate.match_game
floodgate.charge
next_time = floodgate.next_time
$mutex.synchronize do
- Dependencies.clear
+ log_message("Reloading source...")
+ ShogiServer.reload
end
floodgate = ShogiServer::League::Floodgate.new(LEAGUE, next_time)
- log_message("Flooddgate reloaded. The next match will start at %s." %
- [floodgate.next_time])
+ log_message("Floodgate will start the next match at %s." %
+ [floodgate.next_time])
rescue Exception => ex
# ignore errors
log_error("[in Floodgate's thread] #{ex} #{ex.backtrace}")
def main
- [ShogiServer::League::Floodgate, ShogiServer::Pairing].each do |klass|
- Dependencies.unloadable klass
- end
+ #[ShogiServer::League::Floodgate, ShogiServer::Pairing].each do |klass|
+ # Dependencies.unloadable klass
+ #end
setup_watchdog_for_giant_lock
config[:ServerType] = WEBrick::Daemon if $options["daemon"]
config[:Logger] = $logger
+ fg_thread = nil
config[:StartCallback] = Proc.new do
if $options["pid-file"]
write_pid_file($options["pid-file"])
end
- setup_floodgate
+ fg_thread = setup_floodgate
end
config[:StopCallback] = Proc.new do
trap(signal) do
LEAGUE.shutdown
server.shutdown
- # TODO Shutdown Floodgate's thread
+ fg_thread.kill if fg_thread
end
end
trap("HUP") do
LEAGUE.shutdown
Dependencies.clear
- # TODO Restart Floodgate's thread
end
$stderr.puts("server started as a deamon [Revision: #{ShogiServer::Revision}]") if $options["daemon"]
log_message("server started [Revision: #{ShogiServer::Revision}]")
require 'fileutils'
require 'logger'
+require 'shogi_server/board'
+require 'shogi_server/game'
+require 'shogi_server/league'
+require 'shogi_server/login'
+require 'shogi_server/piece'
+require 'shogi_server/pieceky'
+require 'shogi_server/player'
+require 'shogi_server/timeout_queue'
+require 'shogi_server/usi'
+require 'shogi_server/util'
+
require 'rubygems'
-require 'active_support'
-Dependencies.log_activity = true
-Dependencies.load_paths << File.dirname(__FILE__)
-RAILS_DEFAULT_LOGGER = Logger.new($stdout) if $DEBUG
module ShogiServer # for a namespace
Release = "$Id$"
Revision = (r = /Revision: (\d+)/.match("$Revision$") ? r[1] : 0)
+RELOAD_FILES = ["shogi_server/league/floodgate.rb",
+ "shogi_server/league/persistent.rb",
+ "shogi_server/pairing.rb"]
+
+def reload
+ here = File.dirname(__FILE__)
+ RELOAD_FILES.each do |f|
+ load File.join(here, f)
+ end
+end
+module_function :reload
+
class Formatter < ::Logger::Formatter
def call(severity, time, progname, msg)
%!%s [%s] %s\n! % [format_datetime(time), severity, msg2str(msg)]
## along with this program; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+require 'shogi_server/league/persistent'
+
module ShogiServer # for a namespace
######################################################
class Player < BasicPlayer
+ WRITE_THREAD_WATCH_INTERVAL = 20 # sec
def initialize(str, socket, eol=nil)
super()
@socket = socket
@sente = nil
@socket_buffer = []
@main_thread = Thread::current
- @write_queue = ShogiServer::TimeoutQueue.new(20)
+ @write_queue = ShogiServer::TimeoutQueue.new(WRITE_THREAD_WATCH_INTERVAL)
@player_logger = nil
start_write_thread
end
@status = "finished"
log_message(sprintf("user %s finish", @name))
begin
-# @socket.close if (! @socket.closed?)
+ log_debug("Terminating %s's write thread..." % [@name])
write_safe(nil)
@write_thread.join
@player_logger.close if @player_logger
while !@socket.closed?
begin
str = @write_queue.deq
- break if (str == nil)
- next if (str == :timeout)
+ if (str == nil)
+ log_debug("%s's write thread terminated" % [@name])
+ break
+ end
+ if (str == :timeout)
+ log_debug("%s's write queue timed out. Try again..." % [@name])
+ next
+ end
if r = select(nil, [@socket], nil, 20)
r[1].first.write(str)
log_error("Failed to send a message to #{@name}. #{ex.class}: #{ex.message}\t#{ex.backtrace[0]}")
end
end # while loop
- log_message("terminated %s's write thread" % [@name])
+ log_error("%s's socket closed." % [@name]) if @socket.closed?
end # thread
- rescue
-
end
#
@socket_buffer << str
str = @socket_buffer.shift
end
- log_message("%s (%s)" % [str, @socket_buffer.map {|a| String === a ? a.strip : a }.join(",")]) if $DEBUG
+ log_debug("%s (%s)" % [str, @socket_buffer.map {|a| String === a ? a.strip : a }.join(",")])
if (csa_1st_str)
str = csa_1st_str
#
def deq
timeout_flg = false
- ret = nil
-
+ ret = :timeout
@mon.synchronize do
if @queue.empty?
- if @cond.wait(15)
+ unless @cond.wait(15)
#timeout
timeout_flg = true
- ret = :timeout
end
end
if !timeout_flg && !@queue.empty?