/// <summary> /// Initializes a new instance of the BaseSession class based on the specified connection string. /// </summary> /// <param name="connectionString">The connection used to create the session.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionString"/> is <c>null</c>.</exception> /// <exception cref="UriFormatException">Unable to parse the <paramref name="connectionString"/> when /// in URI format.</exception> /// <remarks> /// <para>When using Unix sockets the <c>protocol=unix</c> or <c>protocol=unixsocket</c> connection option is required. /// This will enable elements passed in the <c>server</c> connection option to be treated as Unix sockets. The user is also required /// to explicitly set <c>sslmode</c> to <c>none</c> since X Plugin does not support SSL when using Unix sockets. Note that /// <c>protocol=unix</c> and <c>protocol=unixsocket</c> are synonyms.</para> /// <para> </para> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionString"/>, /// which will enable client side failover when trying to establish a connection.</para> /// <para> </para> /// <para>Connection string examples (in URI format): /// <para />- mysqlx://test:test@[192.1.10.10,localhost] /// <para />- mysqlx://test:test@[192.1.10.10,127.0.0.1] /// <para />- mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none /// <para />- mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] /// <para />- mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 /// <para />- mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] /// <para />- mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] /// </para> /// <para> </para> /// <para>Connection string examples (in basic format): /// <para />- server=10.10.10.10,localhost;port=33060;uid=test;password=test; /// <para />- host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; /// <para />- host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; /// <para />- server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; /// <para />- server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; /// </para> /// <para> </para> /// <para>Failover methods</para> /// <para>- Sequential: Connection attempts will be performed in a sequential order, that is, one after another until /// a connection is successful or all the elements from the list have been tried. /// </para> /// <para>- Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either /// give a priority for every host or no priority to any host. /// </para> /// </remarks> public BaseSession(string connectionString) { if (string.IsNullOrWhiteSpace(connectionString)) { throw new ArgumentNullException("connectionString"); } this.connectionString = ParseConnectionString(connectionString); if (FailoverManager.FailoverGroup != null) { // Multiple hosts were specified. _internalSession = FailoverManager.AttemptConnection(this.connectionString, out this.connectionString); Settings = new MySqlConnectionStringBuilder(this.connectionString); } else { // A single host was specified. Settings = new MySqlConnectionStringBuilder(this.connectionString); _internalSession = InternalSession.GetSession(Settings); } if (!string.IsNullOrWhiteSpace(Settings.Database)) { GetSchema(Settings.Database); } }
/// <summary> /// Initializes a new instance of the BaseSession class based on the specified connection string. /// </summary> /// <param name="connectionString">The connection used to create the session.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionString"/> is <c>null</c>.</exception> /// <exception cref="UriFormatException">Unable to parse the <paramref name="connectionString"/> when /// in URI format.</exception> /// <remarks> /// <para>When using Unix sockets the <c>protocol=unix</c> or <c>protocol=unixsocket</c> connection option is required. /// This will enable elements passed in the <c>server</c> connection option to be treated as Unix sockets. The user is also required /// to explicitly set <c>sslmode</c> to <c>none</c> since X Plugin does not support SSL when using Unix sockets. Note that /// <c>protocol=unix</c> and <c>protocol=unixsocket</c> are synonyms.</para> /// <para> </para> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionString"/>, /// which enables client-side failover when trying to establish a connection.</para> /// <para> </para> /// <para>Connection URI examples: /// <para />- mysqlx://test:test@[192.1.10.10,localhost] /// <para />- mysqlx://test:test@[192.1.10.10,127.0.0.1] /// <para />- mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none /// <para />- mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] /// <para />- mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 /// <para />- mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] /// <para />- mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] /// </para> /// <para> </para> /// <para>Connection string examples: /// <para />- server=10.10.10.10,localhost;port=33060;uid=test;password=test; /// <para />- host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; /// <para />- host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; /// <para />- server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; /// <para />- server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; /// </para> /// <para> </para> /// <para>Failover methods</para> /// <para>- Sequential: Connection attempts will be performed in a sequential order, that is, one after another until /// a connection is successful or all the elements from the list have been tried. /// </para> /// <para>- Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either /// give a priority for every host or no priority to any host. /// </para> /// </remarks> internal BaseSession(string connectionString, Client client = null) : this() { if (string.IsNullOrWhiteSpace(connectionString)) { throw new ArgumentNullException("connectionString"); } _client = client; this._connectionString = ParseConnectionData(connectionString); // Multiple hosts were specified. if (FailoverManager.FailoverGroup != null) { _internalSession = FailoverManager.AttemptConnection(this._connectionString, out this._connectionString); Settings.ConnectionString = this._connectionString; Settings.AnalyzeConnectionString(this._connectionString, true); } // A single host was specified. else { Settings.ConnectionString = _connectionString; if (!(_connectionString.Contains("sslmode") || _connectionString.Contains("ssl mode") || _connectionString.Contains("ssl-mode"))) { Settings.SslMode = MySqlSslMode.Required; } Settings.AnalyzeConnectionString(this._connectionString, true); _internalSession = InternalSession.GetSession(Settings); } // Set the default schema if provided by the user. if (!string.IsNullOrWhiteSpace(Settings.Database)) { DefaultSchema = GetSchema(Settings.Database); } }
/// <summary> /// Attempts to establish a connection to a host specified from the list. /// </summary> /// <param name="originalConnectionString">The original connection string set by the user.</param> /// <param name="connectionString">An out parameter that stores the updated connection string.</param> /// <returns>An <see cref="InternalSession"/> instance if the connection was succesfully established, a <see cref="MySqlException"/> exception is thrown otherwise.</returns> internal static InternalSession AttemptConnection(string originalConnectionString, out string connectionString) { if (FailoverGroup == null || originalConnectionString == null) { connectionString = null; return(null); } XServer currentHost = FailoverGroup.ActiveHost; string initialHost = currentHost.Host; MySqlXConnectionStringBuilder Settings = null; InternalSession internalSession = null; TimeoutException timeoutException = null; do { // Attempt to connect to each host by retrieving the next host based on the failover method being used. connectionString = "server=" + currentHost.Host + ";" + originalConnectionString.Substring(originalConnectionString.IndexOf(';') + 1); Settings = new MySqlXConnectionStringBuilder(connectionString); if (currentHost != null && currentHost.Port != -1) { Settings.Port = (uint)currentHost.Port; } if (currentHost.Host == initialHost) { string exTimeOutMessage = Settings.ConnectTimeout == 0 ? ResourcesX.TimeOutMultipleHost0ms : String.Format(ResourcesX.TimeOutMultipleHost, Settings.ConnectTimeout); timeoutException = new TimeoutException(exTimeOutMessage); } try { internalSession = InternalSession.GetSession(Settings); timeoutException = null; } catch (Exception ex) { if (!(ex is TimeoutException)) { timeoutException = null; } } if (internalSession != null) { break; } currentHost = FailoverGroup.GetNextHost(); }while (currentHost.Host != initialHost); // All connection attempts failed. if (timeoutException != null) { throw timeoutException; } if (internalSession == null) { throw new MySqlException(Resources.UnableToConnectToHost); } return(internalSession); }
public void AddSession(Socket s,TcpServer server) { lock (_lock) { InternalSession session = new InternalSession(server, s); mDicSession[s] = session; } }
internal Result(InternalSession session) : base(session) { if (session == null) { return; } session.GetProtocol().CloseResult(this); }
internal Result(InternalSession session) : base(session) { if (session == null) { return; } GeneratedIds = new ReadOnlyCollection <string>(_documentIds); session.GetProtocol().CloseResult(this); }
public void ShouldDelegateToAsyncSession() { var asyncSession = new Mock <IInternalAsyncSession>(); var session = new InternalSession(asyncSession.Object, Mock.Of <IRetryLogic>(), Mock.Of <BlockingExecutor>()); var bookmark = session.LastBookmark; asyncSession.Verify(x => x.LastBookmark, Times.Once); }
/// <summary> /// Get a handle to the session manager and request the session object by id /// this is also the signal to the session manager that this NativeSessionHost is ready /// </summary> /// <param name="creatorProcessId"></param> /// <param name="sessionId"></param> private static void RegisterSession2(int creatorProcessId, int sessionId) { SetSessionManagerProcessId(creatorProcessId); INativeSessionManager sessionManager = NativeSessionManagerClientFactory.CreateChannel(); InternalSession session = sessionManager.RegisterNativeSessionHost(sessionId); ((IClientChannel)sessionManager).Close(); InternalSession = session; }
public void ShouldDelegateToAsyncSession() { var asyncSession = new Mock <IInternalAsyncSession>(); var session = new InternalSession(asyncSession.Object, Mock.Of <IRetryLogic>(), Mock.Of <BlockingExecutor>()); var config = session.SessionConfig; asyncSession.Verify(x => x.SessionConfig, Times.Once); }
/// <summary> /// Initializes a new instance of the BaseSession class based on the specified anonymous type object. /// </summary> /// <param name="connectionData">The connection data as an anonymous type used to create the session.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionData"/> is null.</exception> /// <remarks> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionData"/>, which will enable client-side failover when trying to /// establish a connection.</para> /// <para> </para> /// <para>To assign multiple hosts create a property similar to the connection string examples (in basic format) shown in /// <see cref="BaseSession(string)"/>. Note that the value of the property must be a string. /// </para> /// </remarks> public BaseSession(object connectionData) { if (connectionData == null) { throw new ArgumentNullException("connectionData"); } var values = Tools.GetDictionaryFromAnonymous(connectionData); if (!values.Keys.Any(s => s.ToLowerInvariant() == "port")) { values.Add("port", newDefaultPort); } Settings = new MySqlConnectionStringBuilder(); bool hostsParsed = false; foreach (var value in values) { if (!Settings.ContainsKey(value.Key)) { throw new KeyNotFoundException(string.Format(ResourcesX.InvalidConnectionStringAttribute, value.Key)); } Settings.SetValue(value.Key, value.Value); if (!hostsParsed && !string.IsNullOrEmpty(Settings["server"].ToString())) { var server = value.Value.ToString(); if (IsUnixSocket(server)) { Settings.SetValue(value.Key, server = NormalizeUnixSocket(server)); } ParseHostList(server, false); if (FailoverManager.FailoverGroup != null) { Settings["server"] = FailoverManager.FailoverGroup.ActiveHost.Host; } hostsParsed = true; } } this.connectionString = Settings.ToString(); if (FailoverManager.FailoverGroup != null) { // Multiple hosts were specified. _internalSession = FailoverManager.AttemptConnection(this.connectionString, out this.connectionString); Settings = new MySqlConnectionStringBuilder(this.connectionString); } else { _internalSession = InternalSession.GetSession(Settings); } if (!string.IsNullOrWhiteSpace(Settings.Database)) { GetSchema(Settings.Database); } }
public async Task Should_RetryOnNextNodes_When_ANodeIsPaused(bool streamMode) { var pausedNode = TestCluster.GetNode(2); SetupNewSession(b => b.WithPoolingOptions( new PoolingOptions() .SetCoreConnectionsPerHost(HostDistance.Local, 1) .SetMaxConnectionsPerHost(HostDistance.Local, 1)) .WithSocketOptions( new SocketOptions() .SetReadTimeoutMillis(2000) .SetStreamMode(streamMode) .SetDefunctReadTimeoutThreshold(int.MaxValue))); var maxRequestsPerConnection = Session.Cluster.Configuration .GetOrCreatePoolingOptions(Session.Cluster.Metadata.ControlConnection.ProtocolVersion) .GetMaxRequestsPerConnection(); var tenKbBuffer = new byte[10240]; await pausedNode.PauseReadsAsync().ConfigureAwait(false); // send number of requests = max pending var requests = Enumerable.Repeat(0, maxRequestsPerConnection * Session.Cluster.AllHosts().Count) .Select(i => Session.ExecuteAsync(new SimpleStatement("INSERT INTO table1 (id) VALUES (?)", tenKbBuffer))).ToList(); var pools = InternalSession.GetPools().ToList(); var runningNodesPools = pools.Where(kvp => !kvp.Key.Equals(pausedNode.IpEndPoint)); var pausedNodePool = pools.Single(kvp => kvp.Key.Equals(pausedNode.IpEndPoint)); var connections = pools.SelectMany(kvp => kvp.Value.ConnectionsSnapshot).ToList(); var runningNodesConnections = runningNodesPools.SelectMany(kvp => kvp.Value.ConnectionsSnapshot).ToList(); var pausedNodeConnections = pausedNodePool.Value.ConnectionsSnapshot; await Task.WhenAll(requests).ConfigureAwait(false); await AssertRetryUntilWriteQueueStabilizesAsync(connections).ConfigureAwait(false); TestHelper.RetryAssert( () => { Assert.IsTrue(runningNodesConnections.All(c => c.InFlight == 0)); Assert.IsTrue(runningNodesConnections.All(c => c.WriteQueueLength == 0)); Assert.IsTrue(runningNodesConnections.All(c => c.PendingOperationsMapLength == 0)); }, 100, 100); Assert.IsTrue(pausedNodeConnections.All(c => c.InFlight > 0)); Assert.IsTrue(pausedNodeConnections.All(c => c.WriteQueueLength > 0)); Assert.IsTrue(pausedNodeConnections.All(c => c.PendingOperationsMapLength > 0)); }
/// <summary> /// Drops the database/schema with the given name. /// </summary> /// <param name="schema">The name of the schema.</param> /// <exception cref="ArgumentNullException"><paramref name="schema"/> is null.</exception> public void DropSchema(string schema) { if (string.IsNullOrWhiteSpace(schema)) { throw new ArgumentNullException(nameof(schema)); } Schema s = this.GetSchema(schema); if (!s.ExistsInDatabase()) { return; } InternalSession.ExecuteSqlNonQuery("DROP DATABASE `" + schema + "`"); }
/// <summary> /// Closes this session or releases it to the pool. /// </summary> public void Close() { if (XSession.SessionState != SessionState.Closed) { if (_client == null) { CloseFully(); } else { _client.ReleaseSession(this); XSession.SetState(SessionState.Closed, false); _internalSession = null; } } }
/// <summary> /// Initializes a new instance of the BaseSession class based on the specified connection string. /// </summary> /// <param name="connectionString">The connection used to create the session.</param> /// <param name="client">A <see cref="Client"/> object.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionString"/> is <c>null</c>.</exception> /// <exception cref="UriFormatException">Unable to parse the <paramref name="connectionString"/> when /// in URI format.</exception> /// <remarks> /// <para>When using Unix sockets the <c>protocol=unix</c> or <c>protocol=unixsocket</c> connection option is required. /// This will enable elements passed in the <c>server</c> connection option to be treated as Unix sockets. The user is also required /// to explicitly set <c>sslmode</c> to <c>none</c> since X Plugin does not support SSL when using Unix sockets. Note that /// <c>protocol=unix</c> and <c>protocol=unixsocket</c> are synonyms.</para> /// <para> </para> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionString"/>, /// which enables client-side failover when trying to establish a connection.</para> /// <para> </para> /// <para>Connection URI examples: /// <para />- mysqlx://test:test@[192.1.10.10,localhost] /// <para />- mysqlx://test:test@[192.1.10.10,127.0.0.1] /// <para />- mysqlx://root:@[../tmp/mysqlx.sock,/tmp/mysqld.sock]?protocol=unix&sslmode=none /// <para />- mysqlx://test:test@[192.1.10.10:33060,127.0.0.1:33060] /// <para />- mysqlx://test:test@[192.1.10.10,120.0.0.2:22000,[::1]:33060]/test?connectiontimeout=10 /// <para />- mysqlx://test:test@[(address=server.example,priority=20),(address=127.0.0.1,priority=100)] /// <para />- mysqlx://test:test@[(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25)] /// </para> /// <para> </para> /// <para>Connection string examples: /// <para />- server=10.10.10.10,localhost;port=33060;uid=test;password=test; /// <para />- host=10.10.10.10,192.101.10.2,localhost;port=5202;uid=test;password=test; /// <para />- host=./tmp/mysqld.sock,/var/run/mysqldx.sock;port=5202;uid=root;protocol=unix;sslmode=none; /// <para />- server=(address=server.example,priority=20),(address=127.0.0.1,priority=100);port=33060;uid=test;password=test; /// <para />- server=(address=server.example,priority=100),(address=127.0.0.1,priority=75),(address=192.0.10.56,priority=25);port=33060;uid=test;password=test; /// </para> /// <para> </para> /// <para>Failover methods</para> /// <para>- Sequential: Connection attempts will be performed in a sequential order, that is, one after another until /// a connection is successful or all the elements from the list have been tried. /// </para> /// <para>- Priority based: If a priority is provided, the connection attemps will be performed in descending order, starting /// with the host with the highest priority. Priority must be a value between 0 and 100. Additionally, it is required to either /// give a priority for every host or no priority to any host. /// </para> /// </remarks> internal BaseSession(string connectionString, Client client = null) : this() { if (string.IsNullOrWhiteSpace(connectionString)) { throw new ArgumentNullException("connectionString"); } _client = client; this._connectionString = ParseConnectionData(connectionString, client); // Multiple hosts were specified. if (FailoverManager.FailoverGroup != null && FailoverManager.FailoverGroup.Hosts?.Count > 1) { _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = this._connectionString; Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); } // A single host was specified. else { Settings.ConnectionString = _connectionString; if (!(_connectionString.Contains("sslmode") || _connectionString.Contains("ssl mode") || _connectionString.Contains("ssl-mode"))) { Settings.SslMode = MySqlSslMode.Required; } Settings.AnalyzeConnectionString(this._connectionString, true, _isDefaultPort); if (Settings.DnsSrv) { var dnsSrvRecords = DnsResolver.GetDnsSrvRecords(Settings.Server); FailoverManager.SetHostList(dnsSrvRecords.ConvertAll(r => new FailoverServer(r.Target, r.Port, r.Priority)), FailoverMethod.Sequential); _internalSession = FailoverManager.AttemptConnectionXProtocol(this._connectionString, out this._connectionString, _isDefaultPort, client); Settings.ConnectionString = this._connectionString; } else { _internalSession = InternalSession.GetSession(Settings); } } // Set the default schema if provided by the user. if (!string.IsNullOrWhiteSpace(Settings.Database)) { DefaultSchema = GetSchema(Settings.Database); } }
internal BaseResult(InternalSession session) { if (session == null) { return; } _session = session; // if we have an active resultset then we must buffer it entirely if (session.ActiveResult != null) { session.ActiveResult.Buffer(); session.ActiveResult = null; } _hasData = Protocol.HasData(this); if (_hasData) { session.ActiveResult = this; } }
/// <summary> /// Update the ServiceHost with the last invocation time /// </summary> /// <param name="idleTime"></param> static void UpdateServiceHostWithLastInvocationTime(DateTime lastInvocationActiveTime) { try { if (InternalSession == null) { return; } if (LogServiceCalls) { DebugLog.Message("UpdateServiceHostWithLastInvocationTime, Session: " + InternalSession.Id + ", Process: " + Process.GetCurrentProcess().Id); } InternalSession.LastFreshenDT = lastInvocationActiveTime; // send last invocation time SetSessionManagerProcessId(ServiceHostProcessId); INativeSessionManager sessionManager = NativeSessionManagerClientFactory.CreateChannel(); InternalSession session = sessionManager.FreshenNativeSession(InternalSession); ((IClientChannel)sessionManager).Close(); } catch (Exception ex) { string msgToIgnore = "There was no endpoint listening at net.pipe:"; if (Lex.Contains(ex.Message, msgToIgnore)) { return; } DebugLog.Message("Session: " + InternalSession.Id + ", Process: " + Process.GetCurrentProcess().Id + ", " + DebugLog.FormatExceptionMessage(ex)); } return; }
/// <summary> /// Rolls back the current transaction. /// </summary> public Result Rollback() { return(InternalSession.ExecuteSqlNonQuery("ROLLBACK")); }
internal BaseSession(InternalSession internalSession, Client client) { _internalSession = internalSession; Settings = internalSession.Settings; _client = client; }
/// <summary> /// Initializes a new instance of the BaseSession class based on the specified anonymous type object. /// </summary> /// <param name="connectionData">The connection data as an anonymous type used to create the session.</param> /// <exception cref="ArgumentNullException"><paramref name="connectionData"/> is null.</exception> /// <remarks> /// <para>Multiple hosts can be specified as part of the <paramref name="connectionData"/>, which enables client-side failover when trying to /// establish a connection.</para> /// <para> </para> /// <para>To assign multiple hosts, create a property similar to the connection string examples shown in /// <see cref="BaseSession(string)"/>. Note that the value of the property must be a string. /// </para> /// </remarks> internal BaseSession(object connectionData, Client client = null) : this() { if (connectionData == null) { throw new ArgumentNullException("connectionData"); } _client = client; var values = Tools.GetDictionaryFromAnonymous(connectionData); if (!values.Keys.Any(s => s.ToLowerInvariant() == PORT_CONNECTION_OPTION_KEYWORD)) { values.Add(PORT_CONNECTION_OPTION_KEYWORD, X_PROTOCOL_DEFAULT_PORT); } bool hostsParsed = false; foreach (var value in values) { if (!Settings.ContainsKey(value.Key)) { throw new KeyNotFoundException(string.Format(ResourcesX.InvalidConnectionStringAttribute, value.Key)); } Settings.SetValue(value.Key, value.Value); if (!hostsParsed && !string.IsNullOrEmpty(Settings[SERVER_CONNECTION_OPTION_KEYWORD].ToString())) { var server = value.Value.ToString(); if (IsUnixSocket(server)) { Settings.SetValue(value.Key, server = NormalizeUnixSocket(server)); } ParseHostList(server, false); if (FailoverManager.FailoverGroup != null) { Settings[SERVER_CONNECTION_OPTION_KEYWORD] = null; } hostsParsed = true; } } this._connectionString = Settings.ToString(); Settings.AnalyzeConnectionString(this._connectionString, true); if (FailoverManager.FailoverGroup != null) { // Multiple hosts were specified. _internalSession = FailoverManager.AttemptConnection(this._connectionString, out this._connectionString); Settings.ConnectionString = _connectionString; } else { _internalSession = InternalSession.GetSession(Settings); } if (!string.IsNullOrWhiteSpace(Settings.Database)) { DefaultSchema = GetSchema(Settings.Database); } }
public void BuildIndexFromGraphs(CloudTableClient cloudTableClient) { //Let the background thread claim the wait handle. ThreadPool.QueueUserWorkItem( state => { var registeredGraphs = registeredIndexer.GraphsIndexed; var session = new InternalSession(registeredIndexer.Registry, backingStore); //We use the session to manage to loading and deserialisation of graphs that contribute to the index... session .GetEntireStash() .Matching( _ => _.Where<StashTypeHierarchy>().AnyOf(registeredGraphs.Select(rg => StashTypeHierarchy.GetConcreteTypeValue(rg.GraphType)))) .Materialize(); //...but we then use the enrolled persistence events directly to yield the keys for this new index. var graphProjections = session .EnrolledPersistenceEvents .SelectMany( trackedGraph => registeredIndexer.GetUntypedProjections(trackedGraph.UntypedGraph), (graph, projection) => new {Projection = (ProjectedIndex)projection, graph.InternalId}); backingStore.InTransactionDo( work => { foreach(var projection in graphProjections) { try { Insert(projection.Projection.UntypedKey, projection.InternalId, ((AzureStorageWork)work).ServiceContext); } catch(InvalidOperationException ioEx) { var storageEx = ioEx.TranslateDataServiceClientException(); if (storageEx.ExtendedErrorInformation.ErrorCode != TableErrorCodeStrings.EntityAlreadyExists) throw storageEx; //This is acceptable, as it is possible for another session to insert the key //before we match it. We carry on. } } }); session.Abandon(); indexCompiled.Set(); }); }
/// <summary> /// Creates a schema/database with the given name. /// </summary> /// <param name="schema">The name of the schema/database.</param> /// <returns>A <see cref="Schema"/> object that matches the recently created schema/database.</returns> public Schema CreateSchema(string schema) { InternalSession.ExecuteSqlNonQuery("CREATE DATABASE `" + schema + "`"); return(new Schema(this, schema)); }
/// <summary> /// Removes the named savepoint from the set of savepoints within the current transaction. /// </summary> /// <param name="name">The name of the transaction savepoint.</param> public void ReleaseSavepoint(string name) { InternalSession.ExecuteSqlNonQuery($"RELEASE SAVEPOINT {name}"); }
/// <summary> /// Commits the current transaction. /// </summary> /// <returns>A <see cref="Result"/> object containing the results of the commit operation.</returns> public void Commit() { InternalSession.ExecuteSqlNonQuery("COMMIT"); }
/// <summary> /// Starts a new transaction. /// </summary> public void StartTransaction() { InternalSession.ExecuteSqlNonQuery("START TRANSACTION"); }
internal BufferingResult(InternalSession session) : base(session) { LoadColumnData(); PageSize = 20; _position = -1; }
/// <summary> /// Rolls back the current transaction. /// </summary> public void Rollback() { InternalSession.ExecuteSqlNonQuery("ROLLBACK"); }
internal RowResult(InternalSession session) : base(session) { }
/// <summary> /// Sets a named transaction savepoint. /// </summary> /// <param name="name">The name of the transaction savepoint.</param> /// <returns>The name of the transaction savepoint.</returns> public string SetSavepoint(string name) { InternalSession.ExecuteSqlNonQuery($"SAVEPOINT {name}"); return(name); }
public async Task Should_ContinueRoutingTrafficToNonPausedNodes_When_ANodeIsPaused(bool streamMode) { var pausedNode = TestCluster.GetNode(2); const string profileName = "running-nodes"; SetupNewSession(b => b.WithPoolingOptions( new PoolingOptions() .SetCoreConnectionsPerHost(HostDistance.Local, 1) .SetMaxConnectionsPerHost(HostDistance.Local, 1)) .WithSocketOptions( new SocketOptions() .SetReadTimeoutMillis(120000) .SetStreamMode(streamMode)) .WithExecutionProfiles(opt => opt .WithProfile(profileName, profile => profile .WithLoadBalancingPolicy( new TestDisallowListLbp( Cassandra.Policies.NewDefaultLoadBalancingPolicy("dc1")))))); var maxRequestsPerConnection = Session.Cluster.Configuration .GetOrCreatePoolingOptions(Session.Cluster.Metadata.ControlConnection.ProtocolVersion) .GetMaxRequestsPerConnection(); var tenKbBuffer = new byte[10240]; await pausedNode.PauseReadsAsync().ConfigureAwait(false); // send number of requests = max pending var requests = Enumerable.Repeat(0, maxRequestsPerConnection * Session.Cluster.AllHosts().Count) .Select(i => Session.ExecuteAsync(new SimpleStatement("INSERT INTO table1 (id) VALUES (?)", tenKbBuffer))).ToList(); try { var pools = InternalSession.GetPools().ToList(); var runningNodesPools = pools.Where(kvp => !kvp.Key.Equals(pausedNode.IpEndPoint)); var pausedNodePool = pools.Single(kvp => kvp.Key.Equals(pausedNode.IpEndPoint)); var connections = pools.SelectMany(kvp => kvp.Value.ConnectionsSnapshot).ToList(); var runningNodesConnections = runningNodesPools.SelectMany(kvp => kvp.Value.ConnectionsSnapshot).ToList(); var pausedNodeConnections = pausedNodePool.Value.ConnectionsSnapshot; await AssertRetryUntilWriteQueueStabilizesAsync(connections).ConfigureAwait(false); TestHelper.RetryAssert( () => { Assert.IsTrue(runningNodesConnections.All(c => c.InFlight == 0)); Assert.IsTrue(runningNodesConnections.All(c => c.WriteQueueLength == 0)); Assert.IsTrue(runningNodesConnections.All(c => c.PendingOperationsMapLength == 0)); }, 100, 100); Assert.IsTrue(pausedNodeConnections.All(c => c.InFlight > 0)); Assert.IsTrue(pausedNodeConnections.All(c => c.WriteQueueLength > 0)); Assert.IsTrue(pausedNodeConnections.All(c => c.PendingOperationsMapLength > 0)); var writeQueueLengths = pausedNodeConnections.Select(c => c.WriteQueueLength); Assert.AreEqual(pausedNodeConnections.Sum(c => c.InFlight), requests.Count(t => !t.IsCompleted && !t.IsFaulted)); // these should succeed because we are not hitting the paused node with the custom profile var moreRequests = Enumerable.Range(0, 100) .Select(i => Session.ExecuteAsync( new SimpleStatement("INSERT INTO table1 (id) VALUES (?)", tenKbBuffer), profileName)) .ToList(); await Task.WhenAll(moreRequests).ConfigureAwait(false); Assert.IsTrue(moreRequests.All(t => t.IsCompleted && !t.IsFaulted && !t.IsCanceled)); CollectionAssert.AreEqual(writeQueueLengths, pausedNodeConnections.Select(c => c.WriteQueueLength)); } finally { await TestCluster.ResumeReadsAsync().ConfigureAwait(false); await(await Task.WhenAny(Task.WhenAll(requests), Task.Delay(5000)).ConfigureAwait(false)).ConfigureAwait(false); Assert.IsTrue(requests.All(t => t.IsCompleted && !t.IsFaulted && !t.IsCanceled)); } }
/// <summary> /// Rolls back a transaction to the named savepoint without terminating the transaction. /// </summary> /// <param name="name">The name of the transaction savepoint.</param> public void RollbackTo(string name) { InternalSession.ExecuteSqlNonQuery($"ROLLBACK TO {name}"); }
public async Task Should_KeepOperationsInWriteQueue_When_ServerAppliesTcpBackPressure(bool streamMode) { SetupNewSession(b => b.WithPoolingOptions( new PoolingOptions() .SetCoreConnectionsPerHost(HostDistance.Local, 1) .SetMaxConnectionsPerHost(HostDistance.Local, 1)) .WithSocketOptions(new SocketOptions() .SetReadTimeoutMillis(360000) .SetStreamMode(streamMode))); var maxRequestsPerConnection = Session.Cluster.Configuration .GetOrCreatePoolingOptions(Session.Cluster.Metadata.ControlConnection.ProtocolVersion) .GetMaxRequestsPerConnection(); var tenKbBuffer = new byte[10240]; await TestCluster.PauseReadsAsync().ConfigureAwait(false); var pools = InternalSession.GetPools().ToList(); var connections = pools.SelectMany(kvp => kvp.Value.ConnectionsSnapshot).ToList(); var requests = new List <Task>(); using (var cts = new CancellationTokenSource()) { var task = Task.Run( async() => { while (!cts.IsCancellationRequested) { requests.Add(Session.ExecuteAsync(new SimpleStatement("INSERT INTO table1 (id) VALUES (?)", tenKbBuffer))); await Task.Yield(); } }, cts.Token); await AssertRetryUntilWriteQueueStabilizesAsync(connections, maxRequestsPerConnection).ConfigureAwait(false); cts.Cancel(); await task.ConfigureAwait(false); } Assert.IsTrue(connections.All(c => c.WriteQueueLength > 0)); var writeQueueSizes = connections.ToDictionary(c => c, c => c.WriteQueueLength, ReferenceEqualityComparer <IConnection> .Instance); var pendingOps = connections.ToDictionary(c => c, c => c.PendingOperationsMapLength, ReferenceEqualityComparer <IConnection> .Instance); // these should fail because we have hit max pending ops var moreRequests = Enumerable.Range(0, 100) .Select(i => Task.Run(() => Session.ExecuteAsync(new SimpleStatement("INSERT INTO table1 (id) VALUES (?)", tenKbBuffer)))) .ToList(); try { try { await(await Task.WhenAny(Task.WhenAll(moreRequests), Task.Delay(15000)).ConfigureAwait(false)).ConfigureAwait(false); Assert.Fail("Should throw exception."); } catch (NoHostAvailableException) { // ignored } var moreFailedRequests = moreRequests.Where(t => t.IsFaulted).ToList(); Assert.Greater(moreFailedRequests.Count, 1); Assert.AreEqual(moreRequests.Count, moreFailedRequests.Count); Assert.GreaterOrEqual(connections.Sum(c => c.InFlight), maxRequestsPerConnection * Session.Cluster.AllHosts().Count); // ReSharper disable once PossibleNullReferenceException Assert.IsTrue(moreFailedRequests.All(t => t.IsFaulted && ((NoHostAvailableException)t.Exception.InnerException).Errors.All(e => e.Value is BusyPoolException))); var newWriteQueueSizes = connections.ToDictionary(c => c, c => c.WriteQueueLength, ReferenceEqualityComparer <IConnection> .Instance); var newPendingsOps = connections.ToDictionary(c => c, c => c.PendingOperationsMapLength, ReferenceEqualityComparer <IConnection> .Instance); foreach (var kvp in writeQueueSizes) { Assert.GreaterOrEqual(newWriteQueueSizes[kvp.Key], kvp.Value); Assert.Greater(newWriteQueueSizes[kvp.Key], 1); } foreach (var kvp in pendingOps) { Assert.AreEqual(newPendingsOps[kvp.Key], kvp.Value); Assert.Greater(newPendingsOps[kvp.Key], 1); } } finally { await TestCluster.ResumeReadsAsync().ConfigureAwait(false); try { await(await Task.WhenAny(Task.WhenAll(requests), Task.Delay(15000)).ConfigureAwait(false)).ConfigureAwait(false); } catch (NoHostAvailableException) { } Assert.AreEqual( requests.Count, requests.Count(t => t.IsCompleted && !t.IsFaulted && !t.IsCanceled) + requests.Count(t => t.IsFaulted && ((NoHostAvailableException)t.Exception.InnerException) .Errors.All(e => e.Value is BusyPoolException))); } }
internal SqlResult(InternalSession session) : base(session) { }
public void it_should_return_itself() { var sut = new InternalSession(null, null); sut.Internalize().ShouldEqual(sut); }