OSDN Git Service

* [shogi-server] Support a graceful shutdown. (Closes #38544)
[shogi-server/shogi-server.git] / shogi-server
index 263a3f3..21bc9d1 100755 (executable)
@@ -1,4 +1,4 @@
-#! /usr/bin/ruby1.9.1
+#! /usr/bin/ruby
 # $Id$
 #
 # Author:: NABEYA Kenichi, Daigo Moriwaki
@@ -78,6 +78,15 @@ OPTIONS
         port_number
                 a port number for the server to listen. 
                 4081 is often used.
+        --least-time-per-move n
+                Least time in second per move: 0, 1 (default 1).
+                  - 0: The new rule that CSA introduced in November 2014.
+                  - 1: The old rule before it.
+        --max-identifier n
+               maximum length of an identifier
+        --max-moves n
+                when a game with the n-th move played does not end, make the game a draw.
+                Default 256. 0 disables this feature.
         --pid-file file
                 a file path in which a process ID will be written.
                 Use with --daemon option.
@@ -95,14 +104,17 @@ EXAMPLES
            Run the shogi-server. Then clients can connect to port#4081.
            The server output logs to the stdout.
 
-        2. % ./shogi-server --daemon . --pid-file ./shogi-server.pid \
+        2. % ./shogi-server --max-moves 0 --least-time-per-move 1 test 4081
+           Run the shogi-server in compliance with CSA Protocol V1.1.2 or before.
+
+        3. % ./shogi-server --daemon . --pid-file ./shogi-server.pid \
                             --player-log-dir ./player-logs \
                             test 4081
            Run the shogi-server as a daemon. The server outputs regular logs
            to shogi-server.log located in the current directory and network 
            messages in ./player-logs directory.
 
-        3. % ./shogi-server --daemon . --pid-file ./shogi-server.pid \
+        4. % ./shogi-server --daemon . --pid-file ./shogi-server.pid \
                             --player-log-dir ./player-logs \
                             --floodgate-games floodgate-900-0,floodgate-3600-0 \
                             test 4081
@@ -111,6 +123,21 @@ EXAMPLES
            floodgate-0-240.conf.sample or shogi_server/league/floodgate.rb 
            for format details.
 
+GRACEFUL SHUTDOWN
+
+       A file named "STOP" in the base directory prevents the server from
+       starting new games including Floodgate matches.
+       When you want to stop the server gracefully, first, create a STOP file
+
+          $ touch STOP
+
+       then wait for a while until all the running games complete.
+       Now you can stop the process with no game interruptted by the 'kill'
+       command.
+
+       Note that when a server gets started, a STOP file, if any, will be
+       deleted automatically.
+
 FLOODGATE SCHEDULE CONFIGURATIONS
 
            You need to set starting times of floodgate groups in
@@ -193,10 +220,13 @@ end
 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])
+    ["--daemon",              GetoptLong::REQUIRED_ARGUMENT],
+    ["--floodgate-games",     GetoptLong::REQUIRED_ARGUMENT],
+    ["--least-time-per-move", GetoptLong::REQUIRED_ARGUMENT],
+    ["--max-identifier",      GetoptLong::REQUIRED_ARGUMENT],
+    ["--max-moves",           GetoptLong::REQUIRED_ARGUMENT],
+    ["--pid-file",            GetoptLong::REQUIRED_ARGUMENT],
+    ["--player-log-dir",      GetoptLong::REQUIRED_ARGUMENT])
   parser.quiet = true
   begin
     parser.each_option do |name, arg|
@@ -265,6 +295,15 @@ def check_command_line
     $stderr.puts "WARNING: --floodgate-history has been deprecated."
     $options["floodgate-history"] = nil
   end
+
+  $options["max-moves"] ||= ShogiServer::Default_Max_Moves
+  $options["max-moves"] = $options["max-moves"].to_i
+
+  $options["max-identifier"] ||= ShogiServer::Default_Max_Identifier_Length
+  $options["max-identifier"] = $options["max-identifier"].to_i
+
+  $options["least-time-per-move"] ||= ShogiServer::Default_Least_Time_Per_Move
+  $options["least-time-per-move"] = $options["least-time-per-move"].to_i
 end
 
 # See if a file can be created in the directory.
@@ -338,8 +377,9 @@ def login_loop(client)
           # can override the current player.
           if (current_player.password == player.password &&
               (current_player.status != "game" ||
-               Time.now - current_player.modifiled_at > ONE_DAY))
-            log_message("user %s login forcely (previously modified at %s)" % [player.name, player.modified_at])
+               Time.now - current_player.last_command_at > ONE_DAY))
+            log_message("player %s login forcibly, nudging the former player" % [player.name])
+            log_message("  the former player was in %s and received the last command at %s" % [current_player.status, current_player.last_command_at])
             current_player.kill
           else
             login.incorrect_duplicated_player(str)
@@ -433,6 +473,11 @@ def main
   $stderr.puts("server started as a deamon [Revision: #{ShogiServer::Revision}]") if $options["daemon"] 
   log_message("server started [Revision: #{ShogiServer::Revision}]")
 
+  if ShogiServer::STOP_FILE.exist?
+    log_message("Deleted the STOP file")
+    ShogiServer::STOP_FILE.delete
+  end
+
   server.start do |client|
     begin
       # client.sync = true # this is already set in WEBrick