From 598444d591bb8c897cf4cf86f944be1fd92f3b4e Mon Sep 17 00:00:00 2001 From: Ping Xiao Date: Thu, 11 Jun 2020 10:26:46 +0800 Subject: [PATCH 01/37] https://jira.taosdata.com:18080/browse/TD-350: filter for all data types --- tests/pytest/fulltest.sh | 3 + tests/pytest/query/filterAllIntTypes.py | 117 +++++++ tests/pytest/query/filterFloatAndDouble.py | 160 +++++++++ tests/pytest/query/filterOtherTypes.py | 362 +++++++++++++++++++++ tests/pytest/regressiontest.sh | 2 + 5 files changed, 644 insertions(+) create mode 100644 tests/pytest/query/filterAllIntTypes.py create mode 100644 tests/pytest/query/filterFloatAndDouble.py create mode 100644 tests/pytest/query/filterOtherTypes.py diff --git a/tests/pytest/fulltest.sh b/tests/pytest/fulltest.sh index a157100236..7dec2c961e 100755 --- a/tests/pytest/fulltest.sh +++ b/tests/pytest/fulltest.sh @@ -134,6 +134,9 @@ python3 ./test.py -f query/filter.py python3 ./test.py -f query/filterCombo.py python3 ./test.py -f query/queryNormal.py python3 ./test.py -f query/queryError.py +python3 ./test.py -f query/filterAllIntTypes.py +python3 ./test.py -f query/filterFloatAndDouble.py +python3 ./test.py -f query/filterOtherTypes.py #stream python3 ./test.py -f stream/stream1.py diff --git a/tests/pytest/query/filterAllIntTypes.py b/tests/pytest/query/filterAllIntTypes.py new file mode 100644 index 0000000000..32e635d6da --- /dev/null +++ b/tests/pytest/query/filterAllIntTypes.py @@ -0,0 +1,117 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.powers = [7, 15, 31, 63] + self.types = ["tinyint", "smallint", "int", "bigint"] + self.rowNum = 10 + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + for i in range(len(self.powers)): + curType = self.types[i] + print("======= Verify filter for %s type =========" % (curType)) + tdLog.debug( + "create table st%s(ts timestamp, num %s) tags(id %s)" % (curType, curType, curType)) + tdSql.execute( + "create table st%s(ts timestamp, num %s) tags(id %s)" % (curType, curType, curType)) + + #create 10 tables, insert 10 rows for each table + for j in range(self.rowNum): + tdSql.execute("create table st%s%d using st%s tags(%d)" % (curType, j + 1, curType, j + 1)) + for k in range(self.rowNum): + tdSql.execute("insert into st%s%d values(%d, %d)" % (curType, j + 1, self.ts + k + 1, j * 10 + k + 1)) + + tdSql.error("insert into st%s10 values(%d, %d)" % (curType, self.ts + 11, pow(2, self.powers[i]))) + tdSql.execute("insert into st%s10 values(%d, %d)" % (curType, self.ts + 12, pow(2, self.powers[i]) - 1)) + tdSql.error("insert into st%s10 values(%d, %d)" % (curType, self.ts + 13, pow(-2, self.powers[i]))) + tdSql.execute("insert into st%s10 values(%d, %d)" % (curType, self.ts + 14, pow(-2, self.powers[i]) + 1)) + + # > for int type on column + tdSql.query("select * from st%s where num > 50" % curType) + tdSql.checkRows(51) + + # >= for int type on column + tdSql.query("select * from st%s where num >= 50" % curType) + tdSql.checkRows(52) + + # = for int type on column + tdSql.query("select * from st%s where num = 50" % curType) + tdSql.checkRows(1) + + # < for int type on column + tdSql.query("select * from st%s where num < 50" % curType) + tdSql.checkRows(50) + + # <= for int type on column + tdSql.query("select * from st%s where num <= 50" % curType) + tdSql.checkRows(51) + + # <> for int type on column + tdSql.query("select * from st%s where num <> 50" % curType) + tdSql.checkRows(101) + + # != for int type on column + tdSql.query("select * from st%s where num != 50" % curType) + tdSql.checkRows(101) + + # > for int type on tag + tdSql.query("select * from st%s where id > 5" % curType) + tdSql.checkRows(52) + + # >= for int type on tag + tdSql.query("select * from st%s where id >= 5" % curType) + tdSql.checkRows(62) + + # = for int type on tag + tdSql.query("select * from st%s where id = 5" % curType) + tdSql.checkRows(10) + + # < for int type on tag + tdSql.query("select * from st%s where id < 5" % curType) + tdSql.checkRows(40) + + # <= for int type on tag + tdSql.query("select * from st%s where id <= 5" % curType) + tdSql.checkRows(50) + + # <> for int type on tag + tdSql.query("select * from st%s where id <> 5" % curType) + tdSql.checkRows(92) + + # != for int type on tag + tdSql.query("select * from st%s where id != 5" % curType) + tdSql.checkRows(92) + + print("======= Verify filter for %s type finished =========" % curType) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/query/filterFloatAndDouble.py b/tests/pytest/query/filterFloatAndDouble.py new file mode 100644 index 0000000000..bea41be11c --- /dev/null +++ b/tests/pytest/query/filterFloatAndDouble.py @@ -0,0 +1,160 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.rowNum = 10 + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + print("======= Verify filter for float and double type =========") + tdLog.debug( + "create table st(ts timestamp, num float, speed double) tags(tagcol1 float, tagcol2 double)") + tdSql.execute( + "create table st(ts timestamp, num float, speed double) tags(tagcol1 float, tagcol2 double)") + + for j in range(self.rowNum): + tdSql.execute( + "insert into st1 using st tags(1.1, 2.3) values(%d, %f, %f)" % (self.ts + j + 1, 1.1 * (j + 1), 2.3 * (j + 1))) + + # > for float type on column + tdSql.query("select * from st where num > 5.5") + tdSql.checkRows(5) + + # >= for float type on column + tdSql.query("select * from st where num >= 5.5") + tdSql.checkRows(6) + + # = for float type on column + tdSql.query("select * from st where num = 5.5") + tdSql.checkRows(1) + + # <> for float type on column + tdSql.query("select * from st where num <> 5.5") + tdSql.checkRows(9) + + # != for float type on column + tdSql.query("select * from st where num != 5.5") + tdSql.checkRows(9) + + # <= for float type on column + tdSql.query("select * from st where num <= 5.5") + tdSql.checkRows(5) + + # < for float type on column + tdSql.query("select * from st where num < 5.5") + tdSql.checkRows(4) + + # > for float type on tag + tdSql.query("select * from st where tagcol1 > 1.1") + tdSql.checkRows(0) + + # >= for float type on tag + tdSql.query("select * from st where tagcol1 >= 1.1") + tdSql.checkRows(10) + + # = for float type on tag + tdSql.query("select * from st where tagcol1 = 1.1") + tdSql.checkRows(10) + + # <> for float type on tag + tdSql.query("select * from st where tagcol1 <> 1.1") + tdSql.checkRows(0) + + # != for float type on tag + tdSql.query("select * from st where tagcol1 != 1.1") + tdSql.checkRows(0) + + # <= for float type on tag + tdSql.query("select * from st where tagcol1 <= 1.1") + tdSql.checkRows(10) + + # < for float type on tag + tdSql.query("select * from st where tagcol1 < 1.1") + tdSql.checkRows(0) + + # > for double type on column + tdSql.query("select * from st where speed > 11.5") + tdSql.checkRows(5) + + # >= for double type on column + tdSql.query("select * from st where speed >= 11.5") + tdSql.checkRows(6) + + # = for double type on column + tdSql.query("select * from st where speed = 11.5") + tdSql.checkRows(1) + + # <> for double type on column + tdSql.query("select * from st where speed <> 11.5") + tdSql.checkRows(9) + + # != for double type on column + tdSql.query("select * from st where speed != 11.5") + tdSql.checkRows(9) + + # <= for double type on column + tdSql.query("select * from st where speed <= 11.5") + tdSql.checkRows(5) + + # < for double type on column + tdSql.query("select * from st where speed < 11.5") + tdSql.checkRows(4) + + # > for double type on tag + tdSql.query("select * from st where tagcol2 > 2.3") + tdSql.checkRows(0) + + # >= for double type on tag + tdSql.query("select * from st where tagcol2 >= 2.3") + tdSql.checkRows(10) + + # = for double type on tag + tdSql.query("select * from st where tagcol2 = 2.3") + tdSql.checkRows(10) + + # <> for double type on tag + tdSql.query("select * from st where tagcol2 <> 2.3") + tdSql.checkRows(0) + + # != for double type on tag + tdSql.query("select * from st where tagcol2 != 2.3") + tdSql.checkRows(0) + + # <= for double type on tag + tdSql.query("select * from st where tagcol2 <= 2.3") + tdSql.checkRows(10) + + # < for double type on tag + tdSql.query("select * from st where tagcol2 < 2.3") + tdSql.checkRows(0) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/query/filterOtherTypes.py b/tests/pytest/query/filterOtherTypes.py new file mode 100644 index 0000000000..f09ac596c7 --- /dev/null +++ b/tests/pytest/query/filterOtherTypes.py @@ -0,0 +1,362 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + print("======= Verify filter for bool, nchar and binary type =========") + tdLog.debug( + "create table st(ts timestamp, tbcol1 bool, tbcol2 nchar(10), tbcol3 binary(20)) tags(tagcol1 bool, tagcol2 nchar(10), tagcol3 binary(10))") + tdSql.execute( + "create table st(ts timestamp, tbcol1 bool, tbcol2 nchar(10), tbcol3 binary(20)) tags(tagcol1 bool, tagcol2 nchar(10), tagcol3 binary(10))") + + tdSql.execute("create table st1 using st tags(true, 'table1', '水表')") + for i in range(1, 6): + tdSql.execute("insert into st1 values(%d, %d, 'taosdata%d', '涛思数据%d')" % (self.ts + i, i % 2, i, i)) + + tdSql.execute("create table st2 using st tags(false, 'table2', '电表')") + for i in range(6, 11): + tdSql.execute("insert into st2 values(%d, %d, 'taosdata%d', '涛思数据%d')" % (self.ts + i, i % 2, i, i)) + + # =============Verify stable columns==================== + # > for bool type on column + tdSql.error("select * from st where tbcol1 > false") + + # >= for bool type on column + tdSql.error("select * from st where tbcol1 >= false") + + # = for bool type on column + tdSql.query("select * from st where tbcol1 = false") + tdSql.checkRows(5) + + # <> for bool type on column + tdSql.query("select * from st where tbcol1 <> true") + tdSql.checkRows(5) + + # != for bool type on column + tdSql.query("select * from st where tbcol1 != true") + tdSql.checkRows(5) + + # > for bool type on column + tdSql.error("select * from st where tbcol1 < true") + + # >= for bool type on column + tdSql.error("select * from st where tbcol1 <= true") + + # % for bool type on column + tdSql.error("select * from st where tbcol1 like '%'") + + # _ for bool type on column + tdSql.error("select * from st where tbcol1 like '____'") + + # > for nchar type on column + tdSql.error("select * from st where tbcol2 > 'taosdata'") + + # >= for nchar type on column + tdSql.error("select * from st where tbcol2 >= 'taosdata'") + + # = for nchar type on column + tdSql.query("select * from st where tbcol2 = 'taosdata1'") + tdSql.checkRows(1) + + # <> for nchar type on column + tdSql.query("select * from st where tbcol2 <> 'taosdata1'") + tdSql.checkRows(9) + + # != for nchar type on column + tdSql.query("select * from st where tbcol2 != 'taosdata1'") + tdSql.checkRows(9) + + # > for nchar type on column + tdSql.error("select * from st where tbcol2 < 'taodata'") + + # >= for nchar type on column + tdSql.error("select * from st where tbcol2 <= 'taodata'") + + # % for nchar type on column case 1 + tdSql.query("select * from st where tbcol2 like '%'") + tdSql.checkRows(10) + + # % for nchar type on column case 2 + tdSql.query("select * from st where tbcol2 like 'a%'") + tdSql.checkRows(0) + + # % for nchar type on column case 3 + tdSql.query("select * from st where tbcol2 like 't%_'") + tdSql.checkRows(10) + + # % for nchar type on column case 4 + tdSql.query("select * from st where tbcol2 like '%1'") + # tdSql.checkRows(2) + + # _ for nchar type on column case 1 + tdSql.query("select * from st where tbcol2 like '____________'") + tdSql.checkRows(0) + + # _ for nchar type on column case 2 + tdSql.query("select * from st where tbcol2 like '__________'") + tdSql.checkRows(1) + + # _ for nchar type on column case 3 + tdSql.query("select * from st where tbcol2 like '_________'") + tdSql.checkRows(9) + + # _ for nchar type on column case 4 + tdSql.query("select * from st where tbcol2 like 't________'") + tdSql.checkRows(9) + + # _ for nchar type on column case 5 + tdSql.query("select * from st where tbcol2 like '%________'") + tdSql.checkRows(10) + + # > for binary type on column + tdSql.error("select * from st where tbcol3 > '涛思数据'") + + # >= for binary type on column + tdSql.error("select * from st where tbcol3 >= '涛思数据'") + + # = for binary type on column + tdSql.query("select * from st where tbcol3 = '涛思数据1'") + tdSql.checkRows(1) + + # <> for binary type on column + tdSql.query("select * from st where tbcol3 <> '涛思数据1'") + tdSql.checkRows(9) + + # != for binary type on column + tdSql.query("select * from st where tbcol3 != '涛思数据1'") + tdSql.checkRows(9) + + # > for binary type on column + tdSql.error("select * from st where tbcol3 < '涛思数据'") + + # >= for binary type on column + tdSql.error("select * from st where tbcol3 <= '涛思数据'") + + # % for binary type on column case 1 + tdSql.query("select * from st where tbcol3 like '%'") + tdSql.checkRows(10) + + # % for binary type on column case 2 + tdSql.query("select * from st where tbcol3 like '陶%'") + tdSql.checkRows(0) + + # % for binary type on column case 3 + tdSql.query("select * from st where tbcol3 like '涛%_'") + tdSql.checkRows(10) + + # % for binary type on column case 4 + tdSql.query("select * from st where tbcol3 like '%1'") + tdSql.checkRows(1) + + # _ for binary type on column case 1 + tdSql.query("select * from st where tbcol3 like '_______'") + tdSql.checkRows(0) + + # _ for binary type on column case 2 + tdSql.query("select * from st where tbcol3 like '______'") + tdSql.checkRows(1) + + # _ for binary type on column case 2 + tdSql.query("select * from st where tbcol3 like '_____'") + tdSql.checkRows(9) + + # _ for binary type on column case 3 + tdSql.query("select * from st where tbcol3 like '____'") + tdSql.checkRows(0) + + # _ for binary type on column case 4 + tdSql.query("select * from st where tbcol3 like 't____'") + tdSql.checkRows(0) + + # =============Verify stable tags==================== + # > for bool type on tag + tdSql.error("select * from st where tagcol1 > false") + + # >= for bool type on tag + tdSql.error("select * from st where tagcol1 >= false") + + # = for bool type on tag + tdSql.query("select * from st where tagcol1 = false") + tdSql.checkRows(5) + + # <> for bool type on tag + tdSql.query("select * from st where tagcol1 <> true") + tdSql.checkRows(5) + + # != for bool type on tag + tdSql.query("select * from st where tagcol1 != true") + tdSql.checkRows(5) + + # > for bool type on tag + tdSql.error("select * from st where tagcol1 < true") + + # >= for bool type on tag + tdSql.error("select * from st where tagcol1 <= true") + + # % for bool type on tag + tdSql.error("select * from st where tagcol1 like '%'") + + # _ for bool type on tag + tdSql.error("select * from st where tagcol1 like '____'") + + # > for nchar type on tag + tdSql.error("select * from st where tagcol2 > 'table'") + + # >= for nchar type on tag + tdSql.error("select * from st where tagcol2 >= 'table'") + + # = for nchar type on tag + tdSql.query("select * from st where tagcol2 = 'table1'") + tdSql.checkRows(5) + + # <> for nchar type on tag + tdSql.query("select * from st where tagcol2 <> 'table1'") + tdSql.checkRows(5) + + # != for nchar type on tag + tdSql.query("select * from st where tagcol2 != 'table'") + tdSql.checkRows(10) + + # > for nchar type on tag + tdSql.error("select * from st where tagcol2 < 'table'") + + # >= for nchar type on tag + tdSql.error("select * from st where tagcol2 <= 'table'") + + # % for nchar type on tag case 1 + tdSql.query("select * from st where tagcol2 like '%'") + tdSql.checkRows(10) + + # % for nchar type on tag case 2 + tdSql.query("select * from st where tagcol2 like 'a%'") + tdSql.checkRows(0) + + # % for nchar type on tag case 3 + tdSql.query("select * from st where tagcol2 like 't%_'") + tdSql.checkRows(10) + + # % for nchar type on tag case 4 + tdSql.query("select * from st where tagcol2 like '%1'") + tdSql.checkRows(5) + + # _ for nchar type on tag case 1 + tdSql.query("select * from st where tagcol2 like '_______'") + tdSql.checkRows(0) + + # _ for nchar type on tag case 2 + tdSql.query("select * from st where tagcol2 like '______'") + tdSql.checkRows(10) + + # _ for nchar type on tag case 3 + tdSql.query("select * from st where tagcol2 like 't_____'") + tdSql.checkRows(10) + + # _ for nchar type on tag case 4 + tdSql.query("select * from st where tagcol2 like 's________'") + tdSql.checkRows(0) + + # _ for nchar type on tag case 5 + tdSql.query("select * from st where tagcol2 like '%__'") + tdSql.checkRows(10) + + # > for binary type on tag + tdSql.error("select * from st where tagcol3 > '表'") + + # >= for binary type on tag + tdSql.error("select * from st where tagcol3 >= '表'") + + # = for binary type on tag + tdSql.query("select * from st where tagcol3 = '水表'") + tdSql.checkRows(5) + + # <> for binary type on tag + tdSql.query("select * from st where tagcol3 <> '水表'") + tdSql.checkRows(5) + + # != for binary type on tag + tdSql.query("select * from st where tagcol3 != '水表'") + tdSql.checkRows(5) + + # > for binary type on tag + tdSql.error("select * from st where tagcol3 < '水表'") + + # >= for binary type on tag + tdSql.error("select * from st where tagcol3 <= '水表'") + + # % for binary type on tag case 1 + tdSql.query("select * from st where tagcol3 like '%'") + tdSql.checkRows(10) + + # % for binary type on tag case 2 + tdSql.query("select * from st where tagcol3 like '水%'") + tdSql.checkRows(5) + + # % for binary type on tag case 3 + tdSql.query("select * from st where tagcol3 like '数%_'") + tdSql.checkRows(0) + + # % for binary type on tag case 4 + tdSql.query("select * from st where tagcol3 like '%表'") + tdSql.checkRows(10) + + # % for binary type on tag case 5 + tdSql.query("select * from st where tagcol3 like '%据'") + tdSql.checkRows(0) + + # _ for binary type on tag case 1 + tdSql.query("select * from st where tagcol3 like '__'") + tdSql.checkRows(10) + + # _ for binary type on tag case 2 + tdSql.query("select * from st where tagcol3 like '水_'") + tdSql.checkRows(5) + + # _ for binary type on tag case 2 + tdSql.query("select * from st where tagcol3 like '_表'") + tdSql.checkRows(10) + + # _ for binary type on tag case 3 + tdSql.query("select * from st where tagcol3 like '___'") + tdSql.checkRows(0) + + # _ for binary type on tag case 4 + tdSql.query("select * from st where tagcol3 like '数_'") + tdSql.checkRows(0) + + # _ for binary type on tag case 5 + tdSql.query("select * from st where tagcol3 like '_据'") + tdSql.checkRows(0) + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) + diff --git a/tests/pytest/regressiontest.sh b/tests/pytest/regressiontest.sh index d75afca2df..743a837f5e 100755 --- a/tests/pytest/regressiontest.sh +++ b/tests/pytest/regressiontest.sh @@ -131,6 +131,8 @@ python3 ./test.py -f user/pass_len.py #query python3 ./test.py -f query/filter.py +python3 ./test.py -f query/filterAllIntTypes.py +python3 ./test.py -f query/filterFloatAndDouble.py #stream From 6557244eecab6cd8d746e77dd922b8cb96b8350e Mon Sep 17 00:00:00 2001 From: liu0x54 Date: Fri, 12 Jun 2020 10:43:27 +0000 Subject: [PATCH 02/37] [TD-597] fix alter table bugs --- src/mnode/src/mnodeTable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 0e255d011b..478e7790fb 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -1004,7 +1004,7 @@ static int32_t mnodeAddSuperTableColumn(SDbObj *pDb, SSuperTableObj *pStable, SS sizeof(SSchema) * pStable->numOfTags); memcpy(pStable->schema + pStable->numOfColumns, schema, sizeof(SSchema) * ncols); - SSchema *tschema = (SSchema *) (pStable->schema + sizeof(SSchema) * pStable->numOfColumns); + SSchema *tschema = (SSchema *) (pStable->schema + pStable->numOfColumns); for (int32_t i = 0; i < ncols; i++) { tschema[i].colId = pStable->nextColId++; } From 65fe54c4f62e9865580d1b4657b94421f2d7aee5 Mon Sep 17 00:00:00 2001 From: dengyihao Date: Fri, 12 Jun 2020 19:39:17 +0800 Subject: [PATCH 03/37] fixbug TD-327 --- src/client/src/tscParseInsert.c | 2 +- src/client/src/tscSQLParser.c | 4 ++-- src/common/inc/tglobal.h | 1 + src/common/src/tglobal.c | 1 + src/common/src/ttimezone.c | 1 + src/util/inc/ttime.h | 2 +- src/util/src/ttime.c | 40 ++++++++++++++++++++++++++++----- 7 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index c4749e4611..afd1a3e8c8 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -97,7 +97,7 @@ int tsParseTime(SSQLToken *pToken, int64_t *time, char **next, char *error, int1 useconds = str2int64(pToken->z); } else { // strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm); - if (taosParseTime(pToken->z, time, pToken->n, timePrec) != TSDB_CODE_SUCCESS) { + if (taosParseTime(pToken->z, time, pToken->n, timePrec, tsDaylight) != TSDB_CODE_SUCCESS) { return tscInvalidSQLErrMsg(error, "invalid timestamp format", pToken->z); } diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 8e5a439431..7605fae5e5 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -138,7 +138,7 @@ static int setColumnFilterInfoForTimestamp(SQueryInfo* pQueryInfo, tVariant* pVa STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta); if (seg != NULL) { - if (taosParseTime(pVar->pz, &time, pVar->nLen, tinfo.precision) != TSDB_CODE_SUCCESS) { + if (taosParseTime(pVar->pz, &time, pVar->nLen, tinfo.precision, tsDaylight) != TSDB_CODE_SUCCESS) { return invalidSqlErrMsg(pQueryInfo->msg, msg); } } else { @@ -3950,7 +3950,7 @@ int32_t getTimeRange(STimeWindow* win, tSQLExpr* pRight, int32_t optr, int16_t t char* seg = strnchr(pRight->val.pz, '-', pRight->val.nLen, false); if (seg != NULL) { - if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO) == TSDB_CODE_SUCCESS) { + if (taosParseTime(pRight->val.pz, &val, pRight->val.nLen, TSDB_TIME_PRECISION_MICRO, tsDaylight) == TSDB_CODE_SUCCESS) { parsed = true; } else { return TSDB_CODE_TSC_INVALID_SQL; diff --git a/src/common/inc/tglobal.h b/src/common/inc/tglobal.h index 53d821b3d8..eaceea468b 100644 --- a/src/common/inc/tglobal.h +++ b/src/common/inc/tglobal.h @@ -170,6 +170,7 @@ extern char gitinfo[]; extern char gitinfoOfInternal[]; extern char buildinfo[]; +extern int8_t tsDaylight; extern char tsTimezone[64]; extern char tsLocale[64]; extern char tsCharset[64]; // default encode string diff --git a/src/common/src/tglobal.c b/src/common/src/tglobal.c index 86fc6deb1b..e80597ca95 100644 --- a/src/common/src/tglobal.c +++ b/src/common/src/tglobal.c @@ -198,6 +198,7 @@ char tsMonitorDbName[TSDB_DB_NAME_LEN] = "log"; char tsInternalPass[] = "secretkey"; int32_t tsMonitorInterval = 30; // seconds +int8_t tsDaylight = 0; char tsTimezone[64] = {0}; char tsLocale[TSDB_LOCALE_LEN] = {0}; char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string diff --git a/src/common/src/ttimezone.c b/src/common/src/ttimezone.c index 0e8e1316b3..ae6ffea59a 100644 --- a/src/common/src/ttimezone.c +++ b/src/common/src/ttimezone.c @@ -58,6 +58,7 @@ void tsSetTimeZone() { * (BST, +0100) */ sprintf(tsTimezone, "(%s, %s%02d00)", tzname[daylight], tz >= 0 ? "+" : "-", abs(tz)); + tsDaylight = daylight; uPrint("timezone format changed to %s", tsTimezone); } diff --git a/src/util/inc/ttime.h b/src/util/inc/ttime.h index 61df65f345..576c9a51f6 100644 --- a/src/util/inc/ttime.h +++ b/src/util/inc/ttime.h @@ -56,7 +56,7 @@ static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) { int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts); -int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec); +int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth); void deltaToUtcInitOnce(); #ifdef __cplusplus diff --git a/src/util/src/ttime.c b/src/util/src/ttime.c index 8355ed9dc1..4dd6360752 100644 --- a/src/util/src/ttime.c +++ b/src/util/src/ttime.c @@ -24,7 +24,6 @@ #include "taosdef.h" #include "ttime.h" #include "tutil.h" - /* * mktime64 - Converts date to seconds. * Converts Gregorian date to seconds since 1970-01-01 00:00:00. @@ -119,15 +118,21 @@ static int month[12] = { static int64_t parseFraction(char* str, char** end, int32_t timePrec); static int32_t parseTimeWithTz(char* timestr, int64_t* time, int32_t timePrec); static int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec); +static int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec); + +static int32_t (*parseLocaltimeFp[]) (char* timestr, int64_t* time, int32_t timePrec) = { + parseLocaltime, + parseLocaltimeWithDst +}; int32_t taosGetTimestampSec() { return (int32_t)time(NULL); } -int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec) { +int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t daylight) { /* parse datatime string in with tz */ if (strnchr(timestr, 'T', len, false) != NULL) { return parseTimeWithTz(timestr, time, timePrec); } else { - return parseLocaltime(timestr, time, timePrec); + return (*parseLocaltimeFp[daylight])(timestr, time, timePrec); } } @@ -304,9 +309,6 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) { return -1; } - /* mktime will be affected by TZ, set by using taos_options */ - //int64_t seconds = mktime(&tm); - //int64_t seconds = (int64_t)user_mktime(&tm); int64_t seconds = user_mktime64(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); int64_t fraction = 0; @@ -324,6 +326,32 @@ int32_t parseLocaltime(char* timestr, int64_t* time, int32_t timePrec) { return 0; } +int32_t parseLocaltimeWithDst(char* timestr, int64_t* time, int32_t timePrec) { + *time = 0; + struct tm tm = {0}; + tm.tm_isdst = -1; + + char* str = strptime(timestr, "%Y-%m-%d %H:%M:%S", &tm); + if (str == NULL) { + return -1; + } + + /* mktime will be affected by TZ, set by using taos_options */ + int64_t seconds = mktime(&tm); + + int64_t fraction = 0; + + if (*str == '.') { + /* parse the second fraction part */ + if ((fraction = parseFraction(str + 1, &str, timePrec)) < 0) { + return -1; + } + } + + int64_t factor = (timePrec == TSDB_TIME_PRECISION_MILLI) ? 1000 : 1000000; + *time = factor * seconds + fraction; + return 0; +} static int32_t getTimestampInUsFromStrImpl(int64_t val, char unit, int64_t* result) { *result = val; From b99b469da731d3e09ca3cdce0aef776dda46e801 Mon Sep 17 00:00:00 2001 From: dengyihao Date: Fri, 12 Jun 2020 19:47:44 +0800 Subject: [PATCH 04/37] bugfix: double free --- src/kit/shell/src/shellEngine.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/kit/shell/src/shellEngine.c b/src/kit/shell/src/shellEngine.c index f04607f6fa..7705db4b27 100644 --- a/src/kit/shell/src/shellEngine.c +++ b/src/kit/shell/src/shellEngine.c @@ -469,7 +469,6 @@ static int dumpResultToFile(const char* fname, TAOS_RES* result) { } while( row != NULL); fclose(fp); - taos_free_result(result); return numOfRows; } From 6237292f4c567f9ed55b59a73f3a8a72a52b830b Mon Sep 17 00:00:00 2001 From: dengyihao Date: Sat, 13 Jun 2020 05:40:07 +0800 Subject: [PATCH 05/37] fixbug TD-562 --- src/kit/taosdemo/taosdemo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index bfedff0d94..4129659281 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -817,7 +817,7 @@ void queryDB(TAOS *taos, char *command) { i--; } - if (i == 0) { + if (code != 0) { fprintf(stderr, "Failed to run %s, reason: %s\n", command, taos_errstr(pSql)); taos_free_result(pSql); From f909b78c6c4dee5d3e18366b66e70d513c8473d0 Mon Sep 17 00:00:00 2001 From: Jeff Tao Date: Sat, 13 Jun 2020 00:18:36 +0000 Subject: [PATCH 06/37] release local resources only after all messages are consumed --- src/vnode/src/vnodeMain.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/src/vnode/src/vnodeMain.c b/src/vnode/src/vnodeMain.c index 67ba891f93..0882ee983d 100644 --- a/src/vnode/src/vnodeMain.c +++ b/src/vnode/src/vnodeMain.c @@ -321,6 +321,22 @@ void vnodeRelease(void *pVnodeRaw) { return; } + if (pVnode->tsdb) + tsdbCloseRepo(pVnode->tsdb, 1); + pVnode->tsdb = NULL; + + if (pVnode->wal) + walClose(pVnode->wal); + pVnode->wal = NULL; + + if (pVnode->wqueue) + dnodeFreeVnodeWqueue(pVnode->wqueue); + pVnode->wqueue = NULL; + + if (pVnode->rqueue) + dnodeFreeVnodeRqueue(pVnode->rqueue); + pVnode->rqueue = NULL; + tfree(pVnode->rootDir); if (pVnode->status == TAOS_VN_STATUS_DELETING) { @@ -411,33 +427,21 @@ void vnodeBuildStatusMsg(void *param) { } static void vnodeCleanUp(SVnodeObj *pVnode) { + // remove from hash, so new messages wont be consumed taosHashRemove(tsDnodeVnodesHash, (const char *)&pVnode->vgId, sizeof(int32_t)); + // stop replication module if (pVnode->sync) { syncStop(pVnode->sync); pVnode->sync = NULL; } - if (pVnode->tsdb) - tsdbCloseRepo(pVnode->tsdb, 1); - pVnode->tsdb = NULL; - - if (pVnode->wal) - walClose(pVnode->wal); - pVnode->wal = NULL; - + // stop continuous query if (pVnode->cq) cqClose(pVnode->cq); pVnode->cq = NULL; - if (pVnode->wqueue) - dnodeFreeVnodeWqueue(pVnode->wqueue); - pVnode->wqueue = NULL; - - if (pVnode->rqueue) - dnodeFreeVnodeRqueue(pVnode->rqueue); - pVnode->rqueue = NULL; - + // release local resources only after cutting off outside connections vnodeRelease(pVnode); } From f87322f6802ffa453ce9a4f12d14f1888929b4c3 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 11:06:59 +0800 Subject: [PATCH 07/37] [td-225] fix bugs in group by normal columns --- src/client/src/tscFunctionImpl.c | 13 +- src/client/src/tscSQLParser.c | 27 ++- src/client/src/tscServer.c | 4 +- src/query/src/qExecutor.c | 224 +++++++++++++----- src/query/src/qUtil.c | 12 +- tests/script/general/parser/groupby.sim | 2 +- .../script/general/parser/import_commit3.sim | 2 +- 7 files changed, 213 insertions(+), 71 deletions(-) diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index a0deaa519a..457e187971 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -699,7 +699,7 @@ static int32_t first_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, } static int32_t last_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { - if (pCtx->order == TSDB_ORDER_ASC) { + if (pCtx->order != pCtx->param[0].i64Key) { return BLK_DATA_NO_NEEDED; } @@ -727,7 +727,7 @@ static int32_t first_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY } static int32_t last_dist_data_req_info(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) { - if (pCtx->order == TSDB_ORDER_ASC) { + if (pCtx->order != pCtx->param[0].i64Key) { return BLK_DATA_NO_NEEDED; } @@ -1593,7 +1593,7 @@ static void first_dist_function_f(SQLFunctionCtx *pCtx, int32_t index) { if (pCtx->hasNull && isNull(pData, pCtx->inputType)) { return; } - + if (pCtx->order == TSDB_ORDER_DESC) { return; } @@ -1652,7 +1652,7 @@ static void first_dist_func_second_merge(SQLFunctionCtx *pCtx) { * least one data in this block that is not null.(TODO opt for this case) */ static void last_function(SQLFunctionCtx *pCtx) { - if (pCtx->order == TSDB_ORDER_ASC) { + if (pCtx->order != pCtx->param[0].i64Key) { return; } @@ -1681,7 +1681,6 @@ static void last_function(SQLFunctionCtx *pCtx) { } static void last_function_f(SQLFunctionCtx *pCtx, int32_t index) { - assert(pCtx->order != TSDB_ORDER_ASC); void *pData = GET_INPUT_CHAR_INDEX(pCtx, index); if (pCtx->hasNull && isNull(pData, pCtx->inputType)) { return; @@ -1725,7 +1724,7 @@ static void last_dist_function(SQLFunctionCtx *pCtx) { * 1. for scan data in asc order, no need to check data * 2. for data blocks that are not loaded, no need to check data */ - if (pCtx->order == TSDB_ORDER_ASC) { + if (pCtx->order != pCtx->param[0].i64Key) { return; } @@ -1763,7 +1762,7 @@ static void last_dist_function_f(SQLFunctionCtx *pCtx, int32_t index) { * 1. for scan data in asc order, no need to check data * 2. for data blocks that are not loaded, no need to check data */ - if (pCtx->order == TSDB_ORDER_ASC) { + if (pCtx->order != pCtx->param[0].i64Key) { return; } diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 60415a8d74..9db81054a9 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -1452,6 +1452,13 @@ static int32_t setExprInfoForFunctions(SQueryInfo* pQueryInfo, SSchema* pSchema, SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false); tstrncpy(pExpr->aliasName, columnName, sizeof(pExpr->aliasName)); + + // set reverse order scan data blocks for last query + if (functionID == TSDB_FUNC_LAST) { + pExpr->numOfParams = 1; + pExpr->param[0].i64Key = TSDB_ORDER_DESC; + pExpr->param[0].nType = TSDB_DATA_TYPE_INT; + } // for all queries, the timestamp column needs to be loaded SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX}; @@ -1724,6 +1731,22 @@ int32_t addExprAndResultField(SQueryInfo* pQueryInfo, int32_t colIndex, tSQLExpr if (setExprInfoForFunctions(pQueryInfo, pSchema, functionID, pItem->aliasName, colIndex + i, &index) != 0) { return TSDB_CODE_TSC_INVALID_SQL; } + + if (optr == TK_LAST) { // todo refactor + SSqlGroupbyExpr* pGroupBy = &pQueryInfo->groupbyExpr; + if (pGroupBy->numOfGroupCols > 0) { + for(int32_t k = 0; k < pGroupBy->numOfGroupCols; ++k) { + SColIndex* pIndex = taosArrayGet(pGroupBy->columnInfo, k); + if (!TSDB_COL_IS_TAG(pIndex->flag) && pIndex->colIndex < tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) { // group by normal columns + SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, colIndex + i); + pExpr->numOfParams = 1; + pExpr->param->i64Key = TSDB_ORDER_ASC; + + break; + } + } + } + } } } @@ -2586,9 +2609,7 @@ int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd* tscColumnListInsert(pQueryInfo->colList, &index); - SColIndex colIndex = { - .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId, - }; + SColIndex colIndex = { .colIndex = index.columnIndex, .flag = TSDB_COL_NORMAL, .colId = pSchema->colId }; taosArrayPush(pGroupExpr->columnInfo, &colIndex); pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC; diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index cb6a736121..ce174c2473 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -430,7 +430,7 @@ void tscKillSTableQuery(SSqlObj *pSql) { /* * 1. if the subqueries are not launched or partially launched, we need to waiting the launched * query return to successfully free allocated resources. - * 2. if no any subqueries are launched yet, which means the metric query only in parse sql stage, + * 2. if no any subqueries are launched yet, which means the super table query only in parse sql stage, * set the res.code, and return. */ const int64_t MAX_WAITING_TIME = 10000; // 10 Sec. @@ -2200,7 +2200,7 @@ int tscProcessDropTableRsp(SSqlObj *pSql) { * The cached information is expired, however, we may have lost the ref of original meter. So, clear whole cache * instead. */ - tscTrace("%p force release metermeta after drop table:%s", pSql, pTableMetaInfo->name); + tscTrace("%p force release table meta after drop table:%s", pSql, pTableMetaInfo->name); taosCacheRelease(tscCacheHandle, (void **)&pTableMeta, true); if (pTableMetaInfo->pTableMeta) { diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index aa602ed661..13b4511177 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -354,7 +354,7 @@ static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWin int16_t bytes) { SQuery *pQuery = pRuntimeEnv->pQuery; - int32_t *p1 = (int32_t *)taosHashGet(pWindowResInfo->hashList, pData, bytes); + int32_t *p1 = (int32_t *) taosHashGet(pWindowResInfo->hashList, pData, bytes); if (p1 != NULL) { pWindowResInfo->curIndex = *p1; } else { // more than the capacity, reallocate the resources @@ -919,12 +919,25 @@ static int32_t setGroupResultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, char *pDat SDiskbasedResultBuf *pResultBuf = pRuntimeEnv->pResultBuf; + int64_t v = -1; + // not assign result buffer yet, add new result buffer + switch(type) { + case TSDB_DATA_TYPE_BOOL: + case TSDB_DATA_TYPE_TINYINT: v = GET_INT8_VAL(pData); break; + case TSDB_DATA_TYPE_SMALLINT: v = GET_INT16_VAL(pData); break; + case TSDB_DATA_TYPE_INT: v = GET_INT32_VAL(pData); break; + case TSDB_DATA_TYPE_BIGINT: v = GET_INT64_VAL(pData); break; + } + +// assert(pRuntimeEnv->windowResInfo.hashList->size <= 2); SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, pData, bytes); if (pWindowRes == NULL) { return -1; } - // not assign result buffer yet, add new result buffer + pWindowRes->window.skey = v; + pWindowRes->window.ekey = v; + if (pWindowRes->pos.pageId == -1) { int32_t ret = addNewWindowResultBuf(pWindowRes, pResultBuf, GROUPRESULTID, pRuntimeEnv->numOfRowsPerPage); if (ret != 0) { @@ -1022,12 +1035,16 @@ static bool functionNeedToExecute(SQueryRuntimeEnv *pRuntimeEnv, SQLFunctionCtx return false; } - if (functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST) { - return !QUERY_IS_ASC_QUERY(pQuery); - } else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) { + if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_FIRST) { return QUERY_IS_ASC_QUERY(pQuery); } - + + // todo add comments + if ((functionId == TSDB_FUNC_LAST_DST || functionId == TSDB_FUNC_LAST)) { + return pCtx->param[0].i64Key == pQuery->order.order; +// return !QUERY_IS_ASC_QUERY(pQuery); + } + // in the supplementary scan, only the following functions need to be executed if (IS_REVERSE_SCAN(pRuntimeEnv)) { return false; @@ -1079,7 +1096,7 @@ static void rowwiseApplyFunctions(SQueryRuntimeEnv *pRuntimeEnv, SDataStatis *pS int32_t j = 0; int32_t offset = -1; - + for (j = 0; j < pDataBlockInfo->rows; ++j) { offset = GET_COL_DATA_POS(pQuery, j, step); @@ -1478,6 +1495,7 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { } static bool isQueryKilled(SQInfo *pQInfo) { + return false; return (pQInfo->code == TSDB_CODE_TSC_QUERY_CANCELLED); #if 0 /* @@ -1574,10 +1592,14 @@ static bool needReverseScan(SQuery *pQuery) { continue; } - if (((functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) && QUERY_IS_ASC_QUERY(pQuery)) || - ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery))) { + if ((functionId == TSDB_FUNC_FIRST || functionId == TSDB_FUNC_FIRST_DST) && !QUERY_IS_ASC_QUERY(pQuery)) { return true; } + + if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) { + int32_t order = pQuery->pSelectExpr[i].base.arg->argValue.i64; + return order != pQuery->order.order; + } } return false; @@ -2030,6 +2052,34 @@ int32_t binarySearchForKey(char *pValue, int num, TSKEY key, int order) { return midPos; } +static void ensureOutputBufferSimple(SQueryRuntimeEnv* pRuntimeEnv, int32_t capacity) { + SQuery* pQuery = pRuntimeEnv->pQuery; + + if (capacity < pQuery->rec.capacity) { + return; + } + + for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { + int32_t bytes = pQuery->pSelectExpr[i].bytes; + assert(bytes > 0 && capacity > 0); + + char *tmp = realloc(pQuery->sdata[i], bytes * capacity + sizeof(tFilePage)); + if (tmp == NULL) { // todo handle the oom + assert(0); + } else { + pQuery->sdata[i] = (tFilePage *)tmp; + } + + // set the pCtx output buffer position + pRuntimeEnv->pCtx[i].aOutputBuf = pQuery->sdata[i]->data; + } + + qTrace("QInfo:%p realloc output buffer to inc output buffer from: %d rows to:%d rows", GET_QINFO_ADDR(pRuntimeEnv), + pQuery->rec.capacity, capacity); + + pQuery->rec.capacity = capacity; +} + static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pBlockInfo) { // in case of prj/diff query, ensure the output buffer is sufficient to accommodate the results of current block SQuery* pQuery = pRuntimeEnv->pQuery; @@ -2916,8 +2966,7 @@ void skipResults(SQueryRuntimeEnv *pRuntimeEnv) { pRuntimeEnv->pCtx[i].ptsOutputBuf = pRuntimeEnv->pCtx[0].aOutputBuf; } } - - + updateNumOfResult(pRuntimeEnv, pQuery->rec.rows); } } @@ -3054,7 +3103,7 @@ static void clearEnvAfterReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatus pQuery->window = pTableQueryInfo->win; } -void scanAllDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { +void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { SQInfo *pQInfo = (SQInfo *) GET_QINFO_ADDR(pRuntimeEnv); SQuery *pQuery = pRuntimeEnv->pQuery; STableQueryInfo *pTableQueryInfo = pQuery->current; @@ -3496,18 +3545,32 @@ void copyFromWindowResToSData(SQInfo *pQInfo, SWindowResult *result) { assert(pQuery->rec.rows <= pQuery->rec.capacity); } -static void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv, STableQueryInfo *pTableQueryInfo) { +static UNUSED_FUNC void updateWindowResNumOfRes(SQueryRuntimeEnv *pRuntimeEnv, STableQueryInfo *pTableQueryInfo) { SQuery *pQuery = pRuntimeEnv->pQuery; // update the number of result for each, only update the number of rows for the corresponding window result. if (pQuery->intervalTime == 0) { - int32_t g = pTableQueryInfo->groupIndex; - assert(pRuntimeEnv->windowResInfo.size > 0); - SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&g, sizeof(g)); - if (pWindowRes->numOfRows == 0) { - pWindowRes->numOfRows = getNumOfResult(pRuntimeEnv); + for (int32_t i = 0; i < pRuntimeEnv->windowResInfo.size; ++i) { + SWindowResult *pResult = &pRuntimeEnv->windowResInfo.pResult[i]; + + for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { + int32_t functionId = pRuntimeEnv->pCtx[j].functionId; + if (functionId == TSDB_FUNC_TS || functionId == TSDB_FUNC_TAG || functionId == TSDB_FUNC_TAGPRJ) { + continue; + } + + pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes); + } } + +// int32_t g = pTableQueryInfo->groupIndex; +// assert(pRuntimeEnv->windowResInfo.size > 0); +// +// SWindowResult *pWindowRes = doSetTimeWindowFromKey(pRuntimeEnv, &pRuntimeEnv->windowResInfo, (char *)&g, sizeof(g)); +// if (pWindowRes->numOfRows == 0) { +// pWindowRes->numOfRows = getNumOfResult(pRuntimeEnv); +// } } } @@ -4081,21 +4144,22 @@ static int64_t scanMultiTableDataBlocks(SQInfo *pQInfo) { SDataStatis *pStatis = NULL; SArray *pDataBlock = loadDataBlockOnDemand(pRuntimeEnv, pQueryHandle, &blockInfo, &pStatis); - if (!isIntervalQuery(pQuery)) { - int32_t step = QUERY_IS_ASC_QUERY(pQuery)? 1:-1; - setExecutionContext(pQInfo, &pTableQueryInfo->id, pTableQueryInfo->groupIndex, blockInfo.window.ekey + step); - } else { // interval query - TSKEY nextKey = blockInfo.window.skey; - setIntervalQueryRange(pQInfo, nextKey); - /*int32_t ret = */setAdditionalInfo(pQInfo, &pTableQueryInfo->id, pTableQueryInfo); + if (!isGroupbyNormalCol(pQuery->pGroupbyExpr)) { + if (!isIntervalQuery(pQuery)) { + int32_t step = QUERY_IS_ASC_QUERY(pQuery)? 1:-1; + setExecutionContext(pQInfo, &pTableQueryInfo->id, pTableQueryInfo->groupIndex, blockInfo.window.ekey + step); + } else { // interval query + TSKEY nextKey = blockInfo.window.skey; + setIntervalQueryRange(pQInfo, nextKey); + /*int32_t ret = */setAdditionalInfo(pQInfo, &pTableQueryInfo->id, pTableQueryInfo); + } } summary->totalRows += blockInfo.rows; stableApplyFunctionsOnBlock(pRuntimeEnv, &blockInfo, pStatis, pDataBlock, binarySearchForKey); qTrace("QInfo:%p check data block, uid:%"PRId64", tid:%d, brange:%" PRId64 "-%" PRId64 ", numOfRows:%d, lastKey:%" PRId64, - GET_QINFO_ADDR(pRuntimeEnv), blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, - blockInfo.rows, pQuery->current->lastKey); + pQInfo, blockInfo.uid, blockInfo.tid, blockInfo.window.skey, blockInfo.window.ekey, blockInfo.rows, pQuery->current->lastKey); } int64_t et = taosGetTimestampMs(); @@ -4220,7 +4284,7 @@ static void sequentialTableProcess(SQInfo *pQInfo) { // here we simply set the first table as current table pQuery->current = ((SGroupItem*) taosArrayGet(group, 0))->info; - scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey); + scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); int64_t numOfRes = getNumOfResult(pRuntimeEnv); if (numOfRes > 0) { @@ -4233,10 +4297,84 @@ static void sequentialTableProcess(SQInfo *pQInfo) { // enable execution for next table, when handling the projection query enableExecutionForNextTable(pRuntimeEnv); + + if (pQuery->rec.rows >= pQuery->rec.capacity) { + setQueryStatus(pQuery, QUERY_RESBUF_FULL); + break; + } + } + } else if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { // group-by on normal columns query + while (pQInfo->groupIndex < numOfGroups) { + SArray* group = taosArrayGetP(pQInfo->groupInfo.pGroupList, pQInfo->groupIndex); + + qTrace("QInfo:%p group by normal columns group:%d, total group:%d", pQInfo, pQInfo->groupIndex, numOfGroups); + + STsdbQueryCond cond = { + .twindow = pQuery->window, + .colList = pQuery->colList, + .order = pQuery->order.order, + .numOfCols = pQuery->numOfCols, + }; + + SArray *g1 = taosArrayInit(1, POINTER_BYTES); + SArray *tx = taosArrayClone(group); + taosArrayPush(g1, &tx); + + STableGroupInfo gp = {.numOfTables = taosArrayGetSize(tx), .pGroupList = g1}; + + // include only current table + if (pRuntimeEnv->pQueryHandle != NULL) { + tsdbCleanupQueryHandle(pRuntimeEnv->pQueryHandle); + pRuntimeEnv->pQueryHandle = NULL; + } + + pRuntimeEnv->pQueryHandle = tsdbQueryTables(pQInfo->tsdb, &cond, &gp, pQInfo); + + SArray* s = tsdbGetQueriedTableIdList(pRuntimeEnv->pQueryHandle); + assert(taosArrayGetSize(s) >= 1); + + setTagVal(pRuntimeEnv, (STableId*) taosArrayGet(s, 0), pQInfo->tsdb); + + // here we simply set the first table as current table + scanMultiTableDataBlocks(pQInfo); + pQInfo->groupIndex += 1; + + SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo; + + // no results generated for current group, continue to try the next group + if (pWindowResInfo->size <= 0) { + continue; + } + + for (int32_t i = 0; i < pWindowResInfo->size; ++i) { + SWindowStatus *pStatus = &pWindowResInfo->pResult[i].status; + pStatus->closed = true; // enable return all results for group by normal columns + + SWindowResult *pResult = &pWindowResInfo->pResult[i]; + for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { + pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes); + } + } + + qTrace("QInfo:%p generated groupby columns results %d rows for group %d completed", pQInfo, pWindowResInfo->size, + pQInfo->groupIndex); + int32_t currentGroupIndex = pQInfo->groupIndex; + + pQuery->rec.rows = 0; + pQInfo->groupIndex = 0; + + ensureOutputBufferSimple(pRuntimeEnv, pWindowResInfo->size); + copyFromWindowResToSData(pQInfo, pWindowResInfo->pResult); + + pQInfo->groupIndex = currentGroupIndex; //restore the group index + assert(pQuery->rec.rows == pWindowResInfo->size); + + clearClosedTimeWindow(pRuntimeEnv); + break; } } else { /* - * 1. super table projection query, 2. group-by on normal columns query, 3. ts-comp query + * 1. super table projection query, 2. ts-comp query * if the subgroup index is larger than 0, results generated by group by tbname,k is existed. * we need to return it to client in the first place. */ @@ -4283,7 +4421,7 @@ static void sequentialTableProcess(SQInfo *pQInfo) { } } - scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey); + scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); skipResults(pRuntimeEnv); // the limitation of output result is reached, set the query completed @@ -4349,25 +4487,6 @@ static void sequentialTableProcess(SQInfo *pQInfo) { pRuntimeEnv->cur = pRuntimeEnv->pTSBuf->cur; } - // todo refactor - if (isGroupbyNormalCol(pQuery->pGroupbyExpr)) { - SWindowResInfo *pWindowResInfo = &pRuntimeEnv->windowResInfo; - - for (int32_t i = 0; i < pWindowResInfo->size; ++i) { - SWindowStatus *pStatus = &pWindowResInfo->pResult[i].status; - pStatus->closed = true; // enable return all results for group by normal columns - - SWindowResult *pResult = &pWindowResInfo->pResult[i]; - for (int32_t j = 0; j < pQuery->numOfOutput; ++j) { - pResult->numOfRows = MAX(pResult->numOfRows, pResult->resultInfo[j].numOfRes); - } - } - - pQInfo->groupIndex = 0; - pQuery->rec.rows = 0; - copyFromWindowResToSData(pQInfo, pWindowResInfo->pResult); - } - qTrace( "QInfo %p numOfTables:%d, index:%d, numOfGroups:%d, %d points returned, total:%"PRId64", offset:%" PRId64, pQInfo, pQInfo->groupInfo.numOfTables, pQInfo->tableIndex, numOfGroups, pQuery->rec.rows, pQuery->rec.total, @@ -4449,7 +4568,6 @@ static void multiTableQueryProcess(SQInfo *pQInfo) { */ if (isIntervalQuery(pQuery)) { copyResToQueryResultBuf(pQInfo, pQuery); - #ifdef _DEBUG_VIEW displayInterResult(pQuery->sdata, pRuntimeEnv, pQuery->sdata[0]->num); #endif @@ -4527,7 +4645,7 @@ static void tableFixedOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) pQuery->current = pTableInfo; // set current query table info - scanAllDataBlocks(pRuntimeEnv, pTableInfo->lastKey); + scanOneTableDataBlocks(pRuntimeEnv, pTableInfo->lastKey); finalizeQueryResult(pRuntimeEnv); if (isQueryKilled(pQInfo)) { @@ -4560,7 +4678,7 @@ static void tableMultiOutputProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) } while (1) { - scanAllDataBlocks(pRuntimeEnv, pQuery->current->lastKey); + scanOneTableDataBlocks(pRuntimeEnv, pQuery->current->lastKey); finalizeQueryResult(pRuntimeEnv); if (isQueryKilled(pQInfo)) { @@ -4607,7 +4725,7 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) SQuery *pQuery = pRuntimeEnv->pQuery; while (1) { - scanAllDataBlocks(pRuntimeEnv, start); + scanOneTableDataBlocks(pRuntimeEnv, start); if (isQueryKilled(GET_QINFO_ADDR(pRuntimeEnv))) { return; diff --git a/src/query/src/qUtil.c b/src/query/src/qUtil.c index 143d86d5db..aa5550efcb 100644 --- a/src/query/src/qUtil.c +++ b/src/query/src/qUtil.c @@ -113,7 +113,9 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { for (int32_t i = 0; i < num; ++i) { SWindowResult *pResult = &pWindowResInfo->pResult[i]; if (pResult->status.closed) { // remove the window slot from hash table - taosHashRemove(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE); + taosHashRemove(pWindowResInfo->hashList, (const char *)&pResult->window.skey, pWindowResInfo->type); + printf("remove ============>%ld, remain size:%ld\n", pResult->window.skey, pWindowResInfo->hashList->size); + } else { break; } @@ -133,14 +135,16 @@ void clearFirstNTimeWindow(SQueryRuntimeEnv *pRuntimeEnv, int32_t num) { } pWindowResInfo->size = remain; - + printf("---------------size:%ld\n", taosHashGetSize(pWindowResInfo->hashList)); for (int32_t k = 0; k < pWindowResInfo->size; ++k) { SWindowResult *pResult = &pWindowResInfo->pResult[k]; - int32_t *p = (int32_t *)taosHashGet(pWindowResInfo->hashList, (const char *)&pResult->window.skey, TSDB_KEYSIZE); + int32_t *p = (int32_t *)taosHashGet(pWindowResInfo->hashList, (const char *)&pResult->window.skey, + tDataTypeDesc[pWindowResInfo->type].nSize); int32_t v = (*p - num); assert(v >= 0 && v <= pWindowResInfo->size); - taosHashPut(pWindowResInfo->hashList, (char *)&pResult->window.skey, TSDB_KEYSIZE, (char *)&v, sizeof(int32_t)); + taosHashPut(pWindowResInfo->hashList, (char *)&pResult->window.skey, tDataTypeDesc[pWindowResInfo->type].nSize, + (char *)&v, sizeof(int32_t)); } pWindowResInfo->curIndex = -1; diff --git a/tests/script/general/parser/groupby.sim b/tests/script/general/parser/groupby.sim index 513b3cbbbe..5d785a2fc3 100644 --- a/tests/script/general/parser/groupby.sim +++ b/tests/script/general/parser/groupby.sim @@ -355,7 +355,7 @@ if $data00 != 0 then return -1 endi -if $data01 != 800 then +if $data11 != 800 then return -1 endi diff --git a/tests/script/general/parser/import_commit3.sim b/tests/script/general/parser/import_commit3.sim index 916bf6d05e..99ece98278 100644 --- a/tests/script/general/parser/import_commit3.sim +++ b/tests/script/general/parser/import_commit3.sim @@ -25,7 +25,7 @@ step1: sql create database $db cache 16 print ====== create tables sql use $db - +sql reset query cache $i = 0 $ts = $ts0 $tb = $tbPrefix . $i From 315fa7404247750306afc9450699cac36f3cf761 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 11:58:58 +0800 Subject: [PATCH 08/37] [td-225] do not execute query if the link is already broken. --- src/inc/query.h | 3 ++- src/vnode/src/vnodeRead.c | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/inc/query.h b/src/inc/query.h index 10ee0249b6..49ee5248f5 100644 --- a/src/inc/query.h +++ b/src/inc/query.h @@ -70,7 +70,8 @@ int32_t qRetrieveQueryResultInfo(qinfo_t qinfo); int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp** pRsp, int32_t* contLen); /** - * Decide if more results will be produced or not + * Decide if more results will be produced or not, NOTE: this function will increase the ref count of QInfo, + * so it can be only called once for each retrieve * * @param qinfo * @return diff --git a/src/vnode/src/vnodeRead.c b/src/vnode/src/vnodeRead.c index d6227f4270..1e770d8d27 100644 --- a/src/vnode/src/vnodeRead.c +++ b/src/vnode/src/vnodeRead.c @@ -61,7 +61,7 @@ int32_t vnodeProcessRead(void *param, SReadMsg *pReadMsg) { // notify connection(handle) that current qhandle is created, if current connection from // client is broken, the query needs to be killed immediately. -static void vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) { +static int32_t vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) { SRetrieveTableMsg* killQueryMsg = rpcMallocCont(sizeof(SRetrieveTableMsg)); killQueryMsg->qhandle = htobe64((uint64_t) qhandle); killQueryMsg->free = htons(1); @@ -69,7 +69,7 @@ static void vnodeNotifyCurrentQhandle(void* handle, void* qhandle, int32_t vgId) killQueryMsg->header.contLen = htonl(sizeof(SRetrieveTableMsg)); vTrace("QInfo:%p register qhandle to connect:%p", qhandle, handle); - rpcReportProgress(handle, (char*) killQueryMsg, sizeof(SRetrieveTableMsg)); + return rpcReportProgress(handle, (char*) killQueryMsg, sizeof(SRetrieveTableMsg)); } static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { @@ -106,7 +106,17 @@ static int32_t vnodeProcessQueryMsg(SVnodeObj *pVnode, SReadMsg *pReadMsg) { pRet->len = sizeof(SQueryTableRsp); pRet->rsp = pRsp; - vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, pQInfo, pVnode->vgId); + // current connect is broken + if (vnodeNotifyCurrentQhandle(pReadMsg->rpcMsg.handle, pQInfo, pVnode->vgId) != TSDB_CODE_SUCCESS) { + vError("vgId:%d, QInfo:%p, dnode query discarded since link is broken, %p", pVnode->vgId, pQInfo, pReadMsg->rpcMsg.handle); + pRsp->code = TSDB_CODE_RPC_NETWORK_UNAVAIL; + + //NOTE: there two refcount, needs to kill twice, todo refactor + qKillQuery(pQInfo); + qKillQuery(pQInfo); + + return pRsp->code; + } vTrace("vgId:%d, QInfo:%p, dnode query msg disposed", pVnode->vgId, pQInfo); } else { From e65be1be0d3e627149873033aa69609488ea089a Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 12:56:48 +0800 Subject: [PATCH 09/37] [td-225] fix bugs in restore from core dump --- src/mnode/src/mnodeDb.c | 9 ++++++--- src/mnode/src/mnodeTable.c | 10 ++++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/mnode/src/mnodeDb.c b/src/mnode/src/mnodeDb.c index 3666d61adc..69783defc7 100644 --- a/src/mnode/src/mnodeDb.c +++ b/src/mnode/src/mnodeDb.c @@ -84,9 +84,12 @@ static int32_t mnodeDbActionDelete(SSdbOper *pOper) { mnodeDropAllChildTables(pDb); mnodeDropAllSuperTables(pDb); mnodeDropAllDbVgroups(pDb); - mnodeDropDbFromAcct(pAcct, pDb); - mnodeDecAcctRef(pAcct); - + + if (pAcct) { + mnodeDropDbFromAcct(pAcct, pDb); + mnodeDecAcctRef(pAcct); + } + return TSDB_CODE_SUCCESS; } diff --git a/src/mnode/src/mnodeTable.c b/src/mnode/src/mnodeTable.c index 478e7790fb..0ff198bf8f 100644 --- a/src/mnode/src/mnodeTable.c +++ b/src/mnode/src/mnodeTable.c @@ -157,10 +157,12 @@ static int32_t mnodeChildTableActionDelete(SSdbOper *pOper) { if (pDb != NULL) pAcct = mnodeGetAcct(pDb->acct); if (pTable->info.type == TSDB_CHILD_TABLE) { - grantRestore(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); - if (pAcct != NULL) pAcct->acctInfo.numOfTimeSeries -= (pTable->superTable->numOfColumns - 1); - mnodeRemoveTableFromStable(pTable->superTable, pTable); - mnodeDecTableRef(pTable->superTable); + if (pTable->superTable) { + grantRestore(TSDB_GRANT_TIMESERIES, pTable->superTable->numOfColumns - 1); + if (pAcct != NULL) pAcct->acctInfo.numOfTimeSeries -= (pTable->superTable->numOfColumns - 1); + mnodeRemoveTableFromStable(pTable->superTable, pTable); + mnodeDecTableRef(pTable->superTable); + } } else { grantRestore(TSDB_GRANT_TIMESERIES, pTable->numOfColumns - 1); if (pAcct != NULL) pAcct->acctInfo.numOfTimeSeries -= (pTable->numOfColumns - 1); From 1c07ab90639fb6a1bb1fb25a296229bcbeeea440 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 13:10:21 +0800 Subject: [PATCH 10/37] [td-225] --- src/query/src/qExecutor.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 13b4511177..d4cd536adb 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1495,7 +1495,6 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { } static bool isQueryKilled(SQInfo *pQInfo) { - return false; return (pQInfo->code == TSDB_CODE_TSC_QUERY_CANCELLED); #if 0 /* From f6a5c0eabeec2d657da851bf5ec7ac16528f8101 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 13:13:31 +0800 Subject: [PATCH 11/37] [td-225] fix bugs in group by normal columns --- src/query/src/qExecutor.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index d4cd536adb..6ea73827ec 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -1496,19 +1496,6 @@ static void teardownQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv) { static bool isQueryKilled(SQInfo *pQInfo) { return (pQInfo->code == TSDB_CODE_TSC_QUERY_CANCELLED); -#if 0 - /* - * check if the queried meter is going to be deleted. - * if it will be deleted soon, stop current query ASAP. - */ - SMeterObj *pMeterObj = pQInfo->pObj; - if (vnodeIsMeterState(pMeterObj, TSDB_METER_STATE_DROPPING)) { - pQInfo->killed = 1; - return true; - } - - return (pQInfo->killed == 1); -#endif } static void setQueryKilled(SQInfo *pQInfo) { pQInfo->code = TSDB_CODE_TSC_QUERY_CANCELLED; } From 9ed2c049f5972e30da457a688abef11c10c7d843 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 13:31:17 +0800 Subject: [PATCH 12/37] [td-225] fix bugs in group by normal columns --- src/query/src/qExecutor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 6ea73827ec..a1af147b62 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -3568,7 +3568,7 @@ void stableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo * SWindowResInfo * pWindowResInfo = &pTableQueryInfo->windowResInfo; pQuery->pos = QUERY_IS_ASC_QUERY(pQuery)? 0 : pDataBlockInfo->rows - 1; - if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL) { + if (pQuery->numOfFilterCols > 0 || pRuntimeEnv->pTSBuf != NULL || isGroupbyNormalCol(pQuery->pGroupbyExpr)) { rowwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pWindowResInfo, pDataBlock); } else { blockwiseApplyFunctions(pRuntimeEnv, pStatis, pDataBlockInfo, pWindowResInfo, searchFn, pDataBlock); From 25a395ef8099b2297b878b8d9299279538ff40fc Mon Sep 17 00:00:00 2001 From: Hui Li Date: Sat, 13 Jun 2020 13:37:28 +0800 Subject: [PATCH 13/37] [TD-605] --- src/client/src/tscSQLParser.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 60415a8d74..d0b3d91d3b 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -1990,6 +1990,7 @@ static int16_t doGetColumnIndex(SQueryInfo* pQueryInfo, int32_t index, SSQLToken if (strncasecmp(pSchema[i].name, pToken->z, pToken->n) == 0) { columnIndex = i; + break; } } @@ -2886,7 +2887,8 @@ static int32_t extractColumnFilterInfo(SQueryInfo* pQueryInfo, SColumnIndex* pIn SSchema* pSchema = tscGetTableColumnSchema(pTableMeta, pIndex->columnIndex); const char* msg1 = "non binary column not support like operator"; - const char* msg2 = "binary column not support this operator"; + const char* msg2 = "binary column not support this operator"; + const char* msg3 = "bool column not support this operator"; SColumn* pColumn = tscColumnListInsert(pQueryInfo->colList, pIndex); SColumnFilterInfo* pColFilter = NULL; @@ -2920,6 +2922,12 @@ static int32_t extractColumnFilterInfo(SQueryInfo* pQueryInfo, SColumnIndex* pIn if (pExpr->nSQLOptr == TK_LIKE) { return invalidSqlErrMsg(pQueryInfo->msg, msg1); } + + if (pSchema->type == TSDB_DATA_TYPE_BOOL) { + if (pExpr->nSQLOptr != TK_EQ && pExpr->nSQLOptr != TK_NE) { + return invalidSqlErrMsg(pQueryInfo->msg, msg3); + } + } } pColumn->colIndex = *pIndex; @@ -6052,6 +6060,12 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray* } } } + + if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL || pRight->pVal->nType == TSDB_DATA_TYPE_BINARY || pRight->pVal->nType == TSDB_DATA_TYPE_NCHAR) { + if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { + return TSDB_CODE_TSC_INVALID_SQL; + } + } } return TSDB_CODE_SUCCESS; From fe2bd893c3b4921334202fac5030c6f152438e9c Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 13:40:11 +0800 Subject: [PATCH 14/37] [td-225] update the tests scripts --- tests/script/general/parser/testSuite.sim | 64 +++++++++++------------ 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/script/general/parser/testSuite.sim b/tests/script/general/parser/testSuite.sim index 4a3da2f2a0..67ef952c41 100644 --- a/tests/script/general/parser/testSuite.sim +++ b/tests/script/general/parser/testSuite.sim @@ -40,42 +40,42 @@ #run general/parser/nchar.sim #sleep 2000 ##run general/parser/null_char.sim -#sleep 2000 -#run general/parser/single_row_in_tb.sim -#sleep 2000 -#run general/parser/select_from_cache_disk.sim -#sleep 2000 -#run general/parser/selectResNum.sim -#sleep 2000 -#run general/parser/mixed_blocks.sim -#sleep 2000 -#run general/parser/limit1.sim -#sleep 2000 -#run general/parser/limit.sim -#sleep 2000 -#run general/parser/limit1_tblocks100.sim -#sleep 2000 -#run general/parser/select_across_vnodes.sim -#sleep 2000 -#run general/parser/slimit1.sim -#sleep 2000 -#run general/parser/tbnameIn.sim -#sleep 2000 +sleep 2000 +run general/parser/single_row_in_tb.sim +sleep 2000 +run general/parser/select_from_cache_disk.sim +sleep 2000 +run general/parser/selectResNum.sim +sleep 2000 +run general/parser/mixed_blocks.sim +sleep 2000 +run general/parser/limit1.sim +sleep 2000 +run general/parser/limit.sim +sleep 2000 +run general/parser/limit1_tblocks100.sim +sleep 2000 +run general/parser/select_across_vnodes.sim +sleep 2000 +run general/parser/slimit1.sim +sleep 2000 +run general/parser/tbnameIn.sim +sleep 2000 run general/parser/projection_limit_offset.sim sleep 2000 run general/parser/limit2.sim sleep 2000 -#run general/parser/fill.sim -#sleep 2000 -#run general/parser/fill_stb.sim -#sleep 2000 -#run general/parser/where.sim -#sleep 2000 -#run general/parser/slimit.sim -#sleep 2000 -#run general/parser/select_with_tags.sim -#sleep 2000 -#run general/parser/interp.sim +run general/parser/fill.sim +sleep 2000 +run general/parser/fill_stb.sim +sleep 2000 +run general/parser/where.sim +sleep 2000 +run general/parser/slimit.sim +sleep 2000 +run general/parser/select_with_tags.sim +sleep 2000 +run general/parser/interp.sim sleep 2000 run general/parser/tags_dynamically_specifiy.sim sleep 2000 From 65d580b8f77ae6065e8d808f4730a6eb3faa6772 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 13 Jun 2020 13:45:11 +0800 Subject: [PATCH 15/37] move more cases from full test to regression test. --- tests/script/regressionSuite.sim | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/tests/script/regressionSuite.sim b/tests/script/regressionSuite.sim index 40aacd4e98..6ef4001495 100644 --- a/tests/script/regressionSuite.sim +++ b/tests/script/regressionSuite.sim @@ -70,9 +70,9 @@ run general/http/restful_insert.sim run general/http/restful_limit.sim run general/http/restful_full.sim run general/http/prepare.sim -# run general/http/telegraf.sim -# run general/http/grafana_bug.sim -# run general/http/grafana.sim +run general/http/telegraf.sim +run general/http/grafana_bug.sim +run general/http/grafana.sim run general/import/basic.sim run general/import/commit.sim run general/import/large.sim @@ -102,32 +102,32 @@ run general/parser/import_commit1.sim run general/parser/import_commit2.sim run general/parser/import_commit3.sim run general/parser/insert_tb.sim -# run general/parser/first_last.sim +run general/parser/first_last.sim #unsupport run general/parser/import_file.sim -# run general/parser/lastrow.sim +run general/parser/lastrow.sim run general/parser/nchar.sim #unsupport run general/parser/null_char.sim -# run general/parser/single_row_in_tb.sim +run general/parser/single_row_in_tb.sim run general/parser/select_from_cache_disk.sim -# run general/parser/limit.sim +run general/parser/limit.sim # run general/parser/limit1.sim -# run general/parser/limit1_tblocks100.sim -# run general/parser/mixed_blocks.sim +run general/parser/limit1_tblocks100.sim +run general/parser/mixed_blocks.sim # run general/parser/selectResNum.sim run general/parser/select_across_vnodes.sim run general/parser/slimit1.sim run general/parser/tbnameIn.sim run general/parser/binary_escapeCharacter.sim -# run general/parser/projection_limit_offset.sim +run general/parser/projection_limit_offset.sim run general/parser/limit2.sim -# run general/parser/slimit.sim +run general/parser/slimit.sim run general/parser/fill.sim -# run general/parser/fill_stb.sim +run general/parser/fill_stb.sim # run general/parser/interp.sim # run general/parser/where.sim #unsupport run general/parser/join.sim #unsupport run general/parser/join_multivnode.sim -# run general/parser/select_with_tags.sim +run general/parser/select_with_tags.sim #unsupport run general/parser/groupby.sim #unsupport run general/parser/bug.sim #unsupport run general/parser/tags_dynamically_specifiy.sim @@ -142,7 +142,7 @@ run general/stable/dnode3.sim run general/stable/metrics.sim run general/stable/values.sim run general/stable/vnode3.sim -# run general/table/autocreate.sim +run general/table/autocreate.sim run general/table/basic1.sim run general/table/basic2.sim run general/table/basic3.sim @@ -166,7 +166,7 @@ run general/table/int.sim run general/table/limit.sim run general/table/smallint.sim run general/table/table_len.sim -# run general/table/table.sim +run general/table/table.sim run general/table/tinyint.sim run general/table/vgroup.sim run general/tag/3.sim @@ -214,6 +214,7 @@ run general/vector/table_time.sim run general/stream/stream_1.sim run general/stream/stream_2.sim run general/stream/stream_3.sim +run general/stream/stream_restart.sim run general/stream/table_1.sim run general/stream/metrics_1.sim run general/stream/table_n.sim From 1d6edcfed8fcaaa207fe7a1a5ffa3507aa5efed2 Mon Sep 17 00:00:00 2001 From: Ping Xiao Date: Sat, 13 Jun 2020 13:48:53 +0800 Subject: [PATCH 16/37] [TD-350]: sort test case for both columns and tags all - supporting types --- tests/pytest/query/querySort.py | 80 +++++++++++++++++++++++++++++++++ tests/pytest/util/sql.py | 35 +++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 tests/pytest/query/querySort.py diff --git a/tests/pytest/query/querySort.py b/tests/pytest/query/querySort.py new file mode 100644 index 0000000000..bb806c27bc --- /dev/null +++ b/tests/pytest/query/querySort.py @@ -0,0 +1,80 @@ +################################################################### +# Copyright (c) 2016 by TAOS Technologies, Inc. +# All rights reserved. +# +# This file is proprietary and confidential to TAOS Technologies. +# No part of this file may be reproduced, stored, transmitted, +# disclosed or used in any form or by any means other than as +# expressly provided by the written permission from Jianhui Tao +# +################################################################### + +# -*- coding: utf-8 -*- + +import sys +import taos +from util.log import * +from util.cases import * +from util.sql import * + + +class TDTestCase: + def init(self, conn, logSql): + tdLog.debug("start to execute %s" % __file__) + tdSql.init(conn.cursor()) + + self.rowNum = 10 + self.ts = 1537146000000 + + def run(self): + tdSql.prepare() + + print("======= step 1: create table and insert data =========") + tdLog.debug( + ''' create table st(ts timestamp, tbcol1 tinyint, tbcol2 smallint, tbcol3 int, tbcol4 bigint, tbcol5 float, tbcol6 double, + tbcol7 bool, tbcol8 nchar(20), tbcol9 binary(20)) tags(tagcol1 tinyint, tagcol2 smallint, tagcol3 int, tagcol4 bigint, tagcol5 float, + tagcol6 double, tagcol7 bool, tagcol8 nchar(20), tagcol9 binary(20))''') + tdSql.execute( + ''' create table st(ts timestamp, tbcol1 tinyint, tbcol2 smallint, tbcol3 int, tbcol4 bigint, tbcol5 float, tbcol6 double, + tbcol7 bool, tbcol8 nchar(20), tbcol9 binary(20)) tags(tagcol1 tinyint, tagcol2 smallint, tagcol3 int, tagcol4 bigint, tagcol5 float, + tagcol6 double, tagcol7 bool, tagcol8 nchar(20), tagcol9 binary(20))''') + + for i in range(self.rowNum): + tdSql.execute("create table st%d using st tags(%d, %d, %d, %d, %f, %f, %d, 'tag%d', '标签%d')" % (i + 1, i + 1, i + 1, i + 1, i + 1, 1.1 * (i + 1), + 1.23 * (i + 1), (i + 1) % 2, i + 1, i + 1)) + for j in range(self.rowNum): + tdSql.execute("insert into st%d values(%d, %d, %d, %d, %d, %f, %f, %d, 'taosdata%d', '涛思数据%d')" % (i + 1, self.ts + 10 * (i + 1) + j + 1, + j + 1, j + 1, j + 1, j + 1, 1.1 * (j + 1), 1.23 * (j + 1), (j + 1) % 2, j + 1, j + 1)) + + + print("======= step 2: verify order for each column =========") + # sort for timestamp in asc order + tdSql.query("select * from st order by ts asc") + tdSql.checkColumnSorted(0, "asc") + + # sort for timestamp in desc order + tdSql.query("select * from st order by ts desc") + tdSql.checkColumnSorted(0, "desc") + + + for i in range(1, 10): + tdSql.error("select * from st order by tbcol%d" % i) + tdSql.error("select * from st order by tbcol%d asc" % i) + tdSql.error("select * from st order by tbcol%d desc" % i) + + tdSql.query("select avg(tbcol1) from st group by tagcol%d order by tagcol%d" % (i, i)) + tdSql.checkColumnSorted(1, "") + + tdSql.query("select avg(tbcol1) from st group by tagcol%d order by tagcol%d asc" % (i, i)) + tdSql.checkColumnSorted(1, "asc") + + tdSql.query("select avg(tbcol1) from st group by tagcol%d order by tagcol%d desc" % (i, i)) + tdSql.checkColumnSorted(1, "desc") + + def stop(self): + tdSql.close() + tdLog.success("%s successfully executed" % __file__) + + +tdCases.addWindows(__file__, TDTestCase()) +tdCases.addLinux(__file__, TDTestCase()) diff --git a/tests/pytest/util/sql.py b/tests/pytest/util/sql.py index ec7ac117c0..367217cd49 100644 --- a/tests/pytest/util/sql.py +++ b/tests/pytest/util/sql.py @@ -17,6 +17,7 @@ import time import datetime import inspect from util.log import * +import numpy as np class TDSql: @@ -196,5 +197,39 @@ class TDSql: tdLog.info("sql:%s, affectedRows:%d == expect:%d" % (self.sql, self.affectedRows, expectAffectedRows)) + def checkColumnSorted(self, col, order): + frame = inspect.stack()[1] + callerModule = inspect.getmodule(frame[0]) + callerFilename = callerModule.__file__ + + if col < 0: + tdLog.exit( + "%s failed: sql:%s, col:%d is smaller than zero" % + (callerFilename, self.sql, col)) + if col > self.queryCols: + tdLog.exit( + "%s failed: sql:%s, col:%d is larger than queryCols:%d" % + (callerFilename, self.sql, col, self.queryCols)) + + matrix = np.array(self.queryResult) + list = matrix[:, 0] + + if order == "" or order.upper() == "ASC": + if all(sorted(list) == list): + tdLog.info("sql:%s, column :%d is sorted in accending order as expected" % + (self.sql, col)) + else: + tdLog.exit("%s failed: sql:%s, col:%d is not sorted in accesnind order" % + (callerFilename, self.sql, col)) + elif order.upper() == "DESC": + if all(sorted(list, reverse=True) == list): + tdLog.info("sql:%s, column :%d is sorted in decending order as expected" % + (self.sql, col)) + else: + tdLog.exit("%s failed: sql:%s, col:%d is not sorted in decending order" % + (callerFilename, self.sql, col)) + else: + tdLog.exit("%s failed: sql:%s, the order provided for col:%d is not correct" % + (callerFilename, self.sql, col)) tdSql = TDSql() From 1d79ec864063db6d6e63a361e311a425b32d061a Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 13 Jun 2020 14:00:00 +0800 Subject: [PATCH 17/37] move more pytest cases to regression test. [TD-629] --- tests/pytest/regressiontest.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/pytest/regressiontest.sh b/tests/pytest/regressiontest.sh index 743a837f5e..5eefcfc926 100755 --- a/tests/pytest/regressiontest.sh +++ b/tests/pytest/regressiontest.sh @@ -80,8 +80,8 @@ python3 ./test.py -f import_merge/importCacheFileTO.py python3 ./test.py -f import_merge/importCacheFileTPO.py python3 ./test.py -f import_merge/importCacheFileT.py python3 ./test.py -f import_merge/importDataH2.py -# python3 ./test.py -f import_merge/importDataHO2.py -# python3 ./test.py -f import_merge/importDataHO.py +python3 ./test.py -f import_merge/importDataHO2.py +python3 ./test.py -f import_merge/importDataHO.py python3 ./test.py -f import_merge/importDataHPO.py python3 ./test.py -f import_merge/importDataLastHO.py python3 ./test.py -f import_merge/importDataLastHPO.py @@ -92,7 +92,7 @@ python3 ./test.py -f import_merge/importDataLastTO.py python3 ./test.py -f import_merge/importDataLastTPO.py python3 ./test.py -f import_merge/importDataLastT.py python3 ./test.py -f import_merge/importDataS.py -# python3 ./test.py -f import_merge/importDataSub.py +python3 ./test.py -f import_merge/importDataSub.py python3 ./test.py -f import_merge/importDataTO.py python3 ./test.py -f import_merge/importDataTPO.py python3 ./test.py -f import_merge/importDataT.py From 96d7ed762bc4f23116ed13f5a874ea6f92136cfa Mon Sep 17 00:00:00 2001 From: Hui Li Date: Sat, 13 Jun 2020 15:06:33 +0800 Subject: [PATCH 18/37] [TD-605] --- src/client/src/tscSQLParser.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index d0b3d91d3b..8cca7ed7f8 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -6061,9 +6061,13 @@ int32_t exprTreeFromSqlExpr(tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray* } } - if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL || pRight->pVal->nType == TSDB_DATA_TYPE_BINARY || pRight->pVal->nType == TSDB_DATA_TYPE_NCHAR) { - if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { - return TSDB_CODE_TSC_INVALID_SQL; + if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) { + if (pRight->nodeType == TSQL_NODE_VALUE) { + if ( pRight->pVal->nType == TSDB_DATA_TYPE_BOOL + || pRight->pVal->nType == TSDB_DATA_TYPE_BINARY + || pRight->pVal->nType == TSDB_DATA_TYPE_NCHAR) { + return TSDB_CODE_TSC_INVALID_SQL; + } } } } From 10a64cccc8964c618b8d29e05e7e1efcecf8e659 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Sat, 13 Jun 2020 15:12:28 +0800 Subject: [PATCH 19/37] add numpy install to travis [TD-630] --- .travis.yml | 4 ++++ tests/test-all.sh | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 54a7856f7b..4ae38f5032 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,9 @@ matrix: cd ${TRAVIS_BUILD_DIR}/debug make install > /dev/null || travis_terminate $? + pip install numpy pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/ + pip3 install numpy pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/ cd ${TRAVIS_BUILD_DIR}/tests @@ -164,7 +166,9 @@ matrix: cd ${TRAVIS_BUILD_DIR}/debug make install > /dev/null || travis_terminate $? + pip install numpy pip install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python2/ + pip3 install numpy pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/ cd ${TRAVIS_BUILD_DIR}/tests diff --git a/tests/test-all.sh b/tests/test-all.sh index 485c852dc5..0c91229120 100755 --- a/tests/test-all.sh +++ b/tests/test-all.sh @@ -41,7 +41,7 @@ if [ "$2" != "python" ]; then elif [ "$1" == "full" ]; then echo "### run TSIM full test ###" runSimCaseOneByOne fullGeneralSuite.sim - else + elif [ "$1" == "smoke" ] || [ -z "$1" ]; then echo "### run TSIM smoke test ###" runSimCaseOneByOne basicSuite.sim fi @@ -77,7 +77,7 @@ if [ "$2" != "sim" ]; then elif [ "$1" == "full" ]; then echo "### run Python full test ###" runPyCaseOneByOne fulltest.sh - else + elif [ "$1" == "smoke" ] || [ -z "$1" ]; then echo "### run Python smoke test ###" runPyCaseOneByOne smoketest.sh fi From 30b83affceaf0b1bd32dd815124ffc28cf1db507 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Sat, 13 Jun 2020 16:06:34 +0800 Subject: [PATCH 20/37] add stream cases to jenkins --- tests/script/jenkins/basic.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index 191e3212b6..084109623f 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -159,6 +159,21 @@ cd ../../../debug; make ./test.sh -f general/stable/values.sim ./test.sh -f general/stable/vnode3.sim +#./test.sh -f general/stream/metrics_1.sim +#./test.sh -f general/stream/metrics_del.sim +#./test.sh -f general/stream/metrics_n.sim +#./test.sh -f general/stream/metrics_replica1_vnoden.sim +#./test.sh -f general/stream/new_stream.sim +#./test.sh -f general/stream/restart_stream.sim +#./test.sh -f general/stream/stream_1.sim +#./test.sh -f general/stream/stream_2.sim +#./test.sh -f general/stream/stream_3.sim +#./test.sh -f general/stream/stream_restart.sim +#./test.sh -f general/stream/table_1.sim +#./test.sh -f general/stream/table_del.sim +#./test.sh -f general/stream/table_n.sim +#./test.sh -f general/stream/table_replica1_vnoden.sim + ./test.sh -f general/table/autocreate.sim ./test.sh -f general/table/basic1.sim ./test.sh -f general/table/basic2.sim From cc3fb92f4b5a5ee190b7a7072a3f7bfc34f26ec0 Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 16:18:14 +0800 Subject: [PATCH 21/37] [td-225] fix error in scripts --- tests/script/general/parser/limit1_stb.sim | 2 +- tests/script/general/parser/nchar.sim | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/script/general/parser/limit1_stb.sim b/tests/script/general/parser/limit1_stb.sim index a1f9aabd9d..fbcd8d0965 100644 --- a/tests/script/general/parser/limit1_stb.sim +++ b/tests/script/general/parser/limit1_stb.sim @@ -352,7 +352,7 @@ if $data07 != nchar0 then return -1 endi -sql select max(c1), min(c2), avg(c3), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and c1 > 1 and c2 < 9 and c3 > 2 and c4 < 8 and c5 > 3 and c6 < 7 and c7 > 0 and c8 like '%5' and t1 > 3 and t1 < 6 limit 1 offset 0; +sql select max(c1), min(c2), avg(c3), sum(c5), spread(c6), first(c7), last(c8), first(c9) from $stb where ts >= $ts0 and ts <= $tsu and c1 > 1 and c2 < 9 and c3 > 2 and c4 < 8 and c5 > 3 and c6 < 7 and c7 != 0 and c8 like '%5' and t1 > 3 and t1 < 6 limit 1 offset 0; if $rows != 1 then return -1 endi diff --git a/tests/script/general/parser/nchar.sim b/tests/script/general/parser/nchar.sim index 2c86748f21..c0de6f5058 100644 --- a/tests/script/general/parser/nchar.sim +++ b/tests/script/general/parser/nchar.sim @@ -198,15 +198,15 @@ if $rows != 100 then return -1 endi -sql select * from $mt where tgcol > '0' -#print rows = $rows -if $rows != 100 then - return -1 -endi -#print $data03 -if $data03 != 1 then - return -1 -endi +#sql select * from $mt where tgcol > '0' +##print rows = $rows +#if $rows != 100 then +# return -1 +#endi +##print $data03 +#if $data03 != 1 then +# return -1 +#endi # cumulative query with nchar tag filtering sql select count(tbcol1), avg(tbcol1), sum(tbcol1), min(tbcol1), max(tbcol1), first(tbcol1), last(tbcol1) from $mt where tgcol = '1' From 995eb63d98c2efc4e04d79a23e903cf2d330764f Mon Sep 17 00:00:00 2001 From: Haojun Liao Date: Sat, 13 Jun 2020 17:02:23 +0800 Subject: [PATCH 22/37] [td-541] add string length overflow check. --- src/kit/taosdemo/taosdemo.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/kit/taosdemo/taosdemo.c b/src/kit/taosdemo/taosdemo.c index bfedff0d94..bd9d41a4de 100644 --- a/src/kit/taosdemo/taosdemo.c +++ b/src/kit/taosdemo/taosdemo.c @@ -297,7 +297,7 @@ void *deleteTable(); void *asyncWrite(void *sarg); -void generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary); +int generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary); void rand_string(char *str, int size); @@ -846,14 +846,19 @@ void *syncWrite(void *sarg) { int k; for (k = 0; k < winfo->nrecords_per_request;) { int rand_num = rand() % 100; - if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate) - { + int len = -1; + if (winfo->data_of_order ==1 && rand_num < winfo->data_of_rate) { long d = tmp_time - rand() % 1000000 + rand_num; - generateData(data, data_type, ncols_per_record, d, len_of_binary); - } else - { - generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary); + len = generateData(data, data_type, ncols_per_record, d, len_of_binary); + } else { + len = generateData(data, data_type, ncols_per_record, tmp_time += 1000, len_of_binary); } + + //assert(len + pstr - buffer < BUFFER_SIZE); + if (len + pstr - buffer >= BUFFER_SIZE) { // too long + break; + } + pstr += sprintf(pstr, " %s", data); inserted++; k++; @@ -968,7 +973,7 @@ double getCurrentTime() { return tv.tv_sec + tv.tv_usec / 1E6; } -void generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary) { +int32_t generateData(char *res, char **data_type, int num_of_cols, int64_t timestamp, int len_of_binary) { memset(res, 0, MAX_DATA_SIZE); char *pstr = res; pstr += sprintf(pstr, "(%" PRId64, timestamp); @@ -1002,9 +1007,16 @@ void generateData(char *res, char **data_type, int num_of_cols, int64_t timestam rand_string(s, len_of_binary); pstr += sprintf(pstr, ", \"%s\"", s); } + + if (pstr - res > MAX_DATA_SIZE) { + perror("column length too long, abort"); + exit(-1); + } } pstr += sprintf(pstr, ")"); + + return pstr - res; } static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJK1234567890"; From 3ddef8f7e2ec86cdc70b8902958596a26b3ae609 Mon Sep 17 00:00:00 2001 From: Jeff Tao Date: Sun, 14 Jun 2020 00:21:32 +0000 Subject: [PATCH 23/37] add rpcCancelRequest API --- src/inc/trpc.h | 3 ++- src/rpc/src/rpcMain.c | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/inc/trpc.h b/src/inc/trpc.h index 748fad0e62..6c5d7fa889 100644 --- a/src/inc/trpc.h +++ b/src/inc/trpc.h @@ -78,12 +78,13 @@ void rpcClose(void *); void *rpcMallocCont(int contLen); void rpcFreeCont(void *pCont); void *rpcReallocCont(void *ptr, int contLen); -void rpcSendRequest(void *thandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg); +void *rpcSendRequest(void *thandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg); void rpcSendResponse(const SRpcMsg *pMsg); void rpcSendRedirectRsp(void *pConn, const SRpcIpSet *pIpSet); int rpcGetConnInfo(void *thandle, SRpcConnInfo *pInfo); void rpcSendRecv(void *shandle, SRpcIpSet *pIpSet, const SRpcMsg *pReq, SRpcMsg *pRsp); int rpcReportProgress(void *pConn, char *pCont, int contLen); +void rpcCanelRequest(void *pContext); #ifdef __cplusplus } diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index cf15cc690a..86d47f6c65 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -73,6 +73,7 @@ typedef struct { SRpcInfo *pRpc; // associated SRpcInfo SRpcIpSet ipSet; // ip list provided by app void *ahandle; // handle provided by app + struct SRpcConn *pConn; // pConn allocated char msgType; // message type uint8_t *pCont; // content provided by app int32_t contLen; // content length @@ -339,7 +340,7 @@ void *rpcReallocCont(void *ptr, int contLen) { return start + sizeof(SRpcReqContext) + sizeof(SRpcHead); } -void rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg) { +void *rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg) { SRpcInfo *pRpc = (SRpcInfo *)shandle; SRpcReqContext *pContext; @@ -367,7 +368,7 @@ void rpcSendRequest(void *shandle, const SRpcIpSet *pIpSet, const SRpcMsg *pMsg) rpcSendReqToServer(pRpc, pContext); - return; + return pContext; } void rpcSendResponse(const SRpcMsg *pRsp) { @@ -501,6 +502,19 @@ int rpcReportProgress(void *handle, char *pCont, int contLen) { return -1; } +/* todo: cancel process may have race condition, pContext may have been released + just before app calls the rpcCancelRequest */ +void rpcCancelRequest(void *handle) { + SRpcReqContext *pContext = handle; + + if (pContext->pConn) { + tTrace("%s, app trys to cancel request", pConn->info); + rpcCloseConn(pContext->pConn); + pContext->pConn = NULL; + rpcFreeCont(pContext->pCont); + } +} + static void rpcFreeMsg(void *msg) { if ( msg ) { char *temp = (char *)msg - sizeof(SRpcReqContext); @@ -942,6 +956,7 @@ static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) { static void rpcNotifyClient(SRpcReqContext *pContext, SRpcMsg *pMsg) { SRpcInfo *pRpc = pContext->pRpc; + pContext->pConn = NULL; if (pContext->pRsp) { // for synchronous API memcpy(pContext->pSet, &pContext->ipSet, sizeof(SRpcIpSet)); @@ -1110,6 +1125,7 @@ static void rpcSendReqToServer(SRpcInfo *pRpc, SRpcReqContext *pContext) { return; } + pContext->pConn = pConn; pConn->ahandle = pContext->ahandle; rpcLockConn(pConn); From b6a1529322b80914589801e3ea744843b327661b Mon Sep 17 00:00:00 2001 From: Jeff Tao Date: Sun, 14 Jun 2020 01:17:47 +0000 Subject: [PATCH 24/37] add debug info --- src/rpc/src/rpcMain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index 86d47f6c65..e4ba388394 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -508,7 +508,7 @@ void rpcCancelRequest(void *handle) { SRpcReqContext *pContext = handle; if (pContext->pConn) { - tTrace("%s, app trys to cancel request", pConn->info); + tTrace("%s, app trys to cancel request", pContext->pConn->info); rpcCloseConn(pContext->pConn); pContext->pConn = NULL; rpcFreeCont(pContext->pCont); From 6380afb63da4ee330b7721e18475195b90a1f70d Mon Sep 17 00:00:00 2001 From: Jeff Tao Date: Sun, 14 Jun 2020 01:28:26 +0000 Subject: [PATCH 25/37] set handle when report broken link to server --- src/rpc/src/rpcMain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index e4ba388394..dcbcae452d 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -888,6 +888,7 @@ static void rpcReportBrokenLinkToServer(SRpcConn *pConn) { SRpcMsg rpcMsg; rpcMsg.pCont = pConn->pReqMsg; // pReqMsg is re-used to store the APP context from server rpcMsg.contLen = pConn->reqMsgLen; // reqMsgLen is re-used to store the APP context length + rpcMsg.ahandle = pConn->ahandle; rpcMsg.handle = pConn; rpcMsg.msgType = pConn->inType; rpcMsg.code = TSDB_CODE_RPC_NETWORK_UNAVAIL; From 492f1f3889b37858842118b2c98ad5a340d8b751 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Sun, 14 Jun 2020 14:59:59 +0000 Subject: [PATCH 26/37] [TD-637] add refcount to restful --- src/plugins/http/inc/gcHandle.h | 10 +- src/plugins/http/inc/httpAuth.h | 23 ++ src/plugins/http/inc/httpContext.h | 34 +++ src/plugins/http/inc/httpHandle.h | 299 +--------------------- src/plugins/http/inc/httpInt.h | 236 +++++++++++++++++ src/plugins/http/inc/httpJson.h | 4 + src/plugins/http/inc/httpResp.h | 2 +- src/plugins/http/inc/httpServer.h | 28 ++ src/plugins/http/inc/httpSession.h | 27 ++ src/plugins/http/inc/httpSql.h | 38 +++ src/plugins/http/inc/httpUtil.h | 37 +++ src/plugins/http/inc/restHandle.h | 10 +- src/plugins/http/inc/tgHandle.h | 11 +- src/plugins/http/src/httpAuth.c | 4 +- src/plugins/http/src/httpContext.c | 224 ++++++++++++++++ src/plugins/http/src/httpHandle.c | 11 +- src/plugins/http/src/httpJson.c | 1 + src/plugins/http/src/httpResp.c | 1 + src/plugins/http/src/httpServer.c | 393 +++++------------------------ src/plugins/http/src/httpSession.c | 173 ++++--------- src/plugins/http/src/httpSql.c | 27 +- src/plugins/http/src/httpSystem.c | 120 +++------ src/plugins/http/src/httpUtil.c | 7 +- src/plugins/http/src/tgHandle.c | 3 +- 24 files changed, 834 insertions(+), 889 deletions(-) create mode 100644 src/plugins/http/inc/httpAuth.h create mode 100644 src/plugins/http/inc/httpContext.h create mode 100644 src/plugins/http/inc/httpInt.h create mode 100644 src/plugins/http/inc/httpServer.h create mode 100644 src/plugins/http/inc/httpSession.h create mode 100644 src/plugins/http/inc/httpSql.h create mode 100644 src/plugins/http/inc/httpUtil.h create mode 100644 src/plugins/http/src/httpContext.c diff --git a/src/plugins/http/inc/gcHandle.h b/src/plugins/http/inc/gcHandle.h index ed1e9302eb..a3688c6c38 100644 --- a/src/plugins/http/inc/gcHandle.h +++ b/src/plugins/http/inc/gcHandle.h @@ -16,15 +16,11 @@ #ifndef TDENGINE_GC_HANDLE_H #define TDENGINE_GC_HANDLE_H -#include -#include -#include -#include - #include "http.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpUtil.h" #include "httpResp.h" +#include "httpSql.h" #define GC_ROOT_URL_POS 0 #define GC_ACTION_URL_POS 1 diff --git a/src/plugins/http/inc/httpAuth.h b/src/plugins/http/inc/httpAuth.h new file mode 100644 index 0000000000..b8fabbe1ec --- /dev/null +++ b/src/plugins/http/inc/httpAuth.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_TOKEN_H +#define TDENGINE_HTTP_TOKEN_H + +bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len); +bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len); +bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen); + +#endif \ No newline at end of file diff --git a/src/plugins/http/inc/httpContext.h b/src/plugins/http/inc/httpContext.h new file mode 100644 index 0000000000..27b732bf3e --- /dev/null +++ b/src/plugins/http/inc/httpContext.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_CONTEXT_H +#define TDENGINE_HTTP_CONTEXT_H + +#include "httpInt.h" + +bool httpInitContexts(); +void httpCleanupContexts(); +const char *httpContextStateStr(HttpContextState state); + +HttpContext *httpCreateContext(int32_t fd); +bool httpInitContext(HttpContext *pContext); +HttpContext *httpGetContext(int32_t fd); +void httpReleaseContext(HttpContext *pContext); +void httpCloseContextByServer(HttpContext *pContext); +void httpCloseContextByApp(HttpContext *pContext); +void httpNotifyContextClose(HttpContext *pContext); +bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState); + +#endif diff --git a/src/plugins/http/inc/httpHandle.h b/src/plugins/http/inc/httpHandle.h index b888543137..3e6356d805 100644 --- a/src/plugins/http/inc/httpHandle.h +++ b/src/plugins/http/inc/httpHandle.h @@ -13,304 +13,11 @@ * along with this program. If not, see . */ -#ifndef TDENGINE_HTTP_SERVER_H -#define TDENGINE_HTTP_SERVER_H - -#include -#include "pthread.h" -#include "semaphore.h" -#include "tmempool.h" -#include "taosdef.h" -#include "tutil.h" -#include "zlib.h" -#include "http.h" -#include "httpJson.h" - -#define HTTP_MAX_CMD_SIZE 1024 -#define HTTP_MAX_BUFFER_SIZE 1024*1024 - -#define HTTP_LABEL_SIZE 8 -#define HTTP_MAX_EVENTS 10 -#define HTTP_BUFFER_SIZE 1024*65 //65k -#define HTTP_DECOMPRESS_BUF_SIZE 1024*64 -#define HTTP_STEP_SIZE 1024 //http message get process step by step -#define HTTP_MAX_URL 5 //http url stack size -#define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size -#define HTTP_GC_TARGET_SIZE 512 - -#define HTTP_VERSION_10 0 -#define HTTP_VERSION_11 1 -//#define HTTP_VERSION_12 2 - -#define HTTP_UNCUNKED 0 -#define HTTP_CHUNKED 1 - -#define HTTP_KEEPALIVE_NO_INPUT 0 -#define HTTP_KEEPALIVE_ENABLE 1 -#define HTTP_KEEPALIVE_DISABLE 2 - -#define HTTP_REQTYPE_OTHERS 0 -#define HTTP_REQTYPE_LOGIN 1 -#define HTTP_REQTYPE_HEARTBEAT 2 -#define HTTP_REQTYPE_SINGLE_SQL 3 -#define HTTP_REQTYPE_MULTI_SQL 4 - -#define HTTP_CHECK_BODY_ERROR -1 -#define HTTP_CHECK_BODY_CONTINUE 0 -#define HTTP_CHECK_BODY_SUCCESS 1 - -#define HTTP_WRITE_RETRY_TIMES 500 -#define HTTP_WRITE_WAIT_TIME_MS 5 -#define HTTP_EXPIRED_TIME 60000 -#define HTTP_DELAY_CLOSE_TIME_MS 500 - -#define HTTP_COMPRESS_IDENTITY 0 -#define HTTP_COMPRESS_GZIP 2 - -#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_PASSWORD_LEN) - -typedef enum { - HTTP_CONTEXT_STATE_READY, - HTTP_CONTEXT_STATE_HANDLING, - HTTP_CONTEXT_STATE_DROPPING, - HTTP_CONTEXT_STATE_CLOSED -} HttpContextState; - -struct HttpContext; -struct HttpThread; - -typedef struct { - void *signature; - int expire; - int access; - void *taos; - char id[HTTP_SESSION_ID_LEN]; -} HttpSession; - -typedef enum { - HTTP_CMD_TYPE_UN_SPECIFIED, - HTTP_CMD_TYPE_CREATE_DB, - HTTP_CMD_TYPE_CREATE_STBALE, - HTTP_CMD_TYPE_INSERT -} HttpSqlCmdType; - -typedef enum { HTTP_CMD_STATE_NOT_RUN_YET, HTTP_CMD_STATE_RUN_FINISHED } HttpSqlCmdState; - -typedef enum { HTTP_CMD_RETURN_TYPE_WITH_RETURN, HTTP_CMD_RETURN_TYPE_NO_RETURN } HttpSqlCmdReturnType; - -typedef struct { - // used by single cmd - char *nativSql; - int32_t numOfRows; - int32_t code; - - // these are the locations in the buffer - int32_t tagNames[TSDB_MAX_TAGS]; - int32_t tagValues[TSDB_MAX_TAGS]; - int32_t timestamp; - int32_t metric; - int32_t stable; - int32_t table; - int32_t values; - int32_t sql; - - // used by multi-cmd - int8_t cmdType; - int8_t cmdReturnType; - int8_t cmdState; - int8_t tagNum; -} HttpSqlCmd; - -typedef struct { - HttpSqlCmd *cmds; - int16_t pos; - int16_t size; - int16_t maxSize; - int32_t bufferPos; - int32_t bufferSize; - char * buffer; -} HttpSqlCmds; - -typedef struct { - char *module; - bool (*decodeFp)(struct HttpContext *pContext); -} HttpDecodeMethod; - -typedef struct { - void (*startJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result); - void (*stopJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd); - bool (*buildQueryJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result, int numOfRows); - void (*buildAffectRowJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int affectRows); - void (*initJsonFp)(struct HttpContext *pContext); - void (*cleanJsonFp)(struct HttpContext *pContext); - bool (*checkFinishedFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); - void (*setNextCmdFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); -} HttpEncodeMethod; - -typedef struct { - char *pos; - int32_t len; -} HttpBuf; - -typedef struct { - char buffer[HTTP_BUFFER_SIZE]; - int bufsize; - char *pLast; - char *pCur; - HttpBuf method; - HttpBuf path[HTTP_MAX_URL]; // url: dbname/meter/query - HttpBuf data; // body content - HttpBuf token; // auth token - HttpDecodeMethod *pMethod; -} HttpParser; - -typedef struct HttpContext { - void * signature; - int fd; - uint32_t accessTimes; - uint32_t lastAccessTime; - uint8_t httpVersion; - uint8_t httpChunked; - uint8_t httpKeepAlive; // http1.0 and not keep-alive, close connection immediately - uint8_t fromMemPool; - uint8_t acceptEncoding; - uint8_t contentEncoding; - uint8_t reqType; - uint8_t parsed; - int32_t state; - char ipstr[22]; - char user[TSDB_USER_LEN]; // parsed from auth token or login message - char pass[TSDB_PASSWORD_LEN]; - void *taos; - HttpSession *session; - z_stream gzipStream; - HttpEncodeMethod *encodeMethod; - HttpSqlCmd singleCmd; - HttpSqlCmds *multiCmds; - JsonBuf *jsonBuf; - HttpParser parser; - void *timer; - struct HttpThread *pThread; - struct HttpContext *prev; - struct HttpContext *next; -} HttpContext; - -typedef struct HttpThread { - pthread_t thread; - HttpContext * pHead; - pthread_mutex_t threadMutex; - bool stop; - int pollFd; - int numOfFds; - int threadId; - char label[HTTP_LABEL_SIZE]; - bool (*processData)(HttpContext *pContext); - struct HttpServer *pServer; // handle passed by upper layer during pServer initialization -} HttpThread; - -typedef struct HttpServer { - char label[HTTP_LABEL_SIZE]; - uint32_t serverIp; - uint16_t serverPort; - bool online; - int fd; - int cacheContext; - int sessionExpire; - int numOfThreads; - HttpDecodeMethod *methodScanner[HTTP_METHOD_SCANNER_SIZE]; - int methodScannerLen; - pthread_mutex_t serverMutex; - void *pSessionHash; - void *pContextPool; - void *expireTimer; - HttpThread *pThreads; - pthread_t thread; - bool (*processData)(HttpContext *pContext); - int requestNum; - void *timerHandle; -} HttpServer; - -// http util method -bool httpCheckUsedbSql(char *sql); -void httpTimeToString(time_t t, char *buf, int buflen); - -// http init method -void *httpInitServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle); -void httpCleanUpServer(HttpServer *pServer); - -// http server connection -void httpCleanUpConnect(HttpServer *pServer); -bool httpInitConnect(HttpServer *pServer); - -// http context for each client connection -HttpContext *httpCreateContext(HttpServer *pServer); -bool httpInitContext(HttpContext *pContext); -void httpCloseContextByApp(HttpContext *pContext); -void httpCloseContextByServer(HttpThread *pThread, HttpContext *pContext); - -// http session method -void httpCreateSession(HttpContext *pContext, void *taos); -void httpAccessSession(HttpContext *pContext); -void httpFetchSession(HttpContext *pContext); -void httpRestoreSession(HttpContext *pContext); -void httpRemoveExpireSessions(HttpServer *pServer); -bool httpInitAllSessions(HttpServer *pServer); -void httpRemoveAllSessions(HttpServer *pServer); -void httpProcessSessionExpire(void *handle, void *tmrId); - -// http request parser -void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod); - -// http token method -bool httpParseBasicAuthToken(HttpContext *pContext, char *token, int len); -bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len); -bool httpGenTaosdAuthToken(HttpContext *pContext, char *token, int maxLen); - -// util -bool httpUrlMatch(HttpContext *pContext, int pos, char *cmp); -bool httpProcessData(HttpContext *pContext); -bool httpReadDataImp(HttpContext *pContext); -bool httpParseRequest(HttpContext* pContext); -int httpCheckReadCompleted(HttpContext* pContext); -void httpReadDirtyData(HttpContext *pContext); +#ifndef TDENGINE_HTTP_HANDLE_H +#define TDENGINE_HTTP_HANDLE_H // http request handler void httpProcessRequest(HttpContext *pContext); - -// http json printer -JsonBuf *httpMallocJsonBuf(HttpContext *pContext); -void httpFreeJsonBuf(HttpContext *pContext); - -// http multicmds util - -int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, ...); -int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const format, ...); -int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize); -int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext); - -bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize); -bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize); -bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize); -void httpFreeMultiCmds(HttpContext *pContext); - -HttpSqlCmd *httpNewSqlCmd(HttpContext *pContext); -HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext); -int httpCurSqlCmdPos(HttpContext *pContext); - -void httpTrimTableName(char *name); -int httpShrinkTableName(HttpContext *pContext, int pos, char *name); -char *httpGetCmdsString(HttpContext *pContext, int pos); - -int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData); -int httpGzipCompressInit(HttpContext *pContext); -int httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen, - char *outDestData, int32_t *outDestDataLen, bool isTheLast); - -extern const char *httpKeepAliveStr[]; -extern const char *httpVersionStr[]; -const char* httpContextStateStr(HttpContextState state); - -bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState); -void httpRemoveContextFromEpoll(HttpThread *pThread, HttpContext *pContext); +bool httpProcessData(HttpContext *pContext); #endif diff --git a/src/plugins/http/inc/httpInt.h b/src/plugins/http/inc/httpInt.h new file mode 100644 index 0000000000..628ff805f4 --- /dev/null +++ b/src/plugins/http/inc/httpInt.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_INT_H +#define TDENGINE_HTTP_INT_H + +#include +#include "pthread.h" +#include "semaphore.h" +#include "tmempool.h" +#include "taosdef.h" +#include "tutil.h" +#include "zlib.h" +#include "http.h" +#include "httpCode.h" +#include "httpLog.h" +#include "httpJson.h" + +#define HTTP_MAX_CMD_SIZE 1024 +#define HTTP_MAX_BUFFER_SIZE 1024*1024 + +#define HTTP_LABEL_SIZE 8 +#define HTTP_MAX_EVENTS 10 +#define HTTP_BUFFER_SIZE 1024*65 //65k +#define HTTP_DECOMPRESS_BUF_SIZE 1024*64 +#define HTTP_STEP_SIZE 1024 //http message get process step by step +#define HTTP_MAX_URL 5 //http url stack size +#define HTTP_METHOD_SCANNER_SIZE 7 //http method fp size +#define HTTP_GC_TARGET_SIZE 512 + +#define HTTP_VERSION_10 0 +#define HTTP_VERSION_11 1 +//#define HTTP_VERSION_12 2 + +#define HTTP_UNCUNKED 0 +#define HTTP_CHUNKED 1 + +#define HTTP_KEEPALIVE_NO_INPUT 0 +#define HTTP_KEEPALIVE_ENABLE 1 +#define HTTP_KEEPALIVE_DISABLE 2 + +#define HTTP_REQTYPE_OTHERS 0 +#define HTTP_REQTYPE_LOGIN 1 +#define HTTP_REQTYPE_HEARTBEAT 2 +#define HTTP_REQTYPE_SINGLE_SQL 3 +#define HTTP_REQTYPE_MULTI_SQL 4 + +#define HTTP_CHECK_BODY_ERROR -1 +#define HTTP_CHECK_BODY_CONTINUE 0 +#define HTTP_CHECK_BODY_SUCCESS 1 + +#define HTTP_WRITE_RETRY_TIMES 500 +#define HTTP_WRITE_WAIT_TIME_MS 5 +#define HTTP_EXPIRED_TIME 60000 +#define HTTP_DELAY_CLOSE_TIME_MS 500 + +#define HTTP_COMPRESS_IDENTITY 0 +#define HTTP_COMPRESS_GZIP 2 + +#define HTTP_SESSION_ID_LEN (TSDB_USER_LEN + TSDB_PASSWORD_LEN) + +typedef enum { + HTTP_SERVER_INIT, + HTTP_SERVER_RUNNING, + HTTP_SERVER_CLOSING, + HTTP_SERVER_CLOSED +} HttpServerStatus; + +typedef enum { + HTTP_CONTEXT_STATE_READY, + HTTP_CONTEXT_STATE_HANDLING, + HTTP_CONTEXT_STATE_DROPPING, + HTTP_CONTEXT_STATE_CLOSED +} HttpContextState; + +struct HttpContext; +struct HttpThread; + +typedef struct { + char id[HTTP_SESSION_ID_LEN]; + int refCount; + void *taos; +} HttpSession; + +typedef enum { + HTTP_CMD_TYPE_UN_SPECIFIED, + HTTP_CMD_TYPE_CREATE_DB, + HTTP_CMD_TYPE_CREATE_STBALE, + HTTP_CMD_TYPE_INSERT +} HttpSqlCmdType; + +typedef enum { HTTP_CMD_STATE_NOT_RUN_YET, HTTP_CMD_STATE_RUN_FINISHED } HttpSqlCmdState; + +typedef enum { HTTP_CMD_RETURN_TYPE_WITH_RETURN, HTTP_CMD_RETURN_TYPE_NO_RETURN } HttpSqlCmdReturnType; + +typedef struct { + // used by single cmd + char *nativSql; + int32_t numOfRows; + int32_t code; + + // these are the locations in the buffer + int32_t tagNames[TSDB_MAX_TAGS]; + int32_t tagValues[TSDB_MAX_TAGS]; + int32_t timestamp; + int32_t metric; + int32_t stable; + int32_t table; + int32_t values; + int32_t sql; + + // used by multi-cmd + int8_t cmdType; + int8_t cmdReturnType; + int8_t cmdState; + int8_t tagNum; +} HttpSqlCmd; + +typedef struct { + HttpSqlCmd *cmds; + int16_t pos; + int16_t size; + int16_t maxSize; + int32_t bufferPos; + int32_t bufferSize; + char * buffer; +} HttpSqlCmds; + +typedef struct { + char *module; + bool (*decodeFp)(struct HttpContext *pContext); +} HttpDecodeMethod; + +typedef struct { + void (*startJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result); + void (*stopJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd); + bool (*buildQueryJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, void *result, int numOfRows); + void (*buildAffectRowJsonFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int affectRows); + void (*initJsonFp)(struct HttpContext *pContext); + void (*cleanJsonFp)(struct HttpContext *pContext); + bool (*checkFinishedFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); + void (*setNextCmdFp)(struct HttpContext *pContext, HttpSqlCmd *cmd, int code); +} HttpEncodeMethod; + +typedef struct { + char *pos; + int32_t len; +} HttpBuf; + +typedef struct { + char buffer[HTTP_BUFFER_SIZE]; + int bufsize; + char *pLast; + char *pCur; + HttpBuf method; + HttpBuf path[HTTP_MAX_URL]; // url: dbname/meter/query + HttpBuf data; // body content + HttpBuf token; // auth token + HttpDecodeMethod *pMethod; +} HttpParser; + +typedef struct HttpContext { + int32_t refCount; + int fd; + uint32_t accessTimes; + uint32_t lastAccessTime; + int32_t state; + uint8_t httpVersion; + uint8_t httpChunked; + uint8_t httpKeepAlive; // http1.0 and not keep-alive, close connection immediately + uint8_t acceptEncoding; + uint8_t contentEncoding; + uint8_t reqType; + uint8_t parsed; + char ipstr[22]; + char user[TSDB_USER_LEN]; // parsed from auth token or login message + char pass[TSDB_PASSWORD_LEN]; + void * taos; + HttpSession *session; + z_stream gzipStream; + HttpParser parser; + HttpSqlCmd singleCmd; + HttpSqlCmds *multiCmds; + JsonBuf * jsonBuf; + void * timer; + HttpEncodeMethod * encodeMethod; + struct HttpThread *pThread; +} HttpContext; + +typedef struct HttpThread { + pthread_t thread; + HttpContext * pHead; + pthread_mutex_t threadMutex; + bool stop; + int pollFd; + int numOfFds; + int threadId; + char label[HTTP_LABEL_SIZE]; + bool (*processData)(HttpContext *pContext); +} HttpThread; + +typedef struct HttpServer { + char label[HTTP_LABEL_SIZE]; + uint32_t serverIp; + uint16_t serverPort; + int fd; + int numOfThreads; + int methodScannerLen; + int32_t requestNum; + int32_t status; + pthread_t thread; + HttpThread * pThreads; + void * contextCache; + void * sessionCache; + pthread_mutex_t serverMutex; + HttpDecodeMethod *methodScanner[HTTP_METHOD_SCANNER_SIZE]; + bool (*processData)(HttpContext *pContext); +} HttpServer; + +extern const char *httpKeepAliveStr[]; +extern const char *httpVersionStr[]; +extern HttpServer tsHttpServer; + +#endif diff --git a/src/plugins/http/inc/httpJson.h b/src/plugins/http/inc/httpJson.h index 403c20b083..905460c67b 100644 --- a/src/plugins/http/inc/httpJson.h +++ b/src/plugins/http/inc/httpJson.h @@ -97,4 +97,8 @@ void httpJsonPrint(JsonBuf* buf, const char* json, int len); // quick void httpJsonPairStatus(JsonBuf* buf, int code); +// http json printer +JsonBuf* httpMallocJsonBuf(struct HttpContext* pContext); +void httpFreeJsonBuf(struct HttpContext* pContext); + #endif diff --git a/src/plugins/http/inc/httpResp.h b/src/plugins/http/inc/httpResp.h index 4868d4c688..5eaaa2a037 100644 --- a/src/plugins/http/inc/httpResp.h +++ b/src/plugins/http/inc/httpResp.h @@ -16,7 +16,7 @@ #ifndef TDENGINE_HTTP_RESP_H #define TDENGINE_HTTP_RESP_H -#include "httpHandle.h" +#include "httpInt.h" enum _httpRespTempl { HTTP_RESPONSE_JSON_OK, diff --git a/src/plugins/http/inc/httpServer.h b/src/plugins/http/inc/httpServer.h new file mode 100644 index 0000000000..04dadfe04c --- /dev/null +++ b/src/plugins/http/inc/httpServer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_SERVER_H +#define TDENGINE_HTTP_SERVER_H + +#include "httpInt.h" + +bool httpInitConnect(); +void httpCleanUpConnect(); + +void *httpInitServer(char *ip, uint16_t port, char *label, int numOfThreads, void *fp, void *shandle); +void httpCleanUpServer(HttpServer *pServer); +bool httpReadDataImp(HttpContext *pContext); + +#endif diff --git a/src/plugins/http/inc/httpSession.h b/src/plugins/http/inc/httpSession.h new file mode 100644 index 0000000000..393e720f69 --- /dev/null +++ b/src/plugins/http/inc/httpSession.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_SESSION_H +#define TDENGINE_HTTP_SESSION_H + +bool httpInitSessions(); +void httpCleanUpSessions(); + +// http session method +void httpCreateSession(HttpContext *pContext, void *taos); +void httpGetSession(HttpContext *pContext); +void httpReleaseSession(HttpContext *pContext); + +#endif diff --git a/src/plugins/http/inc/httpSql.h b/src/plugins/http/inc/httpSql.h new file mode 100644 index 0000000000..09f5b142fb --- /dev/null +++ b/src/plugins/http/inc/httpSql.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_SQL_H +#define TDENGINE_HTTP_SQL_H + + +int32_t httpAddToSqlCmdBuffer(HttpContext *pContext, const char *const format, ...); +int32_t httpAddToSqlCmdBufferNoTerminal(HttpContext *pContext, const char *const format, ...); +int32_t httpAddToSqlCmdBufferWithSize(HttpContext *pContext, int mallocSize); +int32_t httpAddToSqlCmdBufferTerminal(HttpContext *pContext); + +bool httpMallocMultiCmds(HttpContext *pContext, int cmdSize, int bufferSize); +bool httpReMallocMultiCmdsSize(HttpContext *pContext, int cmdSize); +bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int bufferSize); +void httpFreeMultiCmds(HttpContext *pContext); + +HttpSqlCmd *httpNewSqlCmd(HttpContext *pContext); +HttpSqlCmd *httpCurrSqlCmd(HttpContext *pContext); +int httpCurSqlCmdPos(HttpContext *pContext); + +void httpTrimTableName(char *name); +int httpShrinkTableName(HttpContext *pContext, int pos, char *name); +char *httpGetCmdsString(HttpContext *pContext, int pos); + +#endif diff --git a/src/plugins/http/inc/httpUtil.h b/src/plugins/http/inc/httpUtil.h new file mode 100644 index 0000000000..c82f702ebc --- /dev/null +++ b/src/plugins/http/inc/httpUtil.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef TDENGINE_HTTP_UTIL_H +#define TDENGINE_HTTP_UTIL_H + +bool httpCheckUsedbSql(char *sql); +void httpTimeToString(time_t t, char *buf, int buflen); + +bool httpUrlMatch(HttpContext *pContext, int pos, char *cmp); +bool httpParseRequest(HttpContext *pContext); +int httpCheckReadCompleted(HttpContext *pContext); +void httpReadDirtyData(HttpContext *pContext); + +int httpGzipDeCompress(char *srcData, int32_t nSrcData, char *destData, int32_t *nDestData); +int httpGzipCompressInit(HttpContext *pContext); +int httpGzipCompress(HttpContext *pContext, char *inSrcData, int32_t inSrcDataLen, + char *outDestData, int32_t *outDestDataLen, bool isTheLast); + +// http request parser +void httpAddMethod(HttpServer *pServer, HttpDecodeMethod *pMethod); + + + +#endif diff --git a/src/plugins/http/inc/restHandle.h b/src/plugins/http/inc/restHandle.h index 48ad040c53..632a1dc647 100644 --- a/src/plugins/http/inc/restHandle.h +++ b/src/plugins/http/inc/restHandle.h @@ -16,15 +16,11 @@ #ifndef TDENGINE_REST_HANDLE_H #define TDENGINE_REST_HANDLE_H -#include -#include -#include -#include - #include "http.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpUtil.h" #include "httpResp.h" +#include "httpSql.h" #define REST_ROOT_URL_POS 0 #define REST_ACTION_URL_POS 1 diff --git a/src/plugins/http/inc/tgHandle.h b/src/plugins/http/inc/tgHandle.h index 5622694374..6a3a7bfa4a 100644 --- a/src/plugins/http/inc/tgHandle.h +++ b/src/plugins/http/inc/tgHandle.h @@ -16,16 +16,11 @@ #ifndef TDENGINE_TG_HANDLE_H #define TDENGINE_TG_HANDLE_H -#include -#include -#include -#include - -#include "cJSON.h" #include "http.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpUtil.h" #include "httpResp.h" +#include "httpSql.h" #define TG_ROOT_URL_POS 0 #define TG_DB_URL_POS 1 diff --git a/src/plugins/http/src/httpAuth.c b/src/plugins/http/src/httpAuth.c index cf2ce5ddd9..6350d80299 100644 --- a/src/plugins/http/src/httpAuth.c +++ b/src/plugins/http/src/httpAuth.c @@ -18,8 +18,8 @@ #include "tkey.h" #include "tutil.h" #include "http.h" -#include "httpLog.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpAuth.h" #define KEY_DES_4 4971256377704625728L diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c new file mode 100644 index 0000000000..c0bef8ae9d --- /dev/null +++ b/src/plugins/http/src/httpContext.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "taosmsg.h" +#include "tsocket.h" +#include "tutil.h" +#include "ttime.h" +#include "ttimer.h" +#include "tglobal.h" +#include "tcache.h" +#include "httpInt.h" +#include "httpResp.h" +#include "httpSql.h" +#include "httpSession.h" + +static void httpRemoveContextFromEpoll(HttpContext *pContext) { + HttpThread *pThread = pContext->pThread; + if (pContext->fd >= 0) { + epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL); + taosCloseSocket(pContext->fd); + pContext->fd = -1; + } +} + +static void httpDestroyContext(void *data) { + HttpContext *pContext = *(HttpContext **)data; + httpTrace("context:%p, is destroyed, refCount:%d", pContext, pContext->refCount); + + if (pContext->fd > 0) tclose(pContext->fd); + + HttpThread *pThread = pContext->pThread; + httpRemoveContextFromEpoll(pContext); + httpReleaseSession(pContext); + atomic_sub_fetch_32(&pThread->numOfFds, 1); + + pContext->pThread = 0; + pContext->state = HTTP_CONTEXT_STATE_CLOSED; + + // avoid double free + httpFreeJsonBuf(pContext); + httpFreeMultiCmds(pContext); + + tfree(pContext); +} + +bool httpInitContexts() { + tsHttpServer.contextCache = taosCacheInitWithCb(5, httpDestroyContext); + if (tsHttpServer.contextCache == NULL) { + httpError("failed to init context cache"); + return false; + } + + return true; +} + +void httpCleanupContexts() { + // TODO: wait until all context is closed + if (tsHttpServer.contextCache != NULL) { + httpPrint("context cache is cleanup"); + taosCacheCleanup(tsHttpServer.contextCache); + tsHttpServer.contextCache = NULL; + } +} + +const char *httpContextStateStr(HttpContextState state) { + switch (state) { + case HTTP_CONTEXT_STATE_READY: + return "ready"; + case HTTP_CONTEXT_STATE_HANDLING: + return "handling"; + case HTTP_CONTEXT_STATE_DROPPING: + return "dropping"; + case HTTP_CONTEXT_STATE_CLOSED: + return "closed"; + default: + return "unknown"; + } +} + +void httpNotifyContextClose(HttpContext *pContext) { + shutdown(pContext->fd, SHUT_WR); +} + +bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState) { + return (atomic_val_compare_exchange_32(&pContext->state, srcState, destState) == srcState); +} + +HttpContext *httpCreateContext(int32_t fd) { + HttpContext *pContext = calloc(1, sizeof(HttpContext)); + if (pContext == NULL) return NULL; + + char fdStr[12] = {0}; + snprintf(fdStr, sizeof(fdStr), "%d", fd); + //atomic_add_fetch_32(&pContext->refCount, 1); + + pContext->fd = fd; + pContext->httpVersion = HTTP_VERSION_10; + pContext->lastAccessTime = taosGetTimestampSec(); + pContext->state = HTTP_CONTEXT_STATE_READY; + + taosCachePut(tsHttpServer.contextCache, fdStr, &pContext, sizeof(HttpContext *), 5); + httpTrace("context:%p, fd:%d is created", pContext, fd); + + return pContext; +} + +HttpContext *httpGetContext(int32_t fd) { + char fdStr[12] = {0}; + snprintf(fdStr, sizeof(fdStr), "%d", fd); + + HttpContext **ppContext = taosCacheAcquireByName(tsHttpServer.contextCache, fdStr); + + if (ppContext) { + HttpContext *pContext = *ppContext; + if (pContext) { + int32_t refCount = atomic_add_fetch_32(&pContext->refCount, 1); + httpTrace("context:%p, fd:%d is accquired, refCount:%d", pContext, pContext->fd, refCount); + return pContext; + } + } + return NULL; +} + +void httpReleaseContext(HttpContext *pContext) { + int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1); + assert(refCount >= 0); + httpTrace("context:%p, fd:%d is releasd, refCount:%d", pContext, pContext->fd, refCount); + + taosCacheRelease(tsHttpServer.contextCache, (void **)(&pContext), false); +} + +bool httpInitContext(HttpContext *pContext) { + pContext->accessTimes++; + pContext->lastAccessTime = taosGetTimestampSec(); + pContext->httpVersion = HTTP_VERSION_10; + pContext->httpKeepAlive = HTTP_KEEPALIVE_NO_INPUT; + pContext->httpChunked = HTTP_UNCUNKED; + pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY; + pContext->contentEncoding = HTTP_COMPRESS_IDENTITY; + pContext->reqType = HTTP_REQTYPE_OTHERS; + pContext->encodeMethod = NULL; + pContext->timer = NULL; + memset(&pContext->singleCmd, 0, sizeof(HttpSqlCmd)); + + HttpParser *pParser = &pContext->parser; + memset(pParser, 0, sizeof(HttpParser)); + pParser->pCur = pParser->pLast = pParser->buffer; + + httpTrace("context:%p, fd:%d, ip:%s, thread:%s, accessTimes:%d, parsed:%d", + pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->accessTimes, pContext->parsed); + return true; +} + +void httpCloseContextByApp(HttpContext *pContext) { + pContext->parsed = false; + + bool keepAlive = true; + if (pContext->httpVersion == HTTP_VERSION_10 && pContext->httpKeepAlive != HTTP_KEEPALIVE_ENABLE) { + keepAlive = false; + } else if (pContext->httpVersion != HTTP_VERSION_10 && pContext->httpKeepAlive == HTTP_KEEPALIVE_DISABLE) { + keepAlive = false; + } else {} + + if (keepAlive) { + if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_READY)) { + httpTrace("context:%p, fd:%d, ip:%s, last state:handling, keepAlive:true, reuse connect", + pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_CLOSED)) { + httpRemoveContextFromEpoll(pContext); + httpTrace("context:%p, fd:%d, ip:%s, last state:dropping, keepAlive:true, close connect", + pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) { + httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, reuse connect", + pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { + httpRemoveContextFromEpoll(pContext); + httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, close connect", + pContext, pContext->fd, pContext->ipstr); + } else { + httpRemoveContextFromEpoll(pContext); + httpError("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:true, close connect", + pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); + } + } else { + httpRemoveContextFromEpoll(pContext); + httpTrace("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:false, close connect", + pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); + } + + httpReleaseContext(pContext); +} + +void httpCloseContextByServer(HttpContext *pContext) { + httpRemoveContextFromEpoll(pContext); + pContext->parsed = false; + + if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) { + httpTrace("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) { + httpTrace("context:%p, fd:%d, ip:%s, epoll already finished, wait app finished", pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_CLOSED)) { + httpTrace("context:%p, fd:%d, ip:%s, epoll finished, close context", pContext, pContext->fd, pContext->ipstr); + } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { + httpTrace("context:%p, fd:%d, ip:%s, epoll finished, will be closed soon", pContext, pContext->fd, pContext->ipstr); + } else { + httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state); + } + + httpReleaseContext(pContext); +} diff --git a/src/plugins/http/src/httpHandle.c b/src/plugins/http/src/httpHandle.c index 8323ef7f4e..5f89940a66 100644 --- a/src/plugins/http/src/httpHandle.c +++ b/src/plugins/http/src/httpHandle.c @@ -19,11 +19,12 @@ #include "tglobal.h" #include "tsocket.h" #include "ttimer.h" -#include "http.h" -#include "httpLog.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" #include "httpResp.h" +#include "httpAuth.h" +#include "httpServer.h" +#include "httpContext.h" +#include "httpHandle.h" void httpToLowerUrl(char* url) { /*ignore case */ @@ -159,7 +160,7 @@ bool httpGetHttpMethod(HttpContext* pContext) { bool httpGetDecodeMethod(HttpContext* pContext) { HttpParser* pParser = &pContext->parser; - HttpServer* pServer = pContext->pThread->pServer; + HttpServer* pServer = &tsHttpServer; int methodLen = pServer->methodScannerLen; for (int i = 0; i < methodLen; i++) { HttpDecodeMethod* method = pServer->methodScanner[i]; diff --git a/src/plugins/http/src/httpJson.c b/src/plugins/http/src/httpJson.c index e5e69ae02a..76cc90c48f 100644 --- a/src/plugins/http/src/httpJson.c +++ b/src/plugins/http/src/httpJson.c @@ -22,6 +22,7 @@ #include "httpCode.h" #include "httpJson.h" #include "httpResp.h" +#include "httpUtil.h" #define MAX_NUM_STR_SZ 25 diff --git a/src/plugins/http/src/httpResp.c b/src/plugins/http/src/httpResp.c index d9507072de..de52e10f9a 100644 --- a/src/plugins/http/src/httpResp.c +++ b/src/plugins/http/src/httpResp.c @@ -21,6 +21,7 @@ #include "httpResp.h" #include "httpCode.h" #include "httpJson.h" +#include "httpContext.h" const char *httpKeepAliveStr[] = {"", "Connection: Keep-Alive\r\n", "Connection: Close\r\n"}; diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index 9a9c659b03..d06c1fdbc6 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -21,244 +21,15 @@ #include "ttime.h" #include "ttimer.h" #include "tglobal.h" -#include "http.h" -#include "httpLog.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpContext.h" #include "httpResp.h" +#include "httpUtil.h" #ifndef EPOLLWAKEUP #define EPOLLWAKEUP (1u << 29) #endif -const char* httpContextStateStr(HttpContextState state) { - switch (state) { - case HTTP_CONTEXT_STATE_READY: - return "ready"; - case HTTP_CONTEXT_STATE_HANDLING: - return "handling"; - case HTTP_CONTEXT_STATE_DROPPING: - return "dropping"; - case HTTP_CONTEXT_STATE_CLOSED: - return "closed"; - default: - return "unknown"; - } -} - -void httpRemoveContextFromEpoll(HttpThread *pThread, HttpContext *pContext) { - if (pContext->fd >= 0) { - epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL); - taosCloseSocket(pContext->fd); - pContext->fd = -1; - } -} - -bool httpAlterContextState(HttpContext *pContext, HttpContextState srcState, HttpContextState destState) { - return (atomic_val_compare_exchange_32(&pContext->state, srcState, destState) == srcState); -} - -void httpFreeContext(HttpServer *pServer, HttpContext *pContext); - -/** - * context will be reused while connection exist - * multiCmds and jsonBuf will be malloc after taos_query_a called - * and won't be freed until connection closed - */ -HttpContext *httpCreateContext(HttpServer *pServer) { - HttpContext *pContext = (HttpContext *)taosMemPoolMalloc(pServer->pContextPool); - if (pContext != NULL) { - pContext->fromMemPool = 1; - httpTrace("context:%p, is malloced from mempool", pContext); - } else { - pContext = (HttpContext *)malloc(sizeof(HttpContext)); - if (pContext == NULL) { - return NULL; - } else { - memset(pContext, 0, sizeof(HttpContext)); - } - httpTrace("context:%p, is malloced from raw memory", pContext); - } - - pContext->signature = pContext; - pContext->httpVersion = HTTP_VERSION_10; - pContext->lastAccessTime = taosGetTimestampSec(); - pContext->state = HTTP_CONTEXT_STATE_READY; - return pContext; -} - -void httpFreeContext(HttpServer *pServer, HttpContext *pContext) { - if (pContext->fromMemPool) { - httpTrace("context:%p, is freed from mempool", pContext); - taosMemPoolFree(pServer->pContextPool, (char *)pContext); - } else { - httpTrace("context:%p, is freed from raw memory", pContext); - tfree(pContext); - } -} - -void httpCleanUpContextTimer(HttpContext *pContext) { - if (pContext->timer != NULL) { - taosTmrStopA(&pContext->timer); - //httpTrace("context:%p, ip:%s, close timer:%p", pContext, pContext->ipstr, pContext->timer); - pContext->timer = NULL; - } -} - -void httpCleanUpContext(HttpContext *pContext, void *unused) { - httpTrace("context:%p, start the clean up operation, sig:%p", pContext, pContext->signature); - void *sig = atomic_val_compare_exchange_ptr(&pContext->signature, pContext, 0); - if (sig == NULL) { - httpTrace("context:%p is freed by another thread.", pContext); - return; - } - - HttpThread *pThread = pContext->pThread; - - httpCleanUpContextTimer(pContext); - - httpRemoveContextFromEpoll(pThread, pContext); - - httpRestoreSession(pContext); - - pthread_mutex_lock(&pThread->threadMutex); - - pThread->numOfFds--; - if (pThread->numOfFds < 0) { - httpError("context:%p, ip:%s, thread:%s, number of FDs:%d shall never be negative", - pContext, pContext->ipstr, pThread->label, pThread->numOfFds); - pThread->numOfFds = 0; - } - - // remove from the link list - if (pContext->prev) { - (pContext->prev)->next = pContext->next; - } else { - pThread->pHead = pContext->next; - } - - if (pContext->next) { - (pContext->next)->prev = pContext->prev; - } - - pthread_mutex_unlock(&pThread->threadMutex); - - httpTrace("context:%p, ip:%s, thread:%s, numOfFds:%d, context is cleaned up", pContext, pContext->ipstr, - pThread->label, pThread->numOfFds); - - pContext->signature = 0; - pContext->fd = -1; - pContext->pThread = 0; - pContext->prev = 0; - pContext->next = 0; - pContext->state = HTTP_CONTEXT_STATE_READY; - - // avoid double free - httpFreeJsonBuf(pContext); - httpFreeMultiCmds(pContext); - httpFreeContext(pThread->pServer, pContext); -} - -bool httpInitContext(HttpContext *pContext) { - pContext->accessTimes++; - pContext->lastAccessTime = taosGetTimestampSec(); - pContext->httpVersion = HTTP_VERSION_10; - pContext->httpKeepAlive = HTTP_KEEPALIVE_NO_INPUT; - pContext->httpChunked = HTTP_UNCUNKED; - pContext->acceptEncoding = HTTP_COMPRESS_IDENTITY; - pContext->contentEncoding = HTTP_COMPRESS_IDENTITY; - pContext->reqType = HTTP_REQTYPE_OTHERS; - pContext->encodeMethod = NULL; - pContext->timer = NULL; - memset(&pContext->singleCmd, 0, sizeof(HttpSqlCmd)); - - HttpParser *pParser = &pContext->parser; - memset(pParser, 0, sizeof(HttpParser)); - pParser->pCur = pParser->pLast = pParser->buffer; - - httpTrace("context:%p, fd:%d, ip:%s, thread:%s, accessTimes:%d, parsed:%d", - pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->accessTimes, pContext->parsed); - return true; -} - - -void httpCloseContext(HttpThread *pThread, HttpContext *pContext) { - taosTmrReset((TAOS_TMR_CALLBACK)httpCleanUpContext, HTTP_DELAY_CLOSE_TIME_MS, pContext, pThread->pServer->timerHandle, &pContext->timer); - httpTrace("context:%p, fd:%d, ip:%s, state:%s will be closed after:%d ms, timer:%p", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), HTTP_DELAY_CLOSE_TIME_MS, pContext->timer); -} - -void httpCloseContextByApp(HttpContext *pContext) { - HttpThread *pThread = pContext->pThread; - pContext->parsed = false; - - bool keepAlive = true; - if (pContext->httpVersion == HTTP_VERSION_10 && pContext->httpKeepAlive != HTTP_KEEPALIVE_ENABLE) { - keepAlive = false; - } else if (pContext->httpVersion != HTTP_VERSION_10 && pContext->httpKeepAlive == HTTP_KEEPALIVE_DISABLE) { - keepAlive = false; - } else {} - - if (keepAlive) { - if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_READY)) { - httpTrace("context:%p, fd:%d, ip:%s, last state:handling, keepAlive:true, reuse connect", - pContext, pContext->fd, pContext->ipstr); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_CLOSED)) { - httpRemoveContextFromEpoll(pThread, pContext); - httpTrace("context:%p, fd:%d, ip:%s, last state:dropping, keepAlive:true, close connect", - pContext, pContext->fd, pContext->ipstr); - httpCloseContext(pThread, pContext); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) { - httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, reuse connect", - pContext, pContext->fd, pContext->ipstr); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { - httpRemoveContextFromEpoll(pThread, pContext); - httpTrace("context:%p, fd:%d, ip:%s, last state:ready, keepAlive:true, close connect", - pContext, pContext->fd, pContext->ipstr); - httpCloseContext(pThread, pContext); - } else { - httpRemoveContextFromEpoll(pThread, pContext); - httpError("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:true, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); - httpCloseContext(pThread, pContext); - } - } else { - httpRemoveContextFromEpoll(pThread, pContext); - httpTrace("context:%p, fd:%d, ip:%s, last state:%s:%d, keepAlive:false, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->state); - httpCloseContext(pThread, pContext); - } -} - -void httpCloseContextByServer(HttpThread *pThread, HttpContext *pContext) { - httpRemoveContextFromEpoll(pThread, pContext); - pContext->parsed = false; - - if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) { - httpTrace("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) { - httpTrace("context:%p, fd:%d, ip:%s, epoll already finished, wait app finished", pContext, pContext->fd, pContext->ipstr); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_CLOSED)) { - httpTrace("context:%p, fd:%d, ip:%s, epoll finished, close context", pContext, pContext->fd, pContext->ipstr); - httpCloseContext(pThread, pContext); - } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_CLOSED, HTTP_CONTEXT_STATE_CLOSED)) { - httpTrace("context:%p, fd:%d, ip:%s, epoll finished, will be closed soon", pContext, pContext->fd, pContext->ipstr); - httpCloseContext(pThread, pContext); - } else { - httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state); - httpCloseContext(pThread, pContext); - } -} - -void httpCloseContextByServerForExpired(void *param, void *tmrId) { - HttpContext *pContext = (HttpContext *)param; - httpRemoveContextFromEpoll(pContext->pThread, pContext); - httpError("context:%p, fd:%d, ip:%s, read http body error, time expired, timer:%p", pContext, pContext->fd, pContext->ipstr, tmrId); - httpSendErrorResp(pContext, HTTP_PARSE_BODY_ERROR); - httpCloseContextByServer(pContext->pThread, pContext); -} - - static void httpStopThread(HttpThread* pThread) { pThread->stop = true; @@ -281,17 +52,10 @@ static void httpStopThread(HttpThread* pThread) { close(pThread->pollFd); pthread_mutex_destroy(&(pThread->threadMutex)); - - //while (pThread->pHead) { - // httpCleanUpContext(pThread->pHead, 0); - //} } - -void httpCleanUpConnect(HttpServer *pServer) { - if (pServer == NULL) return; - - shutdown(pServer->fd, SHUT_RD); +void httpCleanUpConnect() { + HttpServer *pServer = &tsHttpServer; pthread_join(pServer->thread, NULL); for (int i = 0; i < pServer->numOfThreads; ++i) { @@ -302,19 +66,10 @@ void httpCleanUpConnect(HttpServer *pServer) { } tfree(pServer->pThreads); + pServer->pThreads = NULL; httpTrace("http server:%s is cleaned up", pServer->label); } -// read all the data, then just discard it -void httpReadDirtyData(HttpContext *pContext) { - int fd = pContext->fd; - char data[1024] = {0}; - int len = (int)taosReadSocket(fd, data, 1024); - while (len >= sizeof(data)) { - len = (int)taosReadSocket(fd, data, 1024); - } -} - bool httpReadDataImp(HttpContext *pContext) { HttpParser *pParser = &pContext->parser; @@ -338,11 +93,10 @@ bool httpReadDataImp(HttpContext *pContext) { } if (pParser->bufsize >= (HTTP_BUFFER_SIZE - HTTP_STEP_SIZE)) { - httpReadDirtyData(pContext); httpError("context:%p, fd:%d, ip:%s, thread:%s, request big than:%d", pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, HTTP_BUFFER_SIZE); - httpRemoveContextFromEpoll(pContext->pThread, pContext); httpSendErrorResp(pContext, HTTP_REQUSET_TOO_BIG); + httpNotifyContextClose(pContext); return false; } } @@ -352,7 +106,7 @@ bool httpReadDataImp(HttpContext *pContext) { return true; } -bool httpDecompressData(HttpContext *pContext) { +static bool httpDecompressData(HttpContext *pContext) { if (pContext->contentEncoding != HTTP_COMPRESS_GZIP) { httpDump("context:%p, fd:%d, ip:%s, content:%s", pContext, pContext->fd, pContext->ipstr, pContext->parser.data.pos); return true; @@ -382,45 +136,43 @@ bool httpDecompressData(HttpContext *pContext) { return ret == 0; } -bool httpReadData(HttpThread *pThread, HttpContext *pContext) { +static bool httpReadData(HttpContext *pContext) { if (!pContext->parsed) { httpInitContext(pContext); } if (!httpReadDataImp(pContext)) { - httpCloseContextByServer(pThread, pContext); + httpNotifyContextClose(pContext); return false; } if (!httpParseRequest(pContext)) { - httpCloseContextByServer(pThread, pContext); + httpNotifyContextClose(pContext); return false; } int ret = httpCheckReadCompleted(pContext); if (ret == HTTP_CHECK_BODY_CONTINUE) { - taosTmrReset(httpCloseContextByServerForExpired, HTTP_EXPIRED_TIME, pContext, pThread->pServer->timerHandle, &pContext->timer); - //httpTrace("context:%p, fd:%d, ip:%s, not finished yet, try another times, timer:%p", pContext, pContext->fd, pContext->ipstr, pContext->timer); + //httpTrace("context:%p, fd:%d, ip:%s, not finished yet, wait another event", pContext, pContext->fd, pContext->ipstr); return false; } else if (ret == HTTP_CHECK_BODY_SUCCESS){ - httpCleanUpContextTimer(pContext); httpTrace("context:%p, fd:%d, ip:%s, thread:%s, read size:%d, dataLen:%d", pContext, pContext->fd, pContext->ipstr, pContext->pThread->label, pContext->parser.bufsize, pContext->parser.data.len); if (httpDecompressData(pContext)) { return true; } else { - httpCloseContextByServer(pThread, pContext); + httpNotifyContextClose(pContext); return false; } } else { - httpCleanUpContextTimer(pContext); httpError("context:%p, fd:%d, ip:%s, failed to read http body, close connect", pContext, pContext->fd, pContext->ipstr); - httpCloseContextByServer(pThread, pContext); + httpNotifyContextClose(pContext); return false; } } -void httpProcessHttpData(void *param) { +static void httpProcessHttpData(void *param) { + HttpServer *pServer = &tsHttpServer; HttpThread *pThread = (HttpThread *)param; HttpContext *pContext; int fdNum; @@ -441,77 +193,72 @@ void httpProcessHttpData(void *param) { if (fdNum <= 0) continue; for (int i = 0; i < fdNum; ++i) { - pContext = events[i].data.ptr; - if (pContext->signature != pContext || pContext->pThread != pThread || pContext->fd <= 0) { + pContext = httpGetContext(events[i].data.fd); + if (pContext == NULL) { + httpError("fd:%d, is already released, close connect", events[i].data.fd); + epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL); + tclose(events[i].data.fd); continue; } if (events[i].events & EPOLLPRI) { httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLPRI events occured, accessed:%d, close connect", pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpRemoveContextFromEpoll(pThread, pContext); - httpCloseContextByServer(pThread, pContext); + httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLRDHUP) { httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLRDHUP events occured, accessed:%d, close connect", pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpRemoveContextFromEpoll(pThread, pContext); - httpCloseContextByServer(pThread, pContext); + httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLERR) { httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLERR events occured, accessed:%d, close connect", pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpRemoveContextFromEpoll(pThread, pContext); - httpCloseContextByServer(pThread, pContext); + httpCloseContextByServer(pContext); continue; } if (events[i].events & EPOLLHUP) { httpTrace("context:%p, fd:%d, ip:%s, state:%s, EPOLLHUP events occured, accessed:%d, close connect", pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpRemoveContextFromEpoll(pThread, pContext); - httpCloseContextByServer(pThread, pContext); + httpCloseContextByServer(pContext); continue; } if (!httpAlterContextState(pContext, HTTP_CONTEXT_STATE_READY, HTTP_CONTEXT_STATE_READY)) { httpTrace("context:%p, fd:%d, ip:%s, state:%s, not in ready state, ignore read events", pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state)); + httpReleaseContext(pContext); continue; } - if (!pContext->pThread->pServer->online) { - httpTrace("context:%p, fd:%d, ip:%s, state:%s, server is not online, accessed:%d, close connect", - pContext, pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); - httpRemoveContextFromEpoll(pThread, pContext); - httpReadDirtyData(pContext); + if (pServer->status != HTTP_SERVER_RUNNING) { + httpTrace("context:%p, fd:%d, ip:%s, state:%s, server is not running, accessed:%d, close connect", pContext, + pContext->fd, pContext->ipstr, httpContextStateStr(pContext->state), pContext->accessTimes); httpSendErrorResp(pContext, HTTP_SERVER_OFFLINE); - httpCloseContextByServer(pThread, pContext); - continue; + httpNotifyContextClose(pContext); } else { - if (httpReadData(pThread, pContext)) { + if (httpReadData(pContext)) { (*(pThread->processData))(pContext); - atomic_fetch_add_32(&pThread->pServer->requestNum, 1); + atomic_fetch_add_32(&pServer->requestNum, 1); } } } } } -void* httpAcceptHttpConnection(void *arg) { +static void *httpAcceptHttpConnection(void *arg) { int connFd = -1; struct sockaddr_in clientAddr; int threadId = 0; - HttpThread * pThread; - HttpServer * pServer; - HttpContext * pContext; - int totalFds; - - pServer = (HttpServer *)arg; + HttpServer * pServer = &tsHttpServer; + HttpThread * pThread = NULL; + HttpContext * pContext = NULL; + int totalFds = 0; sigset_t set; sigemptyset(&set); @@ -521,12 +268,12 @@ void* httpAcceptHttpConnection(void *arg) { pServer->fd = taosOpenTcpServerSocket(pServer->serverIp, pServer->serverPort); if (pServer->fd < 0) { - httpError("http server:%s, failed to open http socket, ip:%s:%u error:%s", pServer->label, taosIpStr(pServer->serverIp), - pServer->serverPort, strerror(errno)); + httpError("http server:%s, failed to open http socket, ip:%s:%u error:%s", pServer->label, + taosIpStr(pServer->serverIp), pServer->serverPort, strerror(errno)); return NULL; } else { httpPrint("http service init success at %u", pServer->serverPort); - pServer->online = true; + pServer->status = HTTP_SERVER_RUNNING; } while (1) { @@ -534,10 +281,10 @@ void* httpAcceptHttpConnection(void *arg) { connFd = (int)accept(pServer->fd, (struct sockaddr *)&clientAddr, &addrlen); if (connFd == -1) { if (errno == EINVAL) { - httpTrace("%s HTTP server socket was shutdown, exiting...", pServer->label); + httpTrace("http server:%s socket was shutdown, exiting...", pServer->label); break; } - httpError("http server:%s, accept connect failure, errno:%d, reason:%s", pServer->label, errno, strerror(errno)); + httpError("http server:%s, accept connect failure, errno:%d reason:%s", pServer->label, errno, strerror(errno)); continue; } @@ -547,8 +294,8 @@ void* httpAcceptHttpConnection(void *arg) { } if (totalFds > tsHttpCacheSessions * 100) { - httpError("fd:%d, ip:%s:%u, totalFds:%d larger than httpCacheSessions:%d*100, refuse connection", - connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), totalFds, tsHttpCacheSessions); + httpError("fd:%d, ip:%s:%u, totalFds:%d larger than httpCacheSessions:%d*100, refuse connection", connFd, + inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), totalFds, tsHttpCacheSessions); taosCloseSocket(connFd); continue; } @@ -559,7 +306,7 @@ void* httpAcceptHttpConnection(void *arg) { // pick up the thread to handle this connection pThread = pServer->pThreads + threadId; - pContext = httpCreateContext(pServer); + pContext = httpCreateContext(connFd); if (pContext == NULL) { httpError("fd:%d, ip:%s:%u, no enough resource to allocate http context", connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port)); @@ -567,39 +314,25 @@ void* httpAcceptHttpConnection(void *arg) { continue; } - httpTrace("context:%p, fd:%d, ip:%s:%u, thread:%s, numOfFds:%d, totalFds:%d, accept a new connection", - pContext, connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), pThread->label, - pThread->numOfFds, totalFds); - - pContext->fd = connFd; - sprintf(pContext->ipstr, "%s:%d", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port)); pContext->pThread = pThread; + sprintf(pContext->ipstr, "%s:%u", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port)); + httpTrace("context:%p, fd:%d, ip:%s, thread:%s, numOfFds:%d, totalFds:%d, accept a new connection", pContext, + connFd, pContext->ipstr, pThread->label, pThread->numOfFds, totalFds); struct epoll_event event; event.events = EPOLLIN | EPOLLPRI | EPOLLWAKEUP | EPOLLERR | EPOLLHUP | EPOLLRDHUP; - event.data.ptr = pContext; + event.data.fd = connFd; if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, connFd, &event) < 0) { - httpError("context:%p, fd:%d, ip:%s:%u, thread:%s, failed to add http fd for epoll, error:%s", - pContext, connFd, inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port), pThread->label, - strerror(errno)); - httpFreeContext(pThread->pServer, pContext); - tclose(connFd); + httpError("context:%p, fd:%d, ip:%s, thread:%s, failed to add http fd for epoll, error:%s", pContext, connFd, + pContext->ipstr, pThread->label, strerror(errno)); + tclose(pContext->fd); + httpReleaseContext(pContext); continue; } // notify the data process, add into the FdObj list - pthread_mutex_lock(&(pThread->threadMutex)); - - pContext->next = pThread->pHead; - - if (pThread->pHead) (pThread->pHead)->prev = pContext; - - pThread->pHead = pContext; - - pThread->numOfFds++; - - pthread_mutex_unlock(&(pThread->threadMutex)); + atomic_add_fetch_32(&pThread->numOfFds, 1); // pick up next thread for next connection threadId++; @@ -610,21 +343,17 @@ void* httpAcceptHttpConnection(void *arg) { return NULL; } -bool httpInitConnect(HttpServer *pServer) { - int i; - HttpThread * pThread; - - pServer->pThreads = (HttpThread *)malloc(sizeof(HttpThread) * (size_t)pServer->numOfThreads); +bool httpInitConnect() { + HttpServer *pServer = &tsHttpServer; + pServer->pThreads = calloc(pServer->numOfThreads, sizeof(HttpThread)); if (pServer->pThreads == NULL) { httpError("init error no enough memory"); return false; } - memset(pServer->pThreads, 0, sizeof(HttpThread) * (size_t)pServer->numOfThreads); - pThread = pServer->pThreads; - for (i = 0; i < pServer->numOfThreads; ++i) { + HttpThread *pThread = pServer->pThreads; + for (int i = 0; i < pServer->numOfThreads; ++i) { sprintf(pThread->label, "%s%d", pServer->label, i); - pThread->pServer = pServer; pThread->processData = pServer->processData; pThread->threadId = i; @@ -643,8 +372,8 @@ bool httpInitConnect(HttpServer *pServer) { pthread_attr_init(&thattr); pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); if (pthread_create(&(pThread->thread), &thattr, (void *)httpProcessHttpData, (void *)(pThread)) != 0) { - httpError("http thread:%s, failed to create HTTP process data thread, reason:%s", - pThread->label, strerror(errno)); + httpError("http thread:%s, failed to create HTTP process data thread, reason:%s", pThread->label, + strerror(errno)); return false; } pthread_attr_destroy(&thattr); diff --git a/src/plugins/http/src/httpSession.c b/src/plugins/http/src/httpSession.c index e80d6f26b7..62ec101353 100644 --- a/src/plugins/http/src/httpSession.c +++ b/src/plugins/http/src/httpSession.c @@ -15,44 +15,26 @@ #define _DEFAULT_SOURCE #include "os.h" -#include "hash.h" #include "taos.h" #include "ttime.h" -#include "ttimer.h" -#include "http.h" -#include "httpLog.h" -#include "httpCode.h" -#include "httpHandle.h" -#include "httpResp.h" - -void httpAccessSession(HttpContext *pContext) { - HttpServer *server = pContext->pThread->pServer; - pthread_mutex_lock(&server->serverMutex); - if (pContext->session == pContext->session->signature) { - pContext->session->expire = (int) taosGetTimestampSec() + pContext->pThread->pServer->sessionExpire; - } - pthread_mutex_unlock(&server->serverMutex); -} +#include "tglobal.h" +#include "tcache.h" +#include "httpInt.h" +#include "httpContext.h" +#include "httpSession.h" void httpCreateSession(HttpContext *pContext, void *taos) { - HttpServer *server = pContext->pThread->pServer; + HttpServer *server = &tsHttpServer; + httpReleaseSession(pContext); + pthread_mutex_lock(&server->serverMutex); - if (pContext->session != NULL && pContext->session == pContext->session->signature) { - httpTrace("context:%p, fd:%d, ip:%s, user:%s, set exist session:%p:%p expired", pContext, pContext->fd, - pContext->ipstr, pContext->user, pContext->session, pContext->session->taos); - pContext->session->expire = 0; - pContext->session->access--; - } - - HttpSession session; + HttpSession session = {0}; session.taos = taos; - session.expire = (int)taosGetTimestampSec() + server->sessionExpire; - session.access = 1; - int sessionIdLen = snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); + session.refCount = 1; + snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); - taosHashPut(server->pSessionHash, session.id, sessionIdLen, (char *)(&session), sizeof(HttpSession)); - pContext->session = taosHashGet(server->pSessionHash, session.id, sessionIdLen); + pContext->session = taosCachePut(server->sessionCache, session.id, &session, sizeof(HttpSession), tsHttpSessionExpire); if (pContext->session == NULL) { httpError("context:%p, fd:%d, ip:%s, user:%s, error:%s", pContext, pContext->fd, pContext->ipstr, pContext->user, @@ -62,26 +44,23 @@ void httpCreateSession(HttpContext *pContext, void *taos) { return; } - pContext->session->signature = pContext->session; - httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p", pContext, pContext->fd, pContext->ipstr, - pContext->user, pContext->session, pContext->session->taos); + httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p refCount:%d", pContext, pContext->fd, + pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); pthread_mutex_unlock(&server->serverMutex); } -void httpFetchSessionImp(HttpContext *pContext) { - HttpServer *server = pContext->pThread->pServer; +static void httpFetchSessionImp(HttpContext *pContext) { + HttpServer *server = &tsHttpServer; pthread_mutex_lock(&server->serverMutex); char sessionId[HTTP_SESSION_ID_LEN]; - int sessonIdLen = snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); + snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); - pContext->session = taosHashGet(server->pSessionHash, sessionId, sessonIdLen); - if (pContext->session != NULL && pContext->session == pContext->session->signature) { - pContext->session->access++; - httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, access:%d, expire:%d", - pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, - pContext->session->taos, pContext->session->access, pContext->session->expire); - pContext->session->expire = (int)taosGetTimestampSec() + server->sessionExpire; + pContext->session = taosCacheAcquireByName(server->sessionCache, sessionId); + if (pContext->session != NULL) { + atomic_add_fetch_32(&pContext->refCount, 1); + httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, refCount:%d", pContext, pContext->fd, + pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); } else { httpTrace("context:%p, fd:%d, ip:%s, user:%s, session not found", pContext, pContext->fd, pContext->ipstr, pContext->user); @@ -90,113 +69,53 @@ void httpFetchSessionImp(HttpContext *pContext) { pthread_mutex_unlock(&server->serverMutex); } -void httpFetchSession(HttpContext *pContext) { +void httpGetSession(HttpContext *pContext) { if (pContext->session == NULL) { httpFetchSessionImp(pContext); } else { char sessionId[HTTP_SESSION_ID_LEN]; snprintf(sessionId, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); - if (strcmp(pContext->session->id, sessionId) != 0) { - httpError("context:%p, fd:%d, ip:%s, user:%s, password may be changed", pContext, pContext->fd, pContext->ipstr, pContext->user); - httpRestoreSession(pContext); - httpFetchSessionImp(pContext); - } + httpReleaseSession(pContext); + httpFetchSessionImp(pContext); } } -void httpRestoreSession(HttpContext *pContext) { - HttpServer * server = pContext->pThread->pServer; +void httpReleaseSession(HttpContext *pContext) { + if (pContext == NULL || pContext->session == NULL) return; - // all access to the session is via serverMutex - pthread_mutex_lock(&server->serverMutex); - HttpSession *session = pContext->session; - if (session == NULL || session != session->signature) { - pthread_mutex_unlock(&server->serverMutex); - return; - } - session->access--; - httpTrace("context:%p, ip:%s, user:%s, restore session:%p:%p, access:%d, expire:%d", - pContext, pContext->ipstr, pContext->user, session, session->taos, - session->access, pContext->session->expire); + int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1); + assert(refCount >= 0); + httpTrace("context:%p, session:%p is releasd refCount:%d", pContext, pContext->session, pContext->session->refCount); + + taosCacheRelease(tsHttpServer.sessionCache, (void**)(&(pContext->session)), false); pContext->session = NULL; - pthread_mutex_unlock(&server->serverMutex); } -void httpResetSession(HttpSession *pSession) { - httpTrace("close session:%p:%p", pSession, pSession->taos); +static void httpDestroySession(void *data) { + HttpSession *pSession = data; + httpTrace("session:%p:%p, is destroyed, refCount:%d", pSession, pSession->taos, pSession->refCount); + if (pSession->taos != NULL) { taos_close(pSession->taos); pSession->taos = NULL; } - pSession->signature = NULL; + tfree(pSession); } -void httpRemoveAllSessions(HttpServer *pServer) { - SHashMutableIterator *pIter = taosHashCreateIter(pServer->pSessionHash); - - while (taosHashIterNext(pIter)) { - HttpSession *pSession = taosHashIterGet(pIter); - if (pSession == NULL) continue; - httpResetSession(pSession); +void httpCleanUpSessions() { + if (tsHttpServer.sessionCache != NULL) { + httpPrint("session cache is cleanup"); + taosCacheCleanup(tsHttpServer.sessionCache); + tsHttpServer.sessionCache = NULL; } - - taosHashDestroyIter(pIter); } -bool httpInitAllSessions(HttpServer *pServer) { - if (pServer->pSessionHash == NULL) { - pServer->pSessionHash = taosHashInit(10, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true); - } - if (pServer->pSessionHash == NULL) { - httpError("http init session pool failed"); +bool httpInitSessions() { + tsHttpServer.sessionCache = taosCacheInitWithCb(5, httpDestroySession); + if (tsHttpServer.sessionCache == NULL) { + httpError("failed to init session cache"); return false; } - if (pServer->expireTimer == NULL) { - taosTmrReset(httpProcessSessionExpire, 50000, pServer, pServer->timerHandle, &pServer->expireTimer); - } return true; } - -bool httpSessionExpired(HttpSession *pSession) { - time_t cur = taosGetTimestampSec(); - - if (pSession->taos != NULL) { - if (pSession->expire > cur) { - return false; // un-expired, so return false - } - if (pSession->access > 0) { - httpTrace("session:%p:%p is expired, but still access:%d", pSession, pSession->taos, - pSession->access); - return false; // still used, so return false - } - httpTrace("need close session:%p:%p for it expired, cur:%d, expire:%d, invertal:%d", - pSession, pSession->taos, cur, pSession->expire, cur - pSession->expire); - } - - return true; -} - -void httpRemoveExpireSessions(HttpServer *pServer) { - SHashMutableIterator *pIter = taosHashCreateIter(pServer->pSessionHash); - - while (taosHashIterNext(pIter)) { - HttpSession *pSession = taosHashIterGet(pIter); - if (pSession == NULL) continue; - - pthread_mutex_lock(&pServer->serverMutex); - if (httpSessionExpired(pSession)) { - httpResetSession(pSession); - taosHashRemove(pServer->pSessionHash, pSession->id, strlen(pSession->id)); - } - pthread_mutex_unlock(&pServer->serverMutex); - } - - taosHashDestroyIter(pIter); -} - -void httpProcessSessionExpire(void *handle, void *tmrId) { - HttpServer *pServer = (HttpServer *)handle; - httpRemoveExpireSessions(pServer); - taosTmrReset(httpProcessSessionExpire, 60000, pServer, pServer->timerHandle, &pServer->expireTimer); -} \ No newline at end of file diff --git a/src/plugins/http/src/httpSql.c b/src/plugins/http/src/httpSql.c index efd1aac767..ce2f7a83bd 100644 --- a/src/plugins/http/src/httpSql.c +++ b/src/plugins/http/src/httpSql.c @@ -18,11 +18,12 @@ #include "tnote.h" #include "taos.h" #include "tsclient.h" -#include "http.h" -#include "httpLog.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpContext.h" +#include "httpSql.h" #include "httpResp.h" +#include "httpAuth.h" +#include "httpSession.h" void *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int), void *param, void **taos); @@ -30,7 +31,7 @@ void httpProcessMultiSql(HttpContext *pContext); void httpProcessMultiSqlRetrieveCallBack(void *param, TAOS_RES *result, int numOfRows) { HttpContext *pContext = (HttpContext *)param; - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; HttpSqlCmds * multiCmds = pContext->multiCmds; HttpEncodeMethod *encode = pContext->encodeMethod; @@ -72,7 +73,7 @@ void httpProcessMultiSqlRetrieveCallBack(void *param, TAOS_RES *result, int numO void httpProcessMultiSqlCallBack(void *param, TAOS_RES *result, int code) { HttpContext *pContext = (HttpContext *)param; - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; HttpSqlCmds * multiCmds = pContext->multiCmds; HttpEncodeMethod *encode = pContext->encodeMethod; @@ -172,7 +173,7 @@ void httpProcessMultiSql(HttpContext *pContext) { } void httpProcessMultiSqlCmd(HttpContext *pContext) { - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; HttpSqlCmds *multiCmds = pContext->multiCmds; if (multiCmds == NULL || multiCmds->size <= 0 || multiCmds->pos >= multiCmds->size || multiCmds->pos < 0) { @@ -192,7 +193,7 @@ void httpProcessMultiSqlCmd(HttpContext *pContext) { void httpProcessSingleSqlRetrieveCallBack(void *param, TAOS_RES *result, int numOfRows) { HttpContext *pContext = (HttpContext *)param; - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; HttpEncodeMethod *encode = pContext->encodeMethod; @@ -230,7 +231,7 @@ void httpProcessSingleSqlRetrieveCallBack(void *param, TAOS_RES *result, int num void httpProcessSingleSqlCallBack(void *param, TAOS_RES *result, int code) { HttpContext *pContext = (HttpContext *)param; - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; HttpEncodeMethod *encode = pContext->encodeMethod; @@ -354,7 +355,7 @@ void httpExecCmd(HttpContext *pContext) { void httpProcessRequestCb(void *param, TAOS_RES *result, int code) { HttpContext *pContext = param; - if (pContext == NULL || pContext->signature != pContext) return; + if (pContext == NULL) return; if (code < 0) { httpError("context:%p, fd:%d, ip:%s, user:%s, login error, code:%s", pContext, pContext->fd, pContext->ipstr, @@ -383,16 +384,14 @@ void httpProcessRequestCb(void *param, TAOS_RES *result, int code) { } void httpProcessRequest(HttpContext *pContext) { - httpFetchSession(pContext); + httpGetSession(pContext); - if (pContext->session == NULL || pContext->session != pContext->session->signature || - pContext->reqType == HTTP_REQTYPE_LOGIN) { + if (pContext->session == NULL || pContext->reqType == HTTP_REQTYPE_LOGIN) { taos_connect_a(NULL, pContext->user, pContext->pass, "", 0, httpProcessRequestCb, (void *)pContext, &(pContext->taos)); httpTrace("context:%p, fd:%d, ip:%s, user:%s, try connect tdengine, taos:%p", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->taos); } else { - httpAccessSession(pContext); httpExecCmd(pContext); } } diff --git a/src/plugins/http/src/httpSystem.c b/src/plugins/http/src/httpSystem.c index e7a5344be5..e6c8d95c88 100644 --- a/src/plugins/http/src/httpSystem.c +++ b/src/plugins/http/src/httpSystem.c @@ -20,84 +20,64 @@ #include "tsocket.h" #include "ttimer.h" #include "tadmin.h" -#include "http.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" +#include "httpContext.h" +#include "httpSession.h" +#include "httpServer.h" #include "httpResp.h" -#include "httpLog.h" -#include "gcHandle.h" #include "httpHandle.h" +#include "gcHandle.h" #include "restHandle.h" #include "tgHandle.h" #ifndef _ADMIN - void adminInitHandle(HttpServer* pServer) {} void opInitHandle(HttpServer* pServer) {} - #endif -static HttpServer *httpServer = NULL; +HttpServer tsHttpServer; void taosInitNote(int numOfNoteLines, int maxNotes, char* lable); int httpInitSystem() { - // taos_init(); + strcpy(tsHttpServer.label, "rest"); + tsHttpServer.serverIp = 0; + tsHttpServer.serverPort = tsHttpPort; + tsHttpServer.numOfThreads = tsHttpMaxThreads; + tsHttpServer.processData = httpProcessData; - httpServer = (HttpServer *)malloc(sizeof(HttpServer)); - memset(httpServer, 0, sizeof(HttpServer)); - - strcpy(httpServer->label, "rest"); - httpServer->serverIp = 0; - httpServer->serverPort = tsHttpPort; - httpServer->cacheContext = tsHttpCacheSessions; - httpServer->sessionExpire = tsHttpSessionExpire; - httpServer->numOfThreads = tsHttpMaxThreads; - httpServer->processData = httpProcessData; - - pthread_mutex_init(&httpServer->serverMutex, NULL); + pthread_mutex_init(&tsHttpServer.serverMutex, NULL); if (tsHttpEnableRecordSql != 0) { taosInitNote(tsNumOfLogLines / 10, 1, (char*)"http_note"); } - restInitHandle(httpServer); - adminInitHandle(httpServer); - gcInitHandle(httpServer); - tgInitHandle(httpServer); - opInitHandle(httpServer); + restInitHandle(&tsHttpServer); + adminInitHandle(&tsHttpServer); + gcInitHandle(&tsHttpServer); + tgInitHandle(&tsHttpServer); + opInitHandle(&tsHttpServer); return 0; } int httpStartSystem() { - httpPrint("starting to initialize http service ..."); + httpPrint("start http server ..."); - if (httpServer == NULL) { - httpError("http server is null"); - httpInitSystem(); - } - - if (httpServer->pContextPool == NULL) { - httpServer->pContextPool = taosMemPoolInit(httpServer->cacheContext, sizeof(HttpContext)); - } - if (httpServer->pContextPool == NULL) { - httpError("http init context pool failed"); + if (tsHttpServer.status != HTTP_SERVER_INIT) { + httpError("http server is already started"); return -1; } - if (httpServer->timerHandle == NULL) { - httpServer->timerHandle = taosTmrInit(tsHttpCacheSessions * 100 + 100, 200, 60000, "http"); - } - if (httpServer->timerHandle == NULL) { - httpError("http init timer failed"); - return -1; - } - - if (!httpInitAllSessions(httpServer)) { + if (!httpInitContexts()) { httpError("http init session failed"); return -1; } - if (!httpInitConnect(httpServer)) { + if (!httpInitSessions()) { + httpError("http init session failed"); + return -1; + } + + if (!httpInitConnect()) { httpError("http init server failed"); return -1; } @@ -106,9 +86,8 @@ int httpStartSystem() { } void httpStopSystem() { - if (httpServer != NULL) { - httpServer->online = false; - } + tsHttpServer.status = HTTP_SERVER_CLOSING; + shutdown(tsHttpServer.fd, SHUT_RD); tgCleanupHandle(); } @@ -116,43 +95,14 @@ void httpCleanUpSystem() { httpPrint("http service cleanup"); httpStopSystem(); -//#if 0 - if (httpServer == NULL) { - return; - } + httpCleanupContexts(); + httpCleanUpSessions(); + httpCleanUpConnect(); + pthread_mutex_destroy(&tsHttpServer.serverMutex); - if (httpServer->expireTimer != NULL) { - taosTmrStopA(&(httpServer->expireTimer)); - } - - if (httpServer->timerHandle != NULL) { - taosTmrCleanUp(httpServer->timerHandle); - httpServer->timerHandle = NULL; - } - - if (httpServer->pThreads != NULL) { - httpCleanUpConnect(httpServer); - httpServer->pThreads = NULL; - } - - -#if 0 - httpRemoveAllSessions(httpServer); - - if (httpServer->pContextPool != NULL) { - taosMemPoolCleanUp(httpServer->pContextPool); - httpServer->pContextPool = NULL; - } - - pthread_mutex_destroy(&httpServer->serverMutex); - - tfree(httpServer); -#endif + tsHttpServer.status = HTTP_SERVER_CLOSED; } int32_t httpGetReqCount() { - if (httpServer != NULL) { - return atomic_exchange_32(&httpServer->requestNum, 0); - } - return 0; + return atomic_exchange_32(&tsHttpServer.requestNum, 0); } diff --git a/src/plugins/http/src/httpUtil.c b/src/plugins/http/src/httpUtil.c index 1fb63ea2fc..694cdec0a0 100644 --- a/src/plugins/http/src/httpUtil.c +++ b/src/plugins/http/src/httpUtil.c @@ -17,11 +17,10 @@ #include "os.h" #include "tmd5.h" #include "taos.h" -#include "http.h" -#include "httpLog.h" -#include "httpCode.h" -#include "httpHandle.h" +#include "httpInt.h" #include "httpResp.h" +#include "httpSql.h" +#include "httpUtil.h" bool httpCheckUsedbSql(char *sql) { if (strstr(sql, "use ") != NULL) { diff --git a/src/plugins/http/src/tgHandle.c b/src/plugins/http/src/tgHandle.c index b85f27d175..fae11127e1 100644 --- a/src/plugins/http/src/tgHandle.c +++ b/src/plugins/http/src/tgHandle.c @@ -18,9 +18,10 @@ #include "tglobal.h" #include "taosdef.h" #include "taosmsg.h" +#include "httpInt.h" #include "tgHandle.h" #include "tgJson.h" -#include "httpLog.h" +#include "cJSON.h" /* * taos.telegraf.cfg formats like From 73f2baac92329ce1fbf33e715730ff972996c082 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Sun, 14 Jun 2020 16:03:21 +0000 Subject: [PATCH 27/37] [TD-637] fix refcount error in restful --- src/mnode/src/mnodeProfile.c | 4 ++-- src/plugins/http/inc/httpInt.h | 1 + src/plugins/http/src/httpContext.c | 20 ++++++++++---------- src/plugins/http/src/httpServer.c | 9 ++++----- src/plugins/http/src/httpSession.c | 4 ++-- src/plugins/http/src/httpSystem.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/mnode/src/mnodeProfile.c b/src/mnode/src/mnodeProfile.c index 4720fb0ddc..b57521e759 100644 --- a/src/mnode/src/mnodeProfile.c +++ b/src/mnode/src/mnodeProfile.c @@ -108,8 +108,8 @@ SConnObj *mnodeCreateConn(char *user, uint32_t ip, uint16_t port) { } void mnodeReleaseConn(SConnObj *pConn) { - if(pConn == NULL) return; - taosCacheRelease(tsMnodeConnCache, (void**)&pConn, false); + if (pConn == NULL) return; + taosCacheRelease(tsMnodeConnCache, (void **)&pConn, false); } SConnObj *mnodeAccquireConn(uint32_t connId, char *user, uint32_t ip, uint16_t port) { diff --git a/src/plugins/http/inc/httpInt.h b/src/plugins/http/inc/httpInt.h index 628ff805f4..5d94e8456e 100644 --- a/src/plugins/http/inc/httpInt.h +++ b/src/plugins/http/inc/httpInt.h @@ -188,6 +188,7 @@ typedef struct HttpContext { char user[TSDB_USER_LEN]; // parsed from auth token or login message char pass[TSDB_PASSWORD_LEN]; void * taos; + void * ppContext; HttpSession *session; z_stream gzipStream; HttpParser parser; diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index c0bef8ae9d..9262e3f609 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -105,15 +105,15 @@ HttpContext *httpCreateContext(int32_t fd) { char fdStr[12] = {0}; snprintf(fdStr, sizeof(fdStr), "%d", fd); - //atomic_add_fetch_32(&pContext->refCount, 1); - + pContext->fd = fd; pContext->httpVersion = HTTP_VERSION_10; pContext->lastAccessTime = taosGetTimestampSec(); pContext->state = HTTP_CONTEXT_STATE_READY; - taosCachePut(tsHttpServer.contextCache, fdStr, &pContext, sizeof(HttpContext *), 5); - httpTrace("context:%p, fd:%d is created", pContext, fd); + HttpContext **ppContext = taosCachePut(tsHttpServer.contextCache, fdStr, &pContext, sizeof(HttpContext *), 5); + pContext->ppContext = ppContext; + httpTrace("context:%p, fd:%d, is created", pContext, fd); return pContext; } @@ -128,7 +128,7 @@ HttpContext *httpGetContext(int32_t fd) { HttpContext *pContext = *ppContext; if (pContext) { int32_t refCount = atomic_add_fetch_32(&pContext->refCount, 1); - httpTrace("context:%p, fd:%d is accquired, refCount:%d", pContext, pContext->fd, refCount); + httpTrace("context:%p, fd:%d, is accquired, refCount:%d", pContext, pContext->fd, refCount); return pContext; } } @@ -138,9 +138,10 @@ HttpContext *httpGetContext(int32_t fd) { void httpReleaseContext(HttpContext *pContext) { int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1); assert(refCount >= 0); - httpTrace("context:%p, fd:%d is releasd, refCount:%d", pContext, pContext->fd, refCount); + httpTrace("context:%p, fd:%d, is releasd, refCount:%d", pContext, pContext->fd, refCount); - taosCacheRelease(tsHttpServer.contextCache, (void **)(&pContext), false); + HttpContext **ppContext = pContext->ppContext; + taosCacheRelease(tsHttpServer.contextCache, (void **)(&ppContext), false); } bool httpInitContext(HttpContext *pContext) { @@ -205,9 +206,6 @@ void httpCloseContextByApp(HttpContext *pContext) { } void httpCloseContextByServer(HttpContext *pContext) { - httpRemoveContextFromEpoll(pContext); - pContext->parsed = false; - if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_HANDLING, HTTP_CONTEXT_STATE_DROPPING)) { httpTrace("context:%p, fd:%d, ip:%s, epoll finished, still used by app", pContext, pContext->fd, pContext->ipstr); } else if (httpAlterContextState(pContext, HTTP_CONTEXT_STATE_DROPPING, HTTP_CONTEXT_STATE_DROPPING)) { @@ -220,5 +218,7 @@ void httpCloseContextByServer(HttpContext *pContext) { httpError("context:%p, fd:%d, ip:%s, unknown state:%d", pContext, pContext->fd, pContext->ipstr, pContext->state); } + pContext->parsed = false; + httpRemoveContextFromEpoll(pContext); httpReleaseContext(pContext); } diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index d06c1fdbc6..06523540b7 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -272,7 +272,7 @@ static void *httpAcceptHttpConnection(void *arg) { taosIpStr(pServer->serverIp), pServer->serverPort, strerror(errno)); return NULL; } else { - httpPrint("http service init success at %u", pServer->serverPort); + httpPrint("http server init success at %u", pServer->serverPort); pServer->status = HTTP_SERVER_RUNNING; } @@ -316,12 +316,9 @@ static void *httpAcceptHttpConnection(void *arg) { pContext->pThread = pThread; sprintf(pContext->ipstr, "%s:%u", inet_ntoa(clientAddr.sin_addr), htons(clientAddr.sin_port)); - httpTrace("context:%p, fd:%d, ip:%s, thread:%s, numOfFds:%d, totalFds:%d, accept a new connection", pContext, - connFd, pContext->ipstr, pThread->label, pThread->numOfFds, totalFds); - + struct epoll_event event; event.events = EPOLLIN | EPOLLPRI | EPOLLWAKEUP | EPOLLERR | EPOLLHUP | EPOLLRDHUP; - event.data.fd = connFd; if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, connFd, &event) < 0) { httpError("context:%p, fd:%d, ip:%s, thread:%s, failed to add http fd for epoll, error:%s", pContext, connFd, @@ -333,6 +330,8 @@ static void *httpAcceptHttpConnection(void *arg) { // notify the data process, add into the FdObj list atomic_add_fetch_32(&pThread->numOfFds, 1); + httpTrace("context:%p, fd:%d, ip:%s, thread:%s numOfFds:%d totalFds:%d, accept a new connection", pContext, connFd, + pContext->ipstr, pThread->label, pThread->numOfFds, totalFds); // pick up next thread for next connection threadId++; diff --git a/src/plugins/http/src/httpSession.c b/src/plugins/http/src/httpSession.c index 62ec101353..af8a3e6002 100644 --- a/src/plugins/http/src/httpSession.c +++ b/src/plugins/http/src/httpSession.c @@ -58,7 +58,7 @@ static void httpFetchSessionImp(HttpContext *pContext) { pContext->session = taosCacheAcquireByName(server->sessionCache, sessionId); if (pContext->session != NULL) { - atomic_add_fetch_32(&pContext->refCount, 1); + atomic_add_fetch_32(&pContext->session->refCount, 1); httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, refCount:%d", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); } else { @@ -83,7 +83,7 @@ void httpGetSession(HttpContext *pContext) { void httpReleaseSession(HttpContext *pContext) { if (pContext == NULL || pContext->session == NULL) return; - int32_t refCount = atomic_sub_fetch_32(&pContext->refCount, 1); + int32_t refCount = atomic_sub_fetch_32(&pContext->session->refCount, 1); assert(refCount >= 0); httpTrace("context:%p, session:%p is releasd refCount:%d", pContext, pContext->session, pContext->session->refCount); diff --git a/src/plugins/http/src/httpSystem.c b/src/plugins/http/src/httpSystem.c index e6c8d95c88..6e21baca04 100644 --- a/src/plugins/http/src/httpSystem.c +++ b/src/plugins/http/src/httpSystem.c @@ -68,7 +68,7 @@ int httpStartSystem() { } if (!httpInitContexts()) { - httpError("http init session failed"); + httpError("http init contexts failed"); return -1; } From e258f1ace0baa5648adcaabacbbd87f71b52852e Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Mon, 15 Jun 2020 11:49:29 +0800 Subject: [PATCH 28/37] fix td-320 --- src/client/inc/tsclient.h | 2 +- src/client/src/tscSQLParser.c | 2 +- src/inc/taosmsg.h | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/client/inc/tsclient.h b/src/client/inc/tsclient.h index 24e0f48ec9..ed3b481d0e 100644 --- a/src/client/inc/tsclient.h +++ b/src/client/inc/tsclient.h @@ -286,7 +286,7 @@ typedef struct STscObj { char user[TSDB_USER_LEN]; char pass[TSDB_KEY_LEN]; char acctId[TSDB_ACCT_LEN]; - char db[TSDB_DB_NAME_LEN]; + char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN]; char sversion[TSDB_VERSION_LEN]; char writeAuth : 1; char superAuth : 1; diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 8e5a439431..3f0af8f466 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -1042,7 +1042,7 @@ int32_t setObjFullName(char* fullName, const char* account, SSQLToken* pDB, SSQL /* db name is not specified, the tableName dose not include db name */ if (pDB != NULL) { - if (pDB->n >= TSDB_DB_NAME_LEN) { + if (pDB->n >= TSDB_ACCT_LEN + TSDB_DB_NAME_LEN) { return TSDB_CODE_TSC_INVALID_SQL; } diff --git a/src/inc/taosmsg.h b/src/inc/taosmsg.h index 1198097895..8e732f0cac 100644 --- a/src/inc/taosmsg.h +++ b/src/inc/taosmsg.h @@ -250,7 +250,7 @@ typedef struct { typedef struct { char tableId[TSDB_TABLE_ID_LEN]; - char db[TSDB_DB_NAME_LEN]; + char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN]; int8_t igExists; int8_t getMeta; int16_t numOfTags; @@ -268,7 +268,7 @@ typedef struct { typedef struct { char tableId[TSDB_TABLE_ID_LEN]; - char db[TSDB_DB_NAME_LEN]; + char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN]; int16_t type; /* operation type */ int16_t numOfCols; /* number of schema */ int32_t tagValLen; @@ -670,7 +670,7 @@ typedef struct { */ typedef struct { int8_t type; - char db[TSDB_DB_NAME_LEN]; + char db[TSDB_ACCT_LEN + TSDB_DB_NAME_LEN]; uint16_t payloadLen; char payload[]; } SCMShowMsg; From 1688b5a396037c79b4bed3b6cd877ba9aa3ce9a5 Mon Sep 17 00:00:00 2001 From: Ping Xiao Date: Mon, 15 Jun 2020 13:40:18 +0800 Subject: [PATCH 29/37] [TD-641]: Update documentation for running python test cases --- tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md b/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md index 3477fe9152..b6859827bf 100644 --- a/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md +++ b/tests/How-To-Run-Test-And-How-To-Add-New-Test-Case.md @@ -11,6 +11,8 @@ 4. pip install ../src/connector/python/linux/python2 ; pip3 install ../src/connector/python/linux/python3 +5. pip install numpy; pip3 install numpy + > Note: Both Python2 and Python3 are currently supported by the Python test > framework. Since Python2 is no longer officially supported by Python Software > Foundation since January 1, 2020, it is recommended that subsequent test case From 209f3db86e00cb93baee471cb36a5695d67545b4 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 15 Jun 2020 06:50:30 +0000 Subject: [PATCH 30/37] [TD-637] cleanup cache in callback function --- src/mnode/src/mnodeProfile.c | 2 +- src/plugins/http/inc/httpContext.h | 2 +- src/plugins/http/src/httpContext.c | 30 +++++++++++++++++------------- src/plugins/http/src/httpServer.c | 4 ++-- src/plugins/http/src/httpSession.c | 25 ++++++++++++++----------- src/plugins/http/src/httpSystem.c | 2 +- src/util/src/tcache.c | 16 ++++++++++++++-- 7 files changed, 50 insertions(+), 31 deletions(-) diff --git a/src/mnode/src/mnodeProfile.c b/src/mnode/src/mnodeProfile.c index b57521e759..7552ea5c25 100644 --- a/src/mnode/src/mnodeProfile.c +++ b/src/mnode/src/mnodeProfile.c @@ -138,7 +138,7 @@ SConnObj *mnodeAccquireConn(uint32_t connId, char *user, uint32_t ip, uint16_t p static void mnodeFreeConn(void *data) { SConnObj *pConn = data; tfree(pConn->pQueries); - tfree(pConn->pQueries); + tfree(pConn->pStreams); mTrace("connId:%d, is destroyed", pConn->connId); } diff --git a/src/plugins/http/inc/httpContext.h b/src/plugins/http/inc/httpContext.h index 27b732bf3e..a2d50d6b7f 100644 --- a/src/plugins/http/inc/httpContext.h +++ b/src/plugins/http/inc/httpContext.h @@ -24,7 +24,7 @@ const char *httpContextStateStr(HttpContextState state); HttpContext *httpCreateContext(int32_t fd); bool httpInitContext(HttpContext *pContext); -HttpContext *httpGetContext(int32_t fd); +HttpContext *httpGetContext(void * pContext); void httpReleaseContext(HttpContext *pContext); void httpCloseContextByServer(HttpContext *pContext); void httpCloseContextByApp(HttpContext *pContext); diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index 9262e3f609..183a332fb6 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -22,6 +22,7 @@ #include "ttimer.h" #include "tglobal.h" #include "tcache.h" +#include "hash.h" #include "httpInt.h" #include "httpResp.h" #include "httpSql.h" @@ -38,15 +39,13 @@ static void httpRemoveContextFromEpoll(HttpContext *pContext) { static void httpDestroyContext(void *data) { HttpContext *pContext = *(HttpContext **)data; - httpTrace("context:%p, is destroyed, refCount:%d", pContext, pContext->refCount); - if (pContext->fd > 0) tclose(pContext->fd); HttpThread *pThread = pContext->pThread; httpRemoveContextFromEpoll(pContext); httpReleaseSession(pContext); atomic_sub_fetch_32(&pThread->numOfFds, 1); - + pContext->pThread = 0; pContext->state = HTTP_CONTEXT_STATE_CLOSED; @@ -54,11 +53,12 @@ static void httpDestroyContext(void *data) { httpFreeJsonBuf(pContext); httpFreeMultiCmds(pContext); + httpTrace("context:%p, is destroyed, refCount:%d", pContext, pContext->refCount); tfree(pContext); } bool httpInitContexts() { - tsHttpServer.contextCache = taosCacheInitWithCb(5, httpDestroyContext); + tsHttpServer.contextCache = taosCacheInitWithCb(2, httpDestroyContext); if (tsHttpServer.contextCache == NULL) { httpError("failed to init context cache"); return false; @@ -70,7 +70,8 @@ bool httpInitContexts() { void httpCleanupContexts() { // TODO: wait until all context is closed if (tsHttpServer.contextCache != NULL) { - httpPrint("context cache is cleanup"); + SCacheObj *cache = tsHttpServer.contextCache; + httpPrint("context cache is cleanuping, size:%d", taosHashGetSize(cache->pHashTable)); taosCacheCleanup(tsHttpServer.contextCache); tsHttpServer.contextCache = NULL; } @@ -103,26 +104,29 @@ HttpContext *httpCreateContext(int32_t fd) { HttpContext *pContext = calloc(1, sizeof(HttpContext)); if (pContext == NULL) return NULL; - char fdStr[12] = {0}; - snprintf(fdStr, sizeof(fdStr), "%d", fd); + char contextStr[16] = {0}; + snprintf(contextStr, sizeof(contextStr), "%p", pContext); pContext->fd = fd; pContext->httpVersion = HTTP_VERSION_10; pContext->lastAccessTime = taosGetTimestampSec(); pContext->state = HTTP_CONTEXT_STATE_READY; - HttpContext **ppContext = taosCachePut(tsHttpServer.contextCache, fdStr, &pContext, sizeof(HttpContext *), 5); + HttpContext **ppContext = taosCachePut(tsHttpServer.contextCache, contextStr, &pContext, sizeof(HttpContext *), 3); pContext->ppContext = ppContext; - httpTrace("context:%p, fd:%d, is created", pContext, fd); + httpTrace("context:%p, fd:%d, is created, item:%p", pContext, fd, ppContext); + + // set the ref to 0 + taosCacheRelease(tsHttpServer.contextCache, (void**)&ppContext, false); return pContext; } -HttpContext *httpGetContext(int32_t fd) { - char fdStr[12] = {0}; - snprintf(fdStr, sizeof(fdStr), "%d", fd); +HttpContext *httpGetContext(void *ptr) { + char contextStr[16] = {0}; + snprintf(contextStr, sizeof(contextStr), "%p", ptr); - HttpContext **ppContext = taosCacheAcquireByName(tsHttpServer.contextCache, fdStr); + HttpContext **ppContext = taosCacheAcquireByName(tsHttpServer.contextCache, contextStr); if (ppContext) { HttpContext *pContext = *ppContext; diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index 06523540b7..bea2bb083a 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -193,7 +193,7 @@ static void httpProcessHttpData(void *param) { if (fdNum <= 0) continue; for (int i = 0; i < fdNum; ++i) { - pContext = httpGetContext(events[i].data.fd); + pContext = httpGetContext(events[i].data.ptr); if (pContext == NULL) { httpError("fd:%d, is already released, close connect", events[i].data.fd); epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL); @@ -319,7 +319,7 @@ static void *httpAcceptHttpConnection(void *arg) { struct epoll_event event; event.events = EPOLLIN | EPOLLPRI | EPOLLWAKEUP | EPOLLERR | EPOLLHUP | EPOLLRDHUP; - event.data.fd = connFd; + event.data.ptr = pContext; if (epoll_ctl(pThread->pollFd, EPOLL_CTL_ADD, connFd, &event) < 0) { httpError("context:%p, fd:%d, ip:%s, thread:%s, failed to add http fd for epoll, error:%s", pContext, connFd, pContext->ipstr, pThread->label, strerror(errno)); diff --git a/src/plugins/http/src/httpSession.c b/src/plugins/http/src/httpSession.c index af8a3e6002..2b0735bfaf 100644 --- a/src/plugins/http/src/httpSession.c +++ b/src/plugins/http/src/httpSession.c @@ -35,6 +35,8 @@ void httpCreateSession(HttpContext *pContext, void *taos) { snprintf(session.id, HTTP_SESSION_ID_LEN, "%s.%s", pContext->user, pContext->pass); pContext->session = taosCachePut(server->sessionCache, session.id, &session, sizeof(HttpSession), tsHttpSessionExpire); + // void *temp = pContext->session; + // taosCacheRelease(server->sessionCache, (void **)&temp, false); if (pContext->session == NULL) { httpError("context:%p, fd:%d, ip:%s, user:%s, error:%s", pContext, pContext->fd, pContext->ipstr, pContext->user, @@ -44,7 +46,7 @@ void httpCreateSession(HttpContext *pContext, void *taos) { return; } - httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p refCount:%d", pContext, pContext->fd, + httpTrace("context:%p, fd:%d, ip:%s, user:%s, create a new session:%p:%p sessionRef:%d", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); pthread_mutex_unlock(&server->serverMutex); } @@ -59,7 +61,7 @@ static void httpFetchSessionImp(HttpContext *pContext) { pContext->session = taosCacheAcquireByName(server->sessionCache, sessionId); if (pContext->session != NULL) { atomic_add_fetch_32(&pContext->session->refCount, 1); - httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, refCount:%d", pContext, pContext->fd, + httpTrace("context:%p, fd:%d, ip:%s, user:%s, find an exist session:%p:%p, sessionRef:%d", pContext, pContext->fd, pContext->ipstr, pContext->user, pContext->session, pContext->session->taos, pContext->session->refCount); } else { httpTrace("context:%p, fd:%d, ip:%s, user:%s, session not found", pContext, pContext->fd, pContext->ipstr, @@ -85,26 +87,27 @@ void httpReleaseSession(HttpContext *pContext) { int32_t refCount = atomic_sub_fetch_32(&pContext->session->refCount, 1); assert(refCount >= 0); - httpTrace("context:%p, session:%p is releasd refCount:%d", pContext, pContext->session, pContext->session->refCount); + httpTrace("context:%p, release session:%p:%p, sessionRef:%d", pContext, pContext->session, pContext->session->taos, + pContext->session->refCount); - taosCacheRelease(tsHttpServer.sessionCache, (void**)(&(pContext->session)), false); + taosCacheRelease(tsHttpServer.sessionCache, (void **)&pContext->session, false); pContext->session = NULL; } static void httpDestroySession(void *data) { - HttpSession *pSession = data; - httpTrace("session:%p:%p, is destroyed, refCount:%d", pSession, pSession->taos, pSession->refCount); + HttpSession *session = data; + httpTrace("session:%p:%p, is destroyed, sessionRef:%d", session, session->taos, session->refCount); - if (pSession->taos != NULL) { - taos_close(pSession->taos); - pSession->taos = NULL; + if (session->taos != NULL) { + taos_close(session->taos); + session->taos = NULL; } - tfree(pSession); } void httpCleanUpSessions() { if (tsHttpServer.sessionCache != NULL) { - httpPrint("session cache is cleanup"); + SCacheObj *cache = tsHttpServer.sessionCache; + httpPrint("session cache is cleanuping, size:%d", taosHashGetSize(cache->pHashTable)); taosCacheCleanup(tsHttpServer.sessionCache); tsHttpServer.sessionCache = NULL; } diff --git a/src/plugins/http/src/httpSystem.c b/src/plugins/http/src/httpSystem.c index 6e21baca04..015b0783b7 100644 --- a/src/plugins/http/src/httpSystem.c +++ b/src/plugins/http/src/httpSystem.c @@ -92,7 +92,7 @@ void httpStopSystem() { } void httpCleanUpSystem() { - httpPrint("http service cleanup"); + httpPrint("http server cleanup"); httpStopSystem(); httpCleanupContexts(); diff --git a/src/util/src/tcache.c b/src/util/src/tcache.c index ac06cf4f3f..2b6083a91c 100644 --- a/src/util/src/tcache.c +++ b/src/util/src/tcache.c @@ -63,10 +63,12 @@ static FORCE_INLINE void __cache_lock_destroy(SCacheObj *pCacheObj) { #endif } +#if 0 static FORCE_INLINE void taosFreeNode(void *data) { SCacheDataNode *pNode = *(SCacheDataNode **)data; free(pNode); } +#endif /** * @param key key of object for hash, usually a null-terminated string @@ -241,7 +243,7 @@ SCacheObj *taosCacheInitWithCb(int64_t refreshTime, void (*freeCb)(void *data)) } // set free cache node callback function for hash table - taosHashSetFreecb(pCacheObj->pHashTable, taosFreeNode); + // taosHashSetFreecb(pCacheObj->pHashTable, taosFreeNode); pCacheObj->freeFp = freeCb; pCacheObj->refreshTime = refreshTime * 1000; @@ -565,7 +567,17 @@ void taosTrashCanEmpty(SCacheObj *pCacheObj, bool force) { void doCleanupDataCache(SCacheObj *pCacheObj) { __cache_wr_lock(pCacheObj); - taosHashCleanup(pCacheObj->pHashTable); + + SHashMutableIterator *pIter = taosHashCreateIter(pCacheObj->pHashTable); + while (taosHashIterNext(pIter)) { + SCacheDataNode *pNode = *(SCacheDataNode **)taosHashIterGet(pIter); + // if (pNode->expiredTime <= expiredTime && T_REF_VAL_GET(pNode) <= 0) { + taosCacheReleaseNode(pCacheObj, pNode); + //} + } + taosHashDestroyIter(pIter); + + taosHashCleanup(pCacheObj->pHashTable); __cache_unlock(pCacheObj); taosTrashCanEmpty(pCacheObj, true); From e0754a90e3766b63e7faaf71ced9de00ce860caa Mon Sep 17 00:00:00 2001 From: liu0x54 Date: Mon, 15 Jun 2020 07:44:22 +0000 Subject: [PATCH 31/37] [TD-591]fix alter table tag value bugs --- src/client/src/tscSQLParser.c | 2 +- src/query/src/tvariant.c | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 60415a8d74..4338756e83 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -4479,7 +4479,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) { if (pTagsSchema->type != TSDB_DATA_TYPE_BINARY && pTagsSchema->type != TSDB_DATA_TYPE_NCHAR) { len = tDataTypeDesc[pTagsSchema->type].nSize; } else { - len = varDataLen(pUpdateMsg->data); + len = varDataTLen(pUpdateMsg->data); } pUpdateMsg->tagValLen = htonl(len); // length may be changed after dump data diff --git a/src/query/src/tvariant.c b/src/query/src/tvariant.c index 2cf60d3e91..b11850a672 100644 --- a/src/query/src/tvariant.c +++ b/src/query/src/tvariant.c @@ -800,12 +800,13 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu break; } case TSDB_DATA_TYPE_NCHAR: { + int32_t newlen = 0; if (!includeLengthPrefix) { if (pVariant->nType == TSDB_DATA_TYPE_NULL) { *(uint32_t *)payload = TSDB_DATA_NCHAR_NULL; } else { if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) { - toNchar(pVariant, &payload, &pVariant->nLen); + toNchar(pVariant, &payload, &newlen); } else { wcsncpy((wchar_t *)payload, pVariant->wpz, pVariant->nLen); } @@ -817,12 +818,13 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu char *p = varDataVal(payload); if (pVariant->nType != TSDB_DATA_TYPE_NCHAR) { - toNchar(pVariant, &p, &pVariant->nLen); + toNchar(pVariant, &p, &newlen); } else { wcsncpy((wchar_t *)p, pVariant->wpz, pVariant->nLen); + newlen = pVariant->nLen; } - varDataSetLen(payload, pVariant->nLen); // the length may be changed after toNchar function called + varDataSetLen(payload, newlen); // the length may be changed after toNchar function called assert(p == varDataVal(payload)); } } From 48821e0f56b4d589f7f4f71dd33cf4f9502220b3 Mon Sep 17 00:00:00 2001 From: Bomin Zhang Date: Mon, 15 Jun 2020 15:54:54 +0800 Subject: [PATCH 32/37] fix td-572 --- src/client/src/tscAsync.c | 4 +++- src/client/src/tscUtil.c | 2 -- src/rpc/src/rpcMain.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index c61402192d..f4fad42719 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -368,7 +368,9 @@ void tscProcessAsyncRes(SSchedMsg *pMsg) { pSql->fp = pSql->fetchFp; } - (*pSql->fp)(pSql->param, taosres, code); + if (pSql->fp) { + (*pSql->fp)(pSql->param, taosres, code); + } if (shouldFree) { tscTrace("%p sqlObj is automatically freed in async res", pSql); diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 57634e73fd..b1f5a99b67 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -1451,8 +1451,6 @@ bool tscShouldBeFreed(SSqlObj* pSql) { return false; } - assert(pSql->fp != NULL); - STscObj* pTscObj = pSql->pTscObj; if (pSql->pStream != NULL || pTscObj->pHb == pSql || pSql->pSubscription != NULL) { return false; diff --git a/src/rpc/src/rpcMain.c b/src/rpc/src/rpcMain.c index dcbcae452d..f05416c0cd 100644 --- a/src/rpc/src/rpcMain.c +++ b/src/rpc/src/rpcMain.c @@ -924,7 +924,7 @@ static void *rpcProcessMsgFromPeer(SRecvInfo *pRecv) { // underlying UDP layer does not know it is server or client pRecv->connType = pRecv->connType | pRpc->connType; - if (pRecv->ip == 0) { + if (pRecv->msg == NULL) { rpcProcessBrokenLink(pConn); return NULL; } From 0c8a20597d36a00c5117cc0762e60b16e6a2de82 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Mon, 15 Jun 2020 15:57:06 +0800 Subject: [PATCH 33/37] add more sleep to make test continue [TD-642] --- tests/script/general/parser/stream.sim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/script/general/parser/stream.sim b/tests/script/general/parser/stream.sim index 8e5dad1595..6c8d8f93ea 100644 --- a/tests/script/general/parser/stream.sim +++ b/tests/script/general/parser/stream.sim @@ -37,7 +37,7 @@ sleep 4000 sql select * from mt sql select * from strm sql drop table tb1 -sleep 10000 +sleep 100000 sql select * from strm if $rows != 2 then if $rows != 1 then @@ -221,4 +221,4 @@ sql use $db sql create table stb (ts timestamp, c1 int) tags(t1 int) sql create table tb1 using stb tags(1) -system sh/exec.sh -n dnode1 -s stop -x SIGINT \ No newline at end of file +system sh/exec.sh -n dnode1 -s stop -x SIGINT From 7bae0faeacb5d7200cb1522f030866b78823a014 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 15 Jun 2020 16:02:07 +0800 Subject: [PATCH 34/37] [TD-571] merge changes of 1.6 --- src/plugins/http/src/httpAuth.c | 1 + src/plugins/http/src/httpContext.c | 1 - src/plugins/http/src/httpServer.c | 9 +++++---- tests/script/general/db/len.sim | 2 +- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/plugins/http/src/httpAuth.c b/src/plugins/http/src/httpAuth.c index 6350d80299..0439083f31 100644 --- a/src/plugins/http/src/httpAuth.c +++ b/src/plugins/http/src/httpAuth.c @@ -73,6 +73,7 @@ bool httpParseTaosdAuthToken(HttpContext *pContext, char *token, int len) { unsigned char *base64 = base64_decode(token, len, &outlen); if (base64 == NULL || outlen == 0) { httpError("context:%p, fd:%d, ip:%s, taosd token:%s parsed error", pContext, pContext->fd, pContext->ipstr, token); + if (base64) free(base64); return false; } if (outlen != (TSDB_USER_LEN + TSDB_PASSWORD_LEN)) { diff --git a/src/plugins/http/src/httpContext.c b/src/plugins/http/src/httpContext.c index 183a332fb6..981492681a 100644 --- a/src/plugins/http/src/httpContext.c +++ b/src/plugins/http/src/httpContext.c @@ -68,7 +68,6 @@ bool httpInitContexts() { } void httpCleanupContexts() { - // TODO: wait until all context is closed if (tsHttpServer.contextCache != NULL) { SCacheObj *cache = tsHttpServer.contextCache; httpPrint("context cache is cleanuping, size:%d", taosHashGetSize(cache->pHashTable)); diff --git a/src/plugins/http/src/httpServer.c b/src/plugins/http/src/httpServer.c index bea2bb083a..684f77e7d8 100644 --- a/src/plugins/http/src/httpServer.c +++ b/src/plugins/http/src/httpServer.c @@ -56,8 +56,9 @@ static void httpStopThread(HttpThread* pThread) { void httpCleanUpConnect() { HttpServer *pServer = &tsHttpServer; - pthread_join(pServer->thread, NULL); + if (pServer->pThreads == NULL) return; + pthread_join(pServer->thread, NULL); for (int i = 0; i < pServer->numOfThreads; ++i) { HttpThread* pThread = pServer->pThreads + i; if (pThread != NULL) { @@ -195,9 +196,9 @@ static void httpProcessHttpData(void *param) { for (int i = 0; i < fdNum; ++i) { pContext = httpGetContext(events[i].data.ptr); if (pContext == NULL) { - httpError("fd:%d, is already released, close connect", events[i].data.fd); - epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, pContext->fd, NULL); - tclose(events[i].data.fd); + httpError("context:%p, is already released, close connect", events[i].data.ptr); + //epoll_ctl(pThread->pollFd, EPOLL_CTL_DEL, events[i].data.fd, NULL); + //tclose(events[i].data.fd); continue; } diff --git a/tests/script/general/db/len.sim b/tests/script/general/db/len.sim index 8add486658..6082f891b2 100644 --- a/tests/script/general/db/len.sim +++ b/tests/script/general/db/len.sim @@ -49,7 +49,7 @@ if $rows != 0 then endi print =============== step4 -sql create database a012345678901201234567890120123456789012 -x step4 +sql create database a012345678901201234567890120123456789012a012345678901201234567890120123456789012 -x step4 return -1 step4: sql show databases From 0b7dea8ce2de2c04a1ab4cd33724271dd2bb99d2 Mon Sep 17 00:00:00 2001 From: Hui Li Date: Mon, 15 Jun 2020 16:16:54 +0800 Subject: [PATCH 35/37] [add cluster sim cases into jenkis] --- tests/script/jenkins/basic.txt | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/tests/script/jenkins/basic.txt b/tests/script/jenkins/basic.txt index 084109623f..fe91e4bbde 100644 --- a/tests/script/jenkins/basic.txt +++ b/tests/script/jenkins/basic.txt @@ -322,3 +322,39 @@ cd ../../../debug; make ./test.sh -f unique/vnode/replica3_basic.sim ./test.sh -f unique/vnode/replica3_repeat.sim ./test.sh -f unique/vnode/replica3_vgroup.sim + +./test.sh -f unique/arbitrator/dn2_mn1_cache_file_sync.sim +#./test.sh -f unique/arbitrator/dn2_mn1_cache_file_sync_second.sim +./test.sh -f unique/arbitrator/dn3_mn1_full_createTableFail.sim +./test.sh -f unique/arbitrator/dn3_mn1_full_dropDnodeFail.sim +./test.sh -f unique/arbitrator/dn3_mn1_multiCreateDropTable.sim +./test.sh -f unique/arbitrator/dn3_mn1_nw_disable_timeout_autoDropDnode.sim +./test.sh -f unique/arbitrator/dn3_mn1_replica2_wal1_AddDelDnode.sim +./test.sh -f unique/arbitrator/dn3_mn1_replica_change_dropDnod.sim +./test.sh -f unique/arbitrator/dn3_mn1_replica_change.sim +./test.sh -f unique/arbitrator/dn3_mn1_stopDnode_timeout.sim +./test.sh -f unique/arbitrator/dn3_mn1_vnode_change.sim +./test.sh -f unique/arbitrator/dn3_mn1_vnode_corruptFile_offline.sim +./test.sh -f unique/arbitrator/dn3_mn1_vnode_corruptFile_online.sim +./test.sh -f unique/arbitrator/dn3_mn1_vnode_nomaster.sim +./test.sh -f unique/arbitrator/dn3_mn2_killDnode.sim +./test.sh -f unique/arbitrator/insert_duplicationTs.sim +./test.sh -f unique/arbitrator/offline_replica2_alterTable_online.sim +./test.sh -f unique/arbitrator/offline_replica2_alterTag_online.sim +./test.sh -f unique/arbitrator/offline_replica2_createTable_online.sim +./test.sh -f unique/arbitrator/offline_replica2_dropDb_online.sim +./test.sh -f unique/arbitrator/offline_replica2_dropTable_online.sim +./test.sh -f unique/arbitrator/offline_replica3_alterTable_online.sim +./test.sh -f unique/arbitrator/offline_replica3_alterTag_online.sim +./test.sh -f unique/arbitrator/offline_replica3_createTable_online.sim +./test.sh -f unique/arbitrator/offline_replica3_dropDb_online.sim +./test.sh -f unique/arbitrator/offline_replica3_dropTable_online.sim +./test.sh -f unique/arbitrator/replica_changeWithArbitrator.sim +./test.sh -f unique/arbitrator/sync_replica2_alterTable_add.sim +./test.sh -f unique/arbitrator/sync_replica2_alterTable_drop.sim +./test.sh -f unique/arbitrator/sync_replica2_dropDb.sim +./test.sh -f unique/arbitrator/sync_replica2_dropTable.sim +./test.sh -f unique/arbitrator/sync_replica3_alterTable_add.sim +./test.sh -f unique/arbitrator/sync_replica3_alterTable_drop.sim +./test.sh -f unique/arbitrator/sync_replica3_dropDb.sim +./test.sh -f unique/arbitrator/sync_replica3_dropTable.sim From fcaf198c3043cadcf17fc8a0281f74d2d4836f90 Mon Sep 17 00:00:00 2001 From: liu0x54 Date: Mon, 15 Jun 2020 08:47:57 +0000 Subject: [PATCH 36/37] [TD-401] fix the test case script due to the query interface change and fixed some script bugs --- tests/pytest/tag_lite/add.py | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/tests/pytest/tag_lite/add.py b/tests/pytest/tag_lite/add.py index 1a45237cb0..b23ff350c3 100644 --- a/tests/pytest/tag_lite/add.py +++ b/tests/pytest/tag_lite/add.py @@ -296,13 +296,13 @@ class TDTestCase: # TSIM: return -1 # TSIM: endi # TSIM: if $data23 != 1 then - tdLog.info('tdSql.checkData(2, 3, 1)') - tdSql.checkData(2, 3, 1) + tdLog.info('tdSql.checkData(2, 3, TAG)') + tdSql.checkData(2, 3, "TAG") # TSIM: return -1 # TSIM: endi # TSIM: if $data33 != 2.000000 then tdLog.info('tdSql.checkData(3, 3, 2.000000)') - tdSql.checkData(3, 3, 2.000000) + tdSql.checkData(3, 3, "TAG") # TSIM: return -1 # TSIM: endi # TSIM: @@ -396,7 +396,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 2 then tdLog.info('tdSql.checkData(0, 3, 2)') - tdSql.checkData(0, 3, 2) + tdSql.checkData(0, 3, "2") # TSIM: return -1 # TSIM: endi # TSIM: @@ -553,12 +553,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 5 then tdLog.info('tdSql.checkData(0, 3, 5)') - tdSql.checkData(0, 3, 5) + tdSql.checkData(0, 3, "5") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 6 then tdLog.info('tdSql.checkData(0, 4, 6)') - tdSql.checkData(0, 4, 6) + tdSql.checkData(0, 4, "6") # TSIM: return -1 # TSIM: endi # TSIM: @@ -584,12 +584,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 5 then tdLog.info('tdSql.checkData(0, 3, 5)') - tdSql.checkData(0, 3, 5) + tdSql.checkData(0, 3, "5") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 6 then tdLog.info('tdSql.checkData(0, 4, 6)') - tdSql.checkData(0, 4, 6) + tdSql.checkData(0, 4, "6") # TSIM: return -1 # TSIM: endi # TSIM: @@ -654,7 +654,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data04 != 3 then tdLog.info('tdSql.checkData(0, 4, 3)') - tdSql.checkData(0, 4, 3) + tdSql.checkData(0, 4, "3") # TSIM: return -1 # TSIM: endi # TSIM: @@ -779,7 +779,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data04 != 3 then tdLog.info('tdSql.checkData(0, 4, 3)') - tdSql.checkData(0, 4, 3) + tdSql.checkData(0, 4, "3") # TSIM: return -1 # TSIM: endi # TSIM: @@ -838,7 +838,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 5 then tdLog.info('tdSql.checkData(0, 3, 5)') - tdSql.checkData(0, 3, 5) + tdSql.checkData(0, 3, "5") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 1 then @@ -900,12 +900,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 2 then tdLog.info('tdSql.checkData(0, 3, 2)') - tdSql.checkData(0, 3, 2) + tdSql.checkData(0, 3, "2") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 3 then tdLog.info('tdSql.checkData(0, 4, 3)') - tdSql.checkData(0, 4, 3) + tdSql.checkData(0, 4, "3") # TSIM: return -1 # TSIM: endi # TSIM: @@ -1024,28 +1024,28 @@ class TDTestCase: # TSIM: endi # TSIM: if $data02 != 1 then tdLog.info('tdSql.checkData(0, 2, 1)') - tdSql.checkData(0, 2, 1) + tdSql.checkData(0, 2, "1") # TSIM: return -1 # TSIM: endi # TSIM: if $data03 != 2 then tdLog.info('tdSql.checkData(0, 3, 2)') - tdSql.checkData(0, 3, 2) + tdSql.checkData(0, 3, "2") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 3 then tdLog.info('tdSql.checkData(0, 4, 3)') - tdSql.checkData(0, 4, 3) + tdSql.checkData(0, 4, "3") # TSIM: return -1 # TSIM: endi # TSIM: if $data05 != 4 then tdLog.info('tdSql.checkData(0, 5, 4)') - tdSql.checkData(0, 5, 4) + tdSql.checkData(0, 5, "4") # TSIM: return -1 # TSIM: endi # TSIM: # TSIM: sql alter table $mt change tag tgcol1 tgcol4 -x step103 tdLog.info('alter table %s change tag tgcol1 tgcol4 -x step103' % (mt)) - tdSql.error('alter table %s change tag tgcol1 tgcol403' % (mt)) + tdSql.error('alter table %s change tag tgcol1 tgcol4' % (mt)) # TSIM: return -1 # TSIM: step103: # TSIM: @@ -1098,12 +1098,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data02 != 1 then tdLog.info('tdSql.checkData(0, 2, 1)') - tdSql.checkData(0, 2, 1) + tdSql.checkData(0, 2, "1") # TSIM: return -1 # TSIM: endi # TSIM: if $data03 != 4 then tdLog.info('tdSql.checkData(0, 3, 4)') - tdSql.checkData(0, 3, 4) + tdSql.checkData(0, 3, "4") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 0 then @@ -1112,8 +1112,8 @@ class TDTestCase: # TSIM: return -1 # TSIM: endi # TSIM: if $data05 != NULL then - tdLog.info('tdSql.checkData(0, 5, NULL)') - tdSql.checkData(0, 5, None) + #tdLog.info('tdSql.checkData(0, 5, NULL)') + # tdSql.checkData(0, 5, None) # TSIM: return -1 # TSIM: endi # TSIM: @@ -1189,13 +1189,13 @@ class TDTestCase: # TSIM: endi # TSIM: if $data06 != 5 then tdLog.info('tdSql.checkData(0, 6, 5)') - tdSql.checkData(0, 6, 5) + tdSql.checkData(0, 6, "5") # TSIM: return -1 # TSIM: endi # TSIM: # TSIM: sql alter table $mt change tag tgcol1 tgcol4 -x step114 tdLog.info('alter table %s change tag tgcol1 tgcol4 -x step114' % (mt)) - tdSql.error('alter table %s change tag tgcol1 tgcol414' % (mt)) + tdSql.error('alter table %s change tag tgcol1 tgcol4' % (mt)) # TSIM: return -1 # TSIM: step114: # TSIM: @@ -1274,7 +1274,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 4 then tdLog.info('tdSql.checkData(0, 3, 4)') - tdSql.checkData(0, 3, 4) + tdSql.checkData(0, 3, "4") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 5 then @@ -1284,7 +1284,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data05 != 6 then tdLog.info('tdSql.checkData(0, 5, 6)') - tdSql.checkData(0, 5, 6) + tdSql.checkData(0, 5, "6") # TSIM: return -1 # TSIM: endi # TSIM: if $data06 != 7 then @@ -1376,12 +1376,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data06 != 5 then tdLog.info('tdSql.checkData(0, 6, 5)') - tdSql.checkData(0, 6, 5) + tdSql.checkData(0, 6, "5") # TSIM: return -1 # TSIM: endi # TSIM: if $data07 != 6 then tdLog.info('tdSql.checkData(0, 7, 6)') - tdSql.checkData(0, 7, 6) + tdSql.checkData(0, 7, "6") # TSIM: return -1 # TSIM: endi # TSIM: @@ -1460,12 +1460,12 @@ class TDTestCase: # TSIM: endi # TSIM: if $data03 != 1 then tdLog.info('tdSql.checkData(0, 3, 1)') - tdSql.checkData(0, 3, 1) + tdSql.checkData(0, 3, "1") # TSIM: return -1 # TSIM: endi # TSIM: if $data04 != 5 then tdLog.info('tdSql.checkData(0, 4, 5)') - tdSql.checkData(0, 4, 5) + tdSql.checkData(0, 4, "5") # TSIM: return -1 # TSIM: endi # TSIM: if $data05 != 4 then @@ -1475,7 +1475,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data06 != 3 then tdLog.info('tdSql.checkData(0, 6, 3)') - tdSql.checkData(0, 6, 3) + tdSql.checkData(0, 6, "3") # TSIM: return -1 # TSIM: endi # TSIM: if $data07 != 2 then @@ -1562,7 +1562,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data02 != 1 then tdLog.info('tdSql.checkData(0, 2, 1)') - tdSql.checkData(0, 2, 1) + tdSql.checkData(0, 2, "1") # TSIM: return -1 # TSIM: endi # TSIM: if $data03 != 2 then @@ -1577,7 +1577,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data05 != 4 then tdLog.info('tdSql.checkData(0, 5, 4)') - tdSql.checkData(0, 5, 4) + tdSql.checkData(0, 5, "4") # TSIM: return -1 # TSIM: endi # TSIM: if $data06 != 5.000000000 then @@ -1587,7 +1587,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data07 != 6 then tdLog.info('tdSql.checkData(0, 7, 6)') - tdSql.checkData(0, 7, 6) + tdSql.checkData(0, 7, "6") # TSIM: return -1 # TSIM: endi # TSIM: @@ -1655,7 +1655,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data02 != 7 then tdLog.info('tdSql.checkData(0, 2, 7)') - tdSql.checkData(0, 2, 7) + tdSql.checkData(0, 2, "7") # TSIM: return -1 # TSIM: endi # TSIM: if $data03 != 9 then @@ -1670,7 +1670,7 @@ class TDTestCase: # TSIM: endi # TSIM: if $data05 != 8 then tdLog.info('tdSql.checkData(0, 5, 8)') - tdSql.checkData(0, 5, 8) + tdSql.checkData(0, 5, "8") # TSIM: return -1 # TSIM: endi # TSIM: if $data06 != 10 then @@ -1744,8 +1744,8 @@ class TDTestCase: # TSIM: print =============== clear tdLog.info('=============== clear') # TSIM: sql drop database $db - tdLog.info('sql drop database $db') - tdSql.execute('sql drop database $db') + tdLog.info('sql drop database db') + tdSql.execute('drop database db') # TSIM: sql show databases tdLog.info('show databases') tdSql.query('show databases') From a4675f027c1ff1b7f9c7283be02a3019be35abf8 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Mon, 15 Jun 2020 08:55:04 +0000 Subject: [PATCH 37/37] [TD-603] fix #2244 reported by freemine --- src/plugins/http/src/httpHandle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/http/src/httpHandle.c b/src/plugins/http/src/httpHandle.c index 5f89940a66..0d9b0ea025 100644 --- a/src/plugins/http/src/httpHandle.c +++ b/src/plugins/http/src/httpHandle.c @@ -59,6 +59,10 @@ bool httpParseURL(HttpContext* pContext) { HttpParser* pParser = &pContext->parser; char* pSeek; char* pEnd = strchr(pParser->pLast, ' '); + if (pEnd == NULL) { + return false; + } + if (*pParser->pLast != '/') { httpSendErrorResp(pContext, HTTP_UNSUPPORT_URL); return false;