/// <summary> /// Gets a connection from the pool or creates a new one if all current connections are being used at peak access. /// </summary> /// <param name="serverName">Name of the PI server for the adapter's PI connection.</param> /// <param name="userName">Name of the PI user ID for the adapter's PI connection.</param> /// <param name="password">Password used for the adapter's PI connection.</param> /// <param name="connectTimeout">Timeout interval (in milliseconds) for the adapter's connection.</param> /// <returns>A <see cref="PIConnection"/> from the pool.</returns> /// <exception cref="InvalidOperationException">Failed to get a pooled PI connection.</exception> public PIConnection GetPooledConnection(string serverName, string userName = null, string password = null, int connectTimeout = PIConnection.DefaultConnectTimeout) { PIConnection connection = null; // We dynamically allocate pooled PI server connections each having a maximum accessibility count. // PI's threading model can handle many connections each archiving a small volume of points, but // falls behind under load when archiving a large volume of points from a single connection. try { lock (m_connectionPool) { while ((object)connection == null) { // Get next connection from the pool with lowest accessibility count if (m_connectionPool.Count > 0) { PIConnection[] availableConnections = m_connectionPool.Where(c => c.AccessCount < m_accessCountPerConnection).ToArray(); if (availableConnections.Length > 0) { connection = availableConnections.Aggregate((currentMin, nextItem) => (object)nextItem != null && currentMin.AccessCount < nextItem.AccessCount ? currentMin : nextItem); } } if ((object)connection == null) { // Add pooled connections in groups for better distribution for (int i = 0; i < m_minimumPoolSize; i++) { // Create a new connection connection = new PIConnection { ServerName = serverName, UserName = userName, Password = password, ConnectTimeout = connectTimeout }; // Since PI doesn't detect disconnection until an operation is attempted, // we must monitor for disconnections from the pooled connections as well connection.Disconnected += connection_Disconnected; connection.Open(); // Add the new connection to the server pool m_connectionPool.Add(connection); } } } // Increment current connection access count connection.AccessCount++; } } catch (Exception ex) { throw new InvalidOperationException(string.Format("Failed to get a pooled PI connection: {0}", ex.Message), ex); } return(connection); }
/// <summary> /// Connects to the configured PI server. /// </summary> protected override void AttemptConnection() { m_processedMappings = 0; m_processedMeasurements = 0; m_totalProcessingTime = 0; m_connection = new PIConnection { ServerName = m_serverName, UserName = m_userName, Password = m_password, ConnectTimeout = m_connectTimeout }; m_connection.Disconnected += m_connection_Disconnected; m_connection.Open(); m_mappedPIPoints.Clear(); lock (m_pendingMappings) { m_pendingMappings.Clear(); } m_mapRequestQueue.Clear(); m_mapRequestQueue.Start(); m_archiveQueue.Start(); // Kick off meta-data refresh RefreshMetadata(); }
/// <summary> /// Connects to the configured PI server. /// </summary> protected override void AttemptConnection() { m_processedMeasurements = 0; m_connection = new PIConnection { ServerName = m_serverName, UserName = m_userName, Password = m_password, ConnectTimeout = m_connectTimeout }; m_connection.Open(); }
/// <summary> /// Connects to the configured PI server. /// </summary> protected override void AttemptConnection() { m_connection = new PIConnection { ServerName = this.ServerName, UserName = this.UserName, Password = this.Password, ConnectTimeout = this.ConnectTimeout }; m_connection.Disconnected += m_connection_Disconnected; m_connection.Open(); m_dataPipe = new PIDataPipe(AFDataPipeType.Snapshot); //m_dataPipe.Subscribe(m_dataUpdateObserver); if (AutoStart && (object)OutputMeasurements != null && OutputMeasurements.Any()) { SubscribeToPointUpdates(this.OutputMeasurementKeys()); } }
/// <summary> /// Attempts to connect to this <see cref="PIAdapters.PIPBInputAdapter"/>. /// </summary> protected override void AttemptConnection() { // This adapter is only engaged for history, so we don't process any data unless a temporal constraint is defined if (this.TemporalConstraintIsDefined()) { // Turn off read timer if it's active m_readTimer.Enabled = false; m_connection = new PIConnection { ServerName = m_serverName, UserName = m_userName, Password = m_password, ConnectTimeout = m_connectTimeout }; m_connection.Open(); // Start the data reader on its own thread so connection attempt can complete in a timely fashion... ThreadPool.QueueUserWorkItem(StartDataReader); } }