/// <summary> /// Parses a single line of a scenario file. /// </summary> /// <param name="Parts">List of tokens of the line being parsed.</param> /// <param name="LineNumber">Line number of the line being parsed.</param> /// <returns>Initialized command object.</returns> public static Command ParseCommand(string[] Parts, int LineNumber) { log.Trace("(Parse:'{0}',LineNumber:{1})", string.Join(" ", Parts), LineNumber); Command res = null; CommandType commandType; if (!Enum.TryParse(Parts[0], out commandType)) { commandType = CommandType.Unknown; } int paramCount = Parts.Length - 1; int p = 1; string line = string.Join(" ", Parts); switch (commandType) { case CommandType.ProfileServer: { if (paramCount != 6) { log.Error("ProfileServer requires 6 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandProfileServer command = new CommandProfileServer(LineNumber, line) { GroupName = Parts[p++], Count = int.Parse(Parts[p++]), BasePort = int.Parse(Parts[p++]), Latitude = decimal.Parse(Parts[p++], CultureInfo.InvariantCulture), Longitude = decimal.Parse(Parts[p++], CultureInfo.InvariantCulture), Radius = int.Parse(Parts[p++]) }; bool countValid = (1 <= command.Count) && (command.Count <= 999); if (!countValid) { log.Error("Count '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.Count, LineNumber); break; } int basePortUpperLimit = 65535 - 20 * command.Count; bool basePortValid = (1 <= command.BasePort) && (command.BasePort <= basePortUpperLimit); if (!basePortValid) { log.Error("Having Count {0}, BasePort '{1}' on line {2} is invalid. It must be an integer between 1 and {3}.", command.Count, command.BasePort, LineNumber, basePortUpperLimit); break; } bool latitudeValid = new GpsLocation(command.Latitude, 0).IsValid(); if (!latitudeValid) { log.Error("Latitude '{0}' on line {1} is invalid. It must be a decimal number between -90 and 90.", command.Latitude, LineNumber); break; } bool longitudeValid = new GpsLocation(0, command.Longitude).IsValid(); if (!longitudeValid) { log.Error("Longitude '{0}' on line {1}. It must be a decimal number between -179.999999 and 180.", command.Longitude, LineNumber); break; } bool radiusValid = (0 <= command.Radius) && (command.Radius <= MaxRadius); if (!radiusValid) { log.Error("Radius '{0}' given on line {1}. It must be an integer between 0 and {2}.", command.Radius, LineNumber, MaxRadius); break; } res = command; break; } case CommandType.StartServer: { if (paramCount != 3) { log.Error("StartServer requires 3 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandStartServer command = new CommandStartServer(LineNumber, line) { PsGroup = Parts[p++], PsIndex = int.Parse(Parts[p++]), PsCount = int.Parse(Parts[p++]) }; bool psIndexValid = (1 <= command.PsIndex) && (command.PsIndex <= 999); if (!psIndexValid) { log.Error("PsIndex '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsIndex, LineNumber); break; } bool psCountValid = (1 <= command.PsCount) && (command.PsCount <= 999); if (!psCountValid) { log.Error("PsCount '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsCount, LineNumber); break; } psCountValid = command.PsIndex + command.PsCount <= 999; if (!psCountValid) { log.Error("Having PsIndex '{0}', PsCount '{1}' on line {2} is invalid. PsIndex + PsCount must not be greater than 999.", command.PsIndex, command.PsCount, LineNumber); break; } res = command; break; } case CommandType.StopServer: { if (paramCount != 3) { log.Error("StopServer requires 3 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandStopServer command = new CommandStopServer(LineNumber, line) { PsGroup = Parts[p++], PsIndex = int.Parse(Parts[p++]), PsCount = int.Parse(Parts[p++]) }; bool psIndexValid = (1 <= command.PsIndex) && (command.PsIndex <= 999); if (!psIndexValid) { log.Error("PsIndex '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsIndex, LineNumber); break; } bool psCountValid = (1 <= command.PsCount) && (command.PsCount <= 999); if (!psCountValid) { log.Error("PsCount '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsCount, LineNumber); break; } psCountValid = command.PsIndex + command.PsCount <= 999; if (!psCountValid) { log.Error("Having PsIndex '{0}', PsCount '{1}' on line {2} is invalid. PsIndex + PsCount must not be greater than 999.", command.PsIndex, command.PsCount, LineNumber); break; } res = command; break; } case CommandType.Neighborhood: { if ((paramCount % 3) != 0) { log.Error("Neighborhood requires 3*N parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandNeighborhood command = new CommandNeighborhood(LineNumber, line) { PsGroups = new List <string>(), PsIndexes = new List <int>(), PsCounts = new List <int>() }; for (int i = 0; i < paramCount; i += 3) { command.PsGroups.Add(Parts[p++]); command.PsIndexes.Add(int.Parse(Parts[p++])); command.PsCounts.Add(int.Parse(Parts[p++])); int groupNo = (i / 3) + 1; int groupIndex = groupNo - 1; bool indexValid = (1 <= command.PsIndexes[groupIndex]) && (command.PsIndexes[groupIndex] <= 999); if (!indexValid) { log.Error("PsIndex${0} '{1}' on line {2} is invalid. It must be an integer between 1 and 999.", groupNo, command.PsIndexes[groupIndex], LineNumber); break; } bool countValid = (1 <= command.PsCounts[groupIndex]) && (command.PsCounts[groupIndex] <= 999); if (!countValid) { log.Error("PsCount${0} '{1}' on line {2} is invalid. It must be an integer between 1 and 999.", groupNo, command.PsCounts[groupIndex], LineNumber); break; } countValid = command.PsIndexes[groupIndex] + command.PsCounts[groupIndex] <= 999; if (!countValid) { log.Error("Having PsIndex${0} '{1}', PsCount{0} '{2}' on line {3} is invalid. PsIndex$i + PsCount$i must not be greater than 999.", groupNo, command.PsIndexes[groupIndex], command.PsCounts[groupIndex], LineNumber); break; } } res = command; break; } case CommandType.CancelNeighborhood: { if ((paramCount % 3) != 0) { log.Error("CancelNeighborhood requires 3*N parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandCancelNeighborhood command = new CommandCancelNeighborhood(LineNumber, line) { PsGroups = new List <string>(), PsIndexes = new List <int>(), PsCounts = new List <int>() }; for (int i = 0; i < paramCount; i += 3) { command.PsGroups.Add(Parts[p++]); command.PsIndexes.Add(int.Parse(Parts[p++])); command.PsCounts.Add(int.Parse(Parts[p++])); int groupNo = (i / 3) + 1; bool indexValid = (1 <= command.PsIndexes[i]) && (command.PsIndexes[i] <= 999); if (!indexValid) { log.Error("PsIndex${0} '{1}' on line {2} is invalid. It must be an integer between 1 and 999.", groupNo, command.PsIndexes[i], LineNumber); break; } bool countValid = (1 <= command.PsCounts[i]) && (command.PsCounts[i] <= 999); if (!countValid) { log.Error("PsCount${0} '{1}' on line {2} is invalid. It must be an integer between 1 and 999.", groupNo, command.PsCounts[i], LineNumber); break; } countValid = command.PsIndexes[i] + command.PsCounts[i] <= 999; if (!countValid) { log.Error("Having PsIndex${0} '{1}', PsCount{0} '{2}' on line {3} is invalid. PsIndex$i + PsCount$i must not be greater than 999.", groupNo, command.PsIndexes[i], command.PsCounts[i], LineNumber); break; } } res = command; break; } case CommandType.Neighbor: { if (paramCount < 2) { log.Error("Neighbor requires 2 or more parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandNeighbor command = new CommandNeighbor(LineNumber, line) { Source = Parts[p++], Targets = new List <string>() }; for (int i = 0; i < paramCount - 1; i++) { command.Targets.Add(Parts[p++]); } res = command; break; } case CommandType.CancelNeighbor: { if (paramCount < 2) { log.Error("CancelNeighbor requires 2 or more parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandCancelNeighbor command = new CommandCancelNeighbor(LineNumber, line) { Source = Parts[p++], Targets = new List <string>() }; for (int i = 0; i < paramCount - 1; i++) { command.Targets.Add(Parts[p++]); } res = command; break; } case CommandType.Identity: { if (paramCount != 11) { log.Error("Neighbor requires 11 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandIdentity command = new CommandIdentity(LineNumber, line) { Name = Parts[p++], Count = int.Parse(Parts[p++]), IdentityType = Parts[p++], Latitude = decimal.Parse(Parts[p++], CultureInfo.InvariantCulture), Longitude = decimal.Parse(Parts[p++], CultureInfo.InvariantCulture), Radius = int.Parse(Parts[p++]), ImageMask = Parts[p++], ImageChance = int.Parse(Parts[p++]), PsGroup = Parts[p++], PsIndex = int.Parse(Parts[p++]), PsCount = int.Parse(Parts[p++]) }; bool countValid = (1 <= command.Count) && (command.Count <= 99999); if (!countValid) { log.Error("Count '{0}' on line {1} is invalid. It must be an integer between 1 and 99999.", command.Count, LineNumber); break; } bool latitudeValid = new GpsLocation(command.Latitude, 0).IsValid(); if (!latitudeValid) { log.Error("Latitude '{0}' on line {1} is invalid. It must be a decimal number between -90 and 90.", command.Latitude, LineNumber); break; } bool longitudeValid = new GpsLocation(0, command.Longitude).IsValid(); if (!longitudeValid) { log.Error("Longitude '{0}' on line {1}. It must be a decimal number between -179.999999 and 180.", command.Longitude, LineNumber); break; } bool radiusValid = (0 <= command.Radius) && (command.Radius <= MaxRadius); if (!radiusValid) { log.Error("Radius '{0}' given on line {1}. It must be an integer between 0 and {2}.", command.Radius, LineNumber, MaxRadius); break; } bool imageChance = (0 <= command.ImageChance) && (command.ImageChance <= 100); if (!imageChance) { log.Error("ImageChance '{0}' on line {1} is invalid. It must be an integer between 0 and 100.", command.ImageChance, LineNumber); break; } bool psIndexValid = (1 <= command.PsIndex) && (command.PsIndex <= 999); if (!psIndexValid) { log.Error("PsIndex '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsIndex, LineNumber); break; } bool psCountValid = (1 <= command.PsCount) && (command.PsCount <= 999); if (!psCountValid) { log.Error("PsCount '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsCount, LineNumber); break; } psCountValid = command.PsIndex + command.PsCount <= 999; if (!psCountValid) { log.Error("Having PsIndex '{0}', PsCount '{1}' on line {2} is invalid. PsIndex + PsCount must not be greater than 999.", command.PsIndex, command.PsCount, LineNumber); break; } countValid = command.Count - command.PsCount * 20000 <= 0; if (!countValid) { log.Error("Having PsCount '{0}', Count '{1}' on line {2} is invalid. Count / PsCount must not be greater than 20000.", command.PsCount, command.Count, LineNumber); break; } res = command; break; } case CommandType.CancelIdentity: { if (paramCount != 3) { log.Error("CancelIdentity requires 3 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandCancelIdentity command = new CommandCancelIdentity(LineNumber, line) { Name = Parts[p++], Index = int.Parse(Parts[p++]), Count = int.Parse(Parts[p++]) }; bool indexValid = (1 <= command.Index) && (command.Index <= 99999); if (!indexValid) { log.Error("Index '{0}' on line {1} is invalid. It must be an integer between 1 and 99999.", command.Index, LineNumber); break; } bool countValid = (1 <= command.Count) && (command.Count <= 99999); if (!countValid) { log.Error("Count '{0}' on line {1} is invalid. It must be an integer between 1 and 99999.", command.Count, LineNumber); break; } countValid = command.Index + command.Count <= 99999; if (!countValid) { log.Error("Having Index '{0}', Count '{1}' on line {2} is invalid. Index + Count must not be greater than 99999.", command.Index, command.Count, LineNumber); break; } res = command; break; } case CommandType.TestQuery: { if (paramCount != 9) { log.Error("TestQuery requires 9 parameters, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } int li = p + 6; string latStr = Parts[li++]; string lonStr = Parts[li++]; string radStr = Parts[li++]; decimal latitude = GpsLocation.NoLocation.Latitude; decimal longitude = GpsLocation.NoLocation.Longitude; int radius = 0; bool noLocation = latStr == "NO_LOCATION"; if (!noLocation) { latitude = decimal.Parse(latStr, CultureInfo.InvariantCulture); longitude = decimal.Parse(lonStr, CultureInfo.InvariantCulture); radius = int.Parse(radStr); } CommandTestQuery command = new CommandTestQuery(LineNumber, line) { PsGroup = Parts[p++], PsIndex = int.Parse(Parts[p++]), PsCount = int.Parse(Parts[p++]), NameFilter = Parts[p++], TypeFilter = Parts[p++], IncludeImages = bool.Parse(Parts[p++]), Latitude = latitude, Longitude = longitude, Radius = radius }; bool psIndexValid = (1 <= command.PsIndex) && (command.PsIndex <= 999); if (!psIndexValid) { log.Error("PsIndex '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsIndex, LineNumber); break; } bool psCountValid = (1 <= command.PsCount) && (command.PsCount <= 999); if (!psCountValid) { log.Error("PsCount '{0}' on line {1} is invalid. It must be an integer between 1 and 999.", command.PsCount, LineNumber); break; } psCountValid = command.PsIndex + command.PsCount <= 999; if (!psCountValid) { log.Error("Having PsIndex '{0}', PsCount '{1}' on line {2} is invalid. PsIndex + PsCount must not be greater than 999.", command.PsIndex, command.PsCount, LineNumber); break; } if (!noLocation) { bool latitudeValid = new GpsLocation(command.Latitude, 0).IsValid(); if (!latitudeValid) { log.Error("Latitude '{0}' on line {1} is invalid. It must be a decimal number between -90 and 90.", command.Latitude, LineNumber); break; } bool longitudeValid = new GpsLocation(0, command.Longitude).IsValid(); if (!longitudeValid) { log.Error("Longitude '{0}' on line {1}. It must be a decimal number between -179.999999 and 180.", command.Longitude, LineNumber); break; } bool radiusValid = (0 <= command.Radius) && (command.Radius <= MaxRadius); if (!radiusValid) { log.Error("Radius '{0}' given on line {1}. It must be an integer between 0 and {2}.", command.Radius, LineNumber, MaxRadius); break; } } res = command; break; } case CommandType.Delay: { if (paramCount != 1) { log.Error("Delay requires 1 parameter, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandDelay command = new CommandDelay(LineNumber, line) { Seconds = decimal.Parse(Parts[p++], CultureInfo.InvariantCulture) }; bool secondsValid = command.Seconds > 0; if (!secondsValid) { log.Error("Seconds '{0}' on line {1} is invalid. It must be a positive decimal number.", command.Seconds); break; } res = command; break; } case CommandType.TakeSnapshot: { if (paramCount != 1) { log.Error("TakeSnapshot requires 1 parameter, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandTakeSnapshot command = new CommandTakeSnapshot(LineNumber, line) { Name = Parts[p++] }; res = command; break; } case CommandType.LoadSnapshot: { if (paramCount != 1) { log.Error("LoadSnapshot requires 1 parameter, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } CommandLoadSnapshot command = new CommandLoadSnapshot(LineNumber, line) { Name = Parts[p++] }; res = command; break; } case CommandType.DebugMode: { if (paramCount != 1) { log.Error("DebugMode requires 1 parameter, but {0} parameters found on line {1}.", paramCount, LineNumber); break; } string enable = Parts[p++].ToLowerInvariant(); CommandDebugMode command = new CommandDebugMode(LineNumber, line) { Enable = enable == "on" }; bool enableValid = (enable == "on") || (enable == "off"); if (!enableValid) { log.Error("Enable on line {0} is invalid. It must be either 'on' or 'off'.", enable); break; } res = command; break; } default: log.Error("Invalid command '{0}' on line number {1}.", Parts[0], LineNumber); break; } log.Trace("(-):{0}", res != null ? "Command" : "null"); return(res); }
/// <summary> /// Executes all commands. /// </summary> /// <returns>true if the function succeeds and all the commands are executed successfully, false otherwise.</returns> public bool Execute() { log.Trace("()"); bool res = false; log.Info("Cleaning old history."); if (!ClearHistory()) { log.Error("Unable to clear history, please make sure the access to the instance folder is not blocked by other process."); log.Trace("(-):{0}", res); return(res); } log.Info(""); int index = 1; bool error = false; foreach (Command command in commands) { log.Info("Executing #{0:0000}@l{1}: {2}", index, command.LineNumber, command.OriginalCommand); switch (command.Type) { case CommandType.ProfileServer: { CommandProfileServer cmd = (CommandProfileServer)command; for (int i = 1; i <= cmd.Count; i++) { string name = GetInstanceName(cmd.GroupName, i); GpsLocation location = Helpers.GenerateRandomGpsLocation(cmd.Latitude, cmd.Longitude, cmd.Radius); int basePort = cmd.BasePort + 20 * (i - 1); ProfileServer profileServer = new ProfileServer(name, location, basePort); if (profileServer.Initialize()) { profileServers.Add(name, profileServer); } else { log.Error(" * Initialization of profile server '{0}' failed.", profileServer.Name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers created.", cmd.Count); } break; } case CommandType.StartServer: { CommandStartServer cmd = (CommandStartServer)command; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { if (!profileServer.Start()) { log.Error(" * Unable to start server instance '{0}'.", name); error = true; break; } } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers started.", cmd.PsCount); } break; } case CommandType.StopServer: { CommandStopServer cmd = (CommandStopServer)command; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { if (!profileServer.Stop()) { log.Error(" * Unable to stop server instance '{0}'.", name); error = true; } } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { log.Info(" * {0} profile servers stopped.", cmd.PsCount); } break; } case CommandType.Identity: { CommandIdentity cmd = (CommandIdentity)command; List <ProfileServer> availableServers = new List <ProfileServer>(); int availableSlots = 0; for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { availableServers.Add(profileServer); availableSlots += profileServer.AvailableIdentitySlots; } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (error) { break; } if (availableSlots < cmd.Count) { log.Error(" * Total number of available identity slots in selected servers is {0}, but {1} slots are required.", availableSlots, cmd.Count); error = true; break; } for (int i = 1; i <= cmd.Count; i++) { string name = GetIdentityName(cmd.Name, i); int serverIndex = Helpers.Rng.Next(availableServers.Count); ProfileServer profileServer = availableServers[serverIndex]; GpsLocation location = Helpers.GenerateRandomGpsLocation(cmd.Latitude, cmd.Longitude, cmd.Radius); IdentityClient identityClient = null; try { identityClient = new IdentityClient(name, cmd.IdentityType, location, cmd.ImageMask, cmd.ImageChance); identityClients.Add(name, identityClient); } catch { log.Error("Unable to create identity '{0}'.", name); error = true; break; } Task <bool> initTask = identityClient.InitializeProfileHosting(profileServer); if (initTask.Result) { profileServer.AddIdentityClient(identityClient); if (profileServer.AvailableIdentitySlots == 0) { availableServers.RemoveAt(serverIndex); } } else { log.Error("Unable to register profile hosting and initialize profile of identity '{0}' on server '{1}'.", name, profileServer.Name); error = true; break; } } if (!error) { log.Info(" * {0} identities created and initialized on {1} servers.", cmd.Count, cmd.PsCount); } break; } case CommandType.CancelIdentity: { CommandCancelIdentity cmd = (CommandCancelIdentity)command; List <IdentityClient> clients = new List <IdentityClient>(); for (int i = 0; i < cmd.Count; i++) { string name = GetIdentityName(cmd.Name, cmd.Index + i); IdentityClient identityClient; if (identityClients.TryGetValue(name, out identityClient)) { clients.Add(identityClient); } else { log.Error(" * Identity name '{0}' does not exist.", name); error = true; break; } } if (error) { break; } foreach (IdentityClient client in clients) { Task <bool> cancelTask = client.CancelProfileHosting(); if (!cancelTask.Result) { log.Error("Unable to cancel profile hosting agreement of identity '{0}' on server '{1}'.", client.Name, client.ProfileServer.Name); error = true; } } if (!error) { log.Info(" * {0} identities cancelled their hosting agreement.", clients.Count); } break; } case CommandType.Neighborhood: { CommandNeighborhood cmd = (CommandNeighborhood)command; List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.PsGroups.Count; i++) { string psGroup = cmd.PsGroups[i]; int psCount = cmd.PsCounts[i]; int psIndex = cmd.PsIndexes[i]; for (int j = 0; j < psCount; j++) { string name = GetInstanceName(psGroup, psIndex + j); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { neighborhoodList.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } } if (!error) { foreach (ProfileServer ps in neighborhoodList) { if (!ps.LocServer.AddNeighborhood(neighborhoodList)) { log.Error(" * Unable to add neighbors to server '{0}'.", ps.Name); error = true; break; } } if (!error) { log.Info(" * Neighborhood of {0} profile servers has been established.", neighborhoodList.Count); } } break; } case CommandType.CancelNeighborhood: { CommandCancelNeighborhood cmd = (CommandCancelNeighborhood)command; List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.PsGroups.Count; i++) { string psGroup = cmd.PsGroups[i]; int psCount = cmd.PsCounts[i]; int psIndex = cmd.PsIndexes[i]; for (int j = 0; j < psCount; j++) { string name = GetInstanceName(psGroup, psIndex + j); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { neighborhoodList.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } } if (!error) { foreach (ProfileServer ps in neighborhoodList) { if (!ps.LocServer.CancelNeighborhood(neighborhoodList)) { log.Error(" * Unable to add neighbors to server '{0}'.", ps.Name); error = true; break; } } if (!error) { log.Info(" * Neighbor relations among {0} profile servers have been cancelled.", neighborhoodList.Count); } } break; } case CommandType.Neighbor: { CommandNeighbor cmd = (CommandNeighbor)command; ProfileServer profileServer; if (profileServers.TryGetValue(cmd.Source, out profileServer)) { List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.Targets.Count; i++) { string name = cmd.Targets[i]; ProfileServer target; if (profileServers.TryGetValue(name, out target)) { neighborhoodList.Add(target); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { if (profileServer.LocServer.AddNeighborhood(neighborhoodList)) { log.Info(" * {0} servers have been added to the neighborhood of server '{1}'.", neighborhoodList.Count, profileServer.Name); } else { log.Error(" * Unable to add neighbors to server '{0}'.", profileServer.Name); error = true; break; } } } else { log.Error(" * Profile server instance '{0}' does not exist.", cmd.Source); error = true; break; } break; } case CommandType.CancelNeighbor: { CommandCancelNeighbor cmd = (CommandCancelNeighbor)command; ProfileServer profileServer; if (profileServers.TryGetValue(cmd.Source, out profileServer)) { List <ProfileServer> neighborhoodList = new List <ProfileServer>(); for (int i = 0; i < cmd.Targets.Count; i++) { string name = cmd.Targets[i]; ProfileServer target; if (profileServers.TryGetValue(name, out target)) { neighborhoodList.Add(target); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } if (!error) { if (profileServer.LocServer.CancelNeighborhood(neighborhoodList)) { log.Info(" * {0} servers have been removed from the neighborhood of server '{1}'.", neighborhoodList.Count, profileServer.Name); } else { log.Error(" * Unable to remove neighbors from neighborhood of server '{0}'.", profileServer.Name); error = true; break; } } } else { log.Error(" * Profile server instance '{0}' does not exist.", cmd.Source); error = true; break; } break; } case CommandType.TestQuery: { CommandTestQuery cmd = (CommandTestQuery)command; List <ProfileServer> targetServers = new List <ProfileServer>(); for (int i = 0; i < cmd.PsCount; i++) { string name = GetInstanceName(cmd.PsGroup, cmd.PsIndex + i); ProfileServer profileServer; if (profileServers.TryGetValue(name, out profileServer)) { targetServers.Add(profileServer); } else { log.Error(" * Profile server instance '{0}' does not exist.", name); error = true; break; } } int serversSkipped = 0; int serversQueried = 0; IdentityClient client = null; try { client = new IdentityClient("Query Client", "Query Client", new GpsLocation(0, 0), null, 0); int maxResults = cmd.IncludeImages ? 1000 : 10000; string nameFilter = cmd.NameFilter != "**" ? cmd.NameFilter : null; string typeFilter = cmd.TypeFilter != "**" ? cmd.TypeFilter : null; GpsLocation queryLocation = cmd.Latitude != GpsLocation.NoLocation.Latitude ? new GpsLocation(cmd.Latitude, cmd.Longitude) : null; foreach (ProfileServer targetServer in targetServers) { if (!targetServer.IsInitialized()) { log.Trace("Profile server '{0}' not initialized, skipping ...", targetServer.Name); serversSkipped++; continue; } byte[] targetServerId = targetServer.GetNetworkId(); client.InitializeTcpClient(); Task <IdentityClient.SearchQueryInfo> searchTask = client.SearchQueryAsync(targetServer, nameFilter, typeFilter, queryLocation, cmd.Radius, false, cmd.IncludeImages); IdentityClient.SearchQueryInfo searchResults = searchTask.Result; if (searchResults != null) { List <byte[]> expectedCoveredServers; int localServerResults; List <IdentityNetworkProfileInformation> expectedSearchResults = targetServer.GetExpectedSearchResults(nameFilter, typeFilter, queryLocation, cmd.Radius, false, cmd.IncludeImages, out expectedCoveredServers, out localServerResults); List <IdentityNetworkProfileInformation> realResults = searchResults.Results; List <byte[]> realCoveredServers = searchResults.CoveredServers; if (DebugModeEnabled) { log.Info(" * '{0}': {1} real results, {2} calculated results, {3} max. real results, {4} local server results, {5} real covered servers, {6} calculated covered servers.", targetServer.Name, realResults.Count, expectedSearchResults.Count, maxResults, localServerResults, realCoveredServers.Count, expectedCoveredServers.Count); } if (!CompareSearchResults(realResults, expectedSearchResults, maxResults)) { log.Error(" * Real search results are different from the expected results on server instance '{0}'.", targetServer.Name); error = true; break; } if (!CompareCoveredServers(targetServerId, realCoveredServers, expectedCoveredServers, localServerResults, maxResults)) { log.Error(" * Real covered servers are different from the expected covered servers on server instance '{0}'.", targetServer.Name); error = true; break; } serversQueried++; } else { log.Error(" * Unable to perform search on server instance '{0}'.", targetServer.Name); error = true; break; } } } catch (Exception e) { log.Error("Exception occurred: {0}", e.ToString()); error = true; break; } if (!error) { log.Info(" * Results of search queries on {0} servers match expected results. {1} servers were offline and skipped.", serversQueried, serversSkipped); } break; } case CommandType.Delay: { CommandDelay cmd = (CommandDelay)command; log.Info(" * Waiting {0} seconds ...", cmd.Seconds); Thread.Sleep(TimeSpan.FromSeconds((double)cmd.Seconds)); break; } case CommandType.TakeSnapshot: { CommandTakeSnapshot cmd = (CommandTakeSnapshot)command; HashSet <string> runningServerNames = new HashSet <string>(StringComparer.Ordinal); foreach (ProfileServer ps in profileServers.Values) { if (ps.IsRunningProcess()) { if (!ps.Stop()) { log.Error(" * Failed to stop profile server '{0}'.", ps.Name); error = true; break; } runningServerNames.Add(ps.Name); } } if (error) { break; } Snapshot snapshot = new Snapshot(cmd.Name); if (snapshot.Take(runningServerNames, profileServers, identityClients)) { log.Info(" * Snapshot '{0}' has been created.", cmd.Name); } else { log.Error(" * Failed to take simulation snapshot."); error = true; } break; } case CommandType.LoadSnapshot: { CommandLoadSnapshot cmd = (CommandLoadSnapshot)command; if (index != 1) { log.Error(" * LoadSnapshot must be the very first command in the scenario."); error = true; break; } Snapshot snapshot = new Snapshot(cmd.Name); if (!snapshot.Load()) { log.Error(" * Unable to load snapshot '{0}'.", cmd.Name); error = true; break; } try { // Initialize profile servers. log.Debug("Initializing profile servers."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = ProfileServer.CreateFromSnapshot(serverSnapshot); profileServers.Add(profileServer.Name, profileServer); } // Initialize identities and connect them with their profile servers. log.Debug("Initializing identity clients."); foreach (IdentitySnapshot identitySnapshot in snapshot.Identities) { ProfileServer profileServer = profileServers[identitySnapshot.ProfileServerName]; IdentityClient identityClient = IdentityClient.CreateFromSnapshot(identitySnapshot, snapshot.Images, profileServer); profileServer.AddIdentityClientSnapshot(identityClient); identityClients.Add(identityClient.Name, identityClient); } // Initialize neighbor relations. log.Debug("Initializing neighborhoods."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = profileServers[serverSnapshot.Name]; List <ProfileServer> neighborServers = new List <ProfileServer>(); foreach (string neighborName in serverSnapshot.LocServer.NeighborsNames) { ProfileServer neighborServer = profileServers[neighborName]; neighborServers.Add(neighborServer); } profileServer.LocServer.SetNeighborhood(neighborServers); } // Start LOC servers and profile servers. log.Debug("Starting servers."); foreach (ProfileServerSnapshot serverSnapshot in snapshot.ProfileServers) { ProfileServer profileServer = profileServers[serverSnapshot.Name]; if (!profileServer.LocServer.Start()) { log.Error(" * Unable to start LOC server of profile server instance '{0}'.", profileServer.Name); error = true; break; } if (serverSnapshot.IsRunning) { if (!profileServer.Start()) { log.Error(" * Unable to start profile server instance '{0}'.", profileServer.Name); error = true; break; } } } } catch (Exception e) { log.Error(" * Snapshot is corrupted, exception occurred: {0}", e.ToString()); error = true; break; } if (!error) { log.Info(" * Simulation state loaded from snapshot '{0}'.", cmd.Name); } break; } case CommandType.DebugMode: { CommandDebugMode cmd = (CommandDebugMode)command; log.Info(" * Debug mode is now {0}.", cmd.Enable ? "ENABLED" : "DISABLED"); DebugModeEnabled = cmd.Enable; break; } default: log.Error("Invalid command type '{0}'.", command.Type); error = true; break; } index++; if (error) { break; } } res = !error; log.Trace("(-):{0}", res); return(res); }