public void Run(Vsync.Group vsyncGroup) { Dictionary <string, ProcessInfo> procs; while (true) { procs = _cloudManagerLocal.GetProcesses(); foreach (string procName in procs.Keys) { ProcessInfo procInfo = procs [procName]; int procId = procInfo.GetId(); try { using (Process proc = Process.GetProcessById(procId)) { if ((proc == null) || proc.HasExited) { #if DEBUG CloudManager.WriteLine(_debugFilename, "Process " + procName + " stopped."); #endif _cloudManagerLocal.RemoveProcess(procName); // TODO: Send STOPPED_PROC message to the leader. } } ; } catch (ArgumentException) { #if DEBUG CloudManager.WriteLine(_debugFilename, "Process " + procName + " stopped."); #endif _cloudManagerLocal.RemoveProcess(procName); // TODO: Send STOPPED_PROC message to the leader. } } System.Threading.Thread.Sleep(_timeout); } }
public void Run(Vsync.Group vsyncGroup) { List <Tuple <MessageType, List <string> > > msgs; _dependencyStructure = _partition >= 0 ? new DependencyStructure(_leaderCloudMakefiles [_partition], _debugFilename) : null; if ((_partition >= 0) && (_rank == 0)) { FindInitialEntries(); } while (true) { lock (_queueLock) { while (_queue.Count == 0) { Monitor.Wait(_queueLock); } msgs = new List <Tuple <MessageType, List <string> > > (_queue); _queue.Clear(); } ProcessMessages(vsyncGroup, msgs); if ((_state == State.ACTIVE) && (_partition >= 0) && (_rank == _leaders [_partition].Count - 1)) { RunCloudMake(vsyncGroup); } } }
public CloudManagerLocal(List <CloudMakefile> leaderCloudMakefiles, CloudMakefile localCloudMakefile, string name, List <List <string> > leaders, List <string> reserveLeaders, int nreplicas, int timeout, Vsync.Group vsyncGroup, string debugFilename, string monitorDebugFilename) { _vsyncAddress = VsyncSystem.GetMyAddress().ToStringVerboseFormat(); _name = name; _curDirectory = Directory.GetCurrentDirectory(); _procs = new Dictionary <string, ProcessInfo> (); _procsLock = new object(); _leaders = leaders; _reserveLeaders = reserveLeaders; _nreplicas = nreplicas; _leaderCloudMakefiles = leaderCloudMakefiles; _localCloudMakefile = localCloudMakefile; _queue = new List <Tuple <MessageType, List <string> > > (); _queueLock = new object(); _debugFilename = debugFilename; _cloudMakeMonitor = new CloudMakeMonitor(this, monitorDebugFilename, timeout); Thread cloudMakeMonitorThread = new Thread(delegate() { _cloudMakeMonitor.Run(vsyncGroup); }); cloudMakeMonitorThread.Start(); }
System.Timers.Timer t; // Thread timer used for sending dictionary //Constructor public handler(TcpClient c, Vsync.Group g) { client = c; bytes = new Byte[4096]; data = null; this.g = g; strm = null; ID = Path.GetRandomFileName().Replace(".", ""); t = new System.Timers.Timer(); }
private void AskState(Vsync.Group vsyncGroup, string path, string filename) { FileSystemWatcher watcher = new FileSystemWatcher(); watcher.Path = path; watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Filter = filename; watcher.Changed += (s, e) => ModifiedState(vsyncGroup, e.FullPath, e.Name); watcher.EnableRaisingEvents = true; }
private void MemberJoin(Vsync.Group vsyncGroup) { string memberDirectory = _name; string eventName = _name + "/new_node"; string cloudMakeDirectory = memberDirectory + Path.DirectorySeparatorChar + "CloudMake"; string cloudMakeConfigFilename = cloudMakeDirectory + Path.DirectorySeparatorChar.ToString() + "config.xml"; List <Tuple <string, int> > newNodeEntries; HashSet <int> nameSet, cloudMakeConfigSet; if (_localCloudMakefile == null) { throw new Exception("CloudMakeLocal: There is no CloudMakefile."); } nameSet = _localCloudMakefile.Compatible(memberDirectory); if (nameSet.Count > 0) { Directory.SetCurrentDirectory(_name); #if DEBUG CloudManager.WriteLine(_debugFilename, "Create Directory: " + memberDirectory); #endif Directory.CreateDirectory(memberDirectory); cloudMakeConfigSet = _localCloudMakefile.Compatible(cloudMakeConfigFilename, nameSet); if (cloudMakeConfigSet.Count > 0) { #if DEBUG CloudManager.WriteLine(_debugFilename, "Create Directory: " + cloudMakeDirectory); CloudManager.WriteLine(_debugFilename, "Added CloudMake Config: " + cloudMakeConfigFilename); #endif Directory.CreateDirectory(cloudMakeDirectory); _dependencyStructure.AddCloudMakeConfigFile(cloudMakeConfigFilename); } Directory.SetCurrentDirectory(_curDirectory); newNodeEntries = _localCloudMakefile.FindMatchingEntries(eventName); if (newNodeEntries.Count > 1) { throw new Exception("It is impossible for a NEW_NODE event to have more than one corresponding " + "DFA."); } if (newNodeEntries.Count == 1) { _dependencyStructure.AddEntry(newNodeEntries [0]); _dependencyStructure.AddTokenToEntry(newNodeEntries [0].Item1); #if DEBUG CloudManager.WriteLine(_debugFilename, "Added Token to New Node Event: " + eventName); #endif RunCloudMake(vsyncGroup); } } else { throw new Exception("CloudMakeLocal: There is no matching entry for " + _name + "/new_node"); } }
private void UpdateState(Vsync.Group vsyncGroup, string filename, string content) { XmlDocument xmlDoc = new XmlDocument(); List <string> filenameList = new List <string> (filename.Split('/')); filename = String.Join(Path.DirectorySeparatorChar.ToString(), filenameList); CloudManager.WriteLine(_debugFilename, filename); CloudManager.WriteLine(_debugFilename, content); xmlDoc.LoadXml(content); xmlDoc.Save(filename); RunCloudMake(vsyncGroup); }
private void RunCloudMake(Vsync.Group vsyncGroup) { _dependencyStructure.Run(); if (_rank == 0) { Dist(vsyncGroup, _dependencyStructure.GetModifiedConfigFiles(), _dependencyStructure.GetModifiedCloudMakeConfigFiles()); } else { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.RUN_CLOUD_MAKE); } _dependencyStructure.Reset(); }
public void Run(Vsync.Group vsyncGroup) { List <Tuple <MessageType, List <string> > > msgs; _dependencyStructure = _localCloudMakefile == null ? null : new DependencyStructure(_localCloudMakefile, _debugFilename); while (true) { lock (_queueLock) { while (_queue.Count == 0) { Monitor.Wait(_queueLock); } msgs = new List <Tuple <MessageType, List <string> > > (_queue); _queue.Clear(); } ProcessMessages(vsyncGroup, msgs); } }
private void ModifiedState(Vsync.Group vsyncGroup, string path, string name) { XmlDocument xmlDoc = new XmlDocument(); string filename = _name + "/" + name; string content; xmlDoc.Load(path); content = xmlDoc.OuterXml; if (_localCloudMakefile.Compatible(filename).Count > 0) { UpdateState(vsyncGroup, filename, content); } for (int i = 0; i < _leaderCloudMakefiles.Count; i++) { if (_leaderCloudMakefiles [i].Compatible(filename).Count > 0) { vsyncGroup.P2PSend(new Address(_leaders [i] [0]), CloudManager.UPDATE_STATE, filename, content); } } }
private void ProcessMessages(Vsync.Group vsyncGroup, List <Tuple <MessageType, List <string> > > msgs) { foreach (Tuple <MessageType, List <string> > msg in msgs) { MessageType type = msg.Item1; List <string> parameters = msg.Item2; string vsyncAddress, procName, path, exec, args, filename, content, configFilename; #if DEBUG WriteMessage(type, parameters); #endif switch (type) { case MessageType.NEW_NODE: if (parameters.Count != 1) { throw new Exception("CloudMakeLocal: NEW_NODE: Does not accept " + parameters.Count.ToString() + " parameters."); } vsyncAddress = parameters [0]; vsyncGroup.P2PSend(new Address(vsyncAddress), CloudManager.MEMBER_INFO, _vsyncAddress, _name); break; case MessageType.FAIL_NODE: break; case MessageType.MEMBER_JOIN: MemberJoin(vsyncGroup); break; case MessageType.LEADER_JOIN: if (parameters.Count != 1) { throw new Exception("CloudMakeLocal: LEADER_JOIN: Does not accept " + parameters.Count.ToString() + " parameters."); } vsyncAddress = parameters [0]; CloudManager.AddLeader(_leaders, _reserveLeaders, _nreplicas, vsyncAddress); break; case MessageType.NEW_CONFIG: if (parameters.Count != 1) { throw new Exception("CloudMakeLocal: NEW CONFIG: Should only have one configFilename."); } configFilename = parameters [0]; NewConfig(configFilename); break; case MessageType.RUN_PROCESS: procName = parameters [0]; path = parameters [1]; exec = parameters [2]; args = parameters [3]; RunProcess(procName, path, exec, args); break; case MessageType.KILL_PROCESS: procName = parameters [0]; KillProcess(procName); break; case MessageType.UPDATE_CONFIG: filename = parameters [0]; content = parameters [1]; UpdateConfig(filename, content); break; case MessageType.ASK_STATE: path = parameters [0]; filename = parameters [1]; AskState(vsyncGroup, path, filename); break; default: throw new Exception("CloudMakeLocal: I should not have received " + msg.ToString() + " message."); } } }
public static void Main(string[] args) { //Set up vsync dictionary and handlers Dictionary <string, string> valueStore = new Dictionary <string, string> (); valueStore ["user1"] = "0,1,0,1,1,2"; valueStore ["user2"] = "1,1,1,1,1,1"; const int UPDATE = 0; const int LOOKUP = 1; const int REFRESH = 2; const int REMOVE = 3; Console.WriteLine("Hello World!"); VsyncSystem.Start(); Console.WriteLine("VSYNC STARTED"); Vsync.Group g = new Vsync.Group("dataHolder"); g.ViewHandlers += (ViewHandler) delegate(View v) { VsyncSystem.WriteLine("New View: " + v); Console.Title = "View " + v.viewid + ", my rank=" + v.GetMyRank(); }; g.Handlers[UPDATE] += (Action <string, string>) delegate(string username, string val) { VsyncSystem.WriteLine("IN UPDATE"); valueStore[username] = val; }; g.Handlers[LOOKUP] += (Action <string>) delegate(string s) { VsyncSystem.WriteLine("IN LOOKUP"); g.Reply(valueStore[s]); }; g.Handlers [REFRESH] += (Action) delegate() { string reply = Extensions.FromDictionaryToJson(valueStore); g.Reply(reply); }; g.Handlers [REMOVE] += (Action <string>) delegate(string s) { VsyncSystem.WriteLine("DELETING USER " + s); valueStore.Remove(s); }; /*g.MakeChkpt += (Vsync.ChkptMaker)delegate(View nv) { * g.SendChkpt(valueStore); * g.EndOfChkpt(); * }; * g.LoadChkpt += (loadVSchkpt)delegate(Dictionary<string, position> vs) { * valueStore = vs; * }; */ g.Join(); //Quick visual check to make sure initialization goes smoothely //UNNECESSARY -> TAKE OUT LATER List <string> valuesDic = new List <string> (); g.Query(1, REFRESH, new EOLMarker(), valuesDic); Console.WriteLine(valuesDic [0]); //Set up TCP Listener TcpListener server = new TcpListener(7569); server.Start(); Console.WriteLine("Server has started on 127.0.0.1:7569.{0}Waiting for a connection...", Environment.NewLine); //Listen for connections while (true) { TcpClient client = server.AcceptTcpClient(); handler h = new handler(client, g); //Spin off new thread to handle clients as they arrive Thread handler = new Thread(new ThreadStart(h.handle)); handler.Start(); Console.WriteLine("A Client Connected!"); } }
private Tuple <HashSet <string>, List <RemoteProcessInfo> > ProcessCloudMakeConfigFile(Vsync.Group vsyncGroup) { string cloudMakeConfigFilename = _name + "/CloudMake/config.xml"; XmlDocument xmlDoc = new XmlDocument(); XmlNode xmlNode; List <RemoteProcessInfo> processes = new List <RemoteProcessInfo> (); List <string> statePathList = new List <string> (); List <string> stateFilenameList = new List <string> (); Dictionary <int, HashSet <string> > configFiles = new Dictionary <int, HashSet <string> > (); HashSet <string> localConfigFiles = new HashSet <string> (); xmlDoc.Load(cloudMakeConfigFilename); xmlNode = xmlDoc.DocumentElement; foreach (XmlNode childNode in xmlNode.ChildNodes) { switch (childNode.Name) { case ("process"): if (childNode.Attributes ["action"].Value == "Run") { string name = childNode ["name"].InnerText; string path = childNode ["path"].InnerText; string exec = childNode ["exec"].InnerText; string args = childNode ["args"].InnerText; #if DEBUG CloudManager.WriteLine(_debugFilename, "Run process " + name + "."); #endif processes.Add(new RemoteProcessInfo(Action.RUN, _name, name, path, exec, args)); } else if (childNode.Attributes ["action"].Value == "Kill") { string name = childNode ["name"].InnerText; #if DEBUG CloudManager.WriteLine(_debugFilename, "Kill process " + name + "."); #endif processes.Add(new RemoteProcessInfo(Action.KILL, _name, name)); } break; case ("stateFile"): string statePath = childNode ["path"].InnerText; string stateName = childNode ["name"].InnerText; if (statePath == "") { statePath = _curDirectory; } else { statePath = _curDirectory + Path.DirectorySeparatorChar.ToString() + statePath; } statePathList.Add(statePath); stateFilenameList.Add(stateName); break; case ("configFile"): string configPath = childNode ["path"].InnerText; string configName = childNode ["name"].InnerText; string configFilename = (configPath == "") ? _name + "/" + configName : _name + "/" + configPath + "/" + configName; for (int i = 0; i < _leaderCloudMakefiles.Count; i++) { if (_leaderCloudMakefiles [i].Compatible(configFilename).Count > 0) { if (!configFiles.ContainsKey(i)) { configFiles [i] = new HashSet <string> (); } configFiles [i].Add(configFilename); } } if (_localCloudMakefile.Compatible(configFilename).Count > 0) { NewConfig(configFilename); localConfigFiles.Add(configFilename); } break; default: throw new Exception("CloudMakeLocal Config: Operation " + childNode.Name + " is not supported " + "from CloudMake."); } } foreach (int i in configFiles.Keys) { vsyncGroup.P2PSend(new Address(_leaders [i] [0]), CloudManager.NEW_CONFIGS, new List <string> (configFiles [i])); } for (int i = 0; i < statePathList.Count; i++) { AskState(vsyncGroup, statePathList [i], stateFilenameList [i]); } return(new Tuple <HashSet <string>, List <RemoteProcessInfo> > (localConfigFiles, processes)); }
private void ProcessMessages(Vsync.Group vsyncGroup, List <Tuple <MessageType, List <string> > > msgs) { foreach (Tuple <MessageType, List <string> > msg in msgs) { MessageType type = msg.Item1; MessageType tempType; List <string> parameters = msg.Item2; List <string> tempParameters = null; string vsyncAddress, memberName, filename, xmlString, procName, configFilename; int minPartition, partition, last; WriteMessage(type, parameters); switch (type) { case MessageType.NEW_NODE: vsyncAddress = parameters [0]; CloudManager.WriteLine(_debugFilename, vsyncAddress.ToString()); vsyncGroup.P2PSend(new Address(vsyncAddress), CloudManager.LEADER_INFO, _vsyncAddress, _partition, _rank); break; case MessageType.FAIL_NODE: vsyncAddress = parameters [0]; partition = CloudManager.FindPartition(_leaders, _reserveLeaders, vsyncAddress); if (partition >= 0) { throw new NotImplementedException(); } else if (partition == -1) { _reserveLeaders.Remove(vsyncAddress); } else if (_addressToName.ContainsKey(vsyncAddress)) { memberName = _addressToName [vsyncAddress]; _addressToName.Remove(vsyncAddress); _nameToAddress.Remove(memberName); if ((_state == State.ACTIVE) && IsEventInPartition(memberName + "/fail_node")) { if (_rank == 0) { if (_leaders [_partition].Count == 1) { MemberLeave(memberName); _updatesDelivered += 1; } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.MEMBER_LEAVE, memberName); } } } } break; case MessageType.MEMBER_JOIN: vsyncAddress = parameters [0]; memberName = parameters [1]; _addressToName.Add(vsyncAddress, memberName); _nameToAddress.Add(memberName, vsyncAddress); if ((_partition >= 0) && (_rank == 0) && (_rank == _leaders [_partition].Count - 1)) { NewMember(memberName); _updatesDelivered += 1; } else if ((_partition >= 0) && (_rank == 0)) { tempType = MessageType.NEW_MEMBER; tempParameters = new List <string> (); tempParameters.Add(memberName); _pending.Add(new Tuple <MessageType, List <string> > (tempType, tempParameters)); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.NEW_MEMBER, memberName); } break; case MessageType.MEMBER_LEAVE: if (!(_state == State.ACTIVE)) { throw new Exception("CloudMakeLeader: Received MEMBER_LEAVE without being active."); } memberName = parameters [0]; if (_rank == _leaders [_partition].Count - 1) { MemberLeave(memberName); _updatesDelivered += 1; if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.MEMBER_LEAVE, memberName); } break; case MessageType.LEADER_JOIN: vsyncAddress = parameters [0]; minPartition = CloudManager.FindMinPartition(_leaders); if ((minPartition >= 0) && (_leaders [minPartition].Count < _nreplicas)) { last = _leaders [minPartition].Count - 1; _leaders [minPartition].Add(vsyncAddress); CloudManager.WriteLine(_debugFilename, "Previous Leader: " + _leaders [minPartition] [last]); CloudManager.WriteLine(_debugFilename, "Me: " + _vsyncAddress); if ((_state == State.ACTIVE) && (_leaders [minPartition] [last] == _vsyncAddress)) { Tuple <List <string>, List <string>, List <string> > triple = GetState(); vsyncGroup.P2PSend(new Address(_leaders [minPartition] [last + 1]), CloudManager.STATE_TRANSFER, triple.Item1, triple.Item2, triple.Item3); } } else { _reserveLeaders.Add(vsyncAddress); } break; case MessageType.NEW_MEMBER: memberName = parameters [0]; CloudManager.WriteLine(_debugFilename, "Partition: " + _partition.ToString()); if (_rank == _leaders [_partition].Count - 1) { CloudManager.WriteLine(_debugFilename, "Call NewMember."); NewMember(memberName); _updatesDelivered += 1; if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.NEW_MEMBER, memberName); } break; case MessageType.NEW_CONFIG: configFilename = parameters [0]; CloudManager.WriteLine(_debugFilename, "Partition: " + _partition.ToString()); if (_rank == _leaders [_partition].Count - 1) { CloudManager.WriteLine(_debugFilename, "Call NewConfig."); NewConfig(configFilename); CloudManager.WriteLine(_debugFilename, "Finished NewConfig."); _updatesDelivered += 1; if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.NEW_CONFIGS, parameters); } break; case MessageType.STOPPED_PROC: if (_state != State.ACTIVE) { throw new Exception("CloudMakeLeader: Received STOPPED_PROC without being active."); } memberName = parameters [0]; procName = parameters [1]; if (_rank == _leaders [_partition].Count - 1) { StoppedProc(memberName, procName); _updatesDelivered += 1; if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.STOPPED_PROC, memberName, procName); } break; case MessageType.UPDATE_STATE: if (_state != State.ACTIVE) { throw new Exception("CloudMakeLeader: Received UPDATE_STATE without being active"); } filename = parameters [0]; xmlString = parameters [1]; if (_rank == _leaders [_partition].Count - 1) { UpdateState(filename, xmlString); _updatesDelivered += 1; if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } } else { _pending.Add(msg); vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.UPDATE_STATE, filename, xmlString); } break; case MessageType.ACK: tempType = _pending [0].Item1; tempParameters = _pending [0].Item2; switch (tempType) { case MessageType.NEW_MEMBER: CloudManager.WriteLine(_debugFilename, "Call NewMember."); memberName = tempParameters [0]; NewMember(memberName); break; case MessageType.NEW_CONFIG: configFilename = tempParameters [0]; CloudManager.WriteLine(_debugFilename, "Call NewConfig."); NewConfig(configFilename); CloudManager.WriteLine(_debugFilename, "Finished NewConfig."); break; case MessageType.MEMBER_LEAVE: memberName = tempParameters [0]; MemberLeave(memberName); break; case MessageType.STOPPED_PROC: memberName = tempParameters [0]; procName = tempParameters [1]; StoppedProc(memberName, procName); break; case MessageType.UPDATE_STATE: filename = tempParameters [0]; xmlString = tempParameters [1]; UpdateState(filename, xmlString); break; default: throw new Exception("CloudMakeLeader: Unknown Message Type " + _pending [0].Item1.ToString() + " in pending queue."); } _updatesDelivered += 1; _pending.RemoveAt(0); if (_rank > 0) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank - 1]), CloudManager.ACK); } break; case MessageType.RUN_CLOUD_MAKE: RunCloudMake(vsyncGroup); break; case MessageType.STATE_TRANSFER: if (_state != State.WAITFORSTATE) { throw new Exception("CloudMakeLeader: Received STATE_TRANSFER without being at WAITFORSTATE " + "state"); } List <string> directories = new List <string> (); List <string> xmlFilenames = new List <string> (); List <string> xmlContents = new List <string> (); int i = 0; while ((parameters.Count > 2 * i + 1) && (parameters [2 * i + 1] == "")) { string dir = parameters [2 * i]; Directory.CreateDirectory(dir); directories.Add(dir); #if DEBUG CloudManager.WriteLine(_debugFilename, "State Transfer Directory: " + dir); #endif i++; } while (parameters.Count > 2 * i + 1) { string xmlFilename = parameters [2 * i]; string xmlContent = parameters [2 * i + 1]; XmlDocument xmlDoc = new XmlDocument(); xmlFilenames.Add(xmlFilename); xmlContents.Add(xmlContent); #if DEBUG CloudManager.WriteLine(_debugFilename, "State Transfer Filename: " + xmlFilename); #endif xmlDoc.LoadXml(xmlContent); xmlDoc.Save(xmlFilename); i++; } _state = State.ACTIVE; if (_rank != _leaders [_partition].Count - 1) { vsyncGroup.P2PSend(new Address(_leaders [_partition] [_rank + 1]), CloudManager.STATE_TRANSFER, directories, xmlFilenames, xmlContents); } break; case MessageType.SEND_PENDING: throw new NotImplementedException(); default: throw new Exception("CloudMakeLeader: I should not have received " + msg.ToString() + " message."); } CloudManager.WriteLine(_debugFilename, "Pending:"); foreach (Tuple <MessageType, List <string> > tempMsg in _pending) { WriteMessage(tempMsg.Item1, tempMsg.Item2); } } }
private void Dist(Vsync.Group vsyncGroup, HashSet <string> activeConfigFiles, HashSet <string> activeCloudMakeConfigFiles) { Tuple <HashSet <string>, List <RemoteProcessInfo> > processedInfo = ProcessCloudMakeConfigFiles(vsyncGroup, activeCloudMakeConfigFiles); HashSet <string> additionalActiveConfigFiles = new HashSet <string> (); List <RemoteProcessInfo> remoteProcesses = processedInfo.Item2; foreach (string activeConfigFile in processedInfo.Item1) { if (File.Exists(activeConfigFile)) { additionalActiveConfigFiles.Add(activeConfigFile); } } #if DEBUG CloudManager.WriteLine(_debugFilename, "Active config files:"); foreach (string filename in activeConfigFiles) { CloudManager.WriteLine(_debugFilename, filename); } CloudManager.WriteLine(_debugFilename, ""); CloudManager.WriteLine(_debugFilename, "Active CloudMake config files:"); foreach (string filename in activeCloudMakeConfigFiles) { CloudManager.WriteLine(_debugFilename, filename); } CloudManager.WriteLine(_debugFilename, ""); #endif activeConfigFiles.UnionWith(additionalActiveConfigFiles); #if DEBUG CloudManager.WriteLine(_debugFilename, "Files to Distribute:"); foreach (string filename in activeConfigFiles) { CloudManager.WriteLine(_debugFilename, filename); } CloudManager.WriteLine(_debugFilename, ""); #endif foreach (string activeConfigFile in activeConfigFiles) { List <string> fields = new List <string> (activeConfigFile.Split('/')); string nodename = fields [0]; List <string> fieldsList = fields.GetRange(1, fields.Count - 1); string path = String.Join("/", fieldsList); XmlDocument xmlDoc = new XmlDocument(); string filename = String.Join(Path.DirectorySeparatorChar.ToString(), fields); string content; List <string> pathList = new List <string> (); List <string> contentList = new List <string> (); xmlDoc.Load(filename); content = xmlDoc.OuterXml; #if DEBUG CloudManager.WriteLine(_debugFilename, "Distribute the content of " + filename + " to " + nodename); #endif pathList.Add(path); contentList.Add(content); if (_nameToAddress.ContainsKey(nodename)) { vsyncGroup.P2PSend(new Address(_nameToAddress [nodename]), CloudManager.UPDATE_CONFIGS, pathList, contentList); } } foreach (RemoteProcessInfo proc in remoteProcesses) { List <string> nameList = new List <string> (); List <string> pathList = new List <string> (); List <string> execList = new List <string> (); List <string> argsList = new List <string> (); string nodename; if (proc.GetAction() == Action.RUN) { nameList.Add(proc.GetName()); pathList.Add(proc.GetPath()); execList.Add(proc.GetExec()); argsList.Add(proc.GetArgs()); nodename = proc.GetNodename(); if (_nameToAddress.ContainsKey(nodename)) { vsyncGroup.P2PSend(new Address(_nameToAddress [nodename]), CloudManager.RUN_PROCESSES, nameList, pathList, execList, argsList); } } else { nameList.Add(proc.GetName()); nodename = proc.GetNodename(); if (_nameToAddress.ContainsKey(nodename)) { vsyncGroup.P2PSend(new Address(_nameToAddress [nodename]), CloudManager.KILL_PROCESSES, nameList); } } } }
ProcessCloudMakeConfigFiles(Vsync.Group vsyncGroup, HashSet <string> cloudMakeConfigFiles) { List <RemoteProcessInfo> remoteProcesses = new List <RemoteProcessInfo> (); List <string> statePathList = new List <string> (); List <string> stateNameList = new List <string> (); Dictionary <int, HashSet <string> > configFiles = new Dictionary <int, HashSet <string> > (); foreach (string cloudMakeConfigFile in cloudMakeConfigFiles) { XmlDocument xmlDoc = new XmlDocument(); XmlNode xmlNode; string nodename = cloudMakeConfigFile.Substring(0, cloudMakeConfigFile.IndexOf('/')); xmlDoc.Load(cloudMakeConfigFile); xmlNode = xmlDoc.DocumentElement; foreach (XmlNode childNode in xmlNode.ChildNodes) { switch (childNode.Name) { case ("process"): if (childNode.Attributes ["action"].Value == "Run") { string name = childNode ["name"].InnerText; string path = childNode ["path"].InnerText; string exec = childNode ["exec"].InnerText; string args = childNode ["args"].InnerText; #if DEBUG CloudManager.WriteLine(_debugFilename, "Run process " + name + "."); #endif remoteProcesses.Add(new RemoteProcessInfo(Action.RUN, nodename, name, path, exec, args)); } else if (childNode.Attributes ["action"].Value == "Kill") { string name = childNode ["name"].InnerText; #if DEBUG CloudManager.WriteLine(_debugFilename, "Kill process " + name + "."); #endif remoteProcesses.Add(new RemoteProcessInfo(Action.KILL, nodename, name)); } break; case ("stateFile"): string statePath = childNode ["path"].InnerText; string stateName = childNode ["name"].InnerText; statePathList.Add(statePath); stateNameList.Add(stateName); break; case ("configFile"): string configPath = childNode ["path"].InnerText; string configName = childNode ["name"].InnerText; string configFilename = (configPath == "") ? nodename + "/" + configName : nodename + "/" + configPath + "/" + configName; for (int i = 0; i < _leaderCloudMakefiles.Count; i++) { if (_leaderCloudMakefiles [i].Compatible(configFilename).Count > 0) { if (!configFiles.ContainsKey(i)) { configFiles [i] = new HashSet <string> (); } configFiles [i].Add(configFilename); } } if ((_localCloudMakefiles.ContainsKey(nodename)) && (_localCloudMakefiles [nodename].Compatible(configFilename).Count > 0)) { List <string> parameters = new List <string> (); parameters.Add(configFilename); vsyncGroup.P2PSend(new Address(_nameToAddress [nodename]), CloudManager.NEW_CONFIGS, parameters); } break; default: #if DEBUG CloudManager.WriteLine(_debugFilename, "CloudMakeLeader: Operation " + childNode.Name + " is not supported from CloudMakefile."); #endif break; } } foreach (int i in configFiles.Keys) { if (i == _partition) { foreach (string configFilename in configFiles[i]) { NewConfig(configFilename); } } else { vsyncGroup.P2PSend(new Address(_leaders [i] [0]), CloudManager.NEW_CONFIGS, new List <string> (configFiles [i])); } } if (statePathList.Count > 0) { vsyncGroup.P2PSend(new Address(_nameToAddress [nodename]), CloudManager.ASK_STATES, statePathList, stateNameList); } } if (configFiles.ContainsKey(_partition)) { return(new Tuple <HashSet <string>, List <RemoteProcessInfo> > (configFiles [_partition], remoteProcesses)); } return(new Tuple <HashSet <string>, List <RemoteProcessInfo> > (new HashSet <string> (), remoteProcesses)); }
public static void Main(String[] Args) { Dictionary <string, List <int> > rooms = new Dictionary <string, List <int> > (); VsyncSystem.Start(); Console.WriteLine("vsync started"); Vsync.Group lGroup = new Vsync.Group("Load Balancers"); lGroup.Handlers [UPDATE] += (Action <String, List <int> >) delegate(string id, List <int> r) { foreach (KeyValuePair <string, List <int> > entry in rooms) { try { if (Int32.Parse(id) == Int32.Parse(entry.Key)) { rooms[entry.Key] = r; return; } } catch (Exception e) { //pass through } } rooms[id] = r; Console.WriteLine("Adding {0} to dict", id); }; lGroup.Handlers [LOOKUP] += (Action <String>) delegate(string id) { //Console.WriteLine("Looking in dict for {0}:end", id); //bool contains = false; foreach (KeyValuePair <string, List <int> > entry in rooms) { //Console.WriteLine("s:{0}:f", entry.Key); try { if (Int32.Parse(id) == Int32.Parse(entry.Key)) { lGroup.Reply(entry.Value); return; } } catch (Exception e) { //pass through } } /*Console.WriteLine(rooms.ContainsKey(id)); * if (contains){ * lGroup.Reply (rooms [id]); * Console.WriteLine("Found room in dictionary!"); * } * else{ */ lGroup.Reply(new List <int>()); Console.WriteLine("Creating room in dictionary!"); }; lGroup.MakeChkpt += (Vsync.ChkptMaker) delegate(View nv){ lGroup.SendChkpt(Extensions.FromDictionaryToJson(rooms)); lGroup.EndOfChkpt(); }; lGroup.LoadChkpt += (loaddckpt) delegate(string rs) { rooms = Extensions.FromJsonToDictionary(rs); }; //loadGroup.DHTEnable (1, 1, 1, 86400000); lGroup.Join(); Console.WriteLine("Server Group Joined"); int port = Int32.Parse(Args [0]); TcpListener server = new TcpListener(port); server.Start(); Console.WriteLine("Server has started on 127.0.0.1:7000.{0}Waiting for a connection...", Environment.NewLine); int counter = 7568; String room = null; while (true) { TcpClient client = server.AcceptTcpClient(); counter++; NetworkStream stream = client.GetStream(); bool connect = true; //String room = null; while (connect) { Byte[] bytes = new Byte[4096]; String data = null; int i = Helpers.Connections.checkRead(stream, bytes); data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); //First request -> Respond with HTTP Change Protocol Handshake if (new Regex("^GET").IsMatch(data)) { Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine + "Connection: Upgrade" + Environment.NewLine + "Upgrade: websocket" + Environment.NewLine + "Sec-WebSocket-Accept: " + Convert.ToBase64String( SHA1.Create().ComputeHash( Encoding.UTF8.GetBytes( new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups [1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ) ) ) + Environment.NewLine + Environment.NewLine); stream.Write(response, 0, response.Length); } else { Byte[] response = Helpers.Connections.decode(bytes); string r = System.Text.Encoding.ASCII.GetString(response); //r = r.Substring(0, 10); room = r; bool isValid = true; //Console.WriteLine ("{0}", r); //Console.WriteLine ("Length: {1}, Last Char: {0}!", room.Substring ((r.Length - 1)), room.Length); if (room.Contains("j")) { Console.WriteLine("here"); try { List <List <int> > rez = new List <List <int> >(); room = room.Remove(room.IndexOf("j"), 1); Console.WriteLine(room); lGroup.OrderedQuery(1, LOOKUP, room, new Vsync.EOLMarker(), rez); List <int> ports = rez[0]; if (ports.Count == 0) { isValid = false; Console.WriteLine("BAD ID"); byte[] f = Encoding.UTF8.GetBytes("BAD ID"); f = Helpers.Connections.encode(f); stream.Write(f, 0, f.Length); } Console.WriteLine(room); //r = room; } catch (Exception e) { Console.WriteLine("Error: {0}", e); } } if (isValid) { Console.WriteLine("The room name is " + room); break; } } } List <List <int> > result = new List <List <int> > (); try { lGroup.OrderedQuery(1, LOOKUP, room, new Vsync.EOLMarker(), result); List <int> ports = result[0]; ports.Add(counter); lGroup.OrderedSend(UPDATE, room, ports); } catch (Exception e) { Console.WriteLine("DICTIONARY ADD Error: {0}", e); } /*Console.WriteLine ("good here..."); * List<int> portlst = loadGroup.DHTGet<String, List<int>>((string) room); * Console.WriteLine ("good after this ish"); * if (portlst == null) { * portlst = new List<int> (); * } * portlst.Add (counter); * Console.WriteLine ("putting"); * loadGroup.DHTPut (room, portlst); * Console.WriteLine ("put"); */ Byte[] q = Encoding.UTF8.GetBytes(counter.ToString()); Byte[] resp = Helpers.Connections.encode(q); Console.WriteLine("HEY " + "../launchServer.sh " + counter.ToString() + " " + room); Process proc = new Process { StartInfo = new ProcessStartInfo { FileName = "/bin/bash", Arguments = "../launchServer.sh " + counter.ToString() + " " + room, UseShellExecute = true, RedirectStandardOutput = false } }; proc.Start(); Console.WriteLine("A Client Connected!Handler server started."); System.Threading.Thread.Sleep(1000); stream.Write(resp, 0, resp.Length); Console.WriteLine("Port Number Sent"); } }
private void RunCloudMake(Vsync.Group vsyncGroup) { Tuple <HashSet <string>, List <RemoteProcessInfo> > processedInfo; HashSet <string> configFiles; HashSet <string> cloudMakeConfigFiles; HashSet <string> activeConfigFiles; List <RemoteProcessInfo> processes = null; Directory.SetCurrentDirectory(_name); _dependencyStructure.Run(); configFiles = _dependencyStructure.GetModifiedConfigFiles(); cloudMakeConfigFiles = _dependencyStructure.GetModifiedCloudMakeConfigFiles(); CloudManager.WriteLine(_debugFilename, _dependencyStructure.ToString()); foreach (string cloudMakeConfigFilename in cloudMakeConfigFiles) { CloudManager.WriteLine(_debugFilename, cloudMakeConfigFilename); } if (cloudMakeConfigFiles.Count > 1) { throw new Exception("CloudMakeLocal: There are more than one CloudMake config files."); } if (cloudMakeConfigFiles.Count == 1) { processedInfo = ProcessCloudMakeConfigFile(vsyncGroup); activeConfigFiles = processedInfo.Item1; processes = processedInfo.Item2; foreach (string activeConfigFile in activeConfigFiles) { if (File.Exists(activeConfigFile)) { configFiles.Add(activeConfigFile); } } } #if DEBUG CloudManager.WriteLine(_debugFilename, "Active config files:"); foreach (string filename in configFiles) { CloudManager.WriteLine(_debugFilename, filename); } CloudManager.WriteLine(_debugFilename, ""); CloudManager.WriteLine(_debugFilename, "Active CloudMake config files:"); foreach (string filename in cloudMakeConfigFiles) { CloudManager.WriteLine(_debugFilename, filename); } CloudManager.WriteLine(_debugFilename, ""); #endif foreach (string activeConfigFile in configFiles) { List <string> fields = new List <string> (activeConfigFile.Split('/')); string filename = String.Join(Path.DirectorySeparatorChar.ToString(), fields); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(filename); UpdateConfig(filename, xmlDoc.OuterXml); } if (cloudMakeConfigFiles.Count == 1) { foreach (RemoteProcessInfo proc in processes) { if (proc.GetAction() == Action.RUN) { RunProcess(proc.GetName(), proc.GetPath(), proc.GetExec(), proc.GetArgs()); } else if (proc.GetAction() == Action.KILL) { KillProcess(proc.GetName()); } } } _dependencyStructure.Reset(); Directory.SetCurrentDirectory(_curDirectory); }
static void Main(string[] args) { Searcher.cacheList(); int MASTER_RANK = 0; //the first one enter is master Log("Start Vsync System"); Vsync.VsyncSystem.Start(); Vsync.Msg.RegisterType(typeof(QueryMessage), 0); Vsync.Msg.RegisterType(typeof(Contact), 1); g = new Vsync.Group(GroupIdentifier); int myRank = 0; g.ViewHandlers += (Vsync.ViewHandler) delegate(Vsync.View view) { //there is changes in View Vsync.VsyncSystem.WriteLine("New view: " + view); int oldRank = myRank; int oldNbNodes = nbNodes; myRank = view.GetMyRank(); nbNodes = view.members.Length; lock (serverLocker) { //if this is Master --> start the server to receive request if (myRank == MASTER_RANK) { if (serverThread == null || !serverThread.IsAlive) { Log("I'm the Master!"); serverThread = new Thread(new ParameterizedThreadStart(startServer)); serverThread.Start(); } } else { if (serverThread != null && serverThread.IsAlive) { server.Stop(); } } } }; g.Handlers[SEARCH] += (Action <QueryMessage>) delegate(QueryMessage queryMsg) { Log(string.Format("Received search request from Master: {0}", queryMsg.query)); bool isFinalNode = (myRank == queryMsg.nbNodes - 1); int nbContacts = Int32.Parse(File.ReadLines(Searcher.dbFileName).Skip(0).Take(1).ElementAt(0)); int nbLines = nbContacts / queryMsg.nbNodes; int startIndex = nbLines * myRank; if (isFinalNode) { Console.WriteLine("Final Node"); nbLines = nbContacts - startIndex; } Searcher searcher = new Searcher(); List <Contact> localResult = searcher.search(queryMsg.query, startIndex, nbLines); g.Reply(localResult); Log(string.Format("Returned result for {0}", queryMsg.query)); }; g.Join(); Log(string.Format("Joined with Rank {0}", myRank)); Vsync.VsyncSystem.WaitForever(); Console.ReadLine(); }
public static void Main(string[] args) { String roomname = "no roomname given"; Console.WriteLine("THE SIZE OF ARGS IS " + args.Length); if (args.Length < 2) { Console.WriteLine("There are less than 2 args given. This is fine for now, but in the future we need to give the room name."); } else { roomname = args [1]; int max_port = 65000; int min_port = 15000; int port_diff = max_port - min_port; int room_hash = roomname.GetHashCode(); room_hash = room_hash % port_diff; room_hash = room_hash + port_diff; room_hash = room_hash % port_diff; Console.WriteLine("Mod is " + room_hash); room_hash += min_port; Vsync.Vsync.VSYNC_GROUPPORT = room_hash; Console.WriteLine("VSYNC PORT NO IS " + room_hash); } currentRoom = new Room(roomname); ID = Path.GetRandomFileName().Replace(".", ""); Console.WriteLine("User ID IS " + ID); //Set up TCP Listener Console.WriteLine(args [0]); int port = Int32.Parse(args [0]); TcpListener server = new TcpListener(port); server.Start(); Console.WriteLine("Server has started on 127.0.0.1:{0}.\nWaiting for a connection...", port); client = server.AcceptTcpClient(); stream = client.GetStream(); Console.WriteLine("Matched with a client! Now Starting VSYNC"); VsyncSystem.Start(); Console.WriteLine("VSYNC STARTED"); String groupName = "TEST ROOM"; roomGroup = new Vsync.Group(groupName); roomGroup.ViewHandlers += (ViewHandler) delegate(View v) { VsyncSystem.WriteLine("New View: " + v); Console.Title = "View " + v.viewid + ", my rank=" + v.GetMyRank(); }; roomGroup.Handlers [UPDATE] += (Action <string, string>) delegate(string username, string val) { lock (currentRoom) { currentRoom.playerLocs [username] = val; } lock (updateLock) { updateCount++; } }; roomGroup.Handlers [LOOKUP] += (Action <string>) delegate(string s) { //VsyncSystem.WriteLine("IN LOOKUP"); lock (currentRoom) { roomGroup.Reply(currentRoom.playerLocs [s]); } }; roomGroup.Handlers [REFRESH] += (Action) delegate() { lock (currentRoom) { string reply = Extensions.FromDictionaryToJson(currentRoom.playerLocs); roomGroup.Reply(reply); } }; roomGroup.Handlers [JOIN_ROOM] += (Action <string>) delegate(string username) { lock (currentRoom) { if (currentRoom.players.Count >= MAX_IN_ROOM) { roomGroup.Reply("FULL"); } else { currentRoom.players.Add(username); roomGroup.Reply("JOINED"); } } }; roomGroup.Handlers [LEAVE_ROOM] += (Action <string>) delegate(string s) { Console.WriteLine("IN LEAVE ROOM"); lock (currentRoom) { currentRoom.playerLocs.Remove(s); currentRoom.players.Remove(s); } }; roomGroup.Join(); Console.WriteLine("Room Group Joined"); Console.WriteLine(groupName); List <String> results = new List <String> (); roomGroup.OrderedQuery(Vsync.Group.ALL, JOIN_ROOM, ID, new Vsync.EOLMarker(), results); Boolean full = false; for (int j = 0; j < results.Count; j++) { if (results [j].Equals("FULL")) { Console.WriteLine("FULL"); full = true; } } if (full) { roomGroup.OrderedSend(LEAVE_ROOM, ID); Byte[] r = Encoding.UTF8.GetBytes("ROOM FULL"); Byte[] resp = Helpers.Connections.encode(r); stream.Write(resp, 0, resp.Length); client.Close(); Console.WriteLine("LEAVING ROOM"); roomGroup.Leave(); return; } send_timer = new System.Timers.Timer(); send_timer.Elapsed += send_info; send_timer.Interval = UPDATE_RATE; send_timer.Start(); test_timer = new System.Timers.Timer(); test_timer.Elapsed += test_print; test_timer.Interval = 10000; test_timer.Start(); Byte[] bytes = new Byte[4096]; String data = null; int i = Helpers.Connections.checkRead(stream, bytes); //Continuously read from the buffer while the connection is open while (i != 0) { data = System.Text.Encoding.ASCII.GetString(bytes, 0, i); //First request -> Respond with HTTP Change Protocol Handshake if (new Regex("^GET").IsMatch(data)) { Byte[] response = Encoding.UTF8.GetBytes("HTTP/1.1 101 Switching Protocols" + Environment.NewLine + "Connection: Upgrade" + Environment.NewLine + "Upgrade: websocket" + Environment.NewLine + "Sec-WebSocket-Accept: " + Convert.ToBase64String( SHA1.Create().ComputeHash( Encoding.UTF8.GetBytes( new Regex("Sec-WebSocket-Key: (.*)").Match(data).Groups [1].Value.Trim() + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" ) ) ) + Environment.NewLine + Environment.NewLine); stream.Write(response, 0, response.Length); //Generate and send user ID Byte[] q = Encoding.UTF8.GetBytes(ID); //Byte[] resp = Helpers.Connections.encode(q); Byte[] resp = Helpers.Connections.encode(q); stream.Write(resp, 0, resp.Length); //Start the timer and send dictionary i = Helpers.Connections.checkRead(stream, bytes); } else { //decode input and put into dictionary if valid location data Byte[] decoded = Helpers.Connections.decode(bytes); //string s = System.Text.Encoding.UTF8.GetString(decoded, 0, decoded.Length); //Console.WriteLine ("RECEIVED MESSAGE " + s); String response = Helpers.Connections.parseAndPut(decoded); //Console.WriteLine ("Received these coordinates" + response); if (response == null) { Console.WriteLine("NULL STUFF RECEIVED"); } else { still_alive = true; roomGroup.OrderedSend(UPDATE, ID, response); } i = Helpers.Connections.checkRead(stream, bytes); //Console.WriteLine ("Decoded: {0}", System.Text.Encoding.UTF8.GetString (decoded, 0, decoded.Length)); } } Console.WriteLine("Reached end of input"); Console.WriteLine("NEW"); try { roomGroup.OrderedSend(LEAVE_ROOM, ID); } catch (Exception) { Console.WriteLine("WE HAVE AN ERROR BUT WE ARE IGNORING IT NOW"); } send_timer.Stop(); //is_alive_timer.Stop (); Console.WriteLine("ROOM GROUP LEAVE"); //roomGroup.Leave(); client.Close(); }
static void Main(string[] args) { Searcher.cacheList(); int MASTER_RANK = 0; //the first one enter is master Log("Start Vsync System"); Vsync.VsyncSystem.Start(); Vsync.Msg.RegisterType(typeof(QueryMessage), 0); Vsync.Msg.RegisterType(typeof(Contact), 1); g = new Vsync.Group(GroupIdentifier); int myRank = 0; g.ViewHandlers += (Vsync.ViewHandler)delegate(Vsync.View view) { //there is changes in View Vsync.VsyncSystem.WriteLine("New view: " + view); int oldRank = myRank; int oldNbNodes = nbNodes; myRank = view.GetMyRank(); nbNodes = view.members.Length; lock (serverLocker) { //if this is Master --> start the server to receive request if (myRank == MASTER_RANK) { if (serverThread == null || !serverThread.IsAlive) { Log("I'm the Master!"); serverThread = new Thread(new ParameterizedThreadStart(startServer)); serverThread.Start(); } } else { if (serverThread != null && serverThread.IsAlive) { server.Stop(); } } } }; g.Handlers[SEARCH] += (Action<QueryMessage>)delegate(QueryMessage queryMsg) { Log(string.Format("Received search request from Master: {0}", queryMsg.query)); bool isFinalNode = (myRank == queryMsg.nbNodes - 1); int nbContacts = Int32.Parse(File.ReadLines(Searcher.dbFileName).Skip(0).Take(1).ElementAt(0)); int nbLines = nbContacts / queryMsg.nbNodes; int startIndex = nbLines * myRank; if (isFinalNode) { Console.WriteLine("Final Node"); nbLines = nbContacts - startIndex; } Searcher searcher = new Searcher(); List<Contact> localResult = searcher.search(queryMsg.query, startIndex, nbLines); g.Reply(localResult); Log(string.Format("Returned result for {0}", queryMsg.query)); }; g.Join(); Log(string.Format("Joined with Rank {0}", myRank)); Vsync.VsyncSystem.WaitForever(); Console.ReadLine(); }