OSDN Git Service

* [shogi-server]
[shogi-server/shogi-server.git] / shogi_server / league / floodgate_thread.rb
1 require 'shogi_server'
2 require 'shogi_server/league/floodgate'
3
4 module ShogiServer
5
6   class SetupFloodgate
7     # Constructor.
8     # @param game_names an array of game name strings
9     #
10     def initialize(game_names)
11       @game_names = game_names
12       @thread = nil
13     end
14
15     # Return the most recent Floodgate instance
16     #
17     def next_league(leagues)
18       floodgate = leagues.min {|a,b| a.next_time <=> b.next_time}
19       return floodgate
20     end
21
22     def floodgate_reload_log(leagues)
23       floodgate = next_league(leagues)
24       diff = floodgate.next_time - Time.now
25       log_message("Floodgate reloaded. The next match will start at %s in %d seconds" % 
26                   [floodgate.next_time, diff])
27     end
28
29     def mk_leagues
30       leagues = @game_names.collect do |game_name|
31         ShogiServer::League::Floodgate.new($league, 
32                                            {:game_name => game_name})
33       end
34       leagues.delete_if do |floodgate|
35         ret = false
36         unless floodgate.next_time 
37           log_error("Unsupported game name: %s" % floodgate.game_name)
38           ret = true
39         end
40         ret
41       end
42       if leagues.empty?
43         log_error("No valid Floodgate game names found")
44         return [] # will exit the thread
45       end
46       floodgate_reload_log(leagues)
47       return leagues
48     end
49
50     def wait_next_floodgate(floodgate)
51       diff = floodgate.next_time - Time.now
52       if diff > 0
53         floodgate_reload_log(leagues) if $DEBUG
54         sleep(diff/2)
55         return true
56       end
57       return false
58     end
59
60     def reload_shogi_server
61       $mutex.synchronize do
62         log_message("Reloading source...")
63         ShogiServer.reload
64       end
65     end
66
67     def start_games(floodgate)
68       log_message("Starting Floodgate games...: %s" % [floodgate.game_name])
69       $league.reload
70       floodgate.match_game
71     end
72
73     # Regenerate floodgate instances from next_array for the next matches.
74     # @param next_array array of [game_name, next_time]
75     #
76     def regenerate_leagues(next_array)
77       leagues = next_array.collect do |game_name, next_time|
78         floodgate = ShogiServer::League::Floodgate.new($league, 
79                                                        {:game_name => game_name,
80                                                         :next_time => next_time})
81       end
82       floodgate_reload_log(leagues)
83       return leagues
84     end
85
86     def start
87       return nil if @game_names.nil? || @game_names.empty?
88
89       log_message("Set up floodgate games: %s" % [@game_names.join(",")])
90       @thread = Thread.start(@game_names) do |game_names|
91         Thread.pass
92         leagues = mk_leagues
93         if leagues.nil? || leagues.empty?
94           return # exit from this thread
95         end
96
97         while (true)
98           begin
99             floodgate = next_league(leagues)
100             next if wait_next_floodgate(floodgate)
101
102             next_array = leagues.collect do |floodgate|
103               if (floodgate.next_time - Time.now) > 0
104                 [floodgate.game_name, floodgate.next_time]
105               else
106                 start_games(floodgate)
107                 floodgate.charge # updates next_time
108                 [floodgate.game_name, floodgate.next_time] 
109               end
110             end
111
112             reload_shogi_server
113
114             # Regenerate floodgate instances after ShogiServer.realod
115             leagues = regenerate_leagues(next_array)
116           rescue Exception => ex 
117             # ignore errors
118             log_error("[in Floodgate's thread] #{ex} #{ex.backtrace}")
119           end
120         end # infinite loop
121
122         return @thread
123       end # Thread
124
125     end # def start
126
127     def kill
128       @thread.kill if @thread
129     end
130
131   end # class SetupFloodgate
132
133 end # module ShogiServer