diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 5cf14a8..6f51da0 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -22,7 +22,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Restore dependencies run: dotnet restore EFCore.Taos.sln - name: Build diff --git a/EFCore.Taos.sln b/EFCore.Taos.sln index a928acc..6bdc8fa 100644 --- a/EFCore.Taos.sln +++ b/EFCore.Taos.sln @@ -12,9 +12,14 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{61AA7587-946B-4B2F-92C9-73D0BA670B97}" ProjectSection(SolutionItems) = preProject appveyor.yml = appveyor.yml + .workflow\BranchPipeline.yml = .workflow\BranchPipeline.yml + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml LICENSE = LICENSE docs\logo.png = docs\logo.png + .workflow\MasterPipeline.yml = .workflow\MasterPipeline.yml + .workflow\PRPipeline.yml = .workflow\PRPipeline.yml README.md = README.md + taos.cfg = taos.cfg docs\taos_ch.png = docs\taos_ch.png docs\taos_ch_600.png = docs\taos_ch_600.png EndProjectSection diff --git a/docker-compose.yml b/docker-compose.yml index 048df7f..c8f91d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,9 +14,11 @@ services: - taos-network taos: - image: tdengine/tdengine:3.0.5.1 + image: tdengine/tdengine:3.2.1.0 restart: always hostname: taos + volumes: + - "./taos.cfg:/etc/taos/taos.cfg" ports: - 6030:6030 - 6035:6035 diff --git a/src/EFCore.Taos.Core/Query/Internal/TaosQuerySqlGenerator.cs b/src/EFCore.Taos.Core/Query/Internal/TaosQuerySqlGenerator.cs index 990daf6..ecddc34 100644 --- a/src/EFCore.Taos.Core/Query/Internal/TaosQuerySqlGenerator.cs +++ b/src/EFCore.Taos.Core/Query/Internal/TaosQuerySqlGenerator.cs @@ -92,7 +92,7 @@ protected override Expression VisitExtension(Expression extensionExpression) return exp; - } + } private Expression VisitTaosMatchExpression(TaosMatchExpression matchExpression) { diff --git a/src/EntityFrameworkCore.Taos.Tests/SqModelTest.cs b/src/EntityFrameworkCore.Taos.Tests/SqModelTest.cs index 875df38..789f8a7 100644 --- a/src/EntityFrameworkCore.Taos.Tests/SqModelTest.cs +++ b/src/EntityFrameworkCore.Taos.Tests/SqModelTest.cs @@ -1,6 +1,6 @@ -using IoTSharp.Data.Taos; +using Carbunql.Analysis; +using IoTSharp.Data.Taos; using Microsoft.VisualStudio.TestTools.UnitTesting; -using SqModel.Analysis; using System; using System.Collections.Generic; using System.Linq; @@ -20,9 +20,9 @@ public void TestExecuteBulkInsert_Json() ,station_uid,longitude,latitude,mn,dev_code,pol_name,pol_unit,pol_id FROM st_pmcm WHERE point_code = @p1;"; const string SQLDemo3 = "SELECT * FROM bytable WHERE t1 = @t1 AND t2 LIKE @t11 LIMIT @t3;"; // const string SQLDemo4 = "INSERT INTO t_status USING st_status (status_key) TAGS ('s1') (status_time, val) VALUES (@x1, @x2);"; - var s1 = SqlParser.Parse(SQLDemo1); + var s1 = SelectQueryParser.Parse(SQLDemo1); Assert.AreEqual(0, ((int?)s1.Parameters?.Count).GetValueOrDefault()); - var s2 = SqlParser.Parse(SQLDemo2); + var s2 = SelectQueryParser.Parse(SQLDemo2); Assert.AreEqual(5, ((int?)s2.Parameters?.Count).GetValueOrDefault()); Assert.AreEqual("@p1", s2.Parameters?.Keys.ToArray()[0]); @@ -30,7 +30,7 @@ public void TestExecuteBulkInsert_Json() var pn2 = s2.Parameters; Assert.AreEqual(1, pn2.Count); Assert.AreEqual("@p1", pn2.Keys.ToArray()[0]); - var s3 = SqlParser.Parse(SQLDemo3); + var s3 = SelectQueryParser.Parse(SQLDemo3); Assert.AreEqual(7, s3.Parameters?.Count); Assert.AreEqual("@t1", s3.Parameters?.ToArray()[1].Key); Assert.AreEqual("@t11", s3.Parameters?.ToArray()[3].Key); @@ -57,7 +57,8 @@ public void TestExecuteBulkInsert_Json() //Assert.AreEqual(2, pn4.Length); //Assert.AreEqual("@x1", pn4[0]); //Assert.AreEqual("@x2", pn4[1]); - var s5 = SqlParser.Parse("insert into #subtable using stable tags($t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9,$t10,$t11,$t12,$t13) values (@t1,@t2,@t3,@t4,@t5,@t6,@t7,@t8,@t9,@t10,@t11,@t12,@t13,@t14)"); + + var s5 = SelectQueryParser.Parse("insert into #subtable using stable tags($t1,$t2,$t3,$t4,$t5,$t6,$t7,$t8,$t9,$t10,$t11,$t12,$t13) values (@t1,@t2,@t3,@t4,@t5,@t6,@t7,@t8,@t9,@t10,@t11,@t12,@t13,@t14)"); Assert.AreEqual(14, s5.Parameters?.Count); Assert.AreEqual("#subtable", s5.Parameters?.ToArray()[0].Key); Assert.AreEqual(13, s5.Parameters?.Count(k=>k.Key.StartsWith('$'))); diff --git a/src/Example/Dockerfile b/src/Example/Dockerfile index 986fbc8..976ad5b 100644 --- a/src/Example/Dockerfile +++ b/src/Example/Dockerfile @@ -1,19 +1,19 @@ #See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging. -FROM mcr.microsoft.com/dotnet/runtime:7.0-bullseye-slim AS base -MAINTAINER Yanhong Ma 2023 -RUN echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye main contrib non-free" > /etc/apt/sources.list && \ - echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-updates main contrib non-free" >> /etc/apt/sources.list && \ - echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bullseye-backports main contrib non-free" >> /etc/apt/sources.list && \ - apt-get -y -q update && apt-get install -y --no-install-recommends -q apt-utils libgdiplus libc6-dev lsof net-tools wget curl iputils-ping inetutils-tools && \ +FROM mcr.microsoft.com/dotnet/runtime:8.0-bookworm-slim AS base +MAINTAINER Yanhong Ma 2024 +RUN echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm main contrib non-free" > /etc/apt/sources.list && \ + echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-updates main contrib non-free" >> /etc/apt/sources.list && \ + echo "deb https://mirrors.tuna.tsinghua.edu.cn/debian/ bookworm-backports main contrib non-free" >> /etc/apt/sources.list && \ + apt-get -y -q update && apt-get install -y --no-install-recommends -q apt-utils lsof net-tools wget curl iputils-ping inetutils-tools && \ apt-get autoremove -y && apt-get clean && apt-get autoclean && rm /var/cache/apt/* -rf && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime -RUN curl -o TDengine-client.tar.gz "https://www.taosdata.com/assets-download/3.0/TDengine-client-3.0.5.1-Linux-x64.tar.gz" && \ +RUN curl -o TDengine-client.tar.gz "https://www.taosdata.com/assets-download/3.0/TDengine-client-3.2.1.0-Linux-x64.tar.gz" && \ tar -xvf TDengine-client.tar.gz && rm TDengine-client.tar.gz -f && cd $(ls TDengine-client* -d) && \ ./install_client.sh && \ rm $(pwd) -rf WORKDIR /app - -FROM mcr.microsoft.com/dotnet/sdk:7.0-bullseye-slim AS build + +FROM mcr.microsoft.com/dotnet/sdk:8.0-bookworm-slim AS build WORKDIR /src COPY ["src/Example/Example.csproj", "src/Example/"] diff --git a/src/IoTSharp.Data.Taos/IoTSharp.Data.Taos.csproj b/src/IoTSharp.Data.Taos/IoTSharp.Data.Taos.csproj index e147e12..31dbd69 100644 --- a/src/IoTSharp.Data.Taos/IoTSharp.Data.Taos.csproj +++ b/src/IoTSharp.Data.Taos/IoTSharp.Data.Taos.csproj @@ -16,7 +16,7 @@ IoTSharp.Data.Taos.TaosParameter IoTSharp.Data.Taos.TaosTransaction - net6;net7;net4.6;netstandard2.0 + net6;net7;net8;net4.6;netstandard2.0 10 Taos;Data;ADO.NET;Entity Framework,;EF; Core;Data O/RM,;entity-framework-core;TDengine;IoTSharp Yanhong Ma @@ -56,7 +56,7 @@ - + diff --git a/src/IoTSharp.Data.Taos/Protocols/TDNative/TaosNative.cs b/src/IoTSharp.Data.Taos/Protocols/TDNative/TaosNative.cs index 89440a7..fef4ef2 100644 --- a/src/IoTSharp.Data.Taos/Protocols/TDNative/TaosNative.cs +++ b/src/IoTSharp.Data.Taos/Protocols/TDNative/TaosNative.cs @@ -1,6 +1,7 @@ using IoTSharp.Data.Taos; using System; using System.Collections; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Data; using System.Diagnostics; @@ -14,7 +15,7 @@ namespace IoTSharp.Data.Taos.Protocols { internal class TaosNative : ITaosProtocol { - private static readonly Dictionary g_pool = new Dictionary(); + private static readonly ConcurrentDictionary g_pool = new ConcurrentDictionary(); private ConcurrentTaosQueue _queue = null; private static bool _dll_isloaded = false; private readonly DateTime _dt1970; @@ -117,24 +118,22 @@ public string GetClientVersion() public bool Open(TaosConnectionStringBuilder builder) { var _connectionString = builder.ConnectionString; - if (!g_pool.ContainsKey(_connectionString)) + lock (g_pool) { - g_pool.Add(_connectionString, new ConcurrentTaosQueue() { Timeout = builder.ConnectionTimeout }); - } - _queue = g_pool[_connectionString]; - _queue.AddRef(); - - for (int i = 0; i < builder.PoolSize + 1; i++) - { - var c = TDengine.Connect(builder.DataSource, builder.Username, builder.Password, "", (short)builder.Port); - if (c != IntPtr.Zero) + _queue = g_pool.GetOrAdd(_connectionString, new ConcurrentTaosQueue() { Timeout = builder.ConnectionTimeout }); + _queue.AddRef(); + for (int i = 0; i < builder.PoolSize + 1; i++) { - _queue.Return(c); + var c = TDengine.Connect(builder.DataSource, builder.Username, builder.Password, "", (short)builder.Port); + if (c != IntPtr.Zero) + { + _queue.Return(c); + } + } + if (_queue.TaosQueue.IsEmpty) + { + TaosException.ThrowExceptionForRC(new TaosErrorResult() { Code = -1, Error = "Can't open connection." }); } - } - if (_queue.TaosQueue.IsEmpty) - { - TaosException.ThrowExceptionForRC(new TaosErrorResult() { Code = -1, Error = "Can't open connection." }); } return true; } @@ -142,27 +141,30 @@ public bool Open(TaosConnectionStringBuilder builder) public void Close(TaosConnectionStringBuilder builder) { var _connectionString = builder.ConnectionString; - _queue.RemoveRef(); - if (_queue.GetRef() == 0) + lock (g_pool) { - for (int i = 0; i < _queue.TaosQueue.Count; i++) + _queue.RemoveRef(); + if (_queue.GetRef() == 0) { - try + for (int i = 0; i < _queue.TaosQueue.Count; i++) { - var tk = _queue.Take(); - if (tk != IntPtr.Zero) + try { - TDengine.Close(tk); + var tk = _queue.Take(); + if (tk != IntPtr.Zero) + { + TDengine.Close(tk); + } } - } - catch (Exception) - { + catch (Exception) + { - + + } } + _queue = null; + g_pool.TryRemove(_connectionString, out var va1l); } - _queue = null; - g_pool.Remove(_connectionString); } } diff --git a/src/IoTSharp.Data.Taos/Protocols/TDWebSocket/TaosWebSocket.cs b/src/IoTSharp.Data.Taos/Protocols/TDWebSocket/TaosWebSocket.cs index b507198..00b6dae 100644 --- a/src/IoTSharp.Data.Taos/Protocols/TDWebSocket/TaosWebSocket.cs +++ b/src/IoTSharp.Data.Taos/Protocols/TDWebSocket/TaosWebSocket.cs @@ -447,7 +447,7 @@ private bool _open_ws(TaosConnectionStringBuilder builder) private bool _ws_conn(TaosConnectionStringBuilder builder, ClientWebSocket _client) { - var rep = WSExecute(_client, new WSActionReq() { Action = "conn", Args = new WSConnReq() { user = builder.Username, password = builder.Password, req_id = 0, db = builder.DataBase } }); + var rep = WSExecute(_client, new WSActionReq() { Action = "conn", Args = new WSConnReq() { user = builder.Username, password = builder.Password, req_id = 0 } }); if (rep.code == 899) { rep = WSExecute(_client, new WSActionReq() { Action = "conn", Args = new WSConnReq() { user = builder.Username, password = builder.Password, req_id = 0 } }); diff --git a/src/IoTSharp.HealthChecks.Taos/IoTSharp.HealthChecks.Taos.csproj b/src/IoTSharp.HealthChecks.Taos/IoTSharp.HealthChecks.Taos.csproj index 0347d0d..aeb973a 100644 --- a/src/IoTSharp.HealthChecks.Taos/IoTSharp.HealthChecks.Taos.csproj +++ b/src/IoTSharp.HealthChecks.Taos/IoTSharp.HealthChecks.Taos.csproj @@ -1,7 +1,7 @@ - net6 + net8 true 1.0.1 @@ -17,8 +17,8 @@ - - + + diff --git a/src/ORMExample/ORMExample.csproj b/src/ORMExample/ORMExample.csproj index 6902639..24b837f 100644 --- a/src/ORMExample/ORMExample.csproj +++ b/src/ORMExample/ORMExample.csproj @@ -2,7 +2,7 @@ Exe - net6.0 + net8.0 diff --git a/taos.cfg b/taos.cfg new file mode 100644 index 0000000..a21c0e7 --- /dev/null +++ b/taos.cfg @@ -0,0 +1,193 @@ +######################################################## +# # +# Configuration # +# # +######################################################## + +######### 0. Client only configurations ############# + +# The interval for CLI to send heartbeat to mnode +# shellActivityTimer 3 + + +############### 1. Cluster End point ############################ + +# The end point of the first dnode in the cluster to be connected to when this dnode or the CLI utility is started +# firstEp hostname:6030 + +# The end point of the second dnode to be connected to if the firstEp is not available +# secondEp + + +############### 2. Configuration Parameters of current dnode ##### + +# The FQDN of the host on which this dnode will be started. It can be IP address +# fqdn hostname + +# The port for external access after this dnode is started +# serverPort 6030 + +# The maximum number of connections a dnode can accept +# maxShellConns 5000 + +# The directory for writing log files, if you are using Windows platform please change to Windows path +# logDir /var/log/taos + +# All data files are stored in this directory, if you are using Windows platform please change to Windows path +# dataDir /var/lib/taos + +# temporary file's directory, if you are using Windows platform please change to Windows path +# tempDir /tmp/ + +# Switch for allowing to collect and report service usage information +# telemetryReporting 0 + +# Switch for allowing to collect and report crash information +# crashReporting 0 + +# The maximum number of vnodes supported by this dnode +supportVnodes 8 + +# The interval of this dnode reporting status to mnode, [1..10] seconds +# statusInterval 1 + +# The minimum sliding window time, milli-second +# minSlidingTime 10 + +# The minimum time window, milli-second +# minIntervalTime 10 + +# The maximum allowed query buffer size in MB during query processing for each data node +# -1 no limit (default) +# 0 no query allowed, queries are disabled +# queryBufferSize -1 + +# The compressed rpc message, option: +# -1 (no compression) +# 0 (all message compressed), +# > 0 (rpc message body which larger than this value will be compressed) +# compressMsgSize -1 + +# query retrieved column data compression option: +# -1 (no compression) +# 0 (all retrieved column data compressed), +# > 0 (any retrieved column size greater than this value all data will be compressed.) +# compressColData -1 + +# system time zone +# timezone UTC-8 + +# system time zone (for windows 10) +# timezone Asia/Shanghai (CST, +0800) + +# system locale +# locale en_US.UTF-8 + +# system charset +# charset UTF-8 + +# stop writing logs when the disk size of the log folder is less than this value +# minimalLogDirGB 1.0 + +# stop writing temporary files when the disk size of the tmp folder is less than this value +# minimalTmpDirGB 1.0 + +# if free disk space is less than this value, this dnode will fail to start +# minimalDataDirGB 2.0 + +# enable/disable system monitor +# monitor 1 + +# enable/disable audit log +# audit 1 + +# enable/disable audit create table +# auditCreateTable 1 + +# The following parameter is used to limit the maximum number of lines in log files. +# max number of lines per log filters +# numOfLogLines 10000000 + +# write log in async way: 1 - async, 0 - sync +# asyncLog 1 + +# time period of keeping log files, in days +# logKeepDays 0 + + +############ 3. Debug Flag and levels ############################################# + +# The following parameters are used for debug purpose only by this dnode. +# debugFlag is a 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR +# Available debug levels are: +# 131: output warning and error +# 135: output debug, warning and error +# 143: output trace, debug, warning and error to log +# 199: output debug, warning and error to both screen and file +# 207: output trace, debug, warning and error to both screen and file + +# debug flag for all log type, take effect when non-zero value +# debugFlag 0 + +# debug flag for timer +# tmrDebugFlag 131 + +# debug flag for util +# uDebugFlag 131 + +# debug flag for rpc +# rpcDebugFlag 131 + +# debug flag for jni +# jniDebugFlag 131 + +# debug flag for query +# qDebugFlag 131 + +# debug flag for client driver +# cDebugFlag 131 + +# debug flag for dnode messages +# dDebugFlag 135 + +# debug flag for vnode +# vDebugFlag 131 + +# debug flag for meta management messages +# mDebugFlag 135 + +# debug flag for wal +# wDebugFlag 135 + +# debug flag for sync module +# sDebugFlag 135 + +# debug flag for tsdb +# tsdbDebugFlag 131 + +# debug flag for tq +# tqDebugFlag 131 + +# debug flag for fs +# fsDebugFlag 131 + +# debug flag for udf +# udfDebugFlag 131 + +# debug flag for sma +# smaDebugFlag 131 + +# debug flag for index +# idxDebugFlag 131 + +# debug flag for tdb +# tdbDebugFlag 131 + +# debug flag for meta +# metaDebugFlag 131 + +# generate core file when service crash +# enableCoreFile 1 +#monitor 1 +#monitorFQDN buildkitsandbox +#audit 1