Add infos into target window
[ryzomcore.git] / ryzom / server / src / entities_game_service / shutdown_handler.cpp
blob756efc61e92c1f0101414f7c80cc9f2367ce10ba
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #error DERPRECATED
19 #include "stdpch.h"
21 #include "shutdown_handler.h"
23 #include "nel/net/service.h"
24 #include "nel/net/message.h"
25 #include "nel/net/unified_network.h"
27 #include "player_manager/player_manager.h"
28 #include "player_manager/player.h"
30 using namespace std;
31 using namespace NLMISC;
32 using namespace NLNET;
35 // Shutdown State
36 CShutdownHandler::TState CShutdownHandler::_State = CShutdownHandler::Running;
38 // Shutdown Timeout
39 NLMISC::TTime CShutdownHandler::_ShutdownTimeout = 0;
41 // Shutdown Timeout
42 NLMISC::TTime CShutdownHandler::_NextBroadcastMessage;
44 // ShardOpen has been closed
45 bool CShutdownHandler::_ShardClosed = false;
47 // Broadcast Message Rate
48 uint CShutdownHandler::_BroadcastMessageRate = 0;
50 // Game cycle of last config file check
51 NLMISC::TGameCycle CAutomaticShutdownHandler::_LastGCChecked = 0;
53 static const TSecTime MaxTime = ~0; //std::numeric_limits<TSecTime>::max()
55 // Time of next planned shutdown sequence start
56 TSecTime CAutomaticShutdownHandler::_NextPlannedShutdownStartTime = MaxTime;
58 // Time of next planned shutdown sequence end
59 TSecTime CAutomaticShutdownHandler::_NextPlannedShutdownEndTime = MaxTime;
62 /**
63 * Shutdown Counter, in minutes
65 CVariable<uint> ShutdownCounter("egs", "ShutdownCounter", "Time to shutdown in minutes", 5, 0, true);
67 /**
68 * Broadcast shutdown message rate in seconds
70 CVariable<uint> BroadcastShutdownMessageRate("egs", "BroadcastShutdownMessageRate", "Number of seconds between 2 shutdown message in seconds", 30, 0, true);
72 /**
73 * Close shard Access at
75 CVariable<uint> CloseShardAccessAt("egs", "CloseShardAccessAt", "Time to shutdown to close shard access, in seconds", 60, 0, true);
78 // Callback for DailyShutdownSequenceTime
79 void cbChangeDailyShutdownSequenceTime( IVariable& var )
81 CAutomaticShutdownHandler::computePlannedShutdownTimes();
84 /**
85 * DailyShutdownSequenceTime
87 CVariable<string> DailyShutdownSequenceTime("egs","DailyShutdownSequenceTime", "Time of day when the service will start a shutdown sequence (ex: \"20:55\"). Set \"\" or -1 to disable)", string(), 0, true, cbChangeDailyShutdownSequenceTime, true );
89 /**
90 * Daily Shutdown Counter, in minutes
92 CVariable<uint> DailyShutdownCounterMinutes("egs", "DailyShutdownCounterMinutes", "Time to shutdown in minutes", 1, 0, true);
94 /**
95 * DailyShutdownBroadcastMessage
97 CVariable<string> DailyShutdownBroadcastMessage("egs","DailyShutdownBroadcastMessage", "Message to broadcast before daily shutdown", string("The shard will be shut down in 1 minute"), 0, true );
99 /**
100 * CheckShutdownPeriodGC
102 CVariable<uint> CheckShutdownPeriodGC("egs","CheckShutdownPeriodGC", "Automatic shutdown sequence is tested every CheckShutdownPeriodGC game cycles", 50, 0, true );
106 * Inits Handler
108 void CShutdownHandler::init()
110 _State = Running;
111 _ShutdownTimeout = NLMISC::CTime::getLocalTime();
112 _NextBroadcastMessage = NLMISC::CTime::getLocalTime();
113 _ShardClosed = false;
117 * Update Handler
119 void CShutdownHandler::update()
121 if (_State == ShuttingDown)
123 NLMISC::TTime now = NLMISC::CTime::getLocalTime();
125 // time to shutdown?
126 if (_ShutdownTimeout <= now)
128 nlinfo("CShutdownHandler::update(): disconnect all players from shard");
130 disconnectPlayers();
132 _State = Closed;
133 return;
136 // time to close shard access?
137 if (_ShutdownTimeout-(CloseShardAccessAt*60*1000) <= now && !_ShardClosed)
139 nlinfo("CShutdownHandler::update(): close access to shard, SET_SHARD_OPEN sent to WS");
141 // send WS setShardOpen message
142 CMessage msgShardOpen("SET_SHARD_OPEN");
143 uint8 close = 0;
144 msgShardOpen.serial(close);
145 CUnifiedNetwork::getInstance()->send("WS", msgShardOpen);
147 _ShardClosed = true;
150 // time to broadcast message?
151 if (_NextBroadcastMessage <= now)
153 broadcastShutdownMessage();
159 * Release Handler
161 void CShutdownHandler::release()
170 * Start Shutdown Counter
172 void CShutdownHandler::startShutdown(sint shutdownCounter, sint broadcastMessageRate)
174 nlinfo("CShutdownHandler::startShutdown(): starting count down to shutdown");
176 if (_State != Running)
178 nlinfo("CShutdownHandler::startShutdown(): shutdown already started, left as is");
179 return;
182 NLMISC::TTime now = NLMISC::CTime::getLocalTime();
184 nlinfo("CShutdownHandler::startShutdown(): counter set to %u seconds", ShutdownCounter.get());
186 // time in ms
187 _State = ShuttingDown;
188 _ShutdownTimeout = now + (shutdownCounter > 0 ? shutdownCounter : ShutdownCounter)*60*1000;
189 _BroadcastMessageRate = (broadcastMessageRate > 0 ? broadcastMessageRate : BroadcastShutdownMessageRate);
190 _NextBroadcastMessage = now;
191 _ShardClosed = false;
195 * Cancel Shutdown
197 void CShutdownHandler::cancelShutdown()
199 nlinfo("CShutdownHandler::cancelShutdown(): cancelling shard shutdown");
201 if (_State != ShuttingDown)
203 nlinfo("CShutdownHandler::cancelShutdown(): shard is not currently shutting down, shard left as is");
204 return;
207 _State = Running;
209 broadcastMessage(std::string("Shutting down cancelled"));
211 if (_ShardClosed)
213 nlinfo("CShutdownHandler::cancelShutdown(): WS ShardOpen state modified, sending restore request");
214 CMessage msgShardOpen("RESTORE_SHARD_OPEN");
215 CUnifiedNetwork::getInstance()->send("WS", msgShardOpen);
220 * Restart shard
221 * Actually reset WS ShardOpen variable to OpenForAll
223 void CShutdownHandler::restartShard()
225 nlinfo("CShutdownHandler::restartShard(): restarting shard after shutdown");
227 if (_State != Closed)
229 nlinfo("CShutdownHandler::restartShard(): shard is not closed");
230 return;
233 _State = Running;
235 broadcastMessage(std::string("Shard is now restarted and open to public."));
237 // send SET_SHARD_OPEN to WS
238 nlinfo("CShutdownHandler::restartShard(): WS ShardOpen state modified, sending restore request");
239 CMessage msgShardOpen("RESTORE_SHARD_OPEN");
240 CUnifiedNetwork::getInstance()->send("WS", msgShardOpen);
248 * Get current shard state
250 std::string CShutdownHandler::getState()
252 if (_State == Running)
254 return "Running";
256 else if (_State == ShuttingDown)
258 sint shutdown = (sint)((_ShutdownTimeout-NLMISC::CTime::getLocalTime()) / 1000);
260 if (_ShardClosed)
262 return NLMISC::toString("Shutdown in %d seconds, shard access closed", shutdown);
264 else
266 return NLMISC::toString("Shutdown in %d seconds", shutdown);
269 else
271 return "Closed, ready to restart";
277 * Broadcast message
279 void CShutdownHandler::broadcastMessage(const ucstring& message)
281 _NextBroadcastMessage = NLMISC::CTime::getLocalTime() + _BroadcastMessageRate*1000;
283 /// \todo handle ucstring somewhere here...
284 PlayerManager.broadcastMessage(1, 0, 0, message.toString());
288 * Broadcast Shutdown message
290 void CShutdownHandler::broadcastShutdownMessage()
292 nlinfo("CShutdownHandler::broadcastShutdownMessage(): broadcasting shutdown message");
294 std::string shutdownMessage;
295 const sint timeAccuracy = 10;
297 sint shutdown = (sint)((_ShutdownTimeout-NLMISC::CTime::getLocalTime()) / 1000);
299 shutdown += (timeAccuracy/2);
301 // clamp to 0
302 if (shutdown < 0)
303 shutdown = 0;
305 shutdown = shutdown - (shutdown%timeAccuracy);
307 if (shutdown < timeAccuracy)
309 broadcastMessage(std::string("Shutting down..."));
311 else
313 if (shutdown < 60)
315 broadcastMessage(NLMISC::toString("Shard shuts down in %d seconds", shutdown));
317 else
319 uint min = shutdown/60;
320 uint sec = shutdown%60;
321 broadcastMessage(NLMISC::toString("Shard shuts down in %dmn %ds", min, sec));
328 * Disconnect all players
330 void CShutdownHandler::disconnectPlayers()
332 nlinfo("CShutdownHandler::disconnectPlayers(): disconnecting all players");
334 CMessage msgout("DISCONNECT_ALL_CLIENTS");
335 CUnifiedNetwork::getInstance()->send("FS", msgout);
338 const CPlayerManager::TMapPlayers& playerMap = PlayerManager.getPlayers();
340 // browse through all players to disconnect them
341 CPlayerManager::TMapPlayers::const_iterator it;
342 for (it = playerMap.begin(); it != playerMap.end(); )
344 const CPlayerManager::SCPlayer& player = (*it).second;
345 ++it;
347 if (player.Player != NULL)
349 uint32 userId = player.Player->getUserId();
350 PlayerManager.savePlayer(userId);
351 PlayerManager.disconnectPlayer(userId);
359 * Update.
360 * If the shutdown sequence is started, it can be canceled by changing DailyShutdownSequenceTime.
362 void CAutomaticShutdownHandler::update()
364 if ( CTickEventHandler::getGameCycle() - _LastGCChecked >= CheckShutdownPeriodGC )
366 _LastGCChecked = CTickEventHandler::getGameCycle();
367 TSecTime nowSec = NLMISC::CTime::getSecondsSince1970();
369 // Time to start an automatic shutdown sequence?
370 if ( nowSec >= _NextPlannedShutdownStartTime )
372 string msg = DailyShutdownBroadcastMessage.get();
373 PlayerManager.broadcastMessage( 1, 0, 0, msg );
374 nlinfo( msg.c_str() );
375 _NextPlannedShutdownEndTime = _NextPlannedShutdownStartTime + (DailyShutdownCounterMinutes.get()*60);
376 _NextPlannedShutdownStartTime = MaxTime;
378 // Time to shutdown?
379 else if ( nowSec >= _NextPlannedShutdownEndTime )
381 _NextPlannedShutdownEndTime = MaxTime;
382 IService::getInstance()->exit();
389 * Use daily shutdown sequence time to compute next time
391 void CAutomaticShutdownHandler::computePlannedShutdownTimes( NLMISC::CLog *log )
393 string dailyTimeStr = DailyShutdownSequenceTime.get();
394 if ( dailyTimeStr.empty() || (dailyTimeStr == "-1") )
396 // No automatic shutdown sequence
397 _NextPlannedShutdownStartTime = MaxTime;
398 _NextPlannedShutdownEndTime = MaxTime;
399 if ( log )
400 log->displayNL( "Automatic shutdown sequence disabled" );
402 else
404 // Setup next automatic shutdown sequence
405 time_t currentTime = time( NULL );
406 struct tm *localTime = localtime( &currentTime );
407 struct tm shutdownTime = *localTime;
408 string::size_type cp = dailyTimeStr.find( ':' );
409 shutdownTime.tm_hour = atoi( dailyTimeStr.substr( 0, cp ).c_str() );
410 shutdownTime.tm_min = 0;
411 if ( cp != string::npos )
412 shutdownTime.tm_min = atoi( dailyTimeStr.substr( cp+1 ).c_str() );
413 shutdownTime.tm_sec = 0;
414 shutdownTime.tm_isdst = -1;
415 _NextPlannedShutdownStartTime = nl_mktime( &shutdownTime );
416 char *dayWhenStr;
417 if ( _NextPlannedShutdownStartTime > (TSecTime)currentTime )
419 dayWhenStr = "today";
421 else
423 dayWhenStr = "tomorrow";
424 ++shutdownTime.tm_mday;
425 _NextPlannedShutdownStartTime = nl_mktime( &shutdownTime );
427 _NextPlannedShutdownEndTime = _NextPlannedShutdownStartTime + (DailyShutdownCounterMinutes.get()*60);
428 if ( log )
429 log->displayNL( "Next automatic shutdown sequence will begin %s at %02u:%02u with %u-minute delay", dayWhenStr, shutdownTime.tm_hour, shutdownTime.tm_min, DailyShutdownCounterMinutes.get() );
434 NLMISC_DYNVARIABLE(std::string, ShutdownState, "Current shutdown state of the shard, as a string (Read only)")
436 // read or write the variable
437 if (get)
438 *pointer = CShutdownHandler::getState();
442 // Commands
444 NLMISC_COMMAND(startShutdown, "Ask the EGS to shutdown the whole shard", "[time to shutdown, minutes] [time between 2 messages, seconds]")
446 if (args.size() > 2)
447 return false;
449 sint counter = -1;
450 sint msgRate = -1;
452 if (args.size() >= 1)
453 counter = atoi(args[0].c_str());
455 if (args.size() >= 2)
456 msgRate = atoi(args[1].c_str());
458 CShutdownHandler::startShutdown(counter, msgRate);
459 return true;
462 NLMISC_COMMAND(cancelShutdown, "Cancel current shutdown in progress", "")
464 CShutdownHandler::cancelShutdown();
465 return true;
468 NLMISC_COMMAND(restartShard, "Restart the shard after a shutdown", "")
470 CShutdownHandler::restartShard();
471 return true;