/// <summary> /// Check to see if the <see cref="MissionSession"/> is cached /// </summary> /// <param name="cachedMissionSession">The current cached <see cref="MissionSession"/></param> /// <param name="lookupMissionSession">The current <see cref="MissionSession"/> to check</param> /// <returns>True if the cached <see cref="MissionSession"/> matches the lookup <see cref="MissionSession"/></returns> private bool IsMissionSessionCached(MissionSession cachedMissionSession, MissionSession lookupMissionSession) { return(cachedMissionSession != null && cachedMissionSession.Mission != null && cachedMissionSession.Session != null && cachedMissionSession.Mission.Map != null && cachedMissionSession.Mission.Name == lookupMissionSession.Mission.Name && cachedMissionSession.Session.Id == lookupMissionSession.Session.Id && cachedMissionSession.Mission.Map.Name == lookupMissionSession.Mission.Map.Name); }
/// <summary> /// Update the database with the modified <see cref="MissionSession"/> object /// </summary> /// <param name="missionSession"><see cref="MissionSession"/> object to update</param> public void UpdateMissionSession(MissionSession missionSession) { _updateMissionSession.Parameters[DatabaseUtil.MISSION_TO_SESSION_ID_KEY].Value = missionSession.Id; _updateMissionSession.Parameters[DatabaseUtil.LENGTH_KEY].Value = missionSession.Length; _updateMissionSession.Parameters[DatabaseUtil.PLAYED_KEY].Value = missionSession.Played; _updateMissionSession.ExecuteNonQuery(); _logger.DebugFormat("Mission session updated on the database with ID: {0}", missionSession.Id); }
/// <summary> /// Helper method to create a <see cref="MissionSession"/> in the database /// </summary> /// <param name="missionSession"><see cref="MissionSession"/> to create</param> /// <returns><see cref="MissionSession"/> with added database id</returns> private MissionSession CreateMissionSession(MissionSession missionSession) { _addMissionSession.Parameters[DatabaseUtil.MISSION_ID_KEY].Value = missionSession.Mission.Id; _addMissionSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = missionSession.Session.Id; _addMissionSession.ExecuteNonQuery(); missionSession.Id = GetLastInsertedId(); _logger.DebugFormat("Mission session added to the database with ID: {0}", missionSession.Id); return(missionSession); }
/// <summary> /// Gets, or creates a mission session with the provided map name, mission name, and <see cref="Session"/>. /// Caches the return value to reduce MySQL interactions and decrease run time /// </summary> /// <param name="mapName">Name of the map that the server is on</param> /// <param name="mission">Name of the mission that the server is on</param> /// <param name="session">Current <see cref="Session"/> object</param> /// <returns>A full <see cref="MissionSession"/> object with information from the database</returns> public MissionSession GetOrCreateMissionSession(string mapName, string mission, Session session) { MissionSession missionSession = new MissionSession(); missionSession.Mission = new Mission(mission); missionSession.Mission.Map = new Map(mapName); missionSession.Session = session; if (IsMissionSessionCached(_cachedMissionSession, missionSession)) { missionSession = _cachedMissionSession; _logger.DebugFormat("Retrieved mission session from cache with ID: {0}", missionSession.Id); } else { _getMissionSession.Parameters[DatabaseUtil.NAME_KEY].Value = missionSession.Mission.Name; _getMissionSession.Parameters[DatabaseUtil.SESSION_ID_KEY].Value = session.Id; MySqlDataReader getMissionResult = _getMissionSession.ExecuteReader(); if (getMissionResult.HasRows) { bool relinkMap = false; getMissionResult.Read(); missionSession.Mission.Id = getMissionResult.GetInt32(0); if (missionSession.Mission.Map.Name.Equals(getMissionResult.GetString(5))) { missionSession.Mission.Map.Id = getMissionResult.GetInt32(4); } else { relinkMap = true; } if (getMissionResult.IsDBNull(1)) { getMissionResult.Close(); CreateMissionSession(missionSession); } else { missionSession.Id = getMissionResult.GetInt32(1); missionSession.Length = getMissionResult.GetInt32(2); missionSession.Played = getMissionResult.GetBoolean(3); _logger.DebugFormat("Retrieved mission session from database with ID: {0}", missionSession.Id); getMissionResult.Close(); } if (relinkMap) { missionSession.Mission.Map.Id = GetMapId(missionSession.Mission.Map.Name); _updateMission.Parameters[DatabaseUtil.MISSION_ID_KEY].Value = missionSession.Mission.Id; _updateMission.Parameters[DatabaseUtil.MAP_ID_KEY].Value = missionSession.Mission.Map.Id; _updateMission.ExecuteNonQuery(); } } else { getMissionResult.Close(); missionSession.Mission.Map.Id = GetMapId(missionSession.Mission.Map.Name); _addMission.Parameters[DatabaseUtil.NAME_KEY].Value = missionSession.Mission.Name; _addMission.Parameters[DatabaseUtil.MAP_ID_KEY].Value = missionSession.Mission.Map.Id; _addMission.ExecuteNonQuery(); missionSession.Mission.Id = GetLastInsertedId(); CreateMissionSession(missionSession); } _cachedMissionSession = missionSession; } return(missionSession); }
/// <summary> /// Begins reporting on a session, should handle DAOs here /// </summary> public void StartReporting() { // define DAO objects to interact with databases MySqlConnection connection = null; PlayerDAO playerDAO = null; MissionDAO missionDAO = null; SessionDAO sessionDAO = null; try { // create DAO objects to interact with databases BuildDAOsIfNeeded(ref connection, ref playerDAO, ref missionDAO, ref sessionDAO); ServerInfoService serverInfoService = new ServerInfoService(); // variables needed to track session playthough Session session = null; MissionSession currentMissionSession = null; ISet <PlayerMissionSession> currentPlayersToMissionSession = new HashSet <PlayerMissionSession>(); int missionCount = 0; bool inGame = false; Stopwatch runTime = new Stopwatch(); runTime.Start(); try { while (session == null && CheckTimeThreshold(runTime.ElapsedMilliseconds)) { try { _logger.Debug("Trying to set up session"); session = SetUpSession(serverInfoService, sessionDAO, Settings.Default.armaServerAddress, Settings.Default.armaServerPort, ref inGame); } catch (MySqlException e) { _logger.Error("Problem setting up session: ", e); BuildDAOsIfNeeded(ref connection, ref playerDAO, ref missionDAO, ref sessionDAO); } Thread.Sleep(Settings.Default.pollRate); } while (CheckMissionThreshold(missionCount, inGame) && CheckTimeThreshold(runTime.ElapsedMilliseconds)) { try { _logger.Debug("Trying to update session details"); ServerInfo serverInfo = serverInfoService.GetServerInfo(Settings.Default.armaServerAddress, Settings.Default.armaServerPort); inGame = CheckServerRunningState(serverInfo.ServerState); if (inGame) { if (session.MaxPing < serverInfo.Ping) { session.MaxPing = serverInfo.Ping; } else if (session.MinPing > serverInfo.Ping) { session.MinPing = serverInfo.Ping; } if (session.MaxPlayers < serverInfo.Players.Count) { session.MaxPlayers = serverInfo.Players.Count; } MissionSession missionSession = missionDAO.GetOrCreateMissionSession(serverInfo.MapName, serverInfo.Mission, session); if (currentMissionSession != null && currentMissionSession.Id != missionSession.Id) // handle case where missions changed between polls { sessionDAO.UpdateSession(session); missionDAO.UpdateMissionSession(currentMissionSession); playerDAO.UpdatePlayerMissionSessions(currentPlayersToMissionSession); currentPlayersToMissionSession.Clear(); } missionSession.Length += (Settings.Default.pollRate / 1000); if (missionSession.Played == false && CheckPlayedThreshold(missionSession.Length)) { missionSession.Played = true; missionCount++; } currentMissionSession = missionSession; ISet <PlayerMissionSession> playersToMissionSession = playerDAO.GetOrCreatePlayerMissionSessions(serverInfo.Players, missionSession); foreach (PlayerMissionSession playerToMissionSession in playersToMissionSession) { playerToMissionSession.Length += (Settings.Default.pollRate / 1000); if (playerToMissionSession.Played == false && CheckPlayedThreshold(playerToMissionSession.Length)) { playerToMissionSession.Played = true; } } currentPlayersToMissionSession.UnionWith(playersToMissionSession); } else if (currentMissionSession != null) { sessionDAO.UpdateSession(session); missionDAO.UpdateMissionSession(currentMissionSession); playerDAO.UpdatePlayerMissionSessions(currentPlayersToMissionSession); currentMissionSession = null; currentPlayersToMissionSession.Clear(); } } catch (MySqlException e) { _logger.Error("Problem updating session details: ", e); BuildDAOsIfNeeded(ref connection, ref playerDAO, ref missionDAO, ref sessionDAO); } Thread.Sleep(Settings.Default.pollRate); } } catch (NoServerInfoException nsie) { _logger.Error("Error reporting", nsie); } } finally { // Ensure disposable objects are disposed if (playerDAO != null) { playerDAO.Dispose(); } if (missionDAO != null) { missionDAO.Dispose(); } if (sessionDAO != null) { sessionDAO.Dispose(); } if (connection != null) { connection.Dispose(); } } }
/// <summary> /// Gets or creates a set of <see cref="PlayerMissionSession"/>s from the given list of <see cref="Player"/>s and the current <see cref="Session"/>. /// Using caching to reduce MySQL calls and speed up runtime /// </summary> /// <param name="players">List of <see cref="Player"/>s to get/create</param> /// <param name="missionSession">Current <see cref="MissionSession"/></param> /// <returns>A set of <see cref="PlayerMissionSession"/> objects, from the database.</returns> public ISet <PlayerMissionSession> GetOrCreatePlayerMissionSessions(IList <Player> players, MissionSession missionSession) { ISet <PlayerMissionSession> playerMissionSessions = new HashSet <PlayerMissionSession>(); foreach (Player player in players) { PlayerMissionSession playerToMissionSession = new PlayerMissionSession(); playerToMissionSession.Player = player; playerToMissionSession.MissionSession = missionSession; string key = player.Name + missionSession.Id; if (_cachedPlayerMissionSessions.ContainsKey(key)) { _cachedPlayerMissionSessions.TryGetValue(key, out playerToMissionSession); _logger.DebugFormat("Retrieved player mission session from the cache with ID: {0}", playerToMissionSession.Id); } else { _getPlayerMissionSession.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name; _getPlayerMissionSession.Parameters[DatabaseUtil.MISSION_TO_SESSION_ID_KEY].Value = missionSession.Id; MySqlDataReader getPlayerResult = _getPlayerMissionSession.ExecuteReader(); if (getPlayerResult.HasRows) { getPlayerResult.Read(); playerToMissionSession.Player.Id = getPlayerResult.GetInt32(0); if (getPlayerResult.GetBoolean(1) != playerToMissionSession.Player.HasClanTag) { playerToMissionSession.Player.Updated = true; } if (getPlayerResult.IsDBNull(2)) { getPlayerResult.Close(); CreatePlayerMissionSession(playerToMissionSession); } else { playerToMissionSession.Id = getPlayerResult.GetInt32(2); playerToMissionSession.Length = getPlayerResult.GetInt32(3); playerToMissionSession.Played = getPlayerResult.GetBoolean(4); _logger.DebugFormat("Retrieved player mission session from the database with ID: {0}", playerToMissionSession.Id); getPlayerResult.Close(); } } else { getPlayerResult.Close(); _addPlayer.Parameters[DatabaseUtil.NAME_KEY].Value = player.Name; _addPlayer.Parameters[DatabaseUtil.HAS_CLAN_TAG_KEY].Value = player.HasClanTag; _addPlayer.ExecuteNonQuery(); playerToMissionSession.Player.Id = GetLastInsertedId(); CreatePlayerMissionSession(playerToMissionSession); } _cachedPlayerMissionSessions.Add(key, playerToMissionSession); } playerMissionSessions.Add(playerToMissionSession); } return(playerMissionSessions); }