/// <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); }
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"))); }
/// <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); }); }
/// <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; }
/// <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)); }
/// <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)); }
/// <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))); }
/// <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)); }
/// <summary> /// Gets the definition of a User defined type /// </summary> internal UdtColumnInfo GetUdtDefinition(string typeName) { return(TaskHelper.WaitToComplete(GetUdtDefinitionAsync(typeName), _parent.Configuration.DefaultRequestOptions.QueryAbortTimeout)); }
/// <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))); }
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); }
/// <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)); }
/// <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)); }
/// <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))); }