/// <summary>
 /// Add mapping definition(s) for UDTs, specifying how UDTs should be mapped to .NET types and vice versa.
 /// </summary>
 /// <exception cref="ArgumentException" />
 public void Define(params UdtMap[] udtMaps)
 {
     TaskHelper.WaitToComplete(DefineAsync(udtMaps), _cluster.Configuration.DefaultRequestOptions.QueryAbortTimeout);
 }
示例#2
0
 public override Task <MaterializedViewMetadata> GetViewAsync(string keyspaceName, string viewName)
 {
     return(TaskHelper.FromException <MaterializedViewMetadata>(new NotSupportedException("Materialized views are supported in Cassandra 3.0 or above")));
 }
示例#3
0
        /// <summary>
        /// Initializes the connection.
        /// </summary>
        /// <exception cref="SocketException">Throws a SocketException when the connection could not be established with the host</exception>
        /// <exception cref="AuthenticationException" />
        /// <exception cref="UnsupportedProtocolVersionException"></exception>
        public Task<Response> Open()
        {
            _freeOperations = new ConcurrentStack<short>(Enumerable.Range(0, MaxConcurrentRequests).Select(s => (short)s).Reverse());
            _pendingOperations = new ConcurrentDictionary<short, OperationState>();
            _writeQueue = new ConcurrentQueue<OperationState>();

            if (Options.CustomCompressor != null)
            {
                Compressor = Options.CustomCompressor;
            }
            else if (Options.Compression == CompressionType.LZ4)
            {
                Compressor = new LZ4Compressor();
            }
            else if (Options.Compression == CompressionType.Snappy)
            {
                Compressor = new SnappyCompressor();
            }

            //Init TcpSocket
            _tcpSocket.Init();
            _tcpSocket.Error += CancelPending;
            _tcpSocket.Closing += () => CancelPending(null, null);
            //Read and write event handlers are going to be invoked using IO Threads
            _tcpSocket.Read += ReadHandler;
            _tcpSocket.WriteCompleted += WriteCompletedHandler;
            return _tcpSocket
                .Connect()
                .Then(_ => Startup())
                .ContinueWith(t =>
                {
                    if (t.IsFaulted && t.Exception != null)
                    {
                        //Adapt the inner exception and rethrow
                        var ex = t.Exception.InnerException;
                        if (ex is ProtocolErrorException)
                        {
                            //As we are starting up, check for protocol version errors
                            //There is no other way than checking the error message from Cassandra
                            if (ex.Message.Contains("Invalid or unsupported protocol version"))
                            {
                                throw new UnsupportedProtocolVersionException(ProtocolVersion, ex);
                            }
                        }
                        if (ex is ServerErrorException && ProtocolVersion >= 3 && ex.Message.Contains("ProtocolException: Invalid or unsupported protocol version"))
                        {
                            //For some versions of Cassandra, the error is wrapped into a server error
                            //See CASSANDRA-9451
                            throw new UnsupportedProtocolVersionException(ProtocolVersion, ex);
                        }
                        throw ex;
                    }
                    return t.Result;
                }, TaskContinuationOptions.ExecuteSynchronously)
                .Then(response =>
                {
                    if (response is AuthenticateResponse)
                    {
                        return Authenticate();
                    }
                    if (response is ReadyResponse)
                    {
                        return TaskHelper.ToTask(response);
                    }
                    throw new DriverInternalError("Expected READY or AUTHENTICATE, obtained " + response.GetType().Name);
                });
        }
示例#4
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;
 }
示例#5
0
 /// <summary>
 /// Gets the definition associated with a User Defined Type from Cassandra
 /// </summary>
 public UdtColumnInfo GetUdtDefinition(string keyspace, string typeName)
 {
     return(TaskHelper.WaitToComplete(GetUdtDefinitionAsync(keyspace, typeName), _queryAbortTimeout));
 }
示例#6
0
 /// <summary>
 /// Updates the keyspace and token information
 /// </summary>
 public bool RefreshSchema(string keyspace = null, string table = null)
 {
     return(TaskHelper.WaitToComplete(RefreshSchemaAsync(keyspace, table), Configuration.DefaultRequestOptions.QueryAbortTimeout * 2));
 }
        internal async Task <bool> Reconnect()
        {
            var tcs         = new TaskCompletionSource <bool>();
            var currentTask = Interlocked.CompareExchange(ref _reconnectTask, tcs.Task, null);

            if (currentTask != null)
            {
                // If there is another thread reconnecting, use the same task
                return(await currentTask.ConfigureAwait(false));
            }
            Unsubscribe();
            try
            {
                await Connect(false).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                // It failed to reconnect, schedule the timer for next reconnection and let go.
                Interlocked.Exchange(ref _reconnectTask, null).Forget();
                tcs.TrySetException(ex);
                var delay = _reconnectionSchedule.NextDelayMs();
                _logger.Error("ControlConnection was not able to reconnect: " + ex);
                try
                {
                    _reconnectionTimer.Change((int)delay, Timeout.Infinite);
                }
                catch (ObjectDisposedException)
                {
                    //Control connection is being disposed
                }
                // It will throw the same exception that it was set in the TCS
                throw;
            }

            if (Interlocked.Read(ref _isShutdown) > 0L)
            {
                return(false);
            }
            try
            {
                await RefreshNodeList().ConfigureAwait(false);

                TaskHelper.WaitToComplete(_metadata.RefreshKeyspaces(false), MetadataAbortTimeout);
                _reconnectionSchedule = _reconnectionPolicy.NewSchedule();
                tcs.TrySetResult(true);
                Interlocked.Exchange(ref _reconnectTask, null).Forget();
                _logger.Info("ControlConnection reconnected to host {0}", _host.Address);
            }
            catch (Exception ex)
            {
                Interlocked.Exchange(ref _reconnectTask, null).Forget();
                _logger.Error("There was an error when trying to refresh the ControlConnection", ex);
                tcs.TrySetException(ex);
                try
                {
                    _reconnectionTimer.Change((int)_reconnectionSchedule.NextDelayMs(), Timeout.Infinite);
                }
                catch (ObjectDisposedException)
                {
                    //Control connection is being disposed
                }
            }
            return(await tcs.Task.ConfigureAwait(false));
        }
 /// <summary>
 ///  Returns metadata of specified view in this keyspace.
 /// </summary>
 /// <param name="viewName">the name of view to retrieve </param>
 /// <returns>the metadata for view <c>viewName</c> in this keyspace if it
 ///  exists, <c>null</c> otherwise.</returns>
 public MaterializedViewMetadata GetMaterializedViewMetadata(string viewName)
 {
     return(TaskHelper.WaitToComplete(
                GetMaterializedViewMetadataAsync(viewName), _parent.Configuration.DefaultRequestOptions.GetQueryAbortTimeout(2)));
 }
 /// <summary>
 /// Gets a CQL aggregate by name and signature
 /// </summary>
 /// <returns>The aggregate metadata or null if not found.</returns>
 public AggregateMetadata GetAggregate(string aggregateName, string[] signature)
 {
     return(TaskHelper.WaitToComplete(
                GetAggregateAsync(aggregateName, signature), _parent.Configuration.DefaultRequestOptions.QueryAbortTimeout));
 }
示例#10
0
 /// <summary>
 /// Creates a new session on this cluster and using a keyspace an existing keyspace.
 /// </summary>
 /// <param name="keyspace">Case-sensitive keyspace name to use</param>
 public ISession Connect(string keyspace)
 {
     return(TaskHelper.WaitToComplete(ConnectAsync(keyspace)));
 }
示例#11
0
 /// <summary>
 /// Gets a CQL function by name and signature
 /// </summary>
 /// <returns>The function metadata or null if not found.</returns>
 public FunctionMetadata GetFunction(string functionName, string[] signature)
 {
     return(TaskHelper.WaitToComplete(
                GetFunctionAsync(functionName, signature), _parent.Configuration.DefaultRequestOptions.QueryAbortTimeout));
 }
示例#12
0
 /// <summary>
 /// Gets the definition of a User defined type
 /// </summary>
 internal UdtColumnInfo GetUdtDefinition(string typeName)
 {
     return(TaskHelper.WaitToComplete(GetUdtDefinitionAsync(typeName), _parent.Configuration.DefaultRequestOptions.QueryAbortTimeout));
 }
示例#13
0
 /// <summary>
 ///  Returns names of all tables defined in this keyspace.
 /// </summary>
 ///
 /// <returns>a collection of all, defined in this
 ///  keyspace tables names.</returns>
 public ICollection <string> GetTablesNames()
 {
     return(TaskHelper.WaitToComplete(_parent.SchemaParser.GetTableNamesAsync(Name)));
 }
示例#14
0
        internal Task <bool> Reconnect()
        {
            //If there is another thread reconnecting, use the same task
            var tcs         = new TaskCompletionSource <bool>();
            var currentTask = Interlocked.CompareExchange(ref _reconnectTask, tcs.Task, null);

            if (currentTask != null)
            {
                return(currentTask);
            }
            Unsubscribe();
            Connect(false).ContinueWith(t =>
            {
                if (Thread.VolatileRead(ref _isShutdown) > 0)
                {
                    if (t.Exception != null)
                    {
                        t.Exception.Handle(e => true);
                    }
                    return;
                }
                if (t.Exception != null)
                {
                    t.Exception.Handle(e => true);
                    Interlocked.Exchange(ref _reconnectTask, null);
                    tcs.TrySetException(t.Exception.InnerException);
                    var delay = _reconnectionSchedule.NextDelayMs();
                    _logger.Error("ControlConnection was not able to reconnect: " + t.Exception.InnerException);
                    try
                    {
                        _reconnectionTimer.Change(delay, Timeout.Infinite);
                    }
                    catch (ObjectDisposedException)
                    {
                        //Control connection is being disposed
                    }
                    return;
                }
                try
                {
                    RefreshNodeList();
                    TaskHelper.WaitToComplete(_metadata.RefreshKeyspaces(false), MetadataAbortTimeout);
                    _reconnectionSchedule = _reconnectionPolicy.NewSchedule();
                    tcs.TrySetResult(true);
                    Interlocked.Exchange(ref _reconnectTask, null);
                    _logger.Info("ControlConnection reconnected to host {0}", _host.Address);
                }
                catch (Exception ex)
                {
                    Interlocked.Exchange(ref _reconnectTask, null);
                    _logger.Error("There was an error when trying to refresh the ControlConnection", ex);
                    tcs.TrySetException(ex);
                    try
                    {
                        _reconnectionTimer.Change(_reconnectionSchedule.NextDelayMs(), Timeout.Infinite);
                    }
                    catch (ObjectDisposedException)
                    {
                        //Control connection is being disposed
                    }
                }
            });
            return(tcs.Task);
        }
示例#15
0
 /// <summary>
 ///  Returns TableMetadata for specified table in specified keyspace.
 /// </summary>
 /// <param name="keyspace">name of the keyspace within specified table is defined.</param>
 /// <param name="tableName">name of table for which metadata should be returned.</param>
 /// <returns>a TableMetadata for the specified table in the specified keyspace.</returns>
 public TableMetadata GetTable(string keyspace, string tableName)
 {
     return(TaskHelper.WaitToComplete(GetTableAsync(keyspace, tableName), _queryAbortTimeout * 2));
 }
示例#16
0
 /// <summary>
 /// Uses the active connection to execute a query
 /// </summary>
 public IEnumerable <Row> Query(string cqlQuery, bool retry = false)
 {
     return(TaskHelper.WaitToComplete(QueryAsync(cqlQuery, retry), MetadataAbortTimeout));
 }
示例#17
0
 /// <summary>
 ///  Returns metadata of specified table in this keyspace.
 /// </summary>
 /// <param name="tableName"> the name of table to retrieve </param>
 /// <returns>the metadata for table <c>tableName</c> in this keyspace if it
 ///  exists, <c>null</c> otherwise.</returns>
 public TableMetadata GetTableMetadata(string tableName)
 {
     return(TaskHelper.WaitToComplete(
                GetTableMetadataAsync(tableName), _parent.Configuration.DefaultRequestOptions.GetQueryAbortTimeout(2)));
 }