/// <summary> /// 连接容器内部方法,子类可以重写此方法。 /// <para>*此方法主要用于确保在使用指定算法获取容器中连接之前,连接容器内部拥有足够多的连接</para> /// <para>*具体策略为优先保证在同步执行代码的情况下,当前连接容器中最少有一个存活的连接,至于剩下的连接需要异步进行创建</para> /// </summary> protected virtual bool MakeSureConnections() { if (_connections.Count >= _min || _connections.Count == 1) { return(true); } lock (_lockObj) { try { IThriftConnectionAgent agent = _createFunc(_tuple.Item1, _tuple.Item2, _tuple.Item3); //如果当前时间点无法正常创建一个连接代理器,则放弃此次同步机会并改为异步进行 if (agent == null || !agent.GetChannel().IsConnected) { return(false); } Register(agent); return(true); } catch (Exception ex) { _tracing.Error(ex, null); return(false); } finally { if (_connections.Count < _min && Interlocked.CompareExchange(ref _usedBackendThread, 1, 0) == 0) { CreateAgentAsync(); } } } }
/// <summary> /// 创建一个HBase表 /// </summary> /// <param name="tableName">表名</param> /// <param name="descriptors">表描述符</param> /// <returns>如果创建成功,则返回可以操作该表的实例</returns> /// <exception cref="AlreadyExistsException">表已经存在</exception> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="IllegalArgumentException">参数错误</exception> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> /// <exception cref="NoConnectionException">内部无任何可用的远程连接异常,这通常代表无法连接到任何一台远程服务器</exception> public IHTable CreateTable(string tableName, params ColumnDescriptor[] descriptors) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } if (descriptors == null || descriptors.Length == 0) { throw new ArgumentNullException("descriptors"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(_regionServers[0], "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { CreateTableResponseMessage rspMsg = (CreateTableResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } else if (rspMsg.IllegalArgumentErrorMessage != null) { ex = new IllegalArgumentException(rspMsg.IllegalArgumentErrorMessage.Reason); } else if (rspMsg.AlreadyExistsErrorMessage != null) { ex = new AlreadyExistsException(rspMsg.AlreadyExistsErrorMessage.Reason); } autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; CreateTableRequestMessage reqMsg = new CreateTableRequestMessage { TableName = tableName, ColumnFamilies = descriptors }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(new HTable(reqMsg.TableName, this, _hostMappingManager)); }
//agent disconnect event handler. private void ServerAgentDisconnected(object sender, EventArgs e) { IThriftConnectionAgent agent = (IThriftConnectionAgent)sender; agent.Disconnected -= ServerAgentDisconnected; lock (_lockObj) _connections.Remove(agent); AgentDisconnectedHandler(new LightSingleArgEventArgs <IThriftConnectionAgent>(agent)); }
/// <summary> /// 按rowkey上下限获取scannerId /// </summary> /// <param name="tableName">表名</param> /// <param name="startKey">rowkey范围上界(结果中包含上界数据)</param> /// <param name="endKey">rowkey范围下界(结果中不包含下界数据)</param> /// <param name="iep">对应的Region的服务器地址</param> /// <param name="columns">指定获取的列名</param> /// <param name="attribute">attribute</param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> /// <returns>scannerId</returns> internal int GetScannerOpenWithStop(string tableName, byte[] startKey, byte[] endKey, IPEndPoint iep, string[] columns, Dictionary <string, string> attribute = null) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } if (startKey == null || startKey.Length == 0) { throw new ArgumentNullException("startKey"); } if (endKey == null || endKey.Length == 0) { throw new ArgumentNullException("endKey"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; int result = -1; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { ScannerOpenWithStopResponseMessage rspMsg = (ScannerOpenWithStopResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } result = rspMsg.ScannerId; autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; ScannerOpenWithStopRequestMessage reqMsg = new ScannerOpenWithStopRequestMessage { TableName = tableName, StartRow = startKey, EndRow = endKey, Columns = columns, Attribute = attribute }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(result); }
/// <summary> /// Get a single row for the specified table, rowkey, and column at the latest timestamp /// </summary> /// <param name="tableName">table name</param> /// <param name="rowKey">rowkey</param> /// <param name="iep">a network endpoint as an IP address and a port number</param> /// <param name="columns">column name</param> /// <param name="attributes">attributes</param> /// <exception cref="IOErrorException"></exception> /// <exception cref="ArgumentNullException"></exception> /// <exception cref="CommunicationTimeoutException"></exception> /// <exception cref="CommunicationFailException"></exception> /// <returns>查询结果</returns> internal RowInfo[] GetRowWithColumnsFromTable(string tableName, byte[] rowKey, string[] columns, IPEndPoint iep, Dictionary <string, string> attributes = null) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } if (rowKey == null || rowKey.Length == 0) { throw new ArgumentNullException("rowKey"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } RowInfo[] result = { }; Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { GetRowWithColumnsResponseMessage rspMsg = (GetRowWithColumnsResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } result = rspMsg.RowInfos; autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; GetRowWithColumnsRequestMessage reqMsg = new GetRowWithColumnsRequestMessage { TableName = tableName, RowKey = rowKey, Columns = columns, Attributes = new Dictionary <string, string>() }; if (attributes != null) { reqMsg.Attributes = attributes; } transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(result); }
/// <summary> /// 原子计数器递增 /// </summary> /// <param name="tableName">表名</param> /// <param name="rowKey">rowKey</param> /// <param name="column">列名</param> /// <param name="iep">对应的Region的服务器地址</param> /// <param name="value">递增值</param> /// <returns>递增后的结果</returns> internal long AtomicIncrement(string tableName, byte[] rowKey, string column, IPEndPoint iep, long @value = 1) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; long result = 0; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { AtomicIncrementResponseMessage rspMsg = (AtomicIncrementResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } else if (rspMsg.IllegalArgumentErrorMessage != null) { ex = new IOErrorException(rspMsg.IllegalArgumentErrorMessage.Reason); } result = rspMsg.Success; autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; AtomicIncrementRequestMessage reqMsg = new AtomicIncrementRequestMessage { TableName = tableName, RowKey = rowKey, Column = column, Value = @value }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(result); }
/// <summary> /// 获取一个HBase表在整体集群中的位置分布 /// </summary> /// <param name="tableName">表名</param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> internal Region[] GetTableRegions(string tableName) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(_regionServers[0], "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; Region[] result = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { GetTableRegionsResponseMessage rspMsg = (GetTableRegionsResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } result = rspMsg.Regions; autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; GetTableRegionsRequestMessage reqMsg = new GetTableRegionsRequestMessage { TableName = tableName }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(result); }
/// <summary> /// 回收指定scanner资源 /// </summary> /// <param name="scannerId">scannerId</param> /// <param name="iep">对应的Region的服务器地址</param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> internal void ScannerClose(int scannerId, IPEndPoint iep) { IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { ScannerCloseResponseMessage rspMsg = (ScannerCloseResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } else if (rspMsg.IllegalArgumentErrorMessage != null) { ex = new IllegalArgumentException(rspMsg.IllegalArgumentErrorMessage.Reason); } autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; ScannerCloseRequestMessage reqMsg = new ScannerCloseRequestMessage { ScannerId = scannerId }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } }
/// <summary> /// 向当前的连接容器中注册一个存活的连接 /// </summary> /// <param name="agent"></param> public virtual void Register(IThriftConnectionAgent agent) { if (agent == null) { return; } if (!agent.GetChannel().IsConnected) { AgentDisconnectedHandler(new LightSingleArgEventArgs <IThriftConnectionAgent>(agent)); return; } agent.Disconnected += ServerAgentDisconnected; lock (_lockObj) _connections.Add(agent); }
/// <summary> /// 插入多行数据 /// </summary> /// <param name="tableName">表名</param> /// <param name="iep">对应的Region的服务器地址</param> /// <param name="batchMutation">列数据集合</param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="ArgumentNullException">参数不能为空</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> /// <returns>是否成功插入</returns> internal bool BatchInsert(string tableName, IPEndPoint iep, BatchMutation[] batchMutation) { if (batchMutation == null) { throw new ArgumentNullException("batchMutation"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { InsertNewRowsResponseMessage rspMsg = (InsertNewRowsResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; InsertNewRowsRequestMessage reqMsg = new InsertNewRowsRequestMessage { TableName = tableName, RowBatch = batchMutation, Attributes = new Dictionary <string, string>() }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(true); }
/// <summary> /// 从指定的scanner获取数据 /// </summary> /// <param name="id">scanner序列号</param> /// <param name="rowCount">查询行数量</param> /// <param name="iep">对应的Region的服务器地址</param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> internal RowInfo[] GetRowsFromScanner(int id, int rowCount, IPEndPoint iep) { IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } RowInfo[] result = { }; Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { ScannerGetListResponseMessage rspMsg = (ScannerGetListResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } result = rspMsg.RowInfos; autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; ScannerGetListRequestMessage reqMsg = new ScannerGetListRequestMessage { Id = id, RowsCount = rowCount }; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(result); }
/// <summary> /// 获取HBase中所有的表名信息 /// </summary> /// <returns>返回所有的表名</returns> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> public List <string> GetTableNames() { IThriftConnectionAgent agent = _connectionPool.GetChannel(_regionServers[0], "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); List <string> tables = null; transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { GetTableNamesResponseMessage rspMsg = (GetTableNamesResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } tables = (rspMsg.Tables == null ? new List <string>() : new List <string>(rspMsg.Tables)); autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; GetTableNamesRequestMessage reqMsg = new GetTableNamesRequestMessage(); transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(tables); }
/// <summary> /// 使用后台线程的方式异步地创建连接代理器 /// </summary> private void CreateAgentAsync() { if (_backendThread != null) { return; } _backendThread = new Thread(delegate() { int retryCount = 0; while (_connections.Count < _min) { try { IThriftConnectionAgent agent = _createFunc(_tuple.Item1, _tuple.Item2, _tuple.Item3); //如果当前时间点无法正常创建一个连接代理器,则默认行为是重试3次 if (agent == null || !agent.GetChannel().IsConnected) { if (retryCount < 3) { retryCount++; continue; } Interlocked.Exchange(ref _usedBackendThread, 0); _backendThread = null; break; } //reset retry counter. retryCount = 0; Register(agent); } catch (Exception ex) { _tracing.Error(ex, null); } Interlocked.Exchange(ref _usedBackendThread, 0); _backendThread = null; } }) { IsBackground = true, Name = "ConnectionSet-Backend-Thread", Priority = ThreadPriority.BelowNormal }; _backendThread.Start(); }
/// <summary> /// 插入一行数据 /// </summary> /// <param name="tableName">表名</param> /// <param name="rowkey">行键</param> /// <param name="iep">对应的Region的服务器地址</param> /// <param name="mutations">列信息</param> /// <param name="attributes"></param> /// <exception cref="IOErrorException">IO错误</exception> /// <exception cref="IllegalArgumentException">参数错误</exception> /// <exception cref="CommunicationTimeoutException">通信超时</exception> /// <exception cref="CommunicationFailException">通信失败</exception> /// <returns></returns> internal bool InsertRow(string tableName, byte[] rowkey, IPEndPoint iep, Mutation[] mutations, Dictionary <string, string> attributes = null) { if (string.IsNullOrEmpty(tableName)) { throw new ArgumentNullException("tableName"); } if (rowkey == null || rowkey.Length == 0) { throw new ArgumentNullException("rowkey"); } if (mutations == null || mutations.Length == 0) { throw new ArgumentNullException("mutations"); } IThriftConnectionAgent agent = _connectionPool.GetChannel(iep, "RegionServer", _protocolStack, _transactionManager); if (agent == null) { throw new NoConnectionException(); } Exception ex = null; ThriftMessageTransaction transaction = agent.CreateTransaction(); AutoResetEvent autoResetEvent = new AutoResetEvent(false); transaction.ResponseArrived += delegate(object sender, LightSingleArgEventArgs <ThriftMessage> e) { InsertNewRowResponseMessage rspMsg = (InsertNewRowResponseMessage)e.Target; if (rspMsg.IOErrorMessage != null) { ex = new IOErrorException(rspMsg.IOErrorMessage.Reason); } else if (rspMsg.IllegalArgumentErrorMessage != null) { ex = new IllegalArgumentException(rspMsg.IllegalArgumentErrorMessage.Reason); } autoResetEvent.Set(); }; transaction.Timeout += delegate { ex = new CommunicationTimeoutException(transaction.SequenceId); autoResetEvent.Set(); }; transaction.Failed += delegate { ex = new CommunicationFailException(transaction.SequenceId); autoResetEvent.Set(); }; InsertNewRowRequestMessage reqMsg = new InsertNewRowRequestMessage { TableName = tableName, RowKey = rowkey }; reqMsg.Mutations = mutations; reqMsg.Attributes = attributes; transaction.SendRequest(reqMsg); autoResetEvent.WaitOne(); if (ex != null) { throw ex; } return(true); }