/// <summary>
 /// Waits until that the schema version in all nodes is the same or the waiting time passed.
 /// This method blocks the calling thread.
 /// </summary>
 internal void WaitForSchemaAgreement(Connection connection)
 {
     if (Hosts.Count == 1)
     {
         //If there is just one node, the schema is up to date in all nodes :)
         return;
     }
     var start = DateTime.Now;
     var waitSeconds = _config.ProtocolOptions.MaxSchemaAgreementWaitSeconds;
     Logger.Info("Waiting for schema agreement");
     try
     {
         var totalVersions = 0;
         while (DateTime.Now.Subtract(start).TotalSeconds < waitSeconds)
         {
             var schemaVersionLocalQuery = new QueryRequest(connection.ProtocolVersion, SelectSchemaVersionLocal, false, QueryProtocolOptions.Default);
             var schemaVersionPeersQuery = new QueryRequest(connection.ProtocolVersion, SelectSchemaVersionPeers, false, QueryProtocolOptions.Default);
             var queries = new [] { connection.Send(schemaVersionLocalQuery), connection.Send(schemaVersionPeersQuery) };
             // ReSharper disable once CoVariantArrayConversion
             Task.WaitAll(queries, _config.ClientOptions.QueryAbortTimeout);
             var versions = new HashSet<Guid>
             {
                 ControlConnection.GetRowSet(queries[0].Result).First().GetValue<Guid>("schema_version")
             };
             var peerVersions = ControlConnection.GetRowSet(queries[1].Result).Select(r => r.GetValue<Guid>("schema_version"));
             foreach (var v in peerVersions)
             {
                 versions.Add(v);
             }
             totalVersions = versions.Count;
             if (versions.Count == 1)
             {
                 return;
             }
             Thread.Sleep(500);
         }
         Logger.Info(String.Format("Waited for schema agreement, still {0} schema versions in the cluster.", totalVersions));
     }
     catch (Exception ex)
     {
         //Exceptions are not fatal
         Logger.Error("There was an exception while trying to retrieve schema versions", ex);
     }
 }
        /// <summary>
        /// Sets the keyspace of the connection.
        /// If the keyspace is different from the current value, it sends a Query request to change it
        /// </summary>
        public Task <bool> SetKeyspace(string value)
        {
            if (String.IsNullOrEmpty(value) || _keyspace == value)
            {
                //No need to switch
                return(TaskHelper.Completed);
            }
            Task <bool> keyspaceSwitch;

            try
            {
                if (!_keyspaceSwitchSemaphore.Wait(0))
                {
                    //Could not enter semaphore
                    //It is very likely that the connection is already switching keyspace
                    keyspaceSwitch = _keyspaceSwitchTask;
                    if (keyspaceSwitch != null)
                    {
                        return(keyspaceSwitch.Then(_ =>
                        {
                            //validate if the new keyspace is the expected
                            if (_keyspace != value)
                            {
                                //multiple concurrent switches to different keyspace
                                return SetKeyspace(value);
                            }
                            return TaskHelper.Completed;
                        }));
                    }
                    _keyspaceSwitchSemaphore.Wait();
                }
            }
            catch (ObjectDisposedException)
            {
                //The semaphore was disposed, this connection is closed
                return(TaskHelper.FromException <bool>(new SocketException((int)SocketError.NotConnected)));
            }
            //Semaphore entered
            if (_keyspace == value)
            {
                //While waiting to enter the semaphore, the connection switched keyspace
                try
                {
                    _keyspaceSwitchSemaphore.Release();
                }
                catch (ObjectDisposedException)
                {
                    //this connection is now closed but the switch completed successfully
                }
                return(TaskHelper.Completed);
            }
            var request = new QueryRequest(_serializer.ProtocolVersion, string.Format("USE \"{0}\"", value), false, QueryProtocolOptions.Default);

            Logger.Info("Connection to host {0} switching to keyspace {1}", Address, value);
            keyspaceSwitch = _keyspaceSwitchTask = Send(request).ContinueSync(r =>
            {
                _keyspace = value;
                try
                {
                    _keyspaceSwitchSemaphore.Release();
                }
                catch (ObjectDisposedException)
                {
                    //this connection is now closed but the switch completed successfully
                }
                _keyspaceSwitchTask = null;
                return(true);
            });
            return(keyspaceSwitch);
        }
 private RowSet Query(string cqlQuery)
 {
     var request = new QueryRequest(ControlConnectionProtocolVersion, cqlQuery, false, QueryProtocolOptions.Default);
     var task = _activeConnection.Value.Send(request);
     TaskHelper.WaitToComplete(task, 10000);
     if (!(task.Result is ResultResponse) && !(((ResultResponse)task.Result).Output is OutputRows))
     {
         throw new DriverInternalError("Expected rows " + task.Result);
     }
     return ((task.Result as ResultResponse).Output as OutputRows).RowSet;
 }
 /// <summary>
 /// Uses the active connection to execute a query
 /// </summary>
 public RowSet Query(string cqlQuery, bool retry = false)
 {
     var request = new QueryRequest(ProtocolVersion, cqlQuery, false, QueryProtocolOptions.Default);
     var task = _connection.Send(request);
     try
     {
         TaskHelper.WaitToComplete(task, 10000);
     }
     catch (SocketException ex)
     {
         const string message = "There was an error while executing on the host {0} the query '{1}'";
         _logger.Error(String.Format(message, cqlQuery, _connection.Address), ex);
         if (retry)
         {
             //Try to connect to another host
             Refresh(reconnect:true, throwExceptions:true);
             //Try to execute again without retry
             return Query(cqlQuery, false);
         }
         throw;
     }
     return GetRowSet(task.Result);
 }
Example #5
0
 /// <summary>
 /// Gets the Request to send to a cassandra node based on the statement type
 /// </summary>
 internal IRequest GetRequest(IStatement statement)
 {
     ICqlRequest request = null;
     if (statement is RegularStatement)
     {
         var s = (RegularStatement)statement;
         s.ProtocolVersion = BinaryProtocolVersion;
         var options = QueryProtocolOptions.CreateFromQuery(s, Configuration.QueryOptions);
         options.ValueNames = s.QueryValueNames;
         request = new QueryRequest(BinaryProtocolVersion, s.QueryString, s.IsTracing, options);
     }
     if (statement is BoundStatement)
     {
         var s = (BoundStatement)statement;
         var options = QueryProtocolOptions.CreateFromQuery(s, Configuration.QueryOptions);
         request = new ExecuteRequest(BinaryProtocolVersion, s.PreparedStatement.Id, null, s.IsTracing, options);
     }
     if (statement is BatchStatement)
     {
         var s = (BatchStatement)statement;
         s.ProtocolVersion = BinaryProtocolVersion;
         var consistency = Configuration.QueryOptions.GetConsistencyLevel();
         if (s.ConsistencyLevel != null)
         {
             consistency = s.ConsistencyLevel.Value;
         }
         request = new BatchRequest(BinaryProtocolVersion, s, consistency);
     }
     if (request == null)
     {
         throw new NotSupportedException("Statement of type " + statement.GetType().FullName + " not supported");   
     }
     //Set the outgoing payload for the request
     request.Payload = statement.OutgoingPayload;
     return request;
 }
Example #6
0
 /// <summary>
 /// Sets the keyspace of the connection.
 /// If the keyspace is different from the current value, it sends a Query request to change it
 /// </summary>
 public Task<bool> SetKeyspace(string value)
 {
     if (String.IsNullOrEmpty(value) || _keyspace == value)
     {
         //No need to switch
         return TaskHelper.Completed;
     }
     Task<bool> keyspaceSwitch;
     try
     {
         if (!_keyspaceSwitchSemaphore.Wait(0))
         {
             //Could not enter semaphore
             //It is very likely that the connection is already switching keyspace
             keyspaceSwitch = _keyspaceSwitchTask;
             if (keyspaceSwitch != null)
             {
                 return keyspaceSwitch.Then(_ =>
                 {
                     //validate if the new keyspace is the expected
                     if (_keyspace != value)
                     {
                         //multiple concurrent switches to different keyspace
                         return SetKeyspace(value);
                     }
                     return TaskHelper.Completed;
                 });
             }
             _keyspaceSwitchSemaphore.Wait();
         }
     }
     catch (ObjectDisposedException)
     {
         //The semaphore was disposed, this connection is closed
         return TaskHelper.FromException<bool>(new SocketException((int) SocketError.NotConnected));
     }
     //Semaphore entered
     if (_keyspace == value)
     {
         //While waiting to enter the semaphore, the connection switched keyspace
         try
         {
             _keyspaceSwitchSemaphore.Release();
         }
         catch (ObjectDisposedException)
         {
             //this connection is now closed but the switch completed successfully
         }
         return TaskHelper.Completed;
     }
     var request = new QueryRequest(ProtocolVersion, string.Format("USE \"{0}\"", value), false, QueryProtocolOptions.Default);
     _logger.Info("Connection to host {0} switching to keyspace {1}", Address, value);
     keyspaceSwitch = _keyspaceSwitchTask = Send(request).ContinueSync(r =>
     {
         _keyspace = value;
         try
         {
             _keyspaceSwitchSemaphore.Release();
         }
         catch (ObjectDisposedException)
         {
             //this connection is now closed but the switch completed successfully
         }
         _keyspaceSwitchTask = null;
         return true;
     });
     return keyspaceSwitch;
 }
Example #7
0
 /// <summary>
 /// Gets executed once the idle timeout has passed
 /// </summary>
 private void IdleTimeoutHandler(object state)
 {
     //Ensure there are no more idle timeouts until the query finished sending
     if (_isCanceled)
     {
         if (!IsDisposed)
         {
             //If it was not manually disposed
             _logger.Warning("Can not issue an heartbeat request as connection is closed");
             if (OnIdleRequestException != null)
             {
                 OnIdleRequestException(new SocketException((int)SocketError.NotConnected));
             }
         }
         return;
     }
     _logger.Verbose("Connection idling, issuing a Request to prevent idle disconnects");
     var request = new QueryRequest(ProtocolVersion, IdleQuery, false, QueryProtocolOptions.Default);
     Send(request, (ex, response) =>
     {
         if (ex == null)
         {
             //The send succeeded
             //There is a valid response but we don't care about the response
             return;
         }
         _logger.Warning("Received heartbeat request exception " + ex.ToString());
         if (ex is SocketException && OnIdleRequestException != null)
         {
             OnIdleRequestException(ex);
         }
     });
 }