/* * Map method to add CachEntry to CacheList * @param map_arg [content,alpha,start,end] */ public override void Map(Channel q, object map_arg) { IList arg = map_arg as IList; object input = arg[0]; double alpha = (double)arg[1]; //replication factor string st = arg[2] as string; // start brunet address of range string ed = arg[3] as string; // end brunet address of range AHAddress a = (AHAddress)AddressParser.Parse(st); AHAddress b = (AHAddress)AddressParser.Parse(ed); Entry ce = new Entry(input, alpha, a, b); int result = 0; // if caching is successful, result will set to 1. int previous_count = _cl.Count; try { if( _cl.Insert(ce) ) { result = 1; } else { result = 0; } } catch { result = 0; } if (_cl.Count > previous_count) { result = 1; } IDictionary my_entry = new ListDictionary(); my_entry["count"]=1; my_entry["height"]=1; my_entry["success"]=result; q.Enqueue(my_entry); }
public override void Map(Channel q, object map_arg) { IList retval = new ArrayList(); IDictionary my_entry = new ListDictionary(); my_entry["node"] = _node.Address.ToString(); retval.Add(my_entry); q.Enqueue(retval); }
public override void Reduce(Channel q, object reduce_arg, object current_result, RpcResult child_rpc) { bool done = false; //ISender child_sender = child_rpc.ResultSender; //the following can throw an exception, will be handled by the framework object child_result = child_rpc.Result; //child result is a valid result if (current_result == null) { q.Enqueue(new Brunet.Collections.Pair<object, bool>(child_result, done)); return; } IDictionary my_entry = current_result as IDictionary; IDictionary value = child_result as IDictionary; int max_height = (int) my_entry["height"]; int count = (int) my_entry["count"]; int y = (int) value["count"]; my_entry["count"] = count + y; int z = (int) value["height"] + 1; if (z > max_height) { my_entry["height"] = z; } q.Enqueue(new Brunet.Collections.Pair<object, bool>(my_entry, done)); }
public override void Reduce(Channel q, object reduce_arg, object current_result, RpcResult child_rpc) { bool done = false; ISender child_sender = child_rpc.ResultSender; //the following can throw an exception, will be handled by the framework object child_result = child_rpc.Result; //child result is a valid result if (current_result == null) { q.Enqueue(new Brunet.Collections.Pair<object, bool>(child_result, done)); return; } ArrayList retval = current_result as ArrayList; IDictionary my_entry = (IDictionary) retval[0]; my_entry["next_con"] = child_sender.ToUri(); retval.AddRange((IList) child_result); if (LogEnabled) { ProtocolLog.Write(ProtocolLog.MapReduce, String.Format("{0}: {1}, reduce list count: {2}.", this.TaskName, _node.Address, retval.Count)); } q.Enqueue(new Brunet.Collections.Pair<object, bool>(retval, done)); }
override public void Start() { base.Start(); foreach(NodeMapping nm_from in Nodes.Values) { foreach(NodeMapping nm_to in Nodes.Values) { if(nm_from == nm_to) { continue; } ISender sender = null; if(Secure) { sender = nm_from.Sso.GetSecureSender(nm_to.Node.Address); } else { sender = new AHGreedySender(nm_from.Node, nm_to.Node.Address); } Channel q = new Channel(1); q.CloseEvent += Callback; try { nm_from.Node.Rpc.Invoke(sender, q, "sys:link.Ping", 0); _waiting_on++; } catch { _waiting_on--; } } } }
override public void Start() { Channel returns = new Channel(); returns.EnqueueEvent += delegate(object o, EventArgs ea) { while(returns.Count > 0) { Hashtable result = null; try { result = returns.Dequeue() as Hashtable; } catch { continue; } byte[] res = result["value"] as byte[]; if(res != null) { Results.Enqueue(MemBlock.Reference(res)); } } if(_enqueue != null) { _enqueue(this, EventArgs.Empty); } }; returns.CloseEvent += delegate(object o, EventArgs ea) { Finished(); }; Dht dht = new Dht(Node, 3, 20); dht.AsyncGet(Key, returns); }
/** * @param e Edge to close * @param cm message to send to other node * This method is used if we want to use a particular CloseMessage * If not, we can use the method with the same name with one fewer * parameters */ public void GracefullyClose(Edge e, string message) { /** * Close any connection on this edge, and * put the edge into the list of unconnected edges */ _connection_table.Disconnect(e); ListDictionary close_info = new ListDictionary(); string reason = message; if (reason != String.Empty) { close_info["reason"] = reason; } ProtocolLog.WriteIf(ProtocolLog.EdgeClose, String.Format( "GracefulCLose - " + e + ": " + reason)); var results = new BCon.Channel(1); EventHandler close_eh = delegate(object o, EventArgs args) { e.Close(); }; results.CloseEvent += close_eh; try { _rpc.Invoke(e, results, "sys:link.Close", close_info); } catch { Close(e); } }
/// <summary>Seek TAs.</summary> protected override void SeekTAs(DateTime now) { Channel queue = new Channel(); queue.EnqueueEvent += HandleSeekTAs; try { ISender mcs = _iphandler.CreateMulticastSender(); _rpc.Invoke(mcs, queue, RPC_CLASS + ".SeekTAs", _realm); } catch(SendException) { /* * On planetlab, it is not uncommon to have a node that does not allow * Multicast, and it will throw an exception here. We just ignore this * information for now. If we don't the heartbeatevent in the node * will not execute properly. */ } }
override public void Start() { Channel returns = new Channel(); returns.CloseEvent += delegate(object o, EventArgs ea) { try { bool success = (bool) returns.Dequeue(); _result = new DhtPutResult(success, null); } catch (Exception e) { _result = new DhtPutResult(false, e); } finally { Finished(); } }; Dht dht = new Dht(Node, 3, 20); dht.AsyncPut(Key, Value, Ttl, returns); }
/** Greedy routing. gen_arg is the Address of the destination */ public override void GenerateTree(Channel q, MapReduceArgs mr_args) { object gen_arg = mr_args.GenArg; Log("{0}: {1}, greedy generator called, arg: {2}.", this.TaskName, _node.Address, gen_arg); string address = gen_arg as string; AHAddress a = (AHAddress) AddressParser.Parse(address); ArrayList retval = new ArrayList(); ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); Connection next_closest = structs.GetNearestTo((AHAddress) _node.Address, a); if (next_closest != null) { //arguments do not change at all MapReduceInfo mr_info = new MapReduceInfo(next_closest.State.Edge, mr_args); retval.Add(mr_info); } Log("{0}: {1}, greedy generator returning: {2} senders.", this.TaskName, _node.Address, retval.Count); //Send the result: q.Enqueue(retval.ToArray(typeof(MapReduceInfo))); }
/* * Map method to add CachEntry to CacheList * @param map_arg [pattern, query_type] */ public override void Map(Channel q, object map_arg) { IList map_args = (IList)map_arg; string query_type = (string)(map_args[0]); Converter<object,QueryMatcher> qmf = null; if( _mut.State.QMFact.TryGetValue(query_type, out qmf) ) { QueryMatcher qm = qmf(map_args[1]); //I need to implement the code that map_args[1] includes x and y coordinate, map_args[1] will be Arraylist. var my_entry = new ListDictionary(); var results = new ArrayList(); foreach(Entry e in _cl.MState.State.Data) { object cont = e.Content; if(qm.Match(cont)) { results.Add(cont); } } my_entry["query_result"] = results; my_entry["count"] = 1; my_entry["height"] = 1; q.Enqueue(my_entry); } else { q.Enqueue(new AdrException(-32608, "No Deetoo match option with this name: " + query_type) ); return; } }
/** * Check all the edges in the ConnectionTable and see if any of them * need to be pinged or closed. * This method is connected to the heartbeat event. */ virtual protected void CheckEdgesCallback(object node, EventArgs args) { DateTime now = DateTime.UtcNow; //_connection_timeout = ComputeDynamicTimeout(); _connection_timeout = MAX_CONNECTION_TIMEOUT; /* * If we haven't heard from any of these people in this time, * we ping them, and if we don't get a response, we close them */ foreach (Connection c in _connection_table) { Edge e = c.Edge; TimeSpan since_last_in = now - e.LastInPacketDateTime; if ((1 == _send_pings) && (since_last_in > _connection_timeout)) { object ping_arg = String.Empty; DateTime start = DateTime.UtcNow; EventHandler on_close = delegate(object q, EventArgs cargs) { BCon.Channel qu = (BCon.Channel)q; if (qu.Count == 0) { /* we never got a response! */ if (!e.IsClosed) { //We are going to close it after waiting: ProtocolLog.WriteIf(ProtocolLog.NodeLog, String.Format( "On an edge timeout({1}), closing connection: {0}", c, DateTime.UtcNow - start)); //Make sure it is indeed closed. e.Close(); } else { //The edge was closed somewhere else, so it //didn't timeout. } } else { //We got a response, let's make sure it's not an exception: bool close = false; try { RpcResult r = (RpcResult)qu.Dequeue(); object o = r.Result; //This will throw an exception if there was a problem if (!o.Equals(ping_arg)) { //Something is wrong with the other node: ProtocolLog.WriteIf(ProtocolLog.NodeLog, String.Format( "Ping({0}) != {1} on {2}", ping_arg, o, c)); close = true; } } catch (Exception x) { ProtocolLog.WriteIf(ProtocolLog.Exceptions, String.Format( "Ping on {0}: resulted in: {1}", c, x)); close = true; } if (close) { e.Close(); } } }; BCon.Channel tmp_queue = new BCon.Channel(1); tmp_queue.CloseEvent += on_close; //Do the ping try { _rpc.Invoke(e, tmp_queue, "sys:link.Ping", ping_arg); } catch (EdgeClosedException) { //Just ignore closed edges, clearly we can't ping them } catch (EdgeException x) { if (!x.IsTransient) { //Go ahead and close the Edge e.Close(); } } } } foreach (Edge e in _connection_table.GetUnconnectedEdges()) { if (now - e.LastInPacketDateTime > _unconnected_timeout) { if (ProtocolLog.Connections.Enabled) { ProtocolLog.Write(ProtocolLog.Connections, String.Format( "Closed an unconnected edge: {0}", e)); } e.Close(); } } }
/** * Generates tree for bounded broadcast. Algorithm works as follows: * The goal is to broadcast to all nodes in range (start, end). * Given a range (a, b), determine all connections that belong to this range. * Let the left connections be l_1, l_2, ..... l_n. * Let the right connections be r_1, r_2, ... , r_n. * To left connection l_i assign the range [b_{i-1}, b_i). * To right connection r_i assign the range [r_i, r_{i-1}] * To the connection ln assign range [l_{n-1}, end) * To the connection rn assign range (start, r_{n-1}] */ public override void GenerateTree(Channel q, MapReduceArgs mr_args) { ArrayList gen_list = mr_args.GenArg as ArrayList; string start_range = gen_list[0] as string; AHAddress start_addr = (AHAddress) AddressParser.Parse(start_range); AHAddress end_addr; string end_range; /// If users do not specify an end range, this method understands /// that users intend to broadcasting the whole range. /// Thus, the address of end range is set to (start_address - 2), /// the farthest address from the start_addr. if (gen_list.Count < 2) { BigInteger start_int = start_addr.ToBigInteger(); BigInteger end_int = start_int -2; end_addr = new AHAddress(end_int); end_range = end_addr.ToString(); } else { end_range = gen_list[1] as string; end_addr = (AHAddress) AddressParser.Parse(end_range); } Log("generating child tree, range start: {0}, range end: {1}.", start_range, end_range); //we are at the start node, here we go: ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); List<MapReduceInfo> retval = new List<MapReduceInfo>(); if (InRange(_this_addr, start_addr, end_addr)) { if (structs.Count > 0) { //make connection list in the range. //left connection list is a list of neighbors which are in the range (this node, end of range) //right connection list is a list of neighbors which are in the range (start of range, this node) Brunet.Collections.Pair<List<Connection>,List<Connection>> cons = GetConnectionInfo(_this_addr, start_addr, end_addr, structs); List<Connection> left_cons = cons.First as List<Connection>; List<Connection> right_cons = cons.Second as List<Connection>; //PrintConnectionList(left_cons); //PrintConnectionList(right_cons); retval = GenerateTreeInRange(start_addr, end_addr, left_cons, true, mr_args); List<MapReduceInfo> ret_right = GenerateTreeInRange(start_addr, end_addr, right_cons, false, mr_args); retval.AddRange(ret_right); } else { //this node is a leaf node. //MapReduceInfo mr_info = null; //retval.Add(mr_info); //Console.WriteLine("no connection in the range: return null info"); } } else { // _node is out of range. Just pass it to the closest to the middle of range. retval = GenerateTreeOutRange(start_addr, end_addr, mr_args); } q.Enqueue( retval.ToArray()); }
/** * Call the GetStatus method on the given connection */ protected void CallGetStatus(string type, Connection c) { ConnectionTable tab = this.ConnectionTable; if( c != null ) { StatusMessage req = GetStatus(type, c.Address); Channel stat_res = new Channel(1); EventHandler handle_result = delegate(object q, EventArgs eargs) { try { RpcResult r = (RpcResult)stat_res.Dequeue(); StatusMessage sm = new StatusMessage( (IDictionary)r.Result ); tab.UpdateStatus(c, sm); } catch(Exception) { //Looks like lc disappeared before we could update it } }; stat_res.CloseEvent += handle_result; _rpc.Invoke(c.Edge, stat_res, "sys:link.GetStatus", req.ToDictionary() ); } }
public void HandleEC(bool succ, Edge e, Exception x) { if(!succ) { ECB(false, null, x); return; } else if(_root) { Interlocked.Increment(ref _pel._count); e.CloseEvent += _pel.CloseHandler; ECB(succ, e, x); return; } /* * Got the underlying Edge, now do the path protocol */ Channel results = new Channel(1); results.CloseEvent += delegate(object q, EventArgs args) { try { RpcResult res = (RpcResult)results.Dequeue(); object o = res.Result; if(o is Exception) { throw (o as Exception); } } catch(Exception cx) { e.Close(); ECB(false, null, cx); return; } //If we get here, everything looks good: PathEdge pe = new PathEdge(_pel._pem, e, LocalPath, RemotePath); //Start sending e's packets into pe pe.Subscribe(); pe.CloseEvent += _pel.CloseHandler; Interlocked.Increment(ref _pel._count); ECB(true, pe, null); }; //Make sure we hear the packets on this edge: e.Subscribe(_pel._pem, null); //Now make the rpc call: _pel._pem.Rpc.Invoke(e, results, "sys:pathing.create", LocalPath, RemotePath ); }
/** * This is a recursive function over the network * It helps to build an IList of IDictionary types that give the address * of each node in the path, and the connection to the next closest node if * there is one, otherwise no next. */ protected void DoTraceRouteTo(AHAddress a, object req_state) { /* * First find the Connection pointing to the node closest to dest, if * there is one closer than us */ ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); Connection next_closest = structs.GetNearestTo((AHAddress) _node.Address, a); //Okay, we have the next closest: ListDictionary my_entry = new ListDictionary(); my_entry["node"] = _node.Address.ToString(); if( next_closest != null ) { my_entry["next_con"] = next_closest.ToString(); Channel result = new Channel(); //We only want one result, so close the queue after we get the first result.CloseAfterEnqueue(); result.CloseEvent += delegate(object o, EventArgs args) { Channel q = (Channel)o; if( q.Count > 0 ) { try { RpcResult rres = (RpcResult)q.Dequeue(); IList l = (IList) rres.Result; ArrayList results = new ArrayList( l.Count + 1); results.Add(my_entry); results.AddRange(l); _rpc.SendResult(req_state, results); } catch(Exception x) { string m = String.Format("<node>{0}</node> trying <connection>{1}</connection> got <exception>{2}</exception>", _node.Address, next_closest, x); Exception nx = new Exception(m); _rpc.SendResult(req_state, nx); } } else { //We got no results. IList l = new ArrayList(1); l.Add( my_entry ); _rpc.SendResult(req_state, l); } }; _rpc.Invoke(next_closest.State.Edge, result, "trace.GetRouteTo", a.ToString()); } else { //We are the end of the line, send the result: ArrayList l = new ArrayList(); l.Add(my_entry); _rpc.SendResult(req_state, l); } }
/*** Gracefully close this connection, if it is not already disconnected. * Idempotent (calling it twice is the same as once). * @return the old state, new state pair. */ public Pair<ConnectionState,ConnectionState> Close(BM.RpcManager rpc, string reason) { var old_new = Abort(); if( old_new.First.Disconnected != true ) { //Now try to tell the other node: var close_info = new ListDictionary(); if( reason != String.Empty ) { close_info["reason"] = reason; } Edge e = old_new.Second.Edge; var results = new Channel(1); //Either the RPC call times out, or we get a response. results.CloseEvent += delegate(object o, EventArgs args) { e.Close(); }; try { rpc.Invoke(e, results, "sys:link.Close", close_info); } catch { e.Close(); } } return old_new; }
protected void CrawlNext(Address addr) { bool finished = false; if(_log && _crawled.Count < _count) { Console.WriteLine("Current address: " + addr); } if(_crawled.ContainsKey(addr)) { finished = true; } else { _crawled.Add(addr, true); try { ISender sender = null; if(_bso != null) { sender = _bso.GetSecureSender(addr); } else { sender = new AHGreedySender(_node, addr); } Channel q = new Channel(1); q.CloseEvent += CrawlHandler; _node.Rpc.Invoke(sender, q, "sys:link.GetNeighbors"); } catch(Exception e) { if(_log) { Console.WriteLine("Crawl failed" + e); } finished = true; } } if(finished) { Interlocked.Exchange(ref _done, 1); if(_log) { Console.WriteLine("Crawl stats: {0}/{1}", _crawled.Count, _count); Console.WriteLine("Consistency: {0}/{1}", _consistency, _crawled.Count); Console.WriteLine("Finished in: {0}", (DateTime.UtcNow - _start)); } } }
/** * Generates tree for bounded broadcast. Algorithm works as follows: * The goal is to broadcast to all nodes in range [local_address, end). * Given a range [local_address, b), determine all connections that belong to this range. * Let the connections be b_1, b_2, ..... b_n. * To connection bi assign the range [b_i, b_{i+1}). * To the connection bn assign range [b_n, end).] */ public override void GenerateTree(Channel q, MapReduceArgs mr_args) { object gen_arg = mr_args.GenArg; string end_range = gen_arg as string; Log("generating child tree, range end: {0}.", end_range); AHAddress end_addr = (AHAddress) AddressParser.Parse(end_range); AHAddress start_addr = _node.Address as AHAddress; //we are at the start node, here we go: ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); ArrayList retval = new ArrayList(); if (structs.Count > 0) { Connection curr_con = structs.GetLeftNeighborOf(_node.Address); int curr_idx = structs.IndexOf(curr_con.Address); //keep going until we leave the range int count = 0; List<Connection> con_list = new List<Connection>(); //ArrayList con_list = new ArrayList(); while (count++ < structs.Count && ((AHAddress) curr_con.Address).IsBetweenFromLeft(start_addr, end_addr)) { con_list.Add(curr_con); //Log("adding connection: {0} to list.", curr_con.Address); curr_idx = (curr_idx + 1)%structs.Count; curr_con = structs[curr_idx]; } Log("{0}: {1}, number of child connections: {2}", this.TaskName, _node.Address, con_list.Count); for (int i = 0; i < con_list.Count; i++) { MapReduceInfo mr_info = null; ISender sender = null; Connection con = (Connection) con_list[i]; sender = con.State.Edge; //check if last connection if (i == con_list.Count - 1) { mr_info = new MapReduceInfo( (ISender) sender, new MapReduceArgs(this.TaskName, mr_args.MapArg, //map argument end_range, //generate argument mr_args.ReduceArg //reduce argument )); Log("{0}: {1}, adding address: {2} to sender list, range end: {3}", this.TaskName, _node.Address, con.Address, end_range); retval.Add(mr_info); } else { string child_end = ((Connection) con_list[i+1]).Address.ToString(); mr_info = new MapReduceInfo( sender, new MapReduceArgs(this.TaskName, mr_args.MapArg, child_end, mr_args.ReduceArg)); Log("{0}: {1}, adding address: {2} to sender list, range end: {3}", this.TaskName, _node.Address, con.Address, child_end); retval.Add(mr_info); } } } q.Enqueue( retval.ToArray(typeof(MapReduceInfo))); }
override public void Start() { ProtocolLog.WriteIf(ProtocolLog.LinkDebug, String.Format("{0}: Starting Connector: {1}, {2}", _local_node.Address, _sender, State)); AbortCheck ac = _abort.Value; if( ac != null ) { if( ac(this) ) { //We are no longer needed: QueueCloseHandler(null, null); return; } } RpcManager rpc = _local_node.Rpc; Channel results = new Channel(); results.EnqueueEvent += this.EnqueueHandler; results.CloseEvent += this.QueueCloseHandler; rpc.Invoke(_sender, results, "sys:ctm.ConnectTo", _ctm.ToDictionary() ); }
public void ChannelTests() { Channel c0 = new Channel(); bool e_event_fired = false; c0.EnqueueEvent += delegate(object o, EventArgs arg) { e_event_fired = true; }; c0.Enqueue(0); bool c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Close(); Assert.IsTrue(c_event_fired, "CloseEvent"); c0 = new Channel(); c0.CloseAfterEnqueue(); c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Enqueue(1); //This should close the channel: Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.IsTrue(c0.Closed, "Closed"); c0 = new Channel(1); c_event_fired = false; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.Enqueue(1); //This should close the channel: Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.IsTrue(c0.Closed, "Closed"); //Try with different starting values: Random r = new Random(); int en_count; for(int i = 0; i < 100; i++) { int max_enqueues = r.Next(1, 1000); c0 = new Channel(max_enqueues); c_event_fired = false; en_count = 0; c0.CloseEvent += delegate(object o, EventArgs arg) { c_event_fired = true; }; c0.EnqueueEvent += delegate(object o, EventArgs arg) { en_count++; }; for(int j = 0; j < max_enqueues; j++) { c0.Enqueue(j); } Assert.IsTrue(c_event_fired, "CloseEvent on Enqueue"); Assert.AreEqual(en_count, max_enqueues, "EnqueueEvent count"); Assert.IsTrue(c0.Closed, "Closed"); try { c0.Enqueue(null); Assert.IsTrue(false, "Enqueue after close didn't fail"); } catch { Assert.IsTrue(true, "Enqueue after close Got exception"); } } }
public override void Start() { //Make sure the Node is listening to this node try { //This will throw an exception if _e is already closed: _e.CloseEvent += this.CloseHandler; //_e must not be closed, let's start listening to it: _e.Subscribe(_node, _e); /* Make the call */ Channel results = new Channel(); results.CloseAfterEnqueue(); results.CloseEvent += this.LinkCloseHandler; RpcManager rpc = _node.Rpc; if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("LPS target: {0} Invoking Start() over edge: {1}", _linker.Target, _e)); } rpc.Invoke(_e, results, "sys:link.Start", MakeLM().ToDictionary() ); } catch (Exception e) { //The Edge must have closed, move on to the next TA if(ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format("LPS target: {0} Start() over edge: {1}, hit exception: {2}", _linker.Target, _e, e)); } Finish(Result.MoveToNextTA); } }
/** * When we get a response to the sys:link method, this handled * is called */ protected void LinkCloseHandler(object q, EventArgs args) { try { Channel resq = (Channel)q; //If the Channel is empty this will throw an exception: RpcResult res = (RpcResult)resq.Dequeue(); /* Here's the LinkMessage response */ LinkMessage lm = new LinkMessage( (IDictionary)res.Result ); /** * This will set our LinkMessageReply variable. It can * only be set once, so all future sets will fail. It * will also make sure we have the lock on the target. * If we don't, that will throw an exception */ SetAndCheckLinkReply(lm); //If we got here, we have our response and the Lock on _target_address StatusMessage sm = _node.GetStatus(_contype, lm.Local.Address); /* Make the call */ Channel results = new Channel(); results.CloseAfterEnqueue(); results.CloseEvent += this.StatusCloseHandler; RpcManager rpc = _node.Rpc; if (ProtocolLog.LinkDebug.Enabled) { ProtocolLog.Write(ProtocolLog.LinkDebug, String.Format( "LPS target: {0} Invoking GetStatus() over edge: {1}", _linker.Target, _e)); } /* * This could throw an exception if the Edge is closed */ rpc.Invoke(_e, results, "sys:link.GetStatus", sm.ToDictionary() ); } catch(AdrException x) { /* * This happens when the RPC call has some kind of issue, * first we check for common error conditions: */ _x.Value = x; Finish( GetResultForErrorCode(x.Code) ); } catch(ConnectionExistsException x) { /* We already have a connection */ _x.Value = x; Finish( Result.ProtocolError ); } catch(CTLockException x) { //This is thrown when ConnectionTable cannot lock. Lets try again: _x.Value = x; Finish( Result.RetryThisTA ); } catch(LinkException x) { _x.Value = x; if( x.IsCritical ) { Finish( Result.MoveToNextTA ); } else { Finish( Result.RetryThisTA ); } } catch(InvalidOperationException) { //The queue never got anything Finish(Result.MoveToNextTA); } catch(EdgeException) { //The Edge is goofy, let's move on: Finish(Result.MoveToNextTA); } catch(Exception x) { //The protocol was not followed correctly by the other node, fail _x.Value = x; Finish( Result.RetryThisTA ); } }
public override void Map(Channel q, object map_arg) { IDictionary my_entry = new ListDictionary(); my_entry["count"] = 1; my_entry["height"] = 1; q.Enqueue( my_entry ); }
public override void Reduce(Channel q, object reduce_arg, object current_val, RpcResult child_r) { var rest = child_r.Result as IEnumerable; //If we get here, the child didn't throw an exception var result = new ArrayList(); AddEnum(result, current_val as IEnumerable); AddEnum(result, rest); q.Enqueue(new Pair<object, bool>(result, false)); }
public void Start() { foreach(NodeMapping nm_from in _nodes.Values) { foreach(NodeMapping nm_to in _nodes.Values) { if(nm_from == nm_to) { continue; } ISender sender = null; if(_secure) { sender = nm_from.Sso.GetSecureSender(nm_to.Node.Address); } else { sender = new AHGreedySender(nm_from.Node, nm_to.Node.Address); } Channel q = new Channel(1); q.CloseEvent += Callback; try { nm_from.Node.Rpc.Invoke(sender, q, "sys:link.Ping", 0); _count++; _waiting_on++; } catch { // } catch(Exception e) { // Console.WriteLine(e); } } } }
/// <summary>Starts a test on the specified node.</summary> protected void Invoke(Address addr) { Channel q = new Channel(1); q.CloseEvent += delegate(object send, EventArgs ea) { RpcResult result = null; if(q.Count > 0) { result = q.Dequeue() as RpcResult; } ProcessResults(addr, result); }; AHSender sender = new AHGreedySender(_node, addr); _node.Rpc.Invoke(sender, q, "sys:link.GetNeighbors"); }
public void Start() { Channel returns = new Channel(); returns.CloseEvent += delegate(object o, EventArgs ea) { try { _successful = (bool) returns.Dequeue(); } catch { } _done = true; if(_callback != null) { _callback(this, EventArgs.Empty); } }; Dht dht = new Dht(_node, 3, 20); dht.AsyncPut(_key, _value, _ttl, returns); }
/** * This is a recursive function over the network * It helps do a link-reliable procedure call on the * on the overlay network. */ protected void RecursiveCall(IList margs, object req_state) { //first argument is the target node. AHAddress a = (AHAddress) AddressParser.Parse( (string) margs[0]); /* * First find the Connection pointing to the node closest to dest, if * there is one closer than us */ ConnectionTable tab = _node.ConnectionTable; ConnectionList structs = tab.GetConnections(ConnectionType.Structured); Connection next_closest = structs.GetNearestTo((AHAddress) _node.Address, a); //Okay, we have the next closest: if( next_closest != null ) { Channel result = new Channel(); //We only want one result, so close the queue after we get the first result.CloseAfterEnqueue(); result.CloseEvent += delegate(object o, EventArgs args) { Channel q = (Channel)o; if( q.Count > 0 ) { try { RpcResult rres = (RpcResult)q.Dequeue(); _rpc.SendResult(req_state, rres.Result); } catch(Exception x) { string m = String.Format("<node>{0}</node> trying <connection>{1}</connection> got <exception>{2}</exception>", _node.Address, next_closest, x); Exception nx = new Exception(m); _rpc.SendResult(req_state, nx); } } else { //We got no results. _rpc.SendResult(req_state, null); } }; object [] new_args = new object[margs.Count]; margs.CopyTo(new_args, 0); _rpc.Invoke(next_closest.State.Edge, result, "trace.RecursiveCall", new_args); } else { //We are the end of the line, send the result: //Console.Error.WriteLine("Doing a local invocation"); Channel result = new Channel(); result.CloseAfterEnqueue(); result.CloseEvent += delegate(object o, EventArgs args) { Channel q = (Channel)o; if( q.Count > 0 ) { try { //Console.Error.WriteLine("Got result."); RpcResult rres = (RpcResult)q.Dequeue(); _rpc.SendResult(req_state, rres.Result); } catch(Exception x) { string m = String.Format("<node>{0}</node> local invocation got <exception>{1}</exception>", _node.Address, x); Exception nx = new Exception(m); _rpc.SendResult(req_state, nx); } } else { //We got no results. _rpc.SendResult(req_state, null); } }; string method_name = (string) margs[1]; object [] new_args = new object[margs.Count - 2]; margs.RemoveAt(0);//extract destination address margs.RemoveAt(0); //extract method name margs.CopyTo(new_args, 0); //Console.Error.WriteLine("Calling method: {0}, args_count: {1}", method_name, new_args.Length); //for (int i = 0; i < new_args.Length; i++) { //Console.Error.WriteLine(new_args[i]); //} _rpc.Invoke(_node, result, method_name, new_args); } }
/** * This informs all the ConnectionOverlord objects * to not respond to loss of edges, then to issue * close messages to all the edges * */ protected void Leave() { if(ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "In StructuredNode.Leave: {0}", this.Address)); } #if !BRUNET_SIMULATOR _iphandler.Stop(); #endif StopConnectionOverlords(); //Stop notifying neighbors of disconnection, we are the one leaving _connection_table.DisconnectionEvent -= this.UpdateNeighborStatus; //Gracefully close all the edges: _connection_table.Close(); //This makes sure we can't add any new connections. ArrayList edges_to_close = new ArrayList(); foreach(Edge e in _connection_table.GetUnconnectedEdges() ) { edges_to_close.Add( e ); } //There is no way unconnected edges could have become Connections, //so we should put the connections in last. foreach(Connection c in _connection_table) { edges_to_close.Add( c.Edge ); } //edges_to_close has all the connections and unconnected edges. IList copy = edges_to_close.ToArray(); //Make sure multiple readers and writers won't have problems: edges_to_close = ArrayList.Synchronized( edges_to_close ); EventHandler ch = delegate(object o, EventArgs a) { if(ProtocolLog.NodeLog.Enabled) ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{1} Handling Close of: {0}", o, this.Address)); edges_to_close.Remove(o); if( edges_to_close.Count == 0 ) { if(ProtocolLog.NodeLog.Enabled) ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Node({0}) Stopping all EdgeListeners", Address)); StopAllEdgeListeners(); } }; if(ProtocolLog.NodeLog.Enabled) ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{0} About to gracefully close all edges", this.Address)); //Use just one of these for all the calls: IDictionary carg = new ListDictionary(); carg["reason"] = "disconnecting"; for(int i = 0; i < copy.Count; i++) { Edge e = (Edge)copy[i]; if(ProtocolLog.NodeLog.Enabled) { ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "{0} Closing: [{1} of {2}]: {3}", this.Address, i, copy.Count, e)); } try { e.CloseEvent += ch; Channel res_q = new Channel(1); DateTime start_time = DateTime.UtcNow; res_q.CloseEvent += delegate(object o, EventArgs arg) { if(ProtocolLog.NodeLog.Enabled) ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Close on edge: {0} took: {1}", e, (DateTime.UtcNow - start_time))); e.Close(); }; try { _rpc.Invoke(e, res_q, "sys:link.Close", carg); } catch(EdgeException) { /* * It is not strange for the other side to have potentially * closed, or some other error be in progress which is why * we might have been shutting down in the first place * No need to print a message */ e.Close(); } catch(Exception x) { if(ProtocolLog.Exceptions.Enabled) ProtocolLog.Write(ProtocolLog.Exceptions, String.Format( "sys:link.Close({0}) threw: {1}", e, x)); e.Close(); } } catch { ch(e,null); } } if( copy.Count == 0 ) { //There were no edges, go ahead an Stop if(ProtocolLog.NodeLog.Enabled) ProtocolLog.Write(ProtocolLog.NodeLog, String.Format( "Node({0}) Stopping all EdgeListeners", Address)); StopAllEdgeListeners(); } }
/** * Reduce method * @param reduce_arg argument for reduce * @param current_result result of current map * @param child_rpc results from children * @param done if done is true, stop reducing and return result * return table of hop count, number of success, tree depth */ public override void Reduce(Channel q, object reduce_arg, object current_result, RpcResult child_rpc) { bool done = false; //ISender child_sender = child_rpc.ResultSender; //the following can throw an exception, will be handled by the framework object child_result = UNSET; try { child_result = child_rpc.Result; } catch(Exception x) { /* if (x.Equals("Child did not return") ) { //there might be at least one timeout from children. //Start boundedcasting again IDictionary ht; string task_name = "Brunet.Services.Deetoo.MapReduceCache; ht["task_name"] = task_name IDictionary map_arg; IDictionary gen_arg; = (IDictionary) args[0]; MapReduceArgs mr_args = new MapReduceArgs(ht); //string task_name = mr_args.TaskName; MapReduceTask task; if (_name_to_task.TryGetValue(task_name, out task)) { MapReduceComputation mr = new MapReduceComputation(_node, req_state, task, mr_args); mr.Start(); } } */ } if( child_result == UNSET ) { //The child threw an exception q.Enqueue(new Brunet.Collections.Pair<object, bool> (current_result, done)); return; } //child result is a valid result if (current_result == null) { q.Enqueue(new Brunet.Collections.Pair<object, bool> (child_result, done)); return; } //else combine them: IDictionary my_entry = (IDictionary)current_result; IDictionary value = (IDictionary)child_result; int max_height = (int) my_entry["height"]; int count = (int) my_entry["count"]; my_entry["success"] = (int) my_entry["success"] + (int) value["success"]; int y = (int) value["count"]; my_entry["count"] = count + y; int z = (int) value["height"] + 1; if (z > max_height) { my_entry["height"] = z; } q.Enqueue(new Brunet.Collections.Pair<object, bool>(my_entry,done)); }
/** * This is how you invoke a method on a remote host. * Results are put into the Channel. * * If you want to have an Event based approach, listen to the EnqueueEvent * on the Channel you pass for the results. That will be fired * immediately from the thread that gets the result. * * When a result comes back, we put and RpcResult into the Channel. * When you have enough responses, Close the queue (please). The code * will stop sending requests after the queue is closed. If you never close * the queue, this will be wasteful of resources. * * @param target the sender to use when making the RPC call * @param q the Channel into which the RpcResult objects will be placed. * q may be null if you don't care about the response. * @param method the Rpc method to call * * @throw Exception if we cannot send the request for some reason. */ virtual public void Invoke(ISender target, Channel q, string method, params object[] args) { //build state for the RPC call RpcRequestState rs = new RpcRequestState(); rs.Results = q; rs.RpcTarget = target; object[] rpc_call = new object[2]; rpc_call[0] = method; if( args != null ) { rpc_call[1] = args; } else { //There are no args, which we represent as a zero length list rpc_call[1] = new object[0]; } AdrCopyable req_copy = new AdrCopyable(rpc_call); #if RPC_DEBUG Console.Error.WriteLine("[RpcClient: {0}] Invoking method: {1} on target: {2}", _rrman.Info, method, target); #endif ICopyable rrpayload = new CopyList( PType.Protocol.Rpc, req_copy ); int reqid = _rrman.SendRequest(target, ReqrepManager.ReqrepType.Request, rrpayload, this, rs); //Make sure we stop this request when the queue is closed. if( q != null ) { try { q.CloseEvent += delegate(object qu, EventArgs eargs) { _rrman.StopRequest(reqid, this); }; } catch { if(q.Closed) { _rrman.StopRequest(reqid, this); } else { throw; } } } }