/// <summary> /// Instantiate a Table by directly deserializing byte data from the given Deserializer. /// </summary> /// <param name="input">The Deserializer providing the data for the table.</param> internal TableBase(Deserializer input) { // Total byte length of the table data (ignored). int tableLength = input.ReadInt32(); // Total byte length of the Table metadata. int tableMetadataLength = input.ReadInt32(); // Status code (custom user-set value). this.Status = input.ReadSByte(); // Column Count. this.ColumnCount = input.ReadInt16(); // Initialize column-driven data store. ColumnType = new DBType[this.ColumnCount]; Column = new object[this.ColumnCount]; // Read column data types. for (short c = 0; c < this.ColumnCount; c++) ColumnType[c] = (DBType)input.ReadSByte(); // Read column names. this.ColumnNameData = input.ReadRaw(tableMetadataLength - 3 - this.ColumnCount); // Row count. this.RowCount = input.ReadInt32(); }
/// <summary> /// Instantiate a Table by directly deserializing byte data from the given Deserializer. /// </summary> /// <param name="input">The Deserializer providing the data for the table.</param> internal SingleRowTable(Deserializer input) : base(input) { // Validate row count. if (this.RowCount > 1) throw new VoltInvalidDataException(Resources.InvalidRowCount, this.RowCount); else if (this.RowCount == 0) return; // Total byte length of the row (ignored). int rowLength = input.ReadInt32(); // Read data and push in storage. for (short c = 0; c < this.ColumnCount; c++) { switch (ColumnType[c]) { case DBType.TINYINT: Column.SetValue(input.ReadSByteN(), c); break; case DBType.SMALLINT: Column.SetValue(input.ReadInt16N(), c); break; case DBType.INTEGER: Column.SetValue(input.ReadInt32N(), c); break; case DBType.BIGINT: Column.SetValue(input.ReadInt64N(), c); break; case DBType.FLOAT: Column.SetValue(input.ReadDoubleN(), c); break; case DBType.DECIMAL: Column.SetValue(input.ReadVoltDecimalN(), c); break; case DBType.TIMESTAMP: Column.SetValue(input.ReadDateTimeN(), c); break; case DBType.VARBINARY: Column.SetValue(input.ReadByteArray(), c); break; default: Column.SetValue(input.ReadString(), c); break; } } }
/// <summary> /// Parses the returned server message to read properties. /// </summary> /// <param name="input">The deserializer holding the data form the server message.</param> internal void ParseHeader(Deserializer input) { try { // Skip the client executionId: the caller (background network thread) already verified a match and // we recorded it at the start. input.Skip(8); // Check field map for status header parsing. this._HasFields = (HasFields)input.ReadByte(); // Read the Status (and optional associated message). this.ServerStatus = (ResponseServerStatus)input.ReadSByte(); if ((this._HasFields & HasFields.Status) == HasFields.Status) this.ServerStatusString = input.ReadString(); // Read the Application Status (and optional associated message). this.ServerApplicationStatus = input.ReadSByte(); if ((this._HasFields & HasFields.ApplicationStatus) == HasFields.ApplicationStatus) this.ServerApplicationStatusString = input.ReadString(); // Track query duration (ms). this.ExecutionDuration = input.ReadInt32(); // Skip exception data (currently not used and initialized to the same value as the Status string!). if ((this._HasFields & HasFields.Exception) == HasFields.Exception) //this.ServerExceptionString = input.ReadString(); input.SkipString(); // Figure out whether to move forward or kill over - note that we don't *really* kill over, but simply // report the Exception in the response's Exception field - the caller should validate that the // response is in good status before proceeding to read the results. switch (this.ServerStatus) { case ResponseServerStatus.Success: break; case ResponseServerStatus.UserAbort: this.Exception = new VoltAbortException( Resources.RequestAborted , this.Status , this.ServerStatusString ); break; case ResponseServerStatus.GracefulFailure: this.Exception = new VoltRequestFailureException( Resources.RequestFailure , this.Status , this.ServerStatusString ); break; case ResponseServerStatus.UnexpectedFailure: this.Exception = new VoltCriticalRequestFailureException( Resources.RequestFailure , this.Status , this.ServerStatusString ); break; default: this.Exception = new VoltCriticalRequestFailureException( Resources.ServerFailure , this.Status , this.ServerStatusString ); break; } } catch (Exception x) { this.Exception = new VoltSerializationException(Resources.ResponseDeserializationFailure, x); } }
/// <summary> /// Instantiate a Table by directly deserializing byte data from the given Deserializer. /// </summary> /// <param name="input">The Deserializer providing the data for the table.</param> internal Table(Deserializer input) : base(input) { // Allocate column-based data storage. for (short c = 0; c < this.ColumnCount; c++) { switch (ColumnType[c]) { case DBType.TINYINT: Column[c] = new sbyte?[this.RowCount]; break; case DBType.SMALLINT: Column[c] = new short?[this.RowCount]; break; case DBType.INTEGER: Column[c] = new int?[this.RowCount]; break; case DBType.BIGINT: Column[c] = new long?[this.RowCount]; break; case DBType.FLOAT: Column[c] = new double?[this.RowCount]; break; case DBType.DECIMAL: Column[c] = new VoltDecimal?[this.RowCount]; break; case DBType.TIMESTAMP: Column[c] = new DateTime?[this.RowCount]; break; case DBType.STRING: Column[c] = new string[this.RowCount]; break; case DBType.VARBINARY: Column[c] = new byte[this.RowCount][]; break; default: throw new VoltUnsupportedTypeException(Resources.UnsupportedDBType, ColumnType[c]); } } // Get data and push to storage. for (int r = 0; r < this.RowCount; r++) { // Total byte length of the row (ignored). input.Skip(4); // Read data and push in storage. for (short c = 0; c < this.ColumnCount; c++) { switch (ColumnType[c]) { case DBType.TINYINT: (Column[c] as sbyte?[])[r] = input.ReadSByteN(); break; case DBType.SMALLINT: (Column[c] as short?[])[r] = input.ReadInt16N(); break; case DBType.INTEGER: (Column[c] as int?[])[r] = input.ReadInt32N(); break; case DBType.BIGINT: (Column[c] as long?[])[r] = input.ReadInt64N(); break; case DBType.FLOAT: (Column[c] as double?[])[r] = input.ReadDoubleN(); break; case DBType.DECIMAL: (Column[c] as VoltDecimal?[])[r] = input.ReadVoltDecimalN(); break; case DBType.TIMESTAMP: (Column[c] as DateTime?[])[r] = input.ReadDateTimeN(); break; case DBType.VARBINARY: (Column[c] as byte[][])[r] = input.ReadByteArray(); break; default: (Column[c] as string[])[r] = input.ReadString(); break; } } } // Attach the enumerable row collection. this._Rows = new RowCollection(this); }
/// <summary> /// Returns a straight data array (boxed) of the requested data type from a single-column Table. /// </summary> /// <param name="input">The deserializer hoding the response data.</param> /// <param name="TResult">The desired output data type of the array elements.</param> /// <returns>A boxed array of elements of the requested data type.</returns> internal static object FromSingleColumn(Deserializer input, Type TResult) { // Skip table length, metadata length, status, get column count. short columnCount = input.Skip(9).ReadInt16(); // Validate there is indeed only one column. if (columnCount != 1) { throw new VoltInvalidDataException(Resources.InvalidColumnCount, columnCount); } // Read column data type. DBType columnType = (DBType)input.ReadSByte(); // Validate the data type matches the .NET casting request. if (VoltType.ToDBType(TResult) != columnType) { throw new VoltInvalidCastException( Resources.InvalidCastException , columnType.ToString() , TResult.ToString() ); } // Skip column name, get Row count. int rowCount = input.SkipString().ReadInt32(); // Load data. switch (VoltType.ToNetType(TResult)) { case VoltType.NetType.Byte: byte[] dataByte = new byte[rowCount]; for (int r = 0; r < rowCount; r++) { dataByte[r] = input.Skip(4).ReadByte(); } return(dataByte); case VoltType.NetType.ByteN: byte?[] dataByteN = new byte?[rowCount]; for (int r = 0; r < rowCount; r++) { dataByteN[r] = input.Skip(4).ReadByteN(); } return(dataByteN); case VoltType.NetType.SByte: sbyte[] dataSByte = new sbyte[rowCount]; for (int r = 0; r < rowCount; r++) { dataSByte[r] = input.Skip(4).ReadSByte(); } return(dataSByte); case VoltType.NetType.SByteN: sbyte?[] dataSByteN = new sbyte?[rowCount]; for (int r = 0; r < rowCount; r++) { dataSByteN[r] = input.Skip(4).ReadSByteN(); } return(dataSByteN); case VoltType.NetType.Int16: short[] dataInt16 = new short[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt16[r] = input.Skip(4).ReadInt16(); } return(dataInt16); case VoltType.NetType.Int16N: short?[] dataInt16N = new short?[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt16N[r] = input.Skip(4).ReadInt16N(); } return(dataInt16N); case VoltType.NetType.Int32: int[] dataInt32 = new int[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt32[r] = input.Skip(4).ReadInt32(); } return(dataInt32); case VoltType.NetType.Int32N: int?[] dataInt32N = new int?[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt32N[r] = input.Skip(4).ReadInt32N(); } return(dataInt32N); case VoltType.NetType.Int64: long[] dataInt64 = new long[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt64[r] = input.Skip(4).ReadInt64(); } return(dataInt64); case VoltType.NetType.Int64N: long?[] dataInt64N = new long?[rowCount]; for (int r = 0; r < rowCount; r++) { dataInt64N[r] = input.Skip(4).ReadInt64N(); } return(dataInt64N); case VoltType.NetType.Double: double[] dataDouble = new double[rowCount]; for (int r = 0; r < rowCount; r++) { dataDouble[r] = input.Skip(4).ReadDouble(); } return(dataDouble); case VoltType.NetType.DoubleN: double?[] dataDoubleN = new double?[rowCount]; for (int r = 0; r < rowCount; r++) { dataDoubleN[r] = input.Skip(4).ReadDoubleN(); } return(dataDoubleN); case VoltType.NetType.DateTime: DateTime[] dataDateTime = new DateTime[rowCount]; for (int r = 0; r < rowCount; r++) { dataDateTime[r] = input.Skip(4).ReadDateTime(); } return(dataDateTime); case VoltType.NetType.DateTimeN: DateTime?[] dataDateTimeN = new DateTime?[rowCount]; for (int r = 0; r < rowCount; r++) { dataDateTimeN[r] = input.Skip(4).ReadDateTimeN(); } return(dataDateTimeN); case VoltType.NetType.String: string[] dataString = new string[rowCount]; for (int r = 0; r < rowCount; r++) { dataString[r] = input.Skip(4).ReadString(); } return(dataString); case VoltType.NetType.VoltDecimal: VoltDecimal[] dataVoltDecimal = new VoltDecimal[rowCount]; for (int r = 0; r < rowCount; r++) { dataVoltDecimal[r] = input.Skip(4).ReadVoltDecimal(); } return(dataVoltDecimal); case VoltType.NetType.VoltDecimalN: VoltDecimal?[] dataVoltDecimalN = new VoltDecimal?[rowCount]; for (int r = 0; r < rowCount; r++) { dataVoltDecimalN[r] = input.Skip(4).ReadVoltDecimalN(); } return(dataVoltDecimalN); case VoltType.NetType.Decimal: Decimal[] dataDecimal = new Decimal[rowCount]; for (int r = 0; r < rowCount; r++) { dataDecimal[r] = input.Skip(4).ReadDecimal(); } return(dataDecimal); case VoltType.NetType.DecimalN: Decimal?[] dataDecimalN = new Decimal?[rowCount]; for (int r = 0; r < rowCount; r++) { dataDecimalN[r] = input.Skip(4).ReadDecimalN(); } return(dataDecimalN); case VoltType.NetType.ByteArray: input.Skip(4); return(input.ReadByteArray()); default: throw new VoltUnsupportedTypeException(Resources.UnsupportedParameterNETType, TResult.ToString()); } }
/// <summary> /// Parses the returned server message to read properties. /// </summary> /// <param name="input">The deserializer holding the data form the server message.</param> internal void ParseHeader(Deserializer input) { try { // Skip the client executionId: the caller (background network thread) already verified a match and // we recorded it at the start. input.Skip(8); // Check field map for status header parsing. this._HasFields = (HasFields)input.ReadByte(); // Read the Status (and optional associated message). this.ServerStatus = (ResponseServerStatus)input.ReadSByte(); if ((this._HasFields & HasFields.Status) == HasFields.Status) { this.ServerStatusString = input.ReadString(); } // Read the Application Status (and optional associated message). this.ServerApplicationStatus = input.ReadSByte(); if ((this._HasFields & HasFields.ApplicationStatus) == HasFields.ApplicationStatus) { this.ServerApplicationStatusString = input.ReadString(); } // Track query duration (ms). this.ExecutionDuration = input.ReadInt32(); // Skip exception data (currently not used and initialized to the same value as the Status string!). if ((this._HasFields & HasFields.Exception) == HasFields.Exception) { //this.ServerExceptionString = input.ReadString(); input.SkipString(); } // Figure out whether to move forward or kill over - note that we don't *really* kill over, but simply // report the Exception in the response's Exception field - the caller should validate that the // response is in good status before proceeding to read the results. switch (this.ServerStatus) { case ResponseServerStatus.Success: break; case ResponseServerStatus.UserAbort: this.Exception = new VoltAbortException( Resources.RequestAborted , this.Status , this.ServerStatusString ); break; case ResponseServerStatus.GracefulFailure: this.Exception = new VoltRequestFailureException( Resources.RequestFailure , this.Status , this.ServerStatusString ); break; case ResponseServerStatus.UnexpectedFailure: this.Exception = new VoltCriticalRequestFailureException( Resources.RequestFailure , this.Status , this.ServerStatusString ); break; default: this.Exception = new VoltCriticalRequestFailureException( Resources.ServerFailure , this.Status , this.ServerStatusString ); break; } } catch (Exception x) { this.Exception = new VoltSerializationException(Resources.ResponseDeserializationFailure, x); } }
/// <summary> /// Returns a single value (strongly-type) of the requested data type from a single-row/single-column Table. /// </summary> /// <typeparam name="TResult">The desired output data type of the returned value.</typeparam> /// <param name="input">The deserializer hoding the response data.</param> /// <returns>The single cell contained in the table read.</returns> internal static TResult FromSingleValue <TResult>(Deserializer input) { // Skip basic metadata and get Column Count. short columnCount = input.Skip(9).ReadInt16(); // Read column data type. DBType columnType = (DBType)input.ReadSByte(); // Validate the data type matches the .NET casting request if (VoltType.ToDBType(typeof(TResult)) != columnType) { throw new VoltInvalidCastException( Resources.InvalidCastException , columnType.ToString() , typeof(TResult).ToString() ); } // Skip column name and get Row count. int rowCount = input.SkipString().ReadInt32(); // Validate there is indeed only one column and row. if ((columnCount != 1) || (rowCount != 1)) { throw new VoltInvalidDataException(Resources.InvalidRowAndColumnCount, rowCount, columnCount); } // Load data (skip row length and load first value) - unfortunately, we do have to box this. switch (VoltType.ToNetType(typeof(TResult))) { case VoltType.NetType.Byte: return((TResult)(object)input.Skip(4).ReadByte()); case VoltType.NetType.ByteN: return((TResult)(object)input.Skip(4).ReadByteN()); case VoltType.NetType.SByte: return((TResult)(object)input.Skip(4).ReadSByte()); case VoltType.NetType.SByteN: return((TResult)(object)input.Skip(4).ReadSByteN()); case VoltType.NetType.Int16: return((TResult)(object)input.Skip(4).ReadInt16()); case VoltType.NetType.Int16N: return((TResult)(object)input.Skip(4).ReadInt16N()); case VoltType.NetType.Int32: return((TResult)(object)input.Skip(4).ReadInt32()); case VoltType.NetType.Int32N: return((TResult)(object)input.Skip(4).ReadInt32N()); case VoltType.NetType.Int64: return((TResult)(object)input.Skip(4).ReadInt64()); case VoltType.NetType.Int64N: return((TResult)(object)input.Skip(4).ReadInt64N()); case VoltType.NetType.Double: return((TResult)(object)input.Skip(4).ReadDouble()); case VoltType.NetType.DoubleN: return((TResult)(object)input.Skip(4).ReadDoubleN()); case VoltType.NetType.DateTime: return((TResult)(object)input.Skip(4).ReadDateTime()); case VoltType.NetType.DateTimeN: return((TResult)(object)input.Skip(4).ReadDateTimeN()); case VoltType.NetType.String: return((TResult)(object)input.Skip(4).ReadString()); case VoltType.NetType.VoltDecimal: return((TResult)(object)input.Skip(4).ReadVoltDecimal()); case VoltType.NetType.VoltDecimalN: return((TResult)(object)input.Skip(4).ReadVoltDecimalN()); case VoltType.NetType.Decimal: return((TResult)(object)input.Skip(4).ReadDecimal()); case VoltType.NetType.DecimalN: return((TResult)(object)input.Skip(4).ReadDecimalN()); default: throw new VoltUnsupportedTypeException( Resources.UnsupportedParameterNETType , typeof(TResult).ToString() ); } }
/// <summary> /// Open the connection. /// </summary> /// <returns>A reference to the current connection instance for action chaining.</returns> public override VoltConnection Open() { // Synchronize access. lock (this.SyncRoot) { // Validate connection status. if (this.Status != ConnectionStatus.Closed) throw new InvalidOperationException(string.Format(Resources.InvalidConnectionStatus, this.Status)); // Set status to "connecting". this.Status = ConnectionStatus.Connecting; // Connect to the default endpoint (there should only be one anyways if this is a managed pool // connection, otherwise, you're on your own - this is a connection, not a Pool!). IPEndPoint endPoint = this.Settings.DefaultIPEndPoint; try { // Create new socket stream and wrap a core protocol stream manager around it. this.BaseStream = new VoltProtocolStream(endPoint, this.Settings.ConnectionTimeout); // Now send login message. using (Serializer serializer = new Serializer()) { var msg = serializer .Write(this.Settings.ServiceType.ToString().ToLowerInvariant()) .Write(this.Settings.UserID) .WriteRaw(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(this.Settings.Password))) .GetBytes(); this.BaseStream.WriteMessage(msg.Array, msg.Offset, msg.Count); } // Receive and process login response message. var deserializer = new Deserializer(this.BaseStream.ReadMessage()); LoginResponseStatus status = (LoginResponseStatus)deserializer.ReadSByte(); if (status != LoginResponseStatus.Connected) { // Re-package server response in an appropriate exception. switch (status) { case LoginResponseStatus.ConnectionHandshakeTimeout: throw new VoltConnectionException( Resources.LRS_ConnectionHandshakeTimeout , endPoint , status ); case LoginResponseStatus.CorruptedHandshake: throw new VoltConnectionException( Resources.LRS_CorruptedHandshake , endPoint , status ); case LoginResponseStatus.InvalidCredentials: throw new VoltPermissionException( Resources.LRS_InvalidCredentials , endPoint , status ); case LoginResponseStatus.ServerTooBusy: throw new VoltConnectionException( Resources.LRS_ServerTooBusy , endPoint , status ); default: throw new VoltConnectionException(Resources.LRS_Unknown, endPoint, status); } } // Parse the rest of the response the get core cluster information. try { this.ServerHostId = deserializer.ReadInt32(); this.ConnectionId = deserializer.ReadInt64(); this.ClusterStartTimeStamp = deserializer.ReadDateTimeFromMilliseconds(); this.LeaderIPEndPoint = new IPEndPoint( new IPAddress(deserializer.ReadRaw(4)) , endPoint.Port ); this.BuildString = deserializer.ReadString(); } catch (Exception x) { throw new VoltConnectionException(Resources.LR_FailedParsingResponse, x, endPoint); } // Now that we are successfully connected, set the socket timeout to infinite (we are constantly // listening for new messages). this.BaseStream.ResetTimeout(Timeout.Infinite); // Create background threads. this.BackgroundNetworkThread = new Thread(this.BackgroundNetworkThreadRun) { IsBackground = true, Priority = ThreadPriority.AboveNormal }; this.BackgroundTimeoutThread = new Thread(this.BackgroundTimeoutThreadRun) { IsBackground = true }; // Starting background processing threads. this.BackgroundNetworkThread.Start(); this.BackgroundTimeoutThread.Start(); // Start Callback executor this.CallbackExecutor.Start(); // Ensure terminal exception is reset this.TerminalException = null; // Connection is now ready. this.Status = ConnectionStatus.Connected; // Initialize statistics as needed. if (this.Settings.StatisticsEnabled) { this.Stats = new Dictionary<string, Statistics>(StringComparer.OrdinalIgnoreCase); // For lifetime statistics, keep track of previous connection cycles, if any. if (this.LifetimeStats != null) { if (this.PastLifetimeStats != null) this.PastLifetimeStats.SummarizeWith(this.LifetimeStats); else this.PastLifetimeStats = this.LifetimeStats; } this.LifetimeStats = new Statistics(); } // Trace as needed if (this.Settings.TraceEnabled) VoltTrace.TraceEvent( TraceEventType.Information , VoltTraceEventType.ConnectionOpened , Resources.TraceConnectionOpened , this.ServerHostId , this.ConnectionId , endPoint , this.LeaderIPEndPoint , this.ClusterStartTimeStamp , this.BuildString ); } catch (Exception x) { try { // In case of failure, terminate everything immediately (will correct status). this.Terminate(); } catch { } // Re-throw exception, wrapping if needed. if (x is VoltException) throw new VoltConnectionException(Resources.ConnectionFailure, x, endPoint); else throw x; } } return this; }
/// <summary> /// Parse the response header (deferred to the based class) and the result Payload. /// </summary> /// <param name="message">The byte buffer of the binary response data from the server.</param> internal override void ParseResponse(byte[] message) { var input = new Deserializer(message); // Parse header information first, deferring to base class this.ParseHeader(input); // Return immediately if header parsing failed if (this.ServerStatus != ResponseServerStatus.Success) { return; } // Parse the result try { // Unfortunately this is ugly: have to dynamically check the type to figure out which path to take // - no generic implementation can seamlessly deal with T, T[] and T[][] Type type = typeof(TResult); // Array type - either of: // - Table[] an array of generic Tables // - SingleRowTable[] an array of generic single-row Tables // - T[][] an array of generic single-column Tables // - T[] a single single-column Table if (type.IsArray) { // Get sub-type within the array Type elementType = type.GetElementType(); // We have a Table Array if (elementType == typeof(Table)) { this._Result = (TResult)(object)input.ReadTableArray(); } // We have a SingleRowTable aArray else if (elementType == typeof(SingleRowTable)) { this._Result = (TResult)(object)input.ReadSingleRowTableArray(); } // We have an array of single-column tables else if (elementType.IsArray) { short count = input.ReadInt16(); Array result = Array.CreateInstance(elementType, count); for (short i = 0; i < count; i++) { result.SetValue(Table.FromSingleColumn(input, elementType.GetElementType()), i); } this._Result = (TResult)(object)result; } // We have a single single-column table else { short count = input.ReadInt16(); if (count != 1) { throw new VoltInvalidDataException(Resources.InvalidResultsetSize, count); } if (elementType == typeof(byte)) { elementType = typeof(byte[]); } this._Result = (TResult)Table.FromSingleColumn(input, elementType); } } // Base type - either of: // - Table // - SingleRowTable // - T else { if (type == typeof(Null)) { this._Result = (TResult)(object)new Null(); } else { // Read count: there should be only 1 data set for those calls short count = input.ReadInt16(); if (count != 1) { throw new VoltInvalidDataException(Resources.InvalidResultsetSize, count); } // A single Table if (type == typeof(Table)) { this._Result = (TResult)(object)new Table(input); } // A single single-row Table else if (type == typeof(SingleRowTable)) { this._Result = (TResult)(object)new SingleRowTable(input); } // A single value else { this._Result = (TResult)Table.FromSingleValue <TResult>(input); } } } } catch (Exception x) { this.Exception = new VoltSerializationException(Resources.ResponseDeserializationFailure, x); } }
/// <summary> /// Open the connection. /// </summary> /// <returns>A reference to the current connection instance for action chaining.</returns> public override VoltConnection Open() { // Synchronize access. lock (this.SyncRoot) { // Validate connection status. if (this.Status != ConnectionStatus.Closed) { throw new InvalidOperationException(string.Format(Resources.InvalidConnectionStatus, this.Status)); } // Set status to "connecting". this.Status = ConnectionStatus.Connecting; // Connect to the default endpoint (there should only be one anyways if this is a managed pool // connection, otherwise, you're on your own - this is a connection, not a Pool!). IPEndPoint endPoint = this.Settings.DefaultIPEndPoint; try { // Create new socket stream and wrap a core protocol stream manager around it. this.BaseStream = new VoltProtocolStream(endPoint, this.Settings.ConnectionTimeout); // Now send login message. using (Serializer serializer = new Serializer()) { var msg = serializer .Write(this.Settings.ServiceType.ToString().ToLowerInvariant()) .Write(this.Settings.UserID) .WriteRaw(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(this.Settings.Password))) .GetBytes(); this.BaseStream.WriteMessage(msg.Array, msg.Offset, msg.Count); } // Receive and process login response message. var deserializer = new Deserializer(this.BaseStream.ReadMessage()); LoginResponseStatus status = (LoginResponseStatus)deserializer.ReadSByte(); if (status != LoginResponseStatus.Connected) { // Re-package server response in an appropriate exception. switch (status) { case LoginResponseStatus.ConnectionHandshakeTimeout: throw new VoltConnectionException( Resources.LRS_ConnectionHandshakeTimeout , endPoint , status ); case LoginResponseStatus.CorruptedHandshake: throw new VoltConnectionException( Resources.LRS_CorruptedHandshake , endPoint , status ); case LoginResponseStatus.InvalidCredentials: throw new VoltPermissionException( Resources.LRS_InvalidCredentials , endPoint , status ); case LoginResponseStatus.ServerTooBusy: throw new VoltConnectionException( Resources.LRS_ServerTooBusy , endPoint , status ); default: throw new VoltConnectionException(Resources.LRS_Unknown, endPoint, status); } } // Parse the rest of the response the get core cluster information. try { this.ServerHostId = deserializer.ReadInt32(); this.ConnectionId = deserializer.ReadInt64(); this.ClusterStartTimeStamp = deserializer.ReadDateTimeFromMilliseconds(); this.LeaderIPEndPoint = new IPEndPoint( new IPAddress(deserializer.ReadRaw(4)) , endPoint.Port ); this.BuildString = deserializer.ReadString(); } catch (Exception x) { throw new VoltConnectionException(Resources.LR_FailedParsingResponse, x, endPoint); } // Now that we are successfully connected, set the socket timeout to infinite (we are constantly // listening for new messages). this.BaseStream.ResetTimeout(Timeout.Infinite); // Create background threads. this.BackgroundNetworkThread = new Thread(this.BackgroundNetworkThreadRun) { IsBackground = true, Priority = ThreadPriority.AboveNormal }; this.BackgroundTimeoutThread = new Thread(this.BackgroundTimeoutThreadRun) { IsBackground = true }; // Starting background processing threads. this.BackgroundNetworkThread.Start(); this.BackgroundTimeoutThread.Start(); // Start Callback executor this.CallbackExecutor.Start(); // Ensure terminal exception is reset this.TerminalException = null; // Connection is now ready. this.Status = ConnectionStatus.Connected; // Initialize statistics as needed. if (this.Settings.StatisticsEnabled) { this.Stats = new Dictionary <string, Statistics>(StringComparer.OrdinalIgnoreCase); // For lifetime statistics, keep track of previous connection cycles, if any. if (this.LifetimeStats != null) { if (this.PastLifetimeStats != null) { this.PastLifetimeStats.SummarizeWith(this.LifetimeStats); } else { this.PastLifetimeStats = this.LifetimeStats; } } this.LifetimeStats = new Statistics(); } // Trace as needed if (this.Settings.TraceEnabled) { VoltTrace.TraceEvent( TraceEventType.Information , VoltTraceEventType.ConnectionOpened , Resources.TraceConnectionOpened , this.ServerHostId , this.ConnectionId , endPoint , this.LeaderIPEndPoint , this.ClusterStartTimeStamp , this.BuildString ); } } catch (Exception x) { try { // In case of failure, terminate everything immediately (will correct status). this.Terminate(); } catch { } // Re-throw exception, wrapping if needed. if (x is VoltException) { throw new VoltConnectionException(Resources.ConnectionFailure, x, endPoint); } else { throw x; } } } return(this); }