public override void Init(string[] args) { m_scope = new IsolatedChannelScope(); Restart(); base.Init(args); }
/// <summary> /// The method that implements this process /// </summary> protected override async Task Start() { var i = 0; try { m_socket = new TcpListener(m_endPoint); m_socket.Start(); // We use a special scope for our channels using (var sc = new IsolatedChannelScope()) while (true) { TcpClient tcl; try { tcl = await m_socket.AcceptTcpClientAsync(); } catch (Exception ex) { if (!(ex is ObjectDisposedException) && !(ex is NullReferenceException)) { LOG.WarnFormat("Stop exception was not ObjectDisposedException nor NullReferenceException", ex); } return; } var nwc = new NetworkClient(tcl); nwc.SelfID = string.Format("SERVER:{0}", i++); LOG.Debug("Accepted a new connection"); Task.Run(() => { try { RunChannelHandler(nwc, sc); } catch (Exception ex) { LOG.Error("Crashed in channel handler", ex); } }).FireAndForget(); } } catch (Exception ex) { LOG.Fatal("Crashed server", ex); throw; } }
/// <summary> /// Runs the peer process /// </summary> /// <returns>An awaitable task.</returns> /// <param name="selfinfo">The information describing the peer.</param> /// <param name="k">The redundancy parameter.</param> /// <param name="storesize">The maximum size of the local store</param> /// <param name="maxage">The maximum age of items in the cache</param> /// <param name="initialContactlist">Initial list of peers to contact.</param> /// <param name="requests">The request channel for local management</param> public static async Task RunPeer(PeerInfo selfinfo, int k, int storesize, TimeSpan maxage, EndPoint[] initialContactlist, IReadChannel <PeerRequest> requests) { try { if (selfinfo == null) { throw new ArgumentNullException(nameof(selfinfo)); } if (initialContactlist == null) { throw new ArgumentNullException(nameof(initialContactlist)); } var ip = selfinfo.Address as IPEndPoint; if (ip == null) { throw new ArgumentException($"Unable to convert {nameof(selfinfo.Address)} to a {nameof(IPEndPoint)}", nameof(selfinfo)); } log.Debug($"Starting a peer with key {selfinfo.Key} and address {selfinfo.Address}"); using (var scope = new IsolatedChannelScope()) { var sock = new TcpListener(ip); sock.Start(); // Set up the helper processes var router = RoutingProcess.RunAsync(selfinfo, k); var broker = ConnectionBroker.RunAsync(selfinfo); var values = MRUProcess.RunAsync(selfinfo, storesize, maxage); var remoter = RemoteProcess.RunAsync(selfinfo); log.Debug("Started router, broker, and value store"); // Handle new connections var listener = ListenAsync(selfinfo, sock); log.Debug("Started listener"); // Start discovery of peers var discovery = DiscoveryProcess.RunAsync(selfinfo, initialContactlist); log.Debug("Started discovery"); // The process handling requests to the local node var proc = AutomationExtensions.RunTask( new { Requests = requests, Refresh = Channels.PeerRequests.ForRead, // Add these, so this process terminates the others as well BrokerReg = Channels.ConnectionBrokerRegistrations.ForWrite, BrokerReq = Channels.ConnectionBrokerRequests.ForWrite, BrokerStat = Channels.ConnectionBrokerStats.ForWrite, MRUReq = Channels.MRURequests.ForWrite, MRUStat = Channels.MRUStats.ForWrite, RouteReq = Channels.RoutingTableRequests.ForWrite, RouteStat = Channels.RoutingTableStats.ForWrite, }, async self => { log.Debug("Running peer main loop"); try { while (true) { var req = (await MultiChannelAccess.ReadFromAnyAsync(self.Requests, self.Refresh)).Value; log.Debug($"Peer {selfinfo.Key} got message: {req.Operation}"); switch (req.Operation) { case PeerOperation.Add: await HandleAddOperation(selfinfo, req, k); break; case PeerOperation.Find: await HandleFindOperation(selfinfo, req, k); break; case PeerOperation.Stats: await HandleStatsOperation(req); break; case PeerOperation.Refresh: await HandleRefreshOperation(selfinfo, req, k); break; default: await req.Response.WriteAsync(new PeerResponse() { SuccessCount = -1 }); break; } log.Debug($"Peer {selfinfo.Key} handled message: {req.Operation}"); } } catch (Exception ex) { if (!ex.IsRetiredException()) { log.Warn($"Terminating peer {selfinfo.Key} due to error", ex); } throw; } finally { log.Debug($"Terminating peer {selfinfo.Key}"); } } ); log.Debug("Started main handler"); // Set up a process that periodically emits refresh operations var refresher = AutomationExtensions.RunTask( new { Control = Channels.PeerRequests.ForWrite }, async self => { var respchan = Channel.Create <PeerResponse>(); while (true) { // Sleep, but exit if the parent does if (await Task.WhenAny(Task.Delay(TimeSpan.FromMinutes(10)), proc) == proc) { return; } await self.Control.WriteAsync(new PeerRequest() { Operation = PeerOperation.Refresh, Response = respchan }); await respchan.ReadAsync(); } } ); log.Debug("Started refresh process, peer is now live"); await proc; await router; await broker; await values; await remoter; await discovery; await refresher; await Task.WhenAll(router, broker, values, remoter, discovery, refresher); } } catch (Exception ex) { log.Warn("Failed to start peer", ex); try { await requests.RetireAsync(); } catch (Exception ex2) { log.Warn("Failed to stop the input channel", ex2); } log.Debug($"Peer with key {selfinfo.Key} and address {selfinfo.Address} stopped..."); throw; } }