From 0829c819b0442cca0fa6ba28673dc35be4d6af3c Mon Sep 17 00:00:00 2001 From: Yiqing Liu Date: Fri, 11 Sep 2020 15:49:32 +0800 Subject: [PATCH 01/10] Update faq-ch.md --- documentation20/webdocs/markdowndocs/faq-ch.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/faq-ch.md b/documentation20/webdocs/markdowndocs/faq-ch.md index e4bb920dd3..7bbf7531c8 100644 --- a/documentation20/webdocs/markdowndocs/faq-ch.md +++ b/documentation20/webdocs/markdowndocs/faq-ch.md @@ -32,7 +32,7 @@ 3. 在服务器,执行 `systemctl status taosd` 检查*taosd*运行状态。如果没有运行,启动*taosd* -4. 确认客户端连接时指定了正确的服务器FQDN (Fully Qualified Domain Name(可在服务器上执行Linux命令hostname -f获得) +4. 确认客户端连接时指定了正确的服务器FQDN (Fully Qualified Domain Name(可在服务器上执行Linux命令hostname -f获得)),FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 5. ping服务器FQDN,如果没有反应,请检查你的网络,DNS设置,或客户端所在计算机的系统hosts文件 @@ -54,7 +54,7 @@ ## 6. 遇到错误“Unexpected generic error in RPC”或者"TDengine Error: Unable to resolve FQDN", 我怎么办? 产生这个错误,是由于客户端或数据节点无法解析FQDN(Fully Qualified Domain Name)导致。对于TAOS Shell或客户端应用,请做如下检查: -1. 请检查连接的服务器的FQDN是否正确 +1. 请检查连接的服务器的FQDN是否正确,FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 2. 如果网络配置有DNS server, 请检查是否正常工作 3. 如果网络没有配置DNS server, 请检查客户端所在机器的hosts文件,查看该FQDN是否配置,并是否有正确的IP地址。 4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法链接服务器的 From 356cfbaf9be4af263a0620056deeaa1179be6a2b Mon Sep 17 00:00:00 2001 From: Yiqing Liu Date: Fri, 11 Sep 2020 16:11:47 +0800 Subject: [PATCH 02/10] Update cluster-ch.md --- documentation20/webdocs/markdowndocs/cluster-ch.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md index 097433a18a..961d7d36c9 100644 --- a/documentation20/webdocs/markdowndocs/cluster-ch.md +++ b/documentation20/webdocs/markdowndocs/cluster-ch.md @@ -2,7 +2,7 @@ 多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。而且在安装集群之前,请按照[《立即开始》](https://www.taosdata.com/cn/getting-started20/)一章安装并体验过单节点功能。 -集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令`hostname -f`获取。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。一个节点可能配置了多个hostname, TDengine会自动获取第一个,但也可以通过taos.cfg里配置参数fqdn进行指定。如果习惯IP地址直接访问,可以将参数fqdn设置为本节点的IP地址。 +集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令`hostname -f`获取,FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。一个节点可能配置了多个hostname, TDengine会自动获取第一个,但也可以通过taos.cfg里配置参数fqdn进行指定。如果习惯IP地址直接访问,可以将参数fqdn设置为本节点的IP地址。 TDengine的集群管理极其简单,除添加和删除节点需要人工干预之外,其他全部是自动完成,最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。 From 19e51adb7080b15e8eb3c41df9cefbfe0f4621e0 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Fri, 11 Sep 2020 08:49:05 +0000 Subject: [PATCH 03/10] TD-1272 fix unaddressable errors --- src/client/src/tscServer.c | 4 ++++ src/vnode/src/vnodeRead.c | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index ae2013cd2b..c9fe5fbd2c 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -2090,6 +2090,10 @@ int tscProcessRetrieveRspFromNode(SSqlObj *pSql) { SSqlCmd *pCmd = &pSql->cmd; SRetrieveTableRsp *pRetrieve = (SRetrieveTableRsp *)pRes->pRsp; + if (pRetrieve == NULL) { + pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY; + return pRes->code; + } pRes->numOfRows = htonl(pRetrieve->numOfRows); pRes->precision = htons(pRetrieve->precision); diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index 11315f5321..017eeaf426 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -93,11 +93,12 @@ static int32_t vnodeDumpQueryResult(SRspRet *pRet, void* pVnode, void** handle, vDebug("QInfo:%p exec completed, free handle:%d", *handle, *freeHandle); } } else { - SRetrieveTableRsp* pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + SRetrieveTableRsp *pRsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); memset(pRsp, 0, sizeof(SRetrieveTableRsp)); pRsp->completed = true; pRet->rsp = pRsp; + pRet->len = sizeof(SRetrieveTableRsp); *freeHandle = true; } @@ -270,6 +271,7 @@ static int32_t vnodeProcessFetchMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { if (code != TSDB_CODE_SUCCESS) { //TODO handle malloc failure pRet->rsp = (SRetrieveTableRsp *)rpcMallocCont(sizeof(SRetrieveTableRsp)); + pRet->len = sizeof(SRetrieveTableRsp); memset(pRet->rsp, 0, sizeof(SRetrieveTableRsp)); freeHandle = true; } else { // result is not ready, return immediately From 541f85a2bacf771981d17146c4dcec51b95a4274 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Fri, 11 Sep 2020 18:17:47 +0800 Subject: [PATCH 04/10] pump up alert version number --- alert/cmd/alert/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alert/cmd/alert/main.go b/alert/cmd/alert/main.go index f934a11d42..f4c30e156a 100644 --- a/alert/cmd/alert/main.go +++ b/alert/cmd/alert/main.go @@ -119,7 +119,7 @@ WantedBy=multi-user.target return nil } -const version = "TDengine alert v2.0.0.0" +const version = "TDengine alert v2.0.0.1" func main() { var ( From 3a38cd8b00e67a920ea6860578069f84323e9338 Mon Sep 17 00:00:00 2001 From: Xiaowei Su <46439638+Shawshank-Smile@users.noreply.github.com> Date: Fri, 11 Sep 2020 18:56:10 +0800 Subject: [PATCH 05/10] Update cluster-ch.md --- documentation20/webdocs/markdowndocs/cluster-ch.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md index 961d7d36c9..a782899ef9 100644 --- a/documentation20/webdocs/markdowndocs/cluster-ch.md +++ b/documentation20/webdocs/markdowndocs/cluster-ch.md @@ -9,6 +9,8 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预 ## 准备工作 **第一步**:如果搭建集群的节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html ) + **注意1:**:因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taosd) + **注意2:**:客户端也需要配置FQDN,并且把集群中所有服务器的FQDN配置到客户端中。请RESTful之外的客户端使用者,一定配置一下。 **第二步**:建议关闭防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口; From 64188561c38ad65dd50b63c431341341b0f4203d Mon Sep 17 00:00:00 2001 From: Xiaowei Su <46439638+Shawshank-Smile@users.noreply.github.com> Date: Fri, 11 Sep 2020 19:23:01 +0800 Subject: [PATCH 06/10] Update cluster-ch.md --- documentation20/webdocs/markdowndocs/cluster-ch.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md index a782899ef9..fa9e7e69f1 100644 --- a/documentation20/webdocs/markdowndocs/cluster-ch.md +++ b/documentation20/webdocs/markdowndocs/cluster-ch.md @@ -9,8 +9,8 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预 ## 准备工作 **第一步**:如果搭建集群的节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html ) - **注意1:**:因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taosd) - **注意2:**:客户端也需要配置FQDN,并且把集群中所有服务器的FQDN配置到客户端中。请RESTful之外的客户端使用者,一定配置一下。 +**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/) +**注意2:**客户端也需要配置,并且把集群中所有服务器的FQDN配置到客户端中(windows中 C:\Windows\System32\drivers\etc\hosts)。 **第二步**:建议关闭防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口; From 772f5b577eca2df4c3e139862183a911b4f22b49 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 11 Sep 2020 19:24:46 +0800 Subject: [PATCH 07/10] TD-1284 mnode illegal pointer operation --- src/mnode/src/mnodeSdb.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index 60f1e8e80b..3611f15032 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -65,6 +65,7 @@ typedef struct _SSdbTable { int32_t (*encodeFp)(SSdbOper *pOper); int32_t (*destroyFp)(SSdbOper *pOper); int32_t (*restoredFp)(); + pthread_mutex_t mutex; } SSdbTable; typedef struct { @@ -447,6 +448,7 @@ void sdbDecRef(void *handle, void *pObj) { } static void *sdbGetRowMeta(SSdbTable *pTable, void *key) { + void *pRet = NULL; if (pTable == NULL) return NULL; int32_t keySize = sizeof(int32_t); @@ -454,9 +456,12 @@ static void *sdbGetRowMeta(SSdbTable *pTable, void *key) { keySize = strlen((char *)key); } + pthread_mutex_lock(&pTable->mutex); void **ppRow = (void **)taosHashGet(pTable->iHandle, key, keySize); - if (ppRow == NULL) return NULL; - return *ppRow; + if (ppRow != NULL) pRet = *ppRow; + pthread_mutex_unlock(&pTable->mutex); + + return pRet; } static void *sdbGetRowMetaFromObj(SSdbTable *pTable, void *key) { @@ -467,10 +472,9 @@ void *sdbGetRow(void *handle, void *key) { void *pRow = sdbGetRowMeta(handle, key); if (pRow) { sdbIncRef(handle, pRow); - return pRow; - } else { - return NULL; } + + return pRow; } static void *sdbGetRowFromObj(SSdbTable *pTable, void *key) { @@ -485,7 +489,9 @@ static int32_t sdbInsertHash(SSdbTable *pTable, SSdbOper *pOper) { keySize = strlen((char *)key); } + pthread_mutex_lock(&pTable->mutex); taosHashPut(pTable->iHandle, key, keySize, &pOper->pObj, sizeof(int64_t)); + pthread_mutex_unlock(&pTable->mutex); sdbIncRef(pTable, pOper->pObj); atomic_add_fetch_32(&pTable->numOfRows, 1); @@ -526,7 +532,10 @@ static int32_t sdbDeleteHash(SSdbTable *pTable, SSdbOper *pOper) { keySize = strlen((char *)key); } + pthread_mutex_lock(&pTable->mutex); taosHashRemove(pTable->iHandle, key, keySize); + pthread_mutex_unlock(&pTable->mutex); + atomic_sub_fetch_32(&pTable->numOfRows, 1); sdbDebug("table:%s, delete record:%s from hash, numOfRows:%" PRId64 ", msg:%p", pTable->tableName, @@ -868,6 +877,7 @@ void *sdbOpenTable(SSdbTableDesc *pDesc) { if (pTable == NULL) return NULL; + pthread_mutex_init(&pTable->mutex, NULL); tstrncpy(pTable->tableName, pDesc->tableName, SDB_TABLE_LEN); pTable->keyType = pDesc->keyType; pTable->tableId = pDesc->tableId; @@ -915,6 +925,7 @@ void sdbCloseTable(void *handle) { taosHashDestroyIter(pIter); taosHashCleanup(pTable->iHandle); + pthread_mutex_destroy(&pTable->mutex); sdbDebug("table:%s, is closed, numOfTables:%d", pTable->tableName, tsSdbObj.numOfTables); free(pTable); From f20723b057b0b3e873c5bebd176b02a2119aa132 Mon Sep 17 00:00:00 2001 From: root Date: Fri, 11 Sep 2020 20:53:42 +0800 Subject: [PATCH 08/10] TD-1284 --- src/mnode/src/mnodeSdb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/mnode/src/mnodeSdb.c b/src/mnode/src/mnodeSdb.c index 3611f15032..646c17b2b8 100644 --- a/src/mnode/src/mnodeSdb.c +++ b/src/mnode/src/mnodeSdb.c @@ -448,7 +448,6 @@ void sdbDecRef(void *handle, void *pObj) { } static void *sdbGetRowMeta(SSdbTable *pTable, void *key) { - void *pRet = NULL; if (pTable == NULL) return NULL; int32_t keySize = sizeof(int32_t); @@ -456,12 +455,10 @@ static void *sdbGetRowMeta(SSdbTable *pTable, void *key) { keySize = strlen((char *)key); } - pthread_mutex_lock(&pTable->mutex); void **ppRow = (void **)taosHashGet(pTable->iHandle, key, keySize); - if (ppRow != NULL) pRet = *ppRow; - pthread_mutex_unlock(&pTable->mutex); + if (ppRow != NULL) return *ppRow; - return pRet; + return NULL; } static void *sdbGetRowMetaFromObj(SSdbTable *pTable, void *key) { @@ -469,10 +466,12 @@ static void *sdbGetRowMetaFromObj(SSdbTable *pTable, void *key) { } void *sdbGetRow(void *handle, void *key) { + SSdbTable *pTable = handle; + + pthread_mutex_lock(&pTable->mutex); void *pRow = sdbGetRowMeta(handle, key); - if (pRow) { - sdbIncRef(handle, pRow); - } + if (pRow) sdbIncRef(handle, pRow); + pthread_mutex_unlock(&pTable->mutex); return pRow; } From dd0b10487fd2997426d717afb611522307832f7f Mon Sep 17 00:00:00 2001 From: Xiaowei Su <46439638+Shawshank-Smile@users.noreply.github.com> Date: Sat, 12 Sep 2020 10:56:53 +0800 Subject: [PATCH 09/10] Update cluster-ch.md --- documentation20/webdocs/markdowndocs/cluster-ch.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation20/webdocs/markdowndocs/cluster-ch.md b/documentation20/webdocs/markdowndocs/cluster-ch.md index fa9e7e69f1..a1ac1d6fd6 100644 --- a/documentation20/webdocs/markdowndocs/cluster-ch.md +++ b/documentation20/webdocs/markdowndocs/cluster-ch.md @@ -9,8 +9,8 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预 ## 准备工作 **第一步**:如果搭建集群的节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html ) -**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/) -**注意2:**客户端也需要配置,并且把集群中所有服务器的FQDN配置到客户端中(windows中 C:\Windows\System32\drivers\etc\hosts)。 +**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/); +**注意2:**客户端也需要配置,确保它可以正确解析每个节点的FQDN配置,不管是通过DNS服务,还是 Host 文件。 **第二步**:建议关闭防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口; @@ -25,7 +25,7 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预 **第五步**:修改TDengine的配置文件(所有节点的文件/etc/taos/taos.cfg都需要修改)。假设准备启动的第一个节点End Point为 h1.taosdata.com:6030, 那么以下几个参数与集群相关: ``` -// firstEp 是每个节点启动后连接的第一个节点 +// firstEp 集群中所有节点的配置都是一致的,对其第一次访问后,就获得了整个集群的信息 firstEp h1.taosdata.com:6030 // 配置本节点的FQDN,如果本机只有一个hostname, 无需配置 @@ -34,7 +34,7 @@ fqdn h1.taosdata.com // 配置本节点的端口号,缺省是6030 serverPort 6030 -// 副本数为偶数的时候,需要配置,请参考《Arbitrator的使用》的部分 +// 服务端节点数为偶数的时候,需要配置,请参考《Arbitrator的使用》的部分 arbitrator ha.taosdata.com:6042 ``` From e7af1188ed75c66cb9112937912a3d7e05f31dd1 Mon Sep 17 00:00:00 2001 From: zyyang Date: Sat, 12 Sep 2020 17:21:45 +0800 Subject: [PATCH 10/10] [TD-1410]test: add a tool for test JDBC Connector --- .../java/com/taosdata/jdbc/SubscribeTest.java | 2 - tests/examples/JDBC/JDBCDemo/pom.xml | 28 +-- .../example/JDBCConnectorChecker.java | 174 ++++++++++++++++++ 3 files changed, 188 insertions(+), 16 deletions(-) create mode 100644 tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCConnectorChecker.java diff --git a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java index 07b43d1227..0a71c77d1d 100644 --- a/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java +++ b/src/connector/jdbc/src/test/java/com/taosdata/jdbc/SubscribeTest.java @@ -10,8 +10,6 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.Properties; -import static org.junit.Assert.assertTrue; - public class SubscribeTest extends BaseTest { Connection connection = null; Statement statement = null; diff --git a/tests/examples/JDBC/JDBCDemo/pom.xml b/tests/examples/JDBC/JDBCDemo/pom.xml index f0234f2bd7..92d757edfd 100644 --- a/tests/examples/JDBC/JDBCDemo/pom.xml +++ b/tests/examples/JDBC/JDBCDemo/pom.xml @@ -9,21 +9,20 @@ 1.0-SNAPSHOT jar - - - - org.apache.maven.plugins - maven-plugins - 30 - - - org.apache.maven.plugins - maven-assembly-plugin - 3.0.0 - - - + + + org.apache.maven.plugins + maven-plugins + 30 + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.0.0 + + org.apache.maven.plugins maven-assembly-plugin @@ -48,6 +47,7 @@ + org.apache.maven.plugins maven-compiler-plugin diff --git a/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCConnectorChecker.java b/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCConnectorChecker.java new file mode 100644 index 0000000000..1e801bc658 --- /dev/null +++ b/tests/examples/JDBC/JDBCDemo/src/main/java/com/taosdata/example/JDBCConnectorChecker.java @@ -0,0 +1,174 @@ +package com.taosdata.example; + +import com.taosdata.jdbc.TSDBDriver; + +import java.sql.*; +import java.util.Properties; + +public class JDBCConnectorChecker { + private static String host; + private static String dbName = "test"; + private static String tbName = "weather"; + private Connection connection; + + + /** + * get connection + **/ + private void init() { + try { + Class.forName("com.taosdata.jdbc.TSDBDriver"); + Properties properties = new Properties(); + properties.setProperty(TSDBDriver.PROPERTY_KEY_HOST, host); + properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8"); + properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8"); + System.out.println("get connection starting..."); + connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties); + if (connection != null) + System.out.println("[ OK ] Connection established."); + } catch (ClassNotFoundException | SQLException e) { + throw new RuntimeException("connection failed: " + host); + } + } + + /** + * create database + */ + private void createDatabase() { + String sql = "create database if not exists " + dbName; + exuete(sql); + } + + /** + * use database + */ + private void useDatabase() { + String sql = "use " + dbName; + exuete(sql); + } + + /** + * select + */ + private void checkSelect() { + final String sql = "select * from test.weather"; + executeQuery(sql); + } + + private void executeQuery(String sql) { + try (Statement statement = connection.createStatement()) { + long start = System.currentTimeMillis(); + ResultSet resultSet = statement.executeQuery(sql); + long end = System.currentTimeMillis(); + printSql(sql, true, (end - start)); + printResult(resultSet); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void printResult(ResultSet resultSet) throws SQLException { + ResultSetMetaData metaData = resultSet.getMetaData(); + while (resultSet.next()) { + for (int i = 1; i <= metaData.getColumnCount(); i++) { + String columnLabel = metaData.getColumnLabel(i); + String value = resultSet.getString(i); + System.out.printf("%s: %s\t", columnLabel, value); + } + System.out.println(); + } + } + + private String formatString(String str) { + StringBuilder sb = new StringBuilder(); + int blankCnt = (26 - str.length()) / 2; + for (int j = 0; j < blankCnt; j++) + sb.append(" "); + sb.append(str); + for (int j = 0; j < blankCnt; j++) + sb.append(" "); + sb.append("|"); + return sb.toString(); + } + + + /** + * insert + */ + private void checkInsert() { + final String sql = "insert into test.weather (ts, temperature, humidity) values(now, 20.5, 34)"; + exuete(sql); + } + + /** + * create table + */ + private void createTable() { + final String sql = "create table if not exists " + dbName + "." + tbName + " (ts timestamp, temperature float, humidity int)"; + exuete(sql); + } + + private final void printSql(String sql, boolean succeed, long cost) { + System.out.println("[ " + (succeed ? "OK" : "ERROR!") + " ] time cost: " + cost + " ms, execute statement ====> " + sql); + } + + private final void exuete(String sql) { + try (Statement statement = connection.createStatement()) { + long start = System.currentTimeMillis(); + boolean execute = statement.execute(sql); + long end = System.currentTimeMillis(); + printSql(sql, execute, (end - start)); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void close() { + try { + if (connection != null) { + this.connection.close(); + System.out.println("connection closed."); + } + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private void checkDropTable() { + final String sql = "drop table if exists " + dbName + "." + tbName + ""; + exuete(sql); + } + + public static void main(String[] args) { + for (int i = 0; i < args.length; i++) { + if ("-host".equalsIgnoreCase(args[i]) && i < args.length - 1) { + host = args[++i]; + } + if ("-db".equalsIgnoreCase(args[i]) && i < args.length - 1) { + dbName = args[++i]; + } + if ("-t".equalsIgnoreCase(args[i]) && i < args.length - 1) { + tbName = args[++i]; + } + } + + if (host == null) { + System.out.println("Usage: java -jar JDBCConnectorChecker.jar -host "); + return; + } + + JDBCConnectorChecker checker = new JDBCConnectorChecker(); + checker.init(); + checker.createDatabase(); + checker.useDatabase(); + checker.checkDropTable(); + checker.createTable(); + checker.checkInsert(); + checker.checkSelect(); + checker.checkDropTable(); + checker.close(); + } + + +}