Пример #1
0
        /// <summary>
        /// Connect one CRA vertex to another, via pre-defined endpoints. We contact the "from" vertex
        /// to initiate the creation of the link.
        /// </summary>
        /// <param name="fromVertexName">Name of the vertex from which connection is being made</param>
        /// <param name="fromEndpoint">Name of the endpoint on the fromVertex, from which connection is being made</param>
        /// <param name="toVertexName">Name of the vertex to which connection is being made</param>
        /// <param name="toEndpoint">Name of the endpoint on the toVertex, to which connection is being made</param>
        /// <param name="direction">Which vertex initiates the connection</param>
        /// <returns>Status of the Connect operation</returns>
        public CRAErrorCode Connect(string fromVertexName, string fromEndpoint, string toVertexName, string toEndpoint, ConnectionInitiator direction)
        {
            // Tell from vertex to establish connection
            // Send request to CRA instance

            // Check that vertex and endpoints are valid and existing
            if (!_vertexTableManager.ExistsVertex(fromVertexName) || !_vertexTableManager.ExistsVertex(toVertexName))
            {
                // Check for sharded vertices
                List <int> fromVertexShards, toVertexShards;

                if (!_vertexTableManager.ExistsShardedVertex(fromVertexName, out fromVertexShards))
                {
                    return(CRAErrorCode.VertexNotFound);
                }

                if (!_vertexTableManager.ExistsShardedVertex(toVertexName, out toVertexShards))
                {
                    return(CRAErrorCode.VertexNotFound);
                }

                return(ConnectSharded(fromVertexName, fromVertexShards, fromEndpoint, toVertexName, toVertexShards, toEndpoint, direction));
            }

            // Make the connection information stable
            _connectionTableManager.AddConnection(fromVertexName, fromEndpoint, toVertexName, toEndpoint);

            // We now try best-effort to tell the CRA instance of this connection
            CRAErrorCode result = CRAErrorCode.Success;

            VertexTable _row;

            try
            {
                // Get instance for source vertex
                _row = direction == ConnectionInitiator.FromSide ?
                       VertexTable.GetRowForVertex(_vertexTable, fromVertexName) :
                       VertexTable.GetRowForVertex(_vertexTable, toVertexName);
            }
            catch
            {
                Console.WriteLine("Unable to find active instance with vertex. On vertex activation, the connection should be completed automatically.");
                return(result);
            }

            try
            {
                if (_localWorker != null)
                {
                    if (_localWorker.InstanceName == _row.InstanceName)
                    {
                        return(_localWorker.Connect_InitiatorSide(fromVertexName, fromEndpoint,
                                                                  toVertexName, toEndpoint, direction == ConnectionInitiator.ToSide));
                    }
                }


                // Send request to CRA instance
                TcpClient client = null;
                // Get address and port for instance, using row with vertex = ""
                var row = VertexTable.GetRowForInstance(_vertexTable, _row.InstanceName);

                // Get a stream connection from the pool if available
                Stream stream;
                if (!TryGetSenderStreamFromPool(row.Address, row.Port.ToString(), out stream))
                {
                    client         = new TcpClient(row.Address, row.Port);
                    client.NoDelay = true;

                    stream = client.GetStream();

                    if (SecureStreamConnectionDescriptor != null)
                    {
                        stream = SecureStreamConnectionDescriptor.CreateSecureClient(stream, _row.InstanceName);
                    }
                }

                if (direction == ConnectionInitiator.FromSide)
                {
                    stream.WriteInt32((int)CRATaskMessageType.CONNECT_VERTEX_INITIATOR);
                }
                else
                {
                    stream.WriteInt32((int)CRATaskMessageType.CONNECT_VERTEX_INITIATOR_REVERSE);
                }

                stream.WriteByteArray(Encoding.UTF8.GetBytes(fromVertexName));
                stream.WriteByteArray(Encoding.UTF8.GetBytes(fromEndpoint));
                stream.WriteByteArray(Encoding.UTF8.GetBytes(toVertexName));
                stream.WriteByteArray(Encoding.UTF8.GetBytes(toEndpoint));

                result = (CRAErrorCode)stream.ReadInt32();
                if (result != 0)
                {
                    Console.WriteLine("Connection was logically established. However, the client received an error code from the connection-initiating CRA instance: " + result);
                }
                else
                {
                    // Add/Return a stream connection to the pool
                    TryAddSenderStreamToPool(row.Address, row.Port.ToString(), stream);
                }
            }
            catch
            {
                Console.WriteLine("The connection-initiating CRA instance appears to be down or could not be found. Restart it and this connection will be completed automatically");
            }
            return(result);
        }
Пример #2
0
        internal CRAErrorCode Connect_InitiatorSide(string fromVertexName, string fromVertexOutput, string toVertexName, string toVertexInput, bool reverse, bool killIfExists = true, bool killRemote = true)
        {
            VertexTable row;

            try
            {
                // Need to get the latest address & port
                row = reverse ? VertexTable.GetRowForVertex(_workerInstanceTable, fromVertexName)
                : VertexTable.GetRowForVertex(_workerInstanceTable, toVertexName);
            }
            catch
            {
                return(CRAErrorCode.ActiveVertexNotFound);
            }

            // If from and to vertices are on the same (this) instance,
            // we can convert a "reverse" connection into a normal connection
            if (reverse && (row.InstanceName == InstanceName))
            {
                reverse = false;
            }

            CancellationTokenSource oldSource;
            var conn = reverse ? inConnections : outConnections;

            if (conn.TryGetValue(fromVertexName + ":" + fromVertexOutput + ":" + toVertexName + ":" + toVertexInput,
                                 out oldSource))
            {
                if (killIfExists)
                {
                    Debug.WriteLine("Deleting prior connection - it will automatically reconnect");
                    oldSource.Cancel();
                }
                return(CRAErrorCode.Success);
            }

            if (TryFusedConnect(row.InstanceName, fromVertexName, fromVertexOutput, toVertexName, toVertexInput))
            {
                return(CRAErrorCode.Success);
            }

            // Re-check the connection table as someone may have successfully
            // created a fused connection
            if (conn.TryGetValue(fromVertexName + ":" + fromVertexOutput + ":" + toVertexName + ":" + toVertexInput,
                                 out oldSource))
            {
                if (killIfExists)
                {
                    Debug.WriteLine("Deleting prior connection - it will automatically reconnect");
                    oldSource.Cancel();
                }
                return(CRAErrorCode.Success);
            }

            // Send request to CRA instance
            Stream ns   = null;
            var    _row = VertexTable.GetRowForInstanceVertex(_workerInstanceTable, row.InstanceName, "");

            try
            {
                // Get a stream connection from the pool if available
                if (!_craClient.TryGetSenderStreamFromPool(_row.Address, _row.Port.ToString(), out ns))
                {
                    TcpClient client = new TcpClient(_row.Address, _row.Port);
                    client.NoDelay = true;

                    ns = _craClient.SecureStreamConnectionDescriptor
                         .CreateSecureClient(client.GetStream(), row.InstanceName);
                }
            }
            catch
            {
                return(CRAErrorCode.ConnectionEstablishFailed);
            }

            if (!reverse)
            {
                ns.WriteInt32((int)CRATaskMessageType.CONNECT_VERTEX_RECEIVER);
            }
            else
            {
                ns.WriteInt32((int)CRATaskMessageType.CONNECT_VERTEX_RECEIVER_REVERSE);
            }

            ns.WriteByteArray(Encoding.UTF8.GetBytes(fromVertexName));
            ns.WriteByteArray(Encoding.UTF8.GetBytes(fromVertexOutput));
            ns.WriteByteArray(Encoding.UTF8.GetBytes(toVertexName));
            ns.WriteByteArray(Encoding.UTF8.GetBytes(toVertexInput));
            ns.WriteInt32(killRemote ? 1 : 0);
            CRAErrorCode result = (CRAErrorCode)ns.ReadInt32();

            if (result != 0)
            {
                Debug.WriteLine("Error occurs while establishing the connection!!");
                return(result);
            }
            else
            {
                CancellationTokenSource source = new CancellationTokenSource();

                if (!reverse)
                {
                    if (outConnections.TryAdd(fromVertexName + ":" + fromVertexOutput + ":" + toVertexName + ":" + toVertexInput, source))
                    {
                        Task.Run(() =>
                                 EgressToStream(fromVertexName, fromVertexOutput, toVertexName, toVertexInput, reverse, ns, source, _row.Address, _row.Port));

                        return(CRAErrorCode.Success);
                    }
                    else
                    {
                        source.Dispose();
                        ns.Close();
                        Console.WriteLine("Race adding connection - deleting outgoing stream");
                        return(CRAErrorCode.ConnectionAdditionRace);
                    }
                }
                else
                {
                    if (inConnections.TryAdd(fromVertexName + ":" + fromVertexOutput + ":" + toVertexName + ":" + toVertexInput, source))
                    {
                        Task.Run(() =>
                                 IngressFromStream(fromVertexName, fromVertexOutput, toVertexName, toVertexInput, reverse, ns, source, _row.Address, _row.Port));
                        return(CRAErrorCode.Success);
                    }
                    else
                    {
                        source.Dispose();
                        ns.Close();
                        Debug.WriteLine("Race adding connection - deleting outgoing stream");
                        return(CRAErrorCode.ConnectionAdditionRace);
                    }
                }
            }
        }