taosdemo.c 279.9 KB
Newer Older
S
TD-1057  
Shengliang Guan 已提交
1
/*
H
hzcheng 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * 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 <http://www.gnu.org/licenses/>.
 */

16 17 18 19 20

/*
   when in some thread query return error, thread don't exit, but return, otherwise coredump in other thread.
*/

21
#include <stdint.h>
22
#include <taos.h>
S
slguan 已提交
23
#define _GNU_SOURCE
24 25
#define CURL_STATICLIB

S
TD-1057  
Shengliang Guan 已提交
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
#ifdef LINUX
  #include <argp.h>
  #include <inttypes.h>
  #ifndef _ALPINE
    #include <error.h>
  #endif
  #include <pthread.h>
  #include <semaphore.h>
  #include <stdbool.h>
  #include <stdio.h>
  #include <string.h>
  #include <sys/time.h>
  #include <time.h>
  #include <unistd.h>
  #include <wordexp.h>
  #include <regex.h>
42
#else
S
TD-1057  
Shengliang Guan 已提交
43 44
  #include <regex.h>
  #include <stdio.h>
45
#endif
H
hzcheng 已提交
46

47
#include <assert.h>
48
#include <stdlib.h>
49 50
#include "cJSON.h"

51
#include "os.h"
H
hzcheng 已提交
52
#include "taos.h"
53
#include "taoserror.h"
H
Hui Li 已提交
54
#include "tutil.h"
S
slguan 已提交
55

56 57
#define STMT_IFACE_ENABLED  0

58 59 60
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

S
slguan 已提交
61 62
extern char configDir[];

63 64 65 66
#define INSERT_JSON_NAME      "insert.json"
#define QUERY_JSON_NAME       "query.json"
#define SUBSCRIBE_JSON_NAME   "subscribe.json"

67 68
#define STR_INSERT_INTO     "INSERT INTO "

69 70 71 72 73 74
enum TEST_MODE {
    INSERT_TEST,            // 0
    QUERY_TEST,             // 1
    SUBSCRIBE_TEST,         // 2
    INVAID_TEST
};
75

76 77
#define MAX_RECORDS_PER_REQ     32766

78 79
#define HEAD_BUFF_LEN    1024*24  // 16*1024 + (192+32)*2 + insert into ..

80 81
#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
82
#define COND_BUF_LEN       (BUFFER_SIZE - 30)
83 84 85
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
#define MAX_HOSTNAME_SIZE  64
86
#define MAX_TB_NAME_SIZE   64
87
#define MAX_DATA_SIZE      (16*1024)+20     // max record len: 16*1024, timestamp string and ,('') need extra space
88 89 90 91
#define MAX_NUM_DATATYPE   10
#define OPT_ABORT          1 /* –abort */
#define STRING_LEN         60000
#define MAX_PREPARED_RAND  1000000
92
#define MAX_FILE_NAME_LEN  256              // max file name length on linux is 255.
93 94 95 96 97

#define   MAX_SAMPLES_ONCE_FROM_FILE   10000
#define   MAX_NUM_DATATYPE 10

#define   MAX_DB_COUNT           8
98
#define   MAX_SUPER_TABLE_COUNT  200
99 100 101
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

102
#define   MAX_QUERY_SQL_COUNT    100
103
#define   MAX_QUERY_SQL_LENGTH   1024
104 105

#define   MAX_DATABASE_COUNT     256
106
#define INPUT_BUF_LEN   256
107

108
#define DEFAULT_TIMESTAMP_STEP  1
109

110

111 112 113 114 115
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
116

117 118
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
119
  TBL_ALREADY_EXISTS,
120 121 122
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

123
enum enumSYNC_MODE {
124 125
  SYNC_MODE,
  ASYNC_MODE,
126 127
  MODE_BUT
};
128

129 130 131 132 133 134 135
enum enum_TAOS_INTERFACE {
    TAOSC_IFACE,
    REST_IFACE,
    STMT_IFACE,
    INTERFACE_BUT
};

136 137 138 139 140 141
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

142
typedef enum enum_PROGRESSIVE_OR_INTERLACE {
143 144 145
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
146
} PROG_OR_INTERLACE_MODE;
147

148
typedef enum enumQUERY_TYPE {
149
  NO_INSERT_TYPE,
150
  INSERT_TYPE,
151
  QUERY_TYPE_BUT
152
} QUERY_TYPE;
153 154 155 156 157 158 159

enum _show_db_index {
  TSDB_SHOW_DB_NAME_INDEX,
  TSDB_SHOW_DB_CREATED_TIME_INDEX,
  TSDB_SHOW_DB_NTABLES_INDEX,
  TSDB_SHOW_DB_VGROUPS_INDEX,
  TSDB_SHOW_DB_REPLICA_INDEX,
160
  TSDB_SHOW_DB_QUORUM_INDEX,
161 162 163 164 165 166 167 168 169 170
  TSDB_SHOW_DB_DAYS_INDEX,
  TSDB_SHOW_DB_KEEP_INDEX,
  TSDB_SHOW_DB_CACHE_INDEX,
  TSDB_SHOW_DB_BLOCKS_INDEX,
  TSDB_SHOW_DB_MINROWS_INDEX,
  TSDB_SHOW_DB_MAXROWS_INDEX,
  TSDB_SHOW_DB_WALLEVEL_INDEX,
  TSDB_SHOW_DB_FSYNC_INDEX,
  TSDB_SHOW_DB_COMP_INDEX,
  TSDB_SHOW_DB_CACHELAST_INDEX,
171
  TSDB_SHOW_DB_PRECISION_INDEX,
172 173 174 175 176 177 178 179 180 181
  TSDB_SHOW_DB_UPDATE_INDEX,
  TSDB_SHOW_DB_STATUS_INDEX,
  TSDB_MAX_SHOW_DB
};

// -----------------------------------------SHOW TABLES CONFIGURE -------------------------------------
enum _show_stables_index {
  TSDB_SHOW_STABLES_NAME_INDEX,
  TSDB_SHOW_STABLES_CREATED_TIME_INDEX,
  TSDB_SHOW_STABLES_COLUMNS_INDEX,
182 183
  TSDB_SHOW_STABLES_METRIC_INDEX,
  TSDB_SHOW_STABLES_UID_INDEX,
184
  TSDB_SHOW_STABLES_TID_INDEX,
185
  TSDB_SHOW_STABLES_VGID_INDEX,
186
  TSDB_MAX_SHOW_STABLES
187 188
};

189 190 191 192 193 194 195 196
enum _describe_table_index {
  TSDB_DESCRIBE_METRIC_FIELD_INDEX,
  TSDB_DESCRIBE_METRIC_TYPE_INDEX,
  TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
  TSDB_DESCRIBE_METRIC_NOTE_INDEX,
  TSDB_MAX_DESCRIBE_METRIC
};

H
hzcheng 已提交
197
/* Used by main to communicate with parse_opt. */
198 199
static char *g_dupstr = NULL;

200
typedef struct SArguments_S {
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
    char *   metaFile;
    uint32_t test_mode;
    char *   host;
    uint16_t port;
    uint16_t iface;
    char *   user;
    char *   password;
    char *   database;
    int      replica;
    char *   tb_prefix;
    char *   sqlFile;
    bool     use_metric;
    bool     drop_database;
    bool     insert_only;
    bool     answer_yes;
    bool     debug_print;
    bool     verbose_print;
    bool     performance_print;
    char *   output_file;
    bool     async_mode;
    char *   datatype[MAX_NUM_DATATYPE + 1];
    uint32_t len_of_binary;
    uint32_t num_of_CPR;
    uint32_t num_of_threads;
    uint64_t insert_interval;
    int64_t  query_times;
    uint32_t interlace_rows;
    uint32_t num_of_RPR;                  // num_of_records_per_req
    uint64_t max_sql_len;
    int64_t  num_of_tables;
    int64_t  num_of_DPT;
    int      abort;
    uint32_t disorderRatio;               // 0: no disorder, >0: x%
    int      disorderRange;               // ms or us by database precision
    uint32_t method_of_delete;
    char **  arg_list;
    uint64_t totalInsertRows;
    uint64_t totalAffectedRows;
    bool     demo_mode;                  // use default column name and semi-random data
240 241 242
} SArguments;

typedef struct SColumn_S {
243 244
  char      field[TSDB_COL_NAME_LEN];
  char      dataType[16];
245
  uint32_t  dataLen;
246
  char      note[128];
247 248 249
} StrColumn;

typedef struct SSuperTable_S {
250 251 252
  char         sTblName[TSDB_TABLE_NAME_LEN];
  char         dataSource[MAX_TB_NAME_SIZE];  // rand_gen or sample
  char         childTblPrefix[TSDB_TABLE_NAME_LEN - 20]; // 20 characters reserved for seq
253 254
  char         insertMode[MAX_TB_NAME_SIZE];    // taosc, rest
  uint16_t     childTblExists;
255
  int64_t      childTblCount;
256 257
  uint64_t     batchCreateTableNum;     // 0: no batch,  > 0: batch table number in one sql
  uint8_t      autoCreateTable;         // 0: create sub table, 1: auto create sub table
258
  uint16_t     iface;                   // 0: taosc, 1: rest, 2: stmt
259
  int64_t      childTblLimit;
260
  uint64_t     childTblOffset;
261

262
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
263
  uint32_t     interlaceRows;           //
264 265
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
266
  uint64_t     maxSqlLen;               //
267

268
  uint64_t     insertInterval;          // insert interval, will override global insert interval
269
  int64_t      insertRows;
270
  int64_t      timeStampStep;
271
  char         startTimestamp[MAX_TB_NAME_SIZE];
272
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
273 274
  char         sampleFile[MAX_FILE_NAME_LEN];
  char         tagsFile[MAX_FILE_NAME_LEN];
275

276
  uint32_t     columnCount;
277
  StrColumn    columns[MAX_COLUMN_COUNT];
278
  uint32_t     tagCount;
279 280 281
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
282
  char*        colsOfCreateChildTable;
283 284
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
285 286 287 288 289

  char*        sampleDataBuf;
  //int          sampleRowCount;
  //int          sampleUsePos;

290
  uint32_t     tagSource;    // 0: rand, 1: tag sample
291
  char*        tagDataBuf;
292 293
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
294

295
  // statistics
296 297
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
298 299 300
} SSuperTable;

typedef struct {
301
  char     name[TSDB_DB_NAME_LEN];
302
  char     create_time[32];
303
  int64_t  ntables;
304
  int32_t  vgroups;
305 306
  int16_t  replica;
  int16_t  quorum;
307
  int16_t  days;
308 309 310 311 312 313 314 315 316 317 318 319 320 321
  char     keeplist[32];
  int32_t  cache; //MB
  int32_t  blocks;
  int32_t  minrows;
  int32_t  maxrows;
  int8_t   wallevel;
  int32_t  fsync;
  int8_t   comp;
  int8_t   cachelast;
  char     precision[8];   // time resolution
  int8_t   update;
  char     status[16];
} SDbInfo;

322
typedef struct SDbCfg_S {
323
//  int       maxtablesPerVnode;
324 325
  uint32_t  minRows;        // 0 means default
  uint32_t  maxRows;        // 0 means default
326 327
  int       comp;
  int       walLevel;
328
  int       cacheLast;
329
  int       fsync;
330 331 332 333 334 335 336
  int       replica;
  int       update;
  int       keep;
  int       days;
  int       cache;
  int       blocks;
  int       quorum;
337
  char      precision[8];
338 339 340
} SDbCfg;

typedef struct SDataBase_S {
341
  char         dbName[TSDB_DB_NAME_LEN];
342
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
343
  SDbCfg       dbCfg;
344
  uint64_t     superTblCount;
345 346 347 348
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
349
  char         cfgDir[MAX_FILE_NAME_LEN];
350
  char         host[MAX_HOSTNAME_SIZE];
351 352
  struct sockaddr_in serv_addr;

353
  uint16_t     port;
354 355
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
356
  char         resultFile[MAX_FILE_NAME_LEN];
357 358 359
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
360
  bool         asyncMode;
361

362 363 364
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
365 366 367
  SDataBase    db[MAX_DB_COUNT];

  // statistics
368 369
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
370

371 372
} SDbs;

373
typedef struct SpecifiedQueryInfo_S {
374
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
375
  uint32_t     concurrent;
376
  int          sqlCount;
377
  uint32_t     asyncMode; // 0: sync, 1: async
378 379
  uint64_t     subscribeInterval; // ms
  uint64_t     queryTimes;
380
  bool         subscribeRestart;
381
  int          subscribeKeepProgress;
382
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
383
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
384
  int          resubAfterConsume[MAX_QUERY_SQL_COUNT];
385
  int          endAfterConsume[MAX_QUERY_SQL_COUNT];
386
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
387 388 389
  char         topic[MAX_QUERY_SQL_COUNT][32];
  int          consumed[MAX_QUERY_SQL_COUNT];
  TAOS_RES*    res[MAX_QUERY_SQL_COUNT];
390
  uint64_t     totalQueried;
391
} SpecifiedQueryInfo;
392

393
typedef struct SuperQueryInfo_S {
394
  char         sTblName[TSDB_TABLE_NAME_LEN];
395 396
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
  uint32_t     threadCnt;
397
  uint32_t     asyncMode; // 0: sync, 1: async
398
  uint64_t     subscribeInterval; // ms
399
  bool         subscribeRestart;
400
  int          subscribeKeepProgress;
401
  uint64_t     queryTimes;
402
  int64_t      childTblCount;
403
  char         childTblPrefix[TSDB_TABLE_NAME_LEN - 20];    // 20 characters reserved for seq
404
  int          sqlCount;
405
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
406
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN];
407
  int          resubAfterConsume;
408
  int          endAfterConsume;
409
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
410

411
  char*        childTblName;
412
  uint64_t     totalQueried;
413
} SuperQueryInfo;
414 415

typedef struct SQueryMetaInfo_S {
416
  char         cfgDir[MAX_FILE_NAME_LEN];
417
  char         host[MAX_HOSTNAME_SIZE];
418
  uint16_t     port;
419
  struct       sockaddr_in serv_addr;
420 421
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
422
  char         dbName[TSDB_DB_NAME_LEN];
423
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
424

425
  SpecifiedQueryInfo  specifiedQueryInfo;
426
  SuperQueryInfo      superQueryInfo;
427
  uint64_t     totalQueried;
428 429 430
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    TAOS *    taos;
    TAOS_STMT *stmt;
    int       threadID;
    char      db_name[TSDB_DB_NAME_LEN];
    uint32_t  time_precision;
    char      filePath[4096];
    FILE      *fp;
    char      tb_prefix[TSDB_TABLE_NAME_LEN];
    uint64_t  start_table_from;
    uint64_t  end_table_to;
    int64_t   ntables;
    uint64_t  data_of_rate;
    int64_t   start_time;
    char*     cols;
    bool      use_metric;
    SSuperTable* superTblInfo;
    char      *buffer;    // sql cmd buffer

    // for async insert
    tsem_t    lock_sem;
    int64_t   counter;
    uint64_t  st;
    uint64_t  et;
    uint64_t  lastTs;

    // sample data
    int64_t   samplePos;
    // statistics
    uint64_t  totalInsertRows;
    uint64_t  totalAffectedRows;

    // insert delay statistics
    uint64_t  cntDelay;
    uint64_t  totalDelay;
    uint64_t  avgDelay;
    uint64_t  maxDelay;
    uint64_t  minDelay;

    // seq of query or subscribe
    uint64_t  querySeq;   // sequence number of sql command
    TAOS_SUB*  tsub;
472

473 474
} threadInfo;

475
#ifdef WINDOWS
476 477
#define _CRT_RAND_S

478
#include <windows.h>
479 480 481 482 483
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
484 485
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
486 487
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
488 489 490 491

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

492
static void setupForAnsiEscape(void) {
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
  DWORD mode = 0;
  g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);

  if(g_stdoutHandle == INVALID_HANDLE_VALUE) {
    exit(GetLastError());
  }

  if(!GetConsoleMode(g_stdoutHandle, &mode)) {
    exit(GetLastError());
  }

  g_consoleMode = mode;

  // Enable ANSI escape codes
  mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;

  if(!SetConsoleMode(g_stdoutHandle, mode)) {
    exit(GetLastError());
511
  }
512 513
}

514
static void resetAfterAnsiEscape(void) {
515
  // Reset colors
516
  printf("\x1b[0m");
517 518 519 520 521 522

  // Reset console mode
  if(!SetConsoleMode(g_stdoutHandle, g_consoleMode)) {
    exit(GetLastError());
  }
}
523

524
static int taosRandom()
525 526 527 528 529 530
{
    int number;
    rand_s(&number);

    return number;
}
531
#else   // Not windows
532
static void setupForAnsiEscape(void) {}
533

534
static void resetAfterAnsiEscape(void) {
535 536 537
  // Reset colors
  printf("\x1b[0m");
}
538

539 540
#include <time.h>

541
static int taosRandom()
542
{
543
  return rand();
544 545
}

546
#endif // ifdef Windows
547

548
static void prompt();
549
static int createDatabasesAndStables();
550
static void createChildTables();
551
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
552
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
553
        uint16_t port, char* sqlstr, threadInfo *pThreadInfo);
554
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
555
        int disorderRatio, int disorderRange);
556 557
static bool getInfoFromJsonFile(char* file);
static void init_rand_data();
558 559 560 561 562 563 564

/* ************ Global variables ************  */

int32_t  randint[MAX_PREPARED_RAND];
int64_t  randbigint[MAX_PREPARED_RAND];
float    randfloat[MAX_PREPARED_RAND];
double   randdouble[MAX_PREPARED_RAND];
565
char *aggreFunc[] = {"*", "count(*)", "avg(col0)", "sum(col0)",
566 567
    "max(col0)", "min(col0)", "first(col0)", "last(col0)"};

568 569
#define DEFAULT_DATATYPE_NUM    3

570
SArguments g_args = {
571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
    NULL,            // metaFile
    0,               // test_mode
    "127.0.0.1",     // host
    6030,            // port
    TAOSC_IFACE,     // iface
    "root",          // user
#ifdef _TD_POWER_
    "powerdb",      // password
#elif (_TD_TQ_ == true)
    "tqueue",      // password
#else
    "taosdata",      // password
#endif
    "test",          // database
    1,               // replica
    "d",             // tb_prefix
    NULL,            // sqlFile
    true,            // use_metric
    true,            // drop_database
    true,            // insert_only
    false,           // debug_print
    false,           // verbose_print
    false,           // performance statistic print
    false,           // answer_yes;
    "./output.txt",  // output_file
    0,               // mode : sync or async
    {
        "FLOAT",         // datatype
        "INT",           // datatype
600
        "FLOAT",         // datatype. DEFAULT_DATATYPE_NUM is 3
601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619
    },
    16,              // len_of_binary
    4,               // num_of_CPR
    10,              // num_of_connections/thread
    0,               // insert_interval
    1,               // query_times
    0,               // interlace_rows;
    30000,           // num_of_RPR
    (1024*1024),     // max_sql_len
    10000,           // num_of_tables
    10000,           // num_of_DPT
    0,               // abort
    0,               // disorderRatio
    1000,            // disorderRange
    1,               // method_of_delete
    NULL,            // arg_list
    0,               // totalInsertRows;
    0,               // totalAffectedRows;
    true,            // demo_mode;
620 621 622 623 624
};



static SDbs            g_Dbs;
625
static int64_t         g_totalChildTables = 0;
626 627 628
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

629 630 631 632
#if _MSC_VER <= 1900
#define __func__ __FUNCTION__
#endif

633
#define debugPrint(fmt, ...) \
634
    do { if (g_args.debug_print || g_args.verbose_print) \
635
      fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
636

637
#define verbosePrint(fmt, ...) \
638 639
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
640

641 642 643 644
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

645 646 647
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)

648 649 650
// for strncpy buffer overflow
#define min(a, b) (((a) < (b)) ? (a) : (b))

651

652
///////////////////////////////////////////////////
H
hzcheng 已提交
653

654 655
static void ERROR_EXIT(const char *msg) { perror(msg); exit(-1); }

656 657 658 659 660 661 662 663
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

664
#ifndef TAOSDEMO_STATUS
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681
#define TAOSDEMO_STATUS "unknown"
#endif

static void printVersion() {
    char tdengine_ver[] = TD_VERNUMBER;
    char taosdemo_ver[] = TAOSDEMO_COMMIT_SHA1;
    char taosdemo_status[] = TAOSDEMO_STATUS;

    if (strlen(taosdemo_status) == 0) {
        printf("taosdemo verison %s-%s\n",
                tdengine_ver, taosdemo_ver);
    } else {
        printf("taosdemo verison %s-%s, status:%s\n",
                tdengine_ver, taosdemo_ver, taosdemo_status);
    }
}

682
static void printHelp() {
683 684 685 686 687
    char indent[10] = "        ";
    printf("%s%s%s%s\n", indent, "-f", indent,
            "The meta file to the execution procedure. Default is './meta.json'.");
    printf("%s%s%s%s\n", indent, "-u", indent,
            "The TDengine user name to use when connecting to the server. Default is 'root'.");
688
#ifdef _TD_POWER_
689 690 691 692 693 694 695 696 697
    printf("%s%s%s%s\n", indent, "-P", indent,
            "The password to use when connecting to the server. Default is 'powerdb'.");
    printf("%s%s%s%s\n", indent, "-c", indent,
            "Configuration directory. Default is '/etc/power/'.");
#elif (_TD_TQ_ == true)
    printf("%s%s%s%s\n", indent, "-P", indent,
            "The password to use when connecting to the server. Default is 'tqueue'.");
    printf("%s%s%s%s\n", indent, "-c", indent,
            "Configuration directory. Default is '/etc/tq/'.");
698
#else
699 700 701 702
    printf("%s%s%s%s\n", indent, "-P", indent,
            "The password to use when connecting to the server. Default is 'taosdata'.");
    printf("%s%s%s%s\n", indent, "-c", indent,
            "Configuration directory. Default is '/etc/taos/'.");
703
#endif
704 705 706 707 708
    printf("%s%s%s%s\n", indent, "-h", indent,
            "The host to connect to TDengine. Default is localhost.");
    printf("%s%s%s%s\n", indent, "-p", indent,
            "The TCP/IP port number to use for the connection. Default is 0.");
    printf("%s%s%s%s\n", indent, "-I", indent,
709
#if STMT_IFACE_ENABLED == 1
710
            "The interface (taosc, rest, and stmt) taosdemo uses. Default is 'taosc'.");
711
#else
712
    "The interface (taosc, rest) taosdemo uses. Default is 'taosc'.");
713
#endif
714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
    printf("%s%s%s%s\n", indent, "-d", indent,
            "Destination database. Default is 'test'.");
    printf("%s%s%s%s\n", indent, "-a", indent,
            "Set the replica parameters of the database, Default 1, min: 1, max: 3.");
    printf("%s%s%s%s\n", indent, "-m", indent,
            "Table prefix name. Default is 'd'.");
    printf("%s%s%s%s\n", indent, "-s", indent, "The select sql file.");
    printf("%s%s%s%s\n", indent, "-N", indent, "Use normal table flag.");
    printf("%s%s%s%s\n", indent, "-o", indent,
            "Direct output to the named file. Default is './output.txt'.");
    printf("%s%s%s%s\n", indent, "-q", indent,
            "Query mode -- 0: SYNC, 1: ASYNC. Default is SYNC.");
    printf("%s%s%s%s\n", indent, "-b", indent,
            "The data_type of columns, default: FLOAT, INT, FLOAT.");
    printf("%s%s%s%s\n", indent, "-w", indent,
            "The length of data_type 'BINARY' or 'NCHAR'. Default is 16");
730 731 732 733
    printf("%s%s%s%s%d%s%d\n", indent, "-l", indent,
            "The number of columns per record. Default is ",
            DEFAULT_DATATYPE_NUM,
            ". Max values is ",
734
            MAX_NUM_DATATYPE);
735 736
    printf("%s%s%s%s\n", indent, indent, indent,
            "All of the new column(s) type is INT. If use -b to specify column type, -l will be ignored.");
737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764
    printf("%s%s%s%s\n", indent, "-T", indent,
            "The number of threads. Default is 10.");
    printf("%s%s%s%s\n", indent, "-i", indent,
            "The sleep time (ms) between insertion. Default is 0.");
    printf("%s%s%s%s\n", indent, "-r", indent,
            "The number of records per request. Default is 30000.");
    printf("%s%s%s%s\n", indent, "-t", indent,
            "The number of tables. Default is 10000.");
    printf("%s%s%s%s\n", indent, "-n", indent,
            "The number of records per table. Default is 10000.");
    printf("%s%s%s%s\n", indent, "-M", indent,
            "The value of records generated are totally random.");
    printf("%s%s%s%s\n", indent, indent, indent,
            " The default is to simulate power equipment senario.");
    printf("%s%s%s%s\n", indent, "-x", indent, "Not insert only flag.");
    printf("%s%s%s%s\n", indent, "-y", indent, "Default input yes for prompt.");
    printf("%s%s%s%s\n", indent, "-O", indent,
            "Insert mode--0: In order, 1 ~ 50: disorder ratio. Default is in order.");
    printf("%s%s%s%s\n", indent, "-R", indent,
            "Out of order data's range, ms, default is 1000.");
    printf("%s%s%s%s\n", indent, "-g", indent,
            "Print debug info.");
    printf("%s%s%s\n", indent, "-V, --version\t",
            "Print version info.");
    printf("%s%s%s%s\n", indent, "--help\t", indent,
            "Print command line arguments list info.");
    /*    printf("%s%s%s%s\n", indent, "-D", indent,
          "Delete database if exists. 0: no, 1: yes, default is 1");
765 766 767
          */
}

768 769
static bool isStringNumber(char *input)
{
770 771 772 773
    int len = strlen(input);
    if (0 == len) {
        return false;
    }
774

775 776 777 778
    for (int i = 0; i < len; i++) {
        if (!isdigit(input[i]))
            return false;
    }
779

780
    return true;
781 782
}

783
static void parse_args(int argc, char *argv[], SArguments *arguments) {
784

785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821
    for (int i = 1; i < argc; i++) {
        if (strcmp(argv[i], "-f") == 0) {
            arguments->demo_mode = false;
            arguments->metaFile = argv[++i];
        } else if (strcmp(argv[i], "-c") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-c need a valid path following!\n");
                exit(EXIT_FAILURE);
            }
            tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
        } else if (strcmp(argv[i], "-h") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-h need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->host = argv[++i];
        } else if (strcmp(argv[i], "-p") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-p need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->port = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-I") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-I need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            ++i;
            if (0 == strcasecmp(argv[i], "taosc")) {
                arguments->iface = TAOSC_IFACE;
            } else if (0 == strcasecmp(argv[i], "rest")) {
                arguments->iface = REST_IFACE;
822
#if STMT_IFACE_ENABLED == 1
823 824
            } else if (0 == strcasecmp(argv[i], "stmt")) {
                arguments->iface = STMT_IFACE;
825
#endif
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
            } else {
                errorPrint("%s", "\n\t-I need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
        } else if (strcmp(argv[i], "-u") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-u need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->user = argv[++i];
        } else if (strcmp(argv[i], "-P") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-P need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->password = argv[++i];
        } else if (strcmp(argv[i], "-o") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-o need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->output_file = argv[++i];
        } else if (strcmp(argv[i], "-s") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-s need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->sqlFile = argv[++i];
        } else if (strcmp(argv[i], "-q") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, not-0: ASYNC. Default is SYNC.\n");
                exit(EXIT_FAILURE);
            }
            arguments->async_mode = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-T") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-T need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->num_of_threads = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-i") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-i need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->insert_interval = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-qt") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-qt need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->query_times = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-B") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-B need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->interlace_rows = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-r") == 0) {
            if ((argc == i+1)
                    || (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-r need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->num_of_RPR = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-t") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-t need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->num_of_tables = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-n") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-n need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->num_of_DPT = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-d") == 0) {
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-d need a valid string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->database = argv[++i];
        } else if (strcmp(argv[i], "-l") == 0) {
            arguments->demo_mode = false;
            if (argc == i+1) {
                if (!isStringNumber(argv[i+1])) {
                    printHelp();
                    errorPrint("%s", "\n\t-l need a number following!\n");
                    exit(EXIT_FAILURE);
                }
            }
            arguments->num_of_CPR = atoi(argv[++i]);
939

940 941 942 943 944
            if (arguments->num_of_CPR > MAX_NUM_DATATYPE) {
                printf("WARNING: max acceptible columns count is %d\n", MAX_NUM_DATATYPE);
                prompt();
                arguments->num_of_CPR = MAX_NUM_DATATYPE;
            }
945

946 947 948
            for (int col = DEFAULT_DATATYPE_NUM; col < arguments->num_of_CPR; col ++) {
                arguments->datatype[col] = "INT";
            }
949 950 951
            for (int col = arguments->num_of_CPR; col < MAX_NUM_DATATYPE; col++) {
                arguments->datatype[col] = NULL;
            }
952

953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
        } else if (strcmp(argv[i], "-b") == 0) {
            arguments->demo_mode = false;
            if (argc == i+1) {
                printHelp();
                errorPrint("%s", "\n\t-b need valid string following!\n");
                exit(EXIT_FAILURE);
            }
            ++i;
            if (strstr(argv[i], ",") == NULL) {
                // only one col
                if (strcasecmp(argv[i], "INT")
                        && strcasecmp(argv[i], "FLOAT")
                        && strcasecmp(argv[i], "TINYINT")
                        && strcasecmp(argv[i], "BOOL")
                        && strcasecmp(argv[i], "SMALLINT")
                        && strcasecmp(argv[i], "BIGINT")
                        && strcasecmp(argv[i], "DOUBLE")
                        && strcasecmp(argv[i], "BINARY")
                        && strcasecmp(argv[i], "TIMESTAMP")
                        && strcasecmp(argv[i], "NCHAR")) {
                    printHelp();
                    errorPrint("%s", "-b: Invalid data_type!\n");
                    exit(EXIT_FAILURE);
                }
                arguments->datatype[0] = argv[i];
            } else {
                // more than one col
                int index = 0;
                g_dupstr = strdup(argv[i]);
                char *running = g_dupstr;
                char *token = strsep(&running, ",");
                while(token != NULL) {
                    if (strcasecmp(token, "INT")
                            && strcasecmp(token, "FLOAT")
                            && strcasecmp(token, "TINYINT")
                            && strcasecmp(token, "BOOL")
                            && strcasecmp(token, "SMALLINT")
                            && strcasecmp(token, "BIGINT")
                            && strcasecmp(token, "DOUBLE")
                            && strcasecmp(token, "BINARY")
                            && strcasecmp(token, "TIMESTAMP")
                            && strcasecmp(token, "NCHAR")) {
                        printHelp();
                        free(g_dupstr);
                        errorPrint("%s", "-b: Invalid data_type!\n");
                        exit(EXIT_FAILURE);
                    }
                    arguments->datatype[index++] = token;
                    token = strsep(&running, ",");
                    if (index >= MAX_NUM_DATATYPE) break;
                }
                arguments->datatype[index] = NULL;
            }
        } else if (strcmp(argv[i], "-w") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-w need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->len_of_binary = atoi(argv[++i]);
        } else if (strcmp(argv[i], "-m") == 0) {
            if ((argc == i+1) ||
                    (isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-m need a letter-initial string following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->tb_prefix = argv[++i];
        } else if (strcmp(argv[i], "-N") == 0) {
            arguments->use_metric = false;
        } else if (strcmp(argv[i], "-M") == 0) {
            arguments->demo_mode = false;
        } else if (strcmp(argv[i], "-x") == 0) {
            arguments->insert_only = false;
        } else if (strcmp(argv[i], "-y") == 0) {
            arguments->answer_yes = true;
        } else if (strcmp(argv[i], "-g") == 0) {
            arguments->debug_print = true;
        } else if (strcmp(argv[i], "-gg") == 0) {
            arguments->verbose_print = true;
        } else if (strcmp(argv[i], "-pp") == 0) {
            arguments->performance_print = true;
        } else if (strcmp(argv[i], "-O") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-O need a number following!\n");
                exit(EXIT_FAILURE);
            }
1043

1044
            arguments->disorderRatio = atoi(argv[++i]);
1045

1046 1047 1048
            if (arguments->disorderRatio > 50) {
                arguments->disorderRatio = 50;
            }
1049

1050 1051 1052
            if (arguments->disorderRatio < 0) {
                arguments->disorderRatio = 0;
            }
1053

1054 1055 1056 1057 1058 1059 1060
        } else if (strcmp(argv[i], "-R") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-R need a number following!\n");
                exit(EXIT_FAILURE);
            }
1061

1062 1063 1064
            arguments->disorderRange = atoi(argv[++i]);
            if (arguments->disorderRange < 0)
                arguments->disorderRange = 1000;
1065

1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
        } else if (strcmp(argv[i], "-a") == 0) {
            if ((argc == i+1) ||
                    (!isStringNumber(argv[i+1]))) {
                printHelp();
                errorPrint("%s", "\n\t-a need a number following!\n");
                exit(EXIT_FAILURE);
            }
            arguments->replica = atoi(argv[++i]);
            if (arguments->replica > 3 || arguments->replica < 1) {
                arguments->replica = 1;
            }
        } else if (strcmp(argv[i], "-D") == 0) {
            arguments->method_of_delete = atoi(argv[++i]);
            if (arguments->method_of_delete > 3) {
                errorPrint("%s", "\n\t-D need a valud (0~3) number following!\n");
                exit(EXIT_FAILURE);
            }
        } else if ((strcmp(argv[i], "--version") == 0) ||
                (strcmp(argv[i], "-V") == 0)){
            printVersion();
            exit(0);
        } else if (strcmp(argv[i], "--help") == 0) {
            printHelp();
            exit(0);
        } else {
            printHelp();
            errorPrint("%s", "ERROR: wrong options\n");
            exit(EXIT_FAILURE);
        }
S
TD-1057  
Shengliang Guan 已提交
1095
    }
1096

1097 1098 1099 1100 1101
    int columnCount;
    for (columnCount = 0; columnCount < MAX_NUM_DATATYPE; columnCount ++) {
        if (g_args.datatype[columnCount] == NULL) {
            break;
        }
1102 1103
    }

1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155
    if (0 == columnCount) {
        perror("data type error!");
        exit(-1);
    }
    g_args.num_of_CPR = columnCount;

    if (((arguments->debug_print) && (arguments->metaFile == NULL))
            || arguments->verbose_print) {
        printf("###################################################################\n");
        printf("# meta file:                         %s\n", arguments->metaFile);
        printf("# Server IP:                         %s:%hu\n",
                arguments->host == NULL ? "localhost" : arguments->host,
                arguments->port );
        printf("# User:                              %s\n", arguments->user);
        printf("# Password:                          %s\n", arguments->password);
        printf("# Use metric:                        %s\n",
                arguments->use_metric ? "true" : "false");
        if (*(arguments->datatype)) {
            printf("# Specified data type:               ");
            for (int i = 0; i < MAX_NUM_DATATYPE; i++)
                if (arguments->datatype[i])
                    printf("%s,", arguments->datatype[i]);
                else
                    break;
            printf("\n");
        }
        printf("# Insertion interval:                %"PRIu64"\n",
                arguments->insert_interval);
        printf("# Number of records per req:         %u\n",
                arguments->num_of_RPR);
        printf("# Max SQL length:                    %"PRIu64"\n",
                arguments->max_sql_len);
        printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
        printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
        printf("# Number of Tables:                  %"PRId64"\n",
                arguments->num_of_tables);
        printf("# Number of Data per Table:          %"PRId64"\n",
                arguments->num_of_DPT);
        printf("# Database name:                     %s\n", arguments->database);
        printf("# Table prefix:                      %s\n", arguments->tb_prefix);
        if (arguments->disorderRatio) {
            printf("# Data order:                        %d\n", arguments->disorderRatio);
            printf("# Data out of order rate:            %d\n", arguments->disorderRange);

        }
        printf("# Delete method:                     %d\n", arguments->method_of_delete);
        printf("# Answer yes when prompt:            %d\n", arguments->answer_yes);
        printf("# Print debug info:                  %d\n", arguments->debug_print);
        printf("# Print verbose info:                %d\n", arguments->verbose_print);
        printf("###################################################################\n");

        prompt();
1156
    }
1157
}
H
hzcheng 已提交
1158

1159
static void tmfclose(FILE *fp) {
1160 1161 1162
    if (NULL != fp) {
        fclose(fp);
    }
1163
}
1164

1165
static void tmfree(char *buf) {
1166 1167 1168
    if (NULL != buf) {
        free(buf);
    }
1169
}
H
Hui Li 已提交
1170

1171
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1172 1173 1174 1175 1176 1177 1178 1179 1180
    int i;
    TAOS_RES *res = NULL;
    int32_t   code = -1;

    for (i = 0; i < 5 /* retry */; i++) {
        if (NULL != res) {
            taos_free_result(res);
            res = NULL;
        }
1181

1182 1183 1184 1185 1186
        res = taos_query(taos, command);
        code = taos_errno(res);
        if (0 == code) {
            break;
        }
H
hzcheng 已提交
1187
    }
1188

1189 1190 1191 1192 1193 1194 1195 1196 1197
    verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
    if (code != 0) {
        if (!quiet) {
            errorPrint("Failed to execute %s, reason: %s\n",
                    command, taos_errstr(res));
        }
        taos_free_result(res);
        //taos_close(taos);
        return -1;
1198
    }
H
hzcheng 已提交
1199

1200 1201 1202 1203
    if (INSERT_TYPE == type) {
        int affectedRows = taos_affected_rows(res);
        taos_free_result(res);
        return affectedRows;
1204
    }
H
hzcheng 已提交
1205

1206
    taos_free_result(res);
1207
    return 0;
1208
}
H
hzcheng 已提交
1209

1210
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
1211
{
1212 1213 1214 1215 1216 1217 1218
    pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
    if (pThreadInfo->fp == NULL) {
        errorPrint(
                "%s() LN%d, failed to open result file: %s, result will not save to file\n",
                __func__, __LINE__, pThreadInfo->filePath);
        return;
    }
1219

1220 1221 1222
    fprintf(pThreadInfo->fp, "%s", resultBuf);
    tmfclose(pThreadInfo->fp);
    pThreadInfo->fp = NULL;
1223
}
1224

1225
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236
    TAOS_ROW    row = NULL;
    int         num_rows = 0;
    int         num_fields = taos_field_count(res);
    TAOS_FIELD *fields     = taos_fetch_fields(res);

    char* databuf = (char*) calloc(1, 100*1024*1024);
    if (databuf == NULL) {
        errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
                __func__, __LINE__);
        return ;
    }
H
hzcheng 已提交
1237

1238
    int64_t   totalLen = 0;
H
hzcheng 已提交
1239

1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264
    // fetch the records row by row
    while((row = taos_fetch_row(res))) {
        if (totalLen >= 100*1024*1024 - 32000) {
            if (strlen(pThreadInfo->filePath) > 0)
                appendResultBufToFile(databuf, pThreadInfo);
            totalLen = 0;
            memset(databuf, 0, 100*1024*1024);
        }
        num_rows++;
        char  temp[16000] = {0};
        int len = taos_print_row(temp, row, fields, num_fields);
        len += sprintf(temp + len, "\n");
        //printf("query result:%s\n", temp);
        memcpy(databuf + totalLen, temp, len);
        totalLen += len;
        verbosePrint("%s() LN%d, totalLen: %"PRId64"\n",
                __func__, __LINE__, totalLen);
    }

    verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
            __func__, __LINE__, databuf, pThreadInfo->filePath);
    if (strlen(pThreadInfo->filePath) > 0) {
        appendResultBufToFile(databuf, pThreadInfo);
    }
    free(databuf);
1265
}
H
hzcheng 已提交
1266

1267
static void selectAndGetResult(
1268
        threadInfo *pThreadInfo, char *command)
1269
{
1270 1271 1272 1273 1274 1275 1276 1277
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
        TAOS_RES *res = taos_query(pThreadInfo->taos, command);
        if (res == NULL || taos_errno(res) != 0) {
            errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n",
                    __func__, __LINE__, command, taos_errstr(res));
            taos_free_result(res);
            return;
        }
1278

1279 1280
        fetchResult(res, pThreadInfo);
        taos_free_result(res);
1281

1282 1283 1284 1285 1286 1287 1288 1289
    } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
        int retCode = postProceSql(
                g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
                command,
                pThreadInfo);
        if (0 != retCode) {
            printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
        }
1290

1291 1292 1293 1294
    } else {
        errorPrint("%s() LN%d, unknown query mode: %s\n",
                __func__, __LINE__, g_queryInfo.queryMode);
    }
1295
}
H
hzcheng 已提交
1296

1297
static int32_t rand_bool(){
1298 1299 1300 1301
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randint[cursor] % 2;
1302 1303 1304
}

static int32_t rand_tinyint(){
1305 1306 1307 1308
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randint[cursor] % 128;
1309 1310 1311
}

static int32_t rand_smallint(){
1312 1313 1314 1315
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randint[cursor] % 32767;
1316 1317 1318
}

static int32_t rand_int(){
1319 1320 1321 1322
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randint[cursor];
1323 1324 1325
}

static int64_t rand_bigint(){
1326 1327 1328 1329
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randbigint[cursor];
1330 1331 1332
}

static float rand_float(){
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randfloat[cursor];
}

static float demo_current_float(){
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return (float)(9.8 + 0.04 * (randint[cursor] % 10) + randfloat[cursor]/1000000000);
}

static int32_t demo_voltage_int(){
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return 215 + randint[cursor] % 10;
}

static float demo_phase_float(){
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return (float)((115 + randint[cursor] % 10 + randfloat[cursor]/1000000000)/360);
1358 1359
}

1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376
#if 0
static const char charNum[] = "0123456789";

static void nonrand_string(char *, int) __attribute__ ((unused));   // reserve for debugging purpose
static void nonrand_string(char *str, int size)
{
  str[0] = 0;
  if (size > 0) {
    int n;
    for (n = 0; n < size; n++) {
      str[n] = charNum[n % 10];
    }
    str[n] = 0;
  }
}
#endif

1377
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1378

1379
static void rand_string(char *str, int size) {
1380 1381 1382 1383 1384 1385 1386 1387 1388
    str[0] = 0;
    if (size > 0) {
        //--size;
        int n;
        for (n = 0; n < size; n++) {
            int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
            str[n] = charset[key];
        }
        str[n] = 0;
1389 1390 1391 1392
    }
}

static double rand_double() {
1393 1394 1395 1396
    static int cursor;
    cursor++;
    cursor = cursor % MAX_PREPARED_RAND;
    return randdouble[cursor];
1397 1398 1399
}

static void init_rand_data() {
1400 1401 1402 1403 1404 1405
    for (int i = 0; i < MAX_PREPARED_RAND; i++){
        randint[i] = (int)(taosRandom() % 65535);
        randbigint[i] = (int64_t)(taosRandom() % 2147483648);
        randfloat[i] = (float)(taosRandom() / 1000.0);
        randdouble[i] = (double)(taosRandom() / 1000000.0);
    }
1406 1407
}

1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427
#define SHOW_PARSE_RESULT_START()   \
    do { if (g_args.metaFile)  \
        printf("\033[1m\033[40;32m================ %s parse result START ================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_END() \
    do { if (g_args.metaFile)   \
        printf("\033[1m\033[40;32m================ %s parse result END================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_START_TO_FILE(fp)   \
    do { if (g_args.metaFile)  \
        fprintf(fp, "\033[1m\033[40;32m================ %s parse result START ================\033[0m\n", \
                g_args.metaFile); } while(0)

#define SHOW_PARSE_RESULT_END_TO_FILE(fp) \
    do { if (g_args.metaFile)   \
        fprintf(fp, "\033[1m\033[40;32m================ %s parse result END================\033[0m\n", \
                g_args.metaFile); } while(0)

1428
static int printfInsertMeta() {
1429 1430
    SHOW_PARSE_RESULT_START();

1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454
    if (g_args.demo_mode)
        printf("\ntaosdemo is simulating data generated by power equipments monitoring...\n\n");
    else
        printf("\ntaosdemo is simulating random data as you request..\n\n");

    printf("interface:                  \033[33m%s\033[0m\n",
            (g_args.iface==TAOSC_IFACE)?"taosc":(g_args.iface==REST_IFACE)?"rest":"stmt");
    printf("host:                       \033[33m%s:%u\033[0m\n",
            g_Dbs.host, g_Dbs.port);
    printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
    printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
    printf("configDir:                  \033[33m%s\033[0m\n", configDir);
    printf("resultFile:                 \033[33m%s\033[0m\n", g_Dbs.resultFile);
    printf("thread num of insert data:  \033[33m%d\033[0m\n", g_Dbs.threadCount);
    printf("thread num of create table: \033[33m%d\033[0m\n",
            g_Dbs.threadCountByCreateTbl);
    printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
            g_args.insert_interval);
    printf("number of records per req:  \033[33m%u\033[0m\n",
            g_args.num_of_RPR);
    printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
            g_args.max_sql_len);

    printf("database count:             \033[33m%d\033[0m\n", g_Dbs.dbCount);
1455

1456 1457 1458 1459 1460 1461 1462 1463 1464
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        printf("database[\033[33m%d\033[0m]:\n", i);
        printf("  database[%d] name:      \033[33m%s\033[0m\n",
                i, g_Dbs.db[i].dbName);
        if (0 == g_Dbs.db[i].drop) {
            printf("  drop:                  \033[33mno\033[0m\n");
        } else {
            printf("  drop:                  \033[33myes\033[0m\n");
        }
1465

1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523
        if (g_Dbs.db[i].dbCfg.blocks > 0) {
            printf("  blocks:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.blocks);
        }
        if (g_Dbs.db[i].dbCfg.cache > 0) {
            printf("  cache:                 \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.cache);
        }
        if (g_Dbs.db[i].dbCfg.days > 0) {
            printf("  days:                  \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.days);
        }
        if (g_Dbs.db[i].dbCfg.keep > 0) {
            printf("  keep:                  \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.keep);
        }
        if (g_Dbs.db[i].dbCfg.replica > 0) {
            printf("  replica:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.replica);
        }
        if (g_Dbs.db[i].dbCfg.update > 0) {
            printf("  update:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.update);
        }
        if (g_Dbs.db[i].dbCfg.minRows > 0) {
            printf("  minRows:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.minRows);
        }
        if (g_Dbs.db[i].dbCfg.maxRows > 0) {
            printf("  maxRows:               \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.maxRows);
        }
        if (g_Dbs.db[i].dbCfg.comp > 0) {
            printf("  comp:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.comp);
        }
        if (g_Dbs.db[i].dbCfg.walLevel > 0) {
            printf("  walLevel:              \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.walLevel);
        }
        if (g_Dbs.db[i].dbCfg.fsync > 0) {
            printf("  fsync:                 \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.fsync);
        }
        if (g_Dbs.db[i].dbCfg.quorum > 0) {
            printf("  quorum:                \033[33m%d\033[0m\n",
                    g_Dbs.db[i].dbCfg.quorum);
        }
        if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
                printf("  precision:             \033[33m%s\033[0m\n",
                        g_Dbs.db[i].dbCfg.precision);
            } else {
                printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                        g_Dbs.db[i].dbCfg.precision);
                return -1;
            }
        }
1524

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540
        printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
                g_Dbs.db[i].superTblCount);
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);

            printf("      stbName:           \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sTblName);

            if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "no");
            } else if (AUTO_CREATE_SUBTBL ==
                    g_Dbs.db[i].superTbls[j].autoCreateTable) {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "yes");
            } else {
                printf("      autoCreateTable:   \033[33m%s\033[0m\n",  "error");
            }
1541

1542 1543 1544 1545 1546 1547 1548
            if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "no");
            } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "yes");
            } else {
                printf("      childTblExists:    \033[33m%s\033[0m\n",  "error");
            }
1549

1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582
            printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].childTblCount);
            printf("      childTblPrefix:    \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].childTblPrefix);
            printf("      dataSource:        \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].dataSource);
            printf("      iface:             \033[33m%s\033[0m\n",
                    (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
                    (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
            if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
                printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].childTblLimit);
            }
            if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
                printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].childTblOffset);
            }
            printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].insertRows);
            /*
               if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
               printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
               }else {
               printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
               }
               */
            printf("      interlaceRows:     \033[33m%u\033[0m\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);

            if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
                printf("      stable insert interval:   \033[33m%"PRIu64"\033[0m\n",
                        g_Dbs.db[i].superTbls[j].insertInterval);
            }
1583

1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634
            printf("      disorderRange:     \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].disorderRange);
            printf("      disorderRatio:     \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].disorderRatio);
            printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].maxSqlLen);
            printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
                    g_Dbs.db[i].superTbls[j].timeStampStep);
            printf("      startTimestamp:    \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].startTimestamp);
            printf("      sampleFormat:      \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sampleFormat);
            printf("      sampleFile:        \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].sampleFile);
            printf("      tagsFile:          \033[33m%s\033[0m\n",
                    g_Dbs.db[i].superTbls[j].tagsFile);
            printf("      columnCount:       \033[33m%d\033[0m\n",
                    g_Dbs.db[i].superTbls[j].columnCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "binary", 6))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "nchar", 5))) {
                    printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType,
                            g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                } else {
                    printf("column[%d]:\033[33m%s\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType);
                }
            }
            printf("\n");

            printf("      tagCount:            \033[33m%d\033[0m\n        ",
                    g_Dbs.db[i].superTbls[j].tagCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "nchar", strlen("nchar")))) {
                    printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].tags[k].dataType,
                            g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                } else {
                    printf("tag[%d]:\033[33m%s\033[0m ", k,
                            g_Dbs.db[i].superTbls[j].tags[k].dataType);
                }
            }
            printf("\n");
1635
        }
1636
        printf("\n");
1637
    }
1638

1639
    SHOW_PARSE_RESULT_END();
1640

1641
    return 0;
1642 1643 1644
}

static void printfInsertMetaToFile(FILE* fp) {
1645

1646
    SHOW_PARSE_RESULT_START_TO_FILE(fp);
1647

1648 1649 1650 1651 1652 1653 1654 1655 1656
    fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
    fprintf(fp, "user:                       %s\n", g_Dbs.user);
    fprintf(fp, "configDir:                  %s\n", configDir);
    fprintf(fp, "resultFile:                 %s\n", g_Dbs.resultFile);
    fprintf(fp, "thread num of insert data:  %d\n", g_Dbs.threadCount);
    fprintf(fp, "thread num of create table: %d\n", g_Dbs.threadCountByCreateTbl);
    fprintf(fp, "number of records per req:  %u\n", g_args.num_of_RPR);
    fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
    fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1657

1658 1659 1660 1661 1662 1663 1664 1665
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        fprintf(fp, "database[%d]:\n", i);
        fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
        if (0 == g_Dbs.db[i].drop) {
            fprintf(fp, "  drop:                  no\n");
        }else {
            fprintf(fp, "  drop:                  yes\n");
        }
1666

1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712
        if (g_Dbs.db[i].dbCfg.blocks > 0) {
            fprintf(fp, "  blocks:                %d\n", g_Dbs.db[i].dbCfg.blocks);
        }
        if (g_Dbs.db[i].dbCfg.cache > 0) {
            fprintf(fp, "  cache:                 %d\n", g_Dbs.db[i].dbCfg.cache);
        }
        if (g_Dbs.db[i].dbCfg.days > 0) {
            fprintf(fp, "  days:                  %d\n", g_Dbs.db[i].dbCfg.days);
        }
        if (g_Dbs.db[i].dbCfg.keep > 0) {
            fprintf(fp, "  keep:                  %d\n", g_Dbs.db[i].dbCfg.keep);
        }
        if (g_Dbs.db[i].dbCfg.replica > 0) {
            fprintf(fp, "  replica:               %d\n", g_Dbs.db[i].dbCfg.replica);
        }
        if (g_Dbs.db[i].dbCfg.update > 0) {
            fprintf(fp, "  update:                %d\n", g_Dbs.db[i].dbCfg.update);
        }
        if (g_Dbs.db[i].dbCfg.minRows > 0) {
            fprintf(fp, "  minRows:               %d\n", g_Dbs.db[i].dbCfg.minRows);
        }
        if (g_Dbs.db[i].dbCfg.maxRows > 0) {
            fprintf(fp, "  maxRows:               %d\n", g_Dbs.db[i].dbCfg.maxRows);
        }
        if (g_Dbs.db[i].dbCfg.comp > 0) {
            fprintf(fp, "  comp:                  %d\n", g_Dbs.db[i].dbCfg.comp);
        }
        if (g_Dbs.db[i].dbCfg.walLevel > 0) {
            fprintf(fp, "  walLevel:              %d\n", g_Dbs.db[i].dbCfg.walLevel);
        }
        if (g_Dbs.db[i].dbCfg.fsync > 0) {
            fprintf(fp, "  fsync:                 %d\n", g_Dbs.db[i].dbCfg.fsync);
        }
        if (g_Dbs.db[i].dbCfg.quorum > 0) {
            fprintf(fp, "  quorum:                %d\n", g_Dbs.db[i].dbCfg.quorum);
        }
        if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
            if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
                    || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
                fprintf(fp, "  precision:             %s\n",
                        g_Dbs.db[i].dbCfg.precision);
            } else {
                fprintf(fp, "  precision error:       %s\n",
                        g_Dbs.db[i].dbCfg.precision);
            }
        }
1713

1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729
        fprintf(fp, "  super table count:     %"PRIu64"\n",
                g_Dbs.db[i].superTblCount);
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
            fprintf(fp, "  super table[%d]:\n", j);

            fprintf(fp, "      stbName:           %s\n",
                    g_Dbs.db[i].superTbls[j].sTblName);

            if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                fprintf(fp, "      autoCreateTable:   %s\n",  "no");
            } else if (AUTO_CREATE_SUBTBL
                    == g_Dbs.db[i].superTbls[j].autoCreateTable) {
                fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
            } else {
                fprintf(fp, "      autoCreateTable:   %s\n",  "error");
            }
1730

1731 1732 1733 1734 1735 1736 1737 1738
            if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
                fprintf(fp, "      childTblExists:    %s\n",  "no");
            } else if (TBL_ALREADY_EXISTS
                    == g_Dbs.db[i].superTbls[j].childTblExists) {
                fprintf(fp, "      childTblExists:    %s\n",  "yes");
            } else {
                fprintf(fp, "      childTblExists:    %s\n",  "error");
            }
1739

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819
            fprintf(fp, "      childTblCount:     %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].childTblCount);
            fprintf(fp, "      childTblPrefix:    %s\n",
                    g_Dbs.db[i].superTbls[j].childTblPrefix);
            fprintf(fp, "      dataSource:        %s\n",
                    g_Dbs.db[i].superTbls[j].dataSource);
            fprintf(fp, "      iface:             %s\n",
                    (g_Dbs.db[i].superTbls[j].iface==TAOSC_IFACE)?"taosc":
                    (g_Dbs.db[i].superTbls[j].iface==REST_IFACE)?"rest":"stmt");
            fprintf(fp, "      insertRows:        %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].insertRows);
            fprintf(fp, "      interlace rows:    %u\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);
            if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
                fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
                        g_Dbs.db[i].superTbls[j].insertInterval);
            }
            /*
               if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
               fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
               }else {
               fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
               }
               */
            fprintf(fp, "      interlaceRows:     %u\n",
                    g_Dbs.db[i].superTbls[j].interlaceRows);
            fprintf(fp, "      disorderRange:     %d\n",
                    g_Dbs.db[i].superTbls[j].disorderRange);
            fprintf(fp, "      disorderRatio:     %d\n",
                    g_Dbs.db[i].superTbls[j].disorderRatio);
            fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
                    g_Dbs.db[i].superTbls[j].maxSqlLen);

            fprintf(fp, "      timeStampStep:     %"PRId64"\n",
                    g_Dbs.db[i].superTbls[j].timeStampStep);
            fprintf(fp, "      startTimestamp:    %s\n",
                    g_Dbs.db[i].superTbls[j].startTimestamp);
            fprintf(fp, "      sampleFormat:      %s\n",
                    g_Dbs.db[i].superTbls[j].sampleFormat);
            fprintf(fp, "      sampleFile:        %s\n",
                    g_Dbs.db[i].superTbls[j].sampleFile);
            fprintf(fp, "      tagsFile:          %s\n",
                    g_Dbs.db[i].superTbls[j].tagsFile);

            fprintf(fp, "      columnCount:       %d\n        ",
                    g_Dbs.db[i].superTbls[j].columnCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                if ((0 == strncasecmp(
                                g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(
                                g_Dbs.db[i].superTbls[j].columns[k].dataType,
                                "nchar", strlen("nchar")))) {
                    fprintf(fp, "column[%d]:%s(%d) ", k,
                            g_Dbs.db[i].superTbls[j].columns[k].dataType,
                            g_Dbs.db[i].superTbls[j].columns[k].dataLen);
                } else {
                    fprintf(fp, "column[%d]:%s ",
                            k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
                }
            }
            fprintf(fp, "\n");

            fprintf(fp, "      tagCount:            %d\n        ",
                    g_Dbs.db[i].superTbls[j].tagCount);
            for (int k = 0; k < g_Dbs.db[i].superTbls[j].tagCount; k++) {
                //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].tags[k].dataType, g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "binary", strlen("binary")))
                        || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                                "nchar", strlen("nchar")))) {
                    fprintf(fp, "tag[%d]:%s(%d) ",
                            k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
                            g_Dbs.db[i].superTbls[j].tags[k].dataLen);
                } else {
                    fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
                }
            }
            fprintf(fp, "\n");
1820
        }
1821
        fprintf(fp, "\n");
1822
    }
1823

1824
    SHOW_PARSE_RESULT_END_TO_FILE(fp);
1825 1826 1827
}

static void printfQueryMeta() {
1828

1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897
    SHOW_PARSE_RESULT_START();

    printf("host:                    \033[33m%s:%u\033[0m\n",
            g_queryInfo.host, g_queryInfo.port);
    printf("user:                    \033[33m%s\033[0m\n", g_queryInfo.user);
    printf("database name:           \033[33m%s\033[0m\n", g_queryInfo.dbName);

    printf("\n");

    if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) {
        printf("specified table query info:                   \n");
        printf("sqlCount:       \033[33m%d\033[0m\n",
                g_queryInfo.specifiedQueryInfo.sqlCount);
        if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
            printf("specified tbl query times:\n");
            printf("                \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.queryTimes);
            printf("query interval: \033[33m%"PRIu64" ms\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.queryInterval);
            printf("top query times:\033[33m%"PRIu64"\033[0m\n", g_args.query_times);
            printf("concurrent:     \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.concurrent);
            printf("mod:            \033[33m%s\033[0m\n",
                    (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
            printf("interval:       \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeInterval);
            printf("restart:        \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeRestart);
            printf("keepProgress:   \033[33m%d\033[0m\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);

            for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
                printf("  sql[%d]: \033[33m%s\033[0m\n",
                        i, g_queryInfo.specifiedQueryInfo.sql[i]);
            }
            printf("\n");
        }

        printf("super table query info:\n");
        printf("sqlCount:       \033[33m%d\033[0m\n",
                g_queryInfo.superQueryInfo.sqlCount);

        if (g_queryInfo.superQueryInfo.sqlCount > 0) {
            printf("query interval: \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.queryInterval);
            printf("threadCnt:      \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.threadCnt);
            printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
                    g_queryInfo.superQueryInfo.childTblCount);
            printf("stable name:    \033[33m%s\033[0m\n",
                    g_queryInfo.superQueryInfo.sTblName);
            printf("stb query times:\033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.queryTimes);

            printf("mod:            \033[33m%s\033[0m\n",
                    (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
            printf("interval:       \033[33m%"PRIu64"\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeInterval);
            printf("restart:        \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeRestart);
            printf("keepProgress:   \033[33m%d\033[0m\n",
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);

            for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
                printf("  sql[%d]: \033[33m%s\033[0m\n",
                        i, g_queryInfo.superQueryInfo.sql[i]);
            }
            printf("\n");
        }
1898
    }
1899

1900
    SHOW_PARSE_RESULT_END();
1901 1902
}

1903
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1904 1905 1906 1907 1908 1909 1910 1911
    time_t tt;
    if (precision == TSDB_TIME_PRECISION_NANO) {
        tt = (time_t)(val / 1000000000);
    } else if (precision == TSDB_TIME_PRECISION_MICRO) {
        tt = (time_t)(val / 1000000);
    } else {
        tt = (time_t)(val / 1000);
    }
1912

1913 1914 1915 1916 1917 1918 1919
    /* comment out as it make testcases like select_with_tags.sim fail.
       but in windows, this may cause the call to localtime crash if tt < 0,
       need to find a better solution.
       if (tt < 0) {
       tt = 0;
       }
       */
1920 1921

#ifdef WINDOWS
1922
    if (tt < 0) tt = 0;
1923 1924
#endif

1925 1926
    struct tm* ptm = localtime(&tt);
    size_t pos = strftime(buf, 32, "%Y-%m-%d %H:%M:%S", ptm);
1927

1928 1929 1930 1931 1932 1933 1934
    if (precision == TSDB_TIME_PRECISION_NANO) {
        sprintf(buf + pos, ".%09d", (int)(val % 1000000000));
    } else if (precision == TSDB_TIME_PRECISION_MICRO) {
        sprintf(buf + pos, ".%06d", (int)(val % 1000000));
    } else {
        sprintf(buf + pos, ".%03d", (int)(val % 1000));
    }
1935

1936
    return buf;
1937 1938
}

1939 1940 1941
static void xDumpFieldToFile(FILE* fp, const char* val,
        TAOS_FIELD* field, int32_t length, int precision) {

1942 1943 1944 1945
    if (val == NULL) {
        fprintf(fp, "%s", TSDB_DATA_NULL_STR);
        return;
    }
1946

1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982
    char buf[TSDB_MAX_BYTES_PER_ROW];
    switch (field->type) {
        case TSDB_DATA_TYPE_BOOL:
            fprintf(fp, "%d", ((((int32_t)(*((char *)val))) == 1) ? 1 : 0));
            break;
        case TSDB_DATA_TYPE_TINYINT:
            fprintf(fp, "%d", *((int8_t *)val));
            break;
        case TSDB_DATA_TYPE_SMALLINT:
            fprintf(fp, "%d", *((int16_t *)val));
            break;
        case TSDB_DATA_TYPE_INT:
            fprintf(fp, "%d", *((int32_t *)val));
            break;
        case TSDB_DATA_TYPE_BIGINT:
            fprintf(fp, "%" PRId64, *((int64_t *)val));
            break;
        case TSDB_DATA_TYPE_FLOAT:
            fprintf(fp, "%.5f", GET_FLOAT_VAL(val));
            break;
        case TSDB_DATA_TYPE_DOUBLE:
            fprintf(fp, "%.9f", GET_DOUBLE_VAL(val));
            break;
        case TSDB_DATA_TYPE_BINARY:
        case TSDB_DATA_TYPE_NCHAR:
            memcpy(buf, val, length);
            buf[length] = 0;
            fprintf(fp, "\'%s\'", buf);
            break;
        case TSDB_DATA_TYPE_TIMESTAMP:
            formatTimestamp(buf, *(int64_t*)val, precision);
            fprintf(fp, "'%s'", buf);
            break;
        default:
            break;
    }
1983 1984 1985
}

static int xDumpResultToFile(const char* fname, TAOS_RES* tres) {
1986 1987 1988 1989
    TAOS_ROW row = taos_fetch_row(tres);
    if (row == NULL) {
        return 0;
    }
1990

1991 1992 1993 1994 1995 1996
    FILE* fp = fopen(fname, "at");
    if (fp == NULL) {
        errorPrint("%s() LN%d, failed to open file: %s\n",
                __func__, __LINE__, fname);
        return -1;
    }
1997

1998 1999 2000
    int num_fields = taos_num_fields(tres);
    TAOS_FIELD *fields = taos_fetch_fields(tres);
    int precision = taos_result_precision(tres);
2001

2002 2003 2004 2005 2006
    for (int col = 0; col < num_fields; col++) {
        if (col > 0) {
            fprintf(fp, ",");
        }
        fprintf(fp, "%s", fields[col].name);
2007 2008 2009
    }
    fputc('\n', fp);

2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024
    int numOfRows = 0;
    do {
        int32_t* length = taos_fetch_lengths(tres);
        for (int i = 0; i < num_fields; i++) {
            if (i > 0) {
                fputc(',', fp);
            }
            xDumpFieldToFile(fp,
                    (const char*)row[i], fields +i, length[i], precision);
        }
        fputc('\n', fp);

        numOfRows++;
        row = taos_fetch_row(tres);
    } while( row != NULL);
2025

2026
    fclose(fp);
2027

2028
    return numOfRows;
2029 2030
}

2031
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
2032 2033 2034
    TAOS_RES * res;
    TAOS_ROW row = NULL;
    int count = 0;
2035

2036 2037
    res = taos_query(taos, "show databases;");
    int32_t code = taos_errno(res);
2038

2039 2040 2041 2042
    if (code != 0) {
        errorPrint( "failed to run <show databases>, reason: %s\n",
                taos_errstr(res));
        return -1;
2043
    }
2044

2045
    TAOS_FIELD *fields = taos_fetch_fields(res);
2046

2047 2048 2049 2050 2051 2052
    while((row = taos_fetch_row(res)) != NULL) {
        // sys database name : 'log'
        if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
                    fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
            continue;
        }
2053

2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095
        dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo));
        if (dbInfos[count] == NULL) {
            errorPrint( "failed to allocate memory for some dbInfo[%d]\n", count);
            return -1;
        }

        tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
        formatTimestamp(dbInfos[count]->create_time,
                *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
                TSDB_TIME_PRECISION_MILLI);
        dbInfos[count]->ntables = *((int64_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
        dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
        dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
        dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
        dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);

        tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
                fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
        dbInfos[count]->cache = *((int32_t *)row[TSDB_SHOW_DB_CACHE_INDEX]);
        dbInfos[count]->blocks = *((int32_t *)row[TSDB_SHOW_DB_BLOCKS_INDEX]);
        dbInfos[count]->minrows = *((int32_t *)row[TSDB_SHOW_DB_MINROWS_INDEX]);
        dbInfos[count]->maxrows = *((int32_t *)row[TSDB_SHOW_DB_MAXROWS_INDEX]);
        dbInfos[count]->wallevel = *((int8_t *)row[TSDB_SHOW_DB_WALLEVEL_INDEX]);
        dbInfos[count]->fsync = *((int32_t *)row[TSDB_SHOW_DB_FSYNC_INDEX]);
        dbInfos[count]->comp = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX]));
        dbInfos[count]->cachelast =
            (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));

        tstrncpy(dbInfos[count]->precision,
                (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
                fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
        dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
        tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
                fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);

        count++;
        if (count > MAX_DATABASE_COUNT) {
            errorPrint("%s() LN%d, The database count overflow than %d\n",
                    __func__, __LINE__, MAX_DATABASE_COUNT);
            break;
        }
2096 2097
    }

2098
    return count;
2099 2100
}

2101 2102
static void printfDbInfoForQueryToFile(
        char* filename, SDbInfo* dbInfos, int index) {
2103

2104 2105
    if (filename[0] == 0)
        return;
2106

2107 2108 2109 2110 2111
    FILE *fp = fopen(filename, "at");
    if (fp == NULL) {
        errorPrint( "failed to open file: %s\n", filename);
        return;
    }
2112

2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133
    fprintf(fp, "================ database[%d] ================\n", index);
    fprintf(fp, "name: %s\n", dbInfos->name);
    fprintf(fp, "created_time: %s\n", dbInfos->create_time);
    fprintf(fp, "ntables: %"PRId64"\n", dbInfos->ntables);
    fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
    fprintf(fp, "replica: %d\n", dbInfos->replica);
    fprintf(fp, "quorum: %d\n", dbInfos->quorum);
    fprintf(fp, "days: %d\n", dbInfos->days);
    fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
    fprintf(fp, "cache(MB): %d\n", dbInfos->cache);
    fprintf(fp, "blocks: %d\n", dbInfos->blocks);
    fprintf(fp, "minrows: %d\n", dbInfos->minrows);
    fprintf(fp, "maxrows: %d\n", dbInfos->maxrows);
    fprintf(fp, "wallevel: %d\n", dbInfos->wallevel);
    fprintf(fp, "fsync: %d\n", dbInfos->fsync);
    fprintf(fp, "comp: %d\n", dbInfos->comp);
    fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
    fprintf(fp, "precision: %s\n", dbInfos->precision);
    fprintf(fp, "update: %d\n", dbInfos->update);
    fprintf(fp, "status: %s\n", dbInfos->status);
    fprintf(fp, "\n");
2134

2135
    fclose(fp);
2136 2137 2138
}

static void printfQuerySystemInfo(TAOS * taos) {
2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153
    char filename[MAX_QUERY_SQL_LENGTH+1] = {0};
    char buffer[MAX_QUERY_SQL_LENGTH+1] = {0};
    TAOS_RES* res;

    time_t t;
    struct tm* lt;
    time(&t);
    lt = localtime(&t);
    snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
            lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
            lt->tm_sec);

    // show variables
    res = taos_query(taos, "show variables;");
    //fetchResult(res, filename);
2154
    xDumpResultToFile(filename, res);
2155

2156 2157
    // show dnodes
    res = taos_query(taos, "show dnodes;");
2158
    xDumpResultToFile(filename, res);
2159
    //fetchResult(res, filename);
2160

2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189
    // show databases
    res = taos_query(taos, "show databases;");
    SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
    if (dbInfos == NULL) {
        errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
        return;
    }
    int dbCount = getDbFromServer(taos, dbInfos);
    if (dbCount <= 0) {
        free(dbInfos);
        return;
    }

    for (int i = 0; i < dbCount; i++) {
        // printf database info
        printfDbInfoForQueryToFile(filename, dbInfos[i], i);

        // show db.vgroups
        snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);

        // show db.stables
        snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.stables;", dbInfos[i]->name);
        res = taos_query(taos, buffer);
        xDumpResultToFile(filename, res);

        free(dbInfos[i]);
    }
2190

2191
    free(dbInfos);
2192 2193
}

2194
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
2195
        char* sqlstr, threadInfo *pThreadInfo)
2196
{
2197
    char *req_fmt = "POST %s HTTP/1.1\r\nHost: %s:%d\r\nAccept: */*\r\nAuthorization: Basic %s\r\nContent-Length: %d\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n%s";
2198 2199 2200

    char *url = "/rest/sql";

2201
    int bytes, sent, received, req_str_len, resp_len;
2202 2203 2204
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
2205

2206 2207 2208
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

    request_buf = malloc(req_buf_len);
2209 2210 2211 2212
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2213

2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};

    static char base64[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
      'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
      'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
      'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
      'w', 'x', 'y', 'z', '0', '1', '2', '3',
      '4', '5', '6', '7', '8', '9', '+', '/'};
2225

2226 2227 2228 2229 2230 2231
    snprintf(userpass_buf, INPUT_BUF_LEN, "%s:%s",
        g_Dbs.user, g_Dbs.password);
    size_t userpass_buf_len = strlen(userpass_buf);
    size_t encoded_len = 4 * ((userpass_buf_len +2) / 3);

    char base64_buf[INPUT_BUF_LEN];
2232
#ifdef WINDOWS
2233
    WSADATA wsaData;
2234
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2235 2236 2237 2238
    SOCKET sockfd;
#else
    int sockfd;
#endif
2239
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
2240
    if (sockfd < 0) {
2241
#ifdef WINDOWS
2242
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2243
#endif
2244
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
2245
        free(request_buf);
2246
        ERROR_EXIT("ERROR opening socket");
2247
    }
2248

2249
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2250 2251
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
2252
        free(request_buf);
2253
        ERROR_EXIT("ERROR connecting");
2254
    }
2255

2256 2257 2258
    memset(base64_buf, 0, INPUT_BUF_LEN);

    for (int n = 0, m = 0; n < userpass_buf_len;) {
2259
      uint32_t oct_a = n < userpass_buf_len ?
2260
        (unsigned char) userpass_buf[n++]:0;
2261
      uint32_t oct_b = n < userpass_buf_len ?
2262
        (unsigned char) userpass_buf[n++]:0;
2263
      uint32_t oct_c = n < userpass_buf_len ?
2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275
        (unsigned char) userpass_buf[n++]:0;
      uint32_t triple = (oct_a << 0x10) + (oct_b << 0x08) + oct_c;

      base64_buf[m++] = base64[(triple >> 3* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 2* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 1* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 0* 6) & 0x3f];
    }

    for (int l = 0; l < mod_table[userpass_buf_len % 3]; l++)
      base64_buf[encoded_len - 1 - l] = '=';

2276 2277
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
2278 2279
    char *auth = base64_buf;

2280 2281 2282
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
2283 2284 2285 2286 2287
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
2288
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
2289

2290
    req_str_len = strlen(request_buf);
2291 2292
    sent = 0;
    do {
2293 2294 2295
#ifdef WINDOWS
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
#else
2296
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2297
#endif
2298
        if (bytes < 0)
2299
            ERROR_EXIT("ERROR writing message to socket");
2300 2301 2302
        if (bytes == 0)
            break;
        sent+=bytes;
2303
    } while(sent < req_str_len);
2304

2305 2306
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
2307 2308
    received = 0;
    do {
2309 2310 2311
#ifdef WINDOWS
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
#else
2312
        bytes = read(sockfd, response_buf + received, resp_len - received);
2313
#endif
2314 2315
        if (bytes < 0) {
            free(request_buf);
2316
            ERROR_EXIT("ERROR reading response from socket");
2317
        }
2318 2319
        if (bytes == 0)
            break;
2320
        received += bytes;
2321
    } while(received < resp_len);
2322

2323 2324
    if (received == resp_len) {
        free(request_buf);
2325
        ERROR_EXIT("ERROR storing complete response from socket");
2326
    }
2327

2328
    response_buf[RESP_BUF_LEN - 1] = '\0';
2329 2330
    printf("Response:\n%s\n", response_buf);

2331 2332
    if (strlen(pThreadInfo->filePath) > 0) {
       appendResultBufToFile(response_buf, pThreadInfo);
2333 2334
    }

2335
    free(request_buf);
2336 2337 2338 2339
#ifdef WINDOWS
    closesocket(sockfd);
    WSACleanup();
#else
2340
    close(sockfd);
2341
#endif
2342 2343 2344 2345

    return 0;
}

2346
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2347 2348 2349 2350 2351 2352
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
        errorPrint("%s() LN%d, calloc failed! size:%d\n",
                __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
        return NULL;
    }
2353

2354 2355 2356
    int    dataLen = 0;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
            "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2357

2358
    return dataBuf;
2359 2360
}

2361
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2362 2363 2364
    char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
    if (NULL == dataBuf) {
        printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1);
2365
        return NULL;
2366
    }
2367

2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380
    int    dataLen = 0;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "(");
    for (int i = 0; i < stbInfo->tagCount; i++) {
        if ((0 == strncasecmp(stbInfo->tags[i].dataType,
                        "binary", strlen("binary")))
                || (0 == strncasecmp(stbInfo->tags[i].dataType,
                        "nchar", strlen("nchar")))) {
            if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
                printf("binary or nchar length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                tmfree(dataBuf);
                return NULL;
            }
2381

2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400
            int tagBufLen = stbInfo->tags[i].dataLen + 1;
            char* buf = (char*)calloc(tagBufLen, 1);
            if (NULL == buf) {
                printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
                tmfree(dataBuf);
                return NULL;
            }

            if (tableSeq % 2) {
                tstrncpy(buf, "beijing", tagBufLen);
            } else {
                tstrncpy(buf, "shanghai", tagBufLen);
            }
            //rand_string(buf, stbInfo->tags[i].dataLen);
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "\'%s\', ", buf);
            tmfree(buf);
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "int", strlen("int"))) {
2401 2402 2403 2404 2405 2406 2407
            if ((g_args.demo_mode) && (i == 0)) {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
                    "%d, ", tableSeq % 10);
            } else {
                dataLen += snprintf(dataBuf + dataLen,
                        TSDB_MAX_SQL_LEN - dataLen,
2408
                    "%d, ", tableSeq);
2409
            }
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442
        } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bigint", strlen("bigint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%"PRId64", ", rand_bigint());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "float", strlen("float"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%f, ", rand_float());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "double", strlen("double"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%f, ", rand_double());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "smallint", strlen("smallint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%d, ", rand_smallint());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "tinyint", strlen("tinyint"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%d, ", rand_tinyint());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "bool", strlen("bool"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%d, ", rand_bool());
        }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                    "timestamp", strlen("timestamp"))) {
            dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
                    "%"PRId64", ", rand_bigint());
        }  else {
            printf("No support data type: %s\n", stbInfo->tags[i].dataType);
            tmfree(dataBuf);
            return NULL;
        }
2443
    }
2444

2445 2446 2447
    dataLen -= 2;
    dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
    return dataBuf;
2448 2449
}

2450
static int calcRowLen(SSuperTable*  superTbls) {
2451 2452
  int colIndex;
  int  lenOfOneRow = 0;
2453

2454 2455
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2456

2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472
    if (strcasecmp(dataType, "BINARY") == 0) {
      lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      lenOfOneRow += 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      lenOfOneRow += 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      lenOfOneRow += 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      lenOfOneRow += 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      lenOfOneRow += 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      lenOfOneRow += 22;
2473
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2474
      lenOfOneRow += 42;
2475
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
      lenOfOneRow += 21;
    } else {
      printf("get error data type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfOneRow = lenOfOneRow + 20; // timestamp

  int tagIndex;
  int lenOfTagOfOneRow = 0;
  for (tagIndex = 0; tagIndex < superTbls->tagCount; tagIndex++) {
    char* dataType = superTbls->tags[tagIndex].dataType;
2489

2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505
    if (strcasecmp(dataType, "BINARY") == 0) {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22;
2506
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2507 2508 2509 2510 2511 2512 2513 2514
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2515

2516 2517 2518 2519
  return 0;
}


2520 2521
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2522
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2523

2524
  char command[BUFFER_SIZE] = "\0";
2525 2526
  char limitBuf[100] = "\0";

2527
  TAOS_RES * res;
2528 2529 2530
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2531 2532

  if (offset >= 0) {
2533
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2534
            limit, offset);
2535 2536
  }

2537
  //get all child table name use cmd: select tbname from superTblName;
2538 2539
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
          dbName, sTblName, limitBuf);
2540

2541
  res = taos_query(taos, command);
2542 2543 2544 2545
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2546 2547
    errorPrint("%s() LN%d, failed to run command %s\n",
           __func__, __LINE__, command);
2548 2549 2550
    exit(-1);
  }

2551 2552
  int64_t childTblCount = (limit < 0)?10000:limit;
  int64_t count = 0;
2553 2554 2555 2556 2557 2558 2559 2560 2561 2562
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
    }
  }

2563
  char* pTblName = childTblName;
2564
  while((row = taos_fetch_row(res)) != NULL) {
2565
    int32_t* len = taos_fetch_lengths(res);
2566 2567 2568 2569 2570 2571 2572

    if (0 == strlen((char *)row[0])) {
        errorPrint("%s() LN%d, No.%"PRId64" table return empty name\n",
            __func__, __LINE__, count);
        exit(-1);
    }

2573
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2574 2575 2576
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2577 2578
      char *tmp = realloc(childTblName,
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2579 2580 2581
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2582 2583
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2584 2585
      } else {
        // exit, if allocate more memory failed
2586 2587
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
               __func__, __LINE__, dbName, sTblName);
2588 2589 2590 2591 2592 2593
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2594
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2595
  }
2596

2597 2598 2599 2600 2601 2602 2603
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2604 2605
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
        char* sTblName, char** childTblNameOfSuperTbl,
2606
        int64_t* childTblCountOfSuperTbl) {
2607 2608 2609

    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2610
            -1, 0);
2611 2612
}

2613 2614
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2615

2616
  char command[BUFFER_SIZE] = "\0";
2617
  TAOS_RES * res;
2618 2619
  TAOS_ROW row = NULL;
  int count = 0;
2620

2621
  //get schema use cmd: describe superTblName;
2622
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2623
  res = taos_query(taos, command);
2624 2625 2626
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2627
    taos_free_result(res);
2628 2629 2630 2631 2632 2633
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2634
  while((row = taos_fetch_row(res)) != NULL) {
2635 2636 2637
    if (0 == count) {
      count++;
      continue;
2638
    }
2639 2640

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2641 2642 2643 2644 2645
      tstrncpy(superTbls->tags[tagIndex].field,
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
      tstrncpy(superTbls->tags[tagIndex].dataType,
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
2646
              min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
2647 2648 2649 2650 2651
      superTbls->tags[tagIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->tags[tagIndex].note,
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2652
      tagIndex++;
2653
    } else {
2654 2655 2656 2657 2658
      tstrncpy(superTbls->columns[columnIndex].field,
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
      tstrncpy(superTbls->columns[columnIndex].dataType,
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
2659
              min(15, fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes));
2660 2661 2662 2663 2664
      superTbls->columns[columnIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->columns[columnIndex].note,
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675
      columnIndex++;
    }
    count++;
  }

  superTbls->columnCount = columnIndex;
  superTbls->tagCount    = tagIndex;
  taos_free_result(res);

  calcRowLen(superTbls);

2676
/*
2677
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2678
    //get all child table name use cmd: select tbname from superTblName;
2679 2680 2681
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2682
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2683 2684
      return -1;
    }
2685
    getAllChildNameOfSuperTable(taos, dbName,
2686 2687 2688
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2689
  }
2690
  */
2691 2692 2693
  return 0;
}

2694 2695
static int createSuperTable(
        TAOS * taos, char* dbName,
2696
        SSuperTable*  superTbl) {
2697

2698
    char command[BUFFER_SIZE] = "\0";
2699

2700 2701 2702
    char cols[STRING_LEN] = "\0";
    int colIndex;
    int len = 0;
2703

2704
    int  lenOfOneRow = 0;
2705

2706 2707 2708 2709 2710
    if (superTbl->columnCount == 0) {
        errorPrint("%s() LN%d, super table column count is %d\n",
                __func__, __LINE__, superTbl->columnCount);
        return -1;
    }
2711

2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756
    for (colIndex = 0; colIndex < superTbl->columnCount; colIndex++) {
        char* dataType = superTbl->columns[colIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
            len += snprintf(cols + len, STRING_LEN - len,
                    ", col%d %s(%d)", colIndex, "BINARY",
                    superTbl->columns[colIndex].dataLen);
            lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
            len += snprintf(cols + len, STRING_LEN - len,
                    ", col%d %s(%d)", colIndex, "NCHAR",
                    superTbl->columns[colIndex].dataLen);
            lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
            if ((g_args.demo_mode) && (colIndex == 1)) {
                    len += snprintf(cols + len, STRING_LEN - len,
                            ", VOLTAGE INT");
            } else {
                len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "INT");
            }
            lenOfOneRow += 11;
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s",
                    colIndex, "BIGINT");
            lenOfOneRow += 21;
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s",
                    colIndex, "SMALLINT");
            lenOfOneRow += 6;
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TINYINT");
            lenOfOneRow += 4;
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "BOOL");
            lenOfOneRow += 6;
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
            if (g_args.demo_mode) {
                if (colIndex == 0) {
                    len += snprintf(cols + len, STRING_LEN - len, ", CURRENT FLOAT");
                } else if (colIndex == 2) {
                    len += snprintf(cols + len, STRING_LEN - len, ", PHASE FLOAT");
                }
            } else {
                len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "FLOAT");
            }
2757

2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772
            lenOfOneRow += 22;
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s",
                    colIndex, "DOUBLE");
            lenOfOneRow += 42;
        }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
            len += snprintf(cols + len, STRING_LEN - len, ", col%d %s",
                    colIndex, "TIMESTAMP");
            lenOfOneRow += 21;
        } else {
            taos_close(taos);
            errorPrint("%s() LN%d, config error data type : %s\n",
                    __func__, __LINE__, dataType);
            exit(-1);
        }
2773 2774
    }

2775
    superTbl->lenOfOneRow = lenOfOneRow + 20; // timestamp
2776

2777 2778 2779 2780 2781 2782 2783 2784
    // save for creating child table
    superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
    if (NULL == superTbl->colsOfCreateChildTable) {
        errorPrint("%s() LN%d, Failed when calloc, size:%d",
                __func__, __LINE__, len+1);
        taos_close(taos);
        exit(-1);
    }
2785

2786 2787 2788
    snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
    verbosePrint("%s() LN%d: %s\n",
            __func__, __LINE__, superTbl->colsOfCreateChildTable);
2789

2790 2791 2792 2793 2794
    if (superTbl->tagCount == 0) {
        errorPrint("%s() LN%d, super table tag count is %d\n",
                __func__, __LINE__, superTbl->tagCount);
        return -1;
    }
2795

2796 2797 2798
    char tags[STRING_LEN] = "\0";
    int tagIndex;
    len = 0;
2799

2800 2801 2802 2803 2804 2805
    int lenOfTagOfOneRow = 0;
    len += snprintf(tags + len, STRING_LEN - len, "(");
    for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
        char* dataType = superTbl->tags[tagIndex].dataType;

        if (strcasecmp(dataType, "BINARY") == 0) {
2806 2807 2808 2809 2810 2811 2812 2813
            if ((g_args.demo_mode) && (tagIndex == 1)) {
                len += snprintf(tags + len, STRING_LEN - len,
                        "loction BINARY(%d), ",
                        superTbl->tags[tagIndex].dataLen);
            } else {
                len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ",
                        tagIndex, "BINARY", superTbl->tags[tagIndex].dataLen);
            }
2814 2815 2816 2817 2818 2819
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "NCHAR") == 0) {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
                    "NCHAR", superTbl->tags[tagIndex].dataLen);
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
        } else if (strcasecmp(dataType, "INT") == 0)  {
2820 2821 2822 2823
            if ((g_args.demo_mode) && (tagIndex == 0)) {
                len += snprintf(tags + len, STRING_LEN - len, "groupId INT, ");
            } else {
                len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2824
                    "INT");
2825
            }
2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
        } else if (strcasecmp(dataType, "BIGINT") == 0)  {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "BIGINT");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
        } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "SMALLINT");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
        } else if (strcasecmp(dataType, "TINYINT") == 0)  {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "TINYINT");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
        } else if (strcasecmp(dataType, "BOOL") == 0)  {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "BOOL");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
        } else if (strcasecmp(dataType, "FLOAT") == 0) {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "FLOAT");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
        } else if (strcasecmp(dataType, "DOUBLE") == 0) {
            len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                    "DOUBLE");
            lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
        } else {
            taos_close(taos);
            errorPrint("%s() LN%d, config error tag type : %s\n",
                    __func__, __LINE__, dataType);
            exit(-1);
        }
2857
    }
2858

2859 2860
    len -= 2;
    len += snprintf(tags + len, STRING_LEN - len, ")");
2861

2862
    superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;
2863

2864 2865 2866 2867 2868 2869 2870 2871 2872 2873
    snprintf(command, BUFFER_SIZE,
            "create table if not exists %s.%s (ts timestamp%s) tags %s",
            dbName, superTbl->sTblName, cols, tags);
    if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
        errorPrint( "create supertable %s failed!\n\n",
                superTbl->sTblName);
        return -1;
    }
    debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
    return 0;
2874 2875
}

2876
static int createDatabasesAndStables() {
2877 2878 2879 2880
  TAOS * taos = NULL;
  int    ret = 0;
  taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, NULL, g_Dbs.port);
  if (taos == NULL) {
2881
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2882
    return -1;
2883 2884 2885
  }
  char command[BUFFER_SIZE] = "\0";

2886
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2887 2888
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2889
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2890 2891 2892 2893
        taos_close(taos);
        return -1;
      }

2894
      int dataLen = 0;
2895
      dataLen += snprintf(command + dataLen,
2896
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2897

2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
      }
      //if (g_Dbs.db[i].dbCfg.maxtablesPerVnode > 0) {
      //  dataLen += snprintf(command + dataLen,
      //  BUFFER_SIZE - dataLen, "tables %d ", g_Dbs.db[i].dbCfg.maxtablesPerVnode);
      //}
      if (g_Dbs.db[i].dbCfg.minRows > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
      }

      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
        taos_close(taos);
        errorPrint( "\ncreate database %s failed!\n\n", g_Dbs.db[i].dbName);
        return -1;
      }
      printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName);
2967 2968
    }

2969
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2970
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2971 2972 2973

    int validStbCount = 0;

2974
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2975 2976 2977 2978 2979
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);

      if ((ret != 0) || (g_Dbs.db[i].drop)) {
2980
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
2981
                &g_Dbs.db[i].superTbls[j]);
2982

2983
        if (0 != ret) {
2984
          errorPrint("create super table %"PRIu64" failed!\n\n", j);
2985
          continue;
2986 2987 2988
        }
      }

2989
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2990
                &g_Dbs.db[i].superTbls[j]);
2991 2992 2993
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2994
        continue;
2995
      }
2996 2997

      validStbCount ++;
2998
    }
2999 3000

    g_Dbs.db[i].superTblCount = validStbCount;
3001 3002 3003 3004 3005 3006
  }

  taos_close(taos);
  return 0;
}

3007 3008
static void* createTable(void *sarg)
{
3009 3010
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
3011

3012
  uint64_t  lastPrintTime = taosGetTimestampMs();
3013

3014
  int buff_len;
3015
  buff_len = BUFFER_SIZE / 8;
3016

3017 3018
  pThreadInfo->buffer = calloc(buff_len, 1);
  if (pThreadInfo->buffer == NULL) {
3019
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
3020 3021
    exit(-1);
  }
3022 3023 3024

  int len = 0;
  int batchNum = 0;
3025

3026
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
3027
          __func__, __LINE__,
3028
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
3029

3030
  for (uint64_t i = pThreadInfo->start_table_from;
3031
          i <= pThreadInfo->end_table_to; i++) {
3032
    if (0 == g_Dbs.use_metric) {
3033
      snprintf(pThreadInfo->buffer, buff_len,
3034
              "create table if not exists %s.%s%"PRIu64" %s;",
3035
              pThreadInfo->db_name,
3036
              g_args.tb_prefix, i,
3037
              pThreadInfo->cols);
3038
    } else {
3039 3040 3041
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
                  __func__, __LINE__);
3042
        free(pThreadInfo->buffer);
3043 3044 3045 3046
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
3047 3048
          memset(pThreadInfo->buffer, 0, buff_len);
          len += snprintf(pThreadInfo->buffer + len,
3049 3050 3051 3052
                  buff_len - len, "create table ");
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
3053
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
3054 3055 3056 3057 3058 3059
        } else {
          tagsValBuf = getTagValueFromTagSample(
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
        }
        if (NULL == tagsValBuf) {
3060
          free(pThreadInfo->buffer);
3061 3062
          return NULL;
        }
3063
        len += snprintf(pThreadInfo->buffer + len,
3064
                buff_len - len,
3065
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
3066 3067
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
3068 3069 3070 3071
                superTblInfo->sTblName, tagsValBuf);
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
3072
                && ((buff_len - len)
3073 3074 3075
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
          continue;
        }
3076 3077 3078 3079
      }
    }

    len = 0;
3080 3081 3082 3083
    if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                NO_INSERT_TYPE, false)){
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
      free(pThreadInfo->buffer);
3084 3085 3086
      return NULL;
    }

3087
    uint64_t  currentPrintTime = taosGetTimestampMs();
3088
    if (currentPrintTime - lastPrintTime > 30*1000) {
3089
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
3090
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
3091 3092 3093
      lastPrintTime = currentPrintTime;
    }
  }
3094

3095
  if (0 != len) {
3096 3097 3098
    if (0 != queryDbExec(pThreadInfo->taos, pThreadInfo->buffer,
                NO_INSERT_TYPE, false)) {
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", pThreadInfo->buffer);
3099
    }
3100
  }
3101

3102
  free(pThreadInfo->buffer);
3103 3104 3105
  return NULL;
}

3106
static int startMultiThreadCreateChildTable(
3107
        char* cols, int threads, uint64_t tableFrom, int64_t ntables,
3108
        char* db_name, SSuperTable* superTblInfo) {
3109

3110
  pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
3111
  threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
3112 3113 3114 3115 3116 3117 3118 3119 3120 3121

  if ((NULL == pids) || (NULL == infos)) {
    printf("malloc failed\n");
    exit(-1);
  }

  if (threads < 1) {
    threads = 1;
  }

3122
  int64_t a = ntables / threads;
3123 3124 3125 3126 3127
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

3128
  int64_t b = 0;
3129
  b = ntables % threads;
3130

3131
  for (int64_t i = 0; i < threads; i++) {
3132 3133
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
3134
    tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
3135
    pThreadInfo->superTblInfo = superTblInfo;
3136
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
3137
    pThreadInfo->taos = taos_connect(
3138 3139 3140 3141 3142
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
3143
    if (pThreadInfo->taos == NULL) {
3144 3145
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
         __func__, __LINE__, taos_errstr(NULL));
3146
      free(pids);
3147
      free(infos);
3148 3149
      return -1;
    }
3150

3151
    pThreadInfo->start_table_from = tableFrom;
3152
    pThreadInfo->ntables = i<b?a+1:a;
3153 3154
    pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
    tableFrom = pThreadInfo->end_table_to + 1;
3155 3156 3157 3158
    pThreadInfo->use_metric = true;
    pThreadInfo->cols = cols;
    pThreadInfo->minDelay = UINT64_MAX;
    pthread_create(pids + i, NULL, createTable, pThreadInfo);
3159
  }
3160

3161 3162 3163 3164 3165
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

  for (int i = 0; i < threads; i++) {
3166 3167
    threadInfo *pThreadInfo = infos + i;
    taos_close(pThreadInfo->taos);
3168 3169 3170
  }

  free(pids);
3171
  free(infos);
3172 3173

  return 0;
3174 3175
}

3176 3177 3178 3179
static void createChildTables() {
    char tblColsBuf[MAX_SQL_SIZE];
    int len;

3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219
    for (int i = 0; i < g_Dbs.dbCount; i++) {
        if (g_Dbs.use_metric) {
            if (g_Dbs.db[i].superTblCount > 0) {
                // with super table
                for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
                    if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
                            || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
                        continue;
                    }
                    verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
                          g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
                    uint64_t startFrom = 0;
                    g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

                    verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
                            __func__, __LINE__, g_totalChildTables, startFrom);

                    startMultiThreadCreateChildTable(
                            g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
                            g_Dbs.threadCountByCreateTbl,
                            startFrom,
                            g_Dbs.db[i].superTbls[j].childTblCount,
                            g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
                }
            }
        } else {
            // normal table
            len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
            for (int j = 0; j < g_args.num_of_CPR; j++) {
                if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0)
                        || (strncasecmp(g_args.datatype[j],
                                "NCHAR", strlen("NCHAR")) == 0)) {
                    snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                            ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary);
                } else {
                    snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                            ", COL%d %s", j, g_args.datatype[j]);
                }
                len = strlen(tblColsBuf);
            }
3220

3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232
            snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");

            verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
                    __func__, __LINE__,
                    g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
            startMultiThreadCreateChildTable(
                    tblColsBuf,
                    g_Dbs.threadCountByCreateTbl,
                    0,
                    g_args.num_of_tables,
                    g_Dbs.db[i].dbName,
                    NULL);
3233
        }
3234
    }
3235 3236 3237 3238 3239
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3240
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3241 3242 3243
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3244

3245 3246
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3247 3248
    printf("Failed to open tags file: %s, reason:%s\n",
            superTblInfo->tagsFile, strerror(errno));
3249 3250 3251 3252 3253 3254 3255
    return -1;
  }

  if (superTblInfo->tagDataBuf) {
    free(superTblInfo->tagDataBuf);
    superTblInfo->tagDataBuf = NULL;
  }
3256

3257 3258 3259 3260 3261 3262 3263 3264 3265
  int tagCount = 10000;
  int count = 0;
  char* tagDataBuf = calloc(1, superTblInfo->lenOfTagOfOneRow * tagCount);
  if (tagDataBuf == NULL) {
    printf("Failed to calloc, reason:%s\n", strerror(errno));
    fclose(fp);
    return -1;
  }

3266
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    memcpy(tagDataBuf + count * superTblInfo->lenOfTagOfOneRow, line, readLen);
    count++;

    if (count >= tagCount - 1) {
3279 3280
      char *tmp = realloc(tagDataBuf,
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3281 3282 3283
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3284 3285
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307
      } else {
        // exit, if allocate more memory failed
        printf("realloc fail for save tag val from %s\n", superTblInfo->tagsFile);
        tmfree(tagDataBuf);
        free(line);
        fclose(fp);
        return -1;
      }
    }
  }

  superTblInfo->tagDataBuf = tagDataBuf;
  superTblInfo->tagSampleCount = count;

  free(line);
  fclose(fp);
  return 0;
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3308 3309
static int readSampleFromCsvFileToMem(
        SSuperTable* superTblInfo) {
3310 3311 3312 3313
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3314

3315 3316
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3317
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
3318 3319 3320
              superTblInfo->sampleFile, strerror(errno));
      return -1;
  }
3321

3322
  assert(superTblInfo->sampleDataBuf);
3323 3324
  memset(superTblInfo->sampleDataBuf, 0,
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3325
  while(1) {
3326
    readLen = tgetline(&line, &n, fp);
3327 3328
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3329
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3330
                superTblInfo->sampleFile, strerror(errno));
3331
        fclose(fp);
3332 3333 3334 3335
        return -1;
      }
      continue;
    }
3336

3337 3338 3339 3340 3341 3342 3343 3344 3345
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3346
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3347
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3348 3349 3350
      continue;
    }

3351 3352
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
          line, readLen);
3353 3354 3355 3356 3357 3358 3359
    getRows++;

    if (getRows == MAX_SAMPLES_ONCE_FROM_FILE) {
      break;
    }
  }

3360
  fclose(fp);
3361 3362 3363 3364
  tmfree(line);
  return 0;
}

3365 3366
static bool getColumnAndTagTypeFromInsertJsonFile(
        cJSON* stbInfo, SSuperTable* superTbls) {
3367
  bool  ret = false;
3368

3369
  // columns
3370 3371
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3372
    printf("ERROR: failed to read json, columns not found\n");
3373 3374 3375 3376 3377 3378
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3379

3380
  int columnSize = cJSON_GetArraySize(columns);
3381
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3382 3383
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
            __func__, __LINE__, MAX_COLUMN_COUNT);
3384 3385 3386 3387 3388 3389
    goto PARSE_OVER;
  }

  int count = 1;
  int index = 0;
  StrColumn    columnCase;
3390

3391
  //superTbls->columnCount = columnSize;
3392 3393 3394 3395 3396 3397 3398
  for (int k = 0; k < columnSize; ++k) {
    cJSON* column = cJSON_GetArrayItem(columns, k);
    if (column == NULL) continue;

    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(column, "count");
    if (countObj && countObj->type == cJSON_Number) {
3399
      count = countObj->valueint;
3400
    } else if (countObj && countObj->type != cJSON_Number) {
3401 3402
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
          __func__, __LINE__);
3403 3404 3405 3406 3407
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3408
    // column info
3409 3410
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3411 3412 3413 3414
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
          __func__, __LINE__);
3415 3416
      goto PARSE_OVER;
    }
3417
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3418
    tstrncpy(columnCase.dataType, dataType->valuestring, strlen(dataType->valuestring) + 1);
3419

3420 3421
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3422
      columnCase.dataLen = dataLen->valueint;
3423
    } else if (dataLen && dataLen->type != cJSON_Number) {
3424 3425
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
          __func__, __LINE__);
3426 3427 3428 3429
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3430

3431
    for (int n = 0; n < count; ++n) {
3432
      tstrncpy(superTbls->columns[index].dataType,
3433
              columnCase.dataType, strlen(columnCase.dataType) + 1);
3434
      superTbls->columns[index].dataLen = columnCase.dataLen;
3435 3436
      index++;
    }
3437
  }
3438

3439 3440
  if ((index + 1 /* ts */) > MAX_COLUMN_COUNT) {
    errorPrint("%s() LN%d, failed to read json, column size overflow, allowed max column size is %d\n",
3441 3442 3443 3444
            __func__, __LINE__, MAX_COLUMN_COUNT);
    goto PARSE_OVER;
  }

3445
  superTbls->columnCount = index;
3446

3447 3448
  count = 1;
  index = 0;
3449
  // tags
3450 3451
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3452 3453
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
        __func__, __LINE__);
3454 3455
    goto PARSE_OVER;
  }
3456

3457 3458
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3459 3460
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
        __func__, __LINE__, MAX_TAG_COUNT);
3461 3462
    goto PARSE_OVER;
  }
3463 3464

  //superTbls->tagCount = tagSize;
3465 3466 3467
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3468

3469 3470 3471
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3472
      count = countObj->valueint;
3473
    } else if (countObj && countObj->type != cJSON_Number) {
3474
      printf("ERROR: failed to read json, column count not found\n");
3475 3476 3477 3478 3479
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3480
    // column info
3481 3482
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3483 3484 3485 3486
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
          __func__, __LINE__);
3487 3488
      goto PARSE_OVER;
    }
3489
    tstrncpy(columnCase.dataType, dataType->valuestring, strlen(dataType->valuestring) + 1);
3490

3491 3492
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3493
      columnCase.dataLen = dataLen->valueint;
3494
    } else if (dataLen && dataLen->type != cJSON_Number) {
3495 3496
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
          __func__, __LINE__);
3497 3498 3499
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3500 3501
    }

3502
    for (int n = 0; n < count; ++n) {
3503
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3504
          strlen(columnCase.dataType) + 1);
3505
      superTbls->tags[index].dataLen = columnCase.dataLen;
3506 3507
      index++;
    }
3508
  }
3509 3510

  if (index > MAX_TAG_COUNT) {
3511
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3512 3513 3514 3515
        __func__, __LINE__, MAX_TAG_COUNT);
    goto PARSE_OVER;
  }

3516 3517
  superTbls->tagCount = index;

3518 3519 3520
  if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > MAX_COLUMN_COUNT) {
    errorPrint("%s() LN%d, columns + tags is more than allowed max columns count: %d\n",
        __func__, __LINE__, MAX_COLUMN_COUNT);
3521 3522
    goto PARSE_OVER;
  }
3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533
  ret = true;

PARSE_OVER:
  return ret;
}

static bool getMetaFromInsertJsonFile(cJSON* root) {
  bool  ret = false;

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
3534
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3535 3536 3537 3538
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3539
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3540
  } else if (!host) {
3541
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3542
  } else {
3543
    printf("ERROR: failed to read json, host not found\n");
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555
    goto PARSE_OVER;
  }

  cJSON* port = cJSON_GetObjectItem(root, "port");
  if (port && port->type == cJSON_Number) {
    g_Dbs.port = port->valueint;
  } else if (!port) {
    g_Dbs.port = 6030;
  }

  cJSON* user = cJSON_GetObjectItem(root, "user");
  if (user && user->type == cJSON_String && user->valuestring != NULL) {
3556
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3557
  } else if (!user) {
3558
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3559 3560 3561 3562
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3563
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3564
  } else if (!password) {
3565
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3566 3567 3568 3569
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3570
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3571
  } else if (!resultfile) {
3572
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3573 3574 3575 3576 3577 3578 3579 3580
  }

  cJSON* threads = cJSON_GetObjectItem(root, "thread_count");
  if (threads && threads->type == cJSON_Number) {
    g_Dbs.threadCount = threads->valueint;
  } else if (!threads) {
    g_Dbs.threadCount = 1;
  } else {
3581
    printf("ERROR: failed to read json, threads not found\n");
3582
    goto PARSE_OVER;
3583 3584
  }

3585 3586 3587 3588
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
3589
    g_Dbs.threadCountByCreateTbl = 1;
3590
  } else {
3591 3592
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
            __func__, __LINE__);
3593
    goto PARSE_OVER;
3594
  }
3595

3596 3597
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3598 3599 3600 3601 3602
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3603 3604 3605 3606
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3607 3608
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
        __func__, __LINE__);
3609 3610
    goto PARSE_OVER;
  }
3611

3612 3613
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3614 3615 3616 3617 3618 3619
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3620 3621
    g_args.interlace_rows = interlaceRows->valueint;
  } else if (!interlaceRows) {
3622
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3623
  } else {
3624 3625
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
3626
    goto PARSE_OVER;
3627
  }
3628

3629 3630
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3631 3632 3633 3634 3635
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3636 3637
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
3638
    g_args.max_sql_len = (1024*1024);
3639
  } else {
3640 3641
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
3642 3643 3644 3645 3646
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3647
    if (numRecPerReq->valueint <= 0) {
3648 3649 3650
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
3651
    } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
3652 3653 3654 3655 3656
      printf("NOTICE: number of records per request value %"PRIu64" > %d\n\n",
              numRecPerReq->valueint, MAX_RECORDS_PER_REQ);
      printf("        number of records per request value will be set to %d\n\n",
              MAX_RECORDS_PER_REQ);
      prompt();
3657
      numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
3658
    }
3659 3660
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3661
    g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
3662
  } else {
3663 3664
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
        __func__, __LINE__);
3665 3666 3667
    goto PARSE_OVER;
  }

3668
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3669
  if (answerPrompt
3670 3671
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3672 3673 3674 3675 3676 3677 3678 3679
    if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
      g_args.answer_yes = false;
    } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
      g_args.answer_yes = true;
    } else {
      g_args.answer_yes = false;
    }
  } else if (!answerPrompt) {
3680
    g_args.answer_yes = true;   // default is no, mean answer_yes.
3681
  } else {
3682
    errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
3683
    goto PARSE_OVER;
3684
  }
3685

3686 3687
  // rows per table need be less than insert batch
  if (g_args.interlace_rows > g_args.num_of_RPR) {
3688
      printf("NOTICE: interlace rows value %u > num_of_records_per_req %u\n\n",
3689
              g_args.interlace_rows, g_args.num_of_RPR);
3690
      printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
3691 3692 3693 3694 3695
              g_args.num_of_RPR);
      prompt();
      g_args.interlace_rows = g_args.num_of_RPR;
  }

3696 3697
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3698
    printf("ERROR: failed to read json, databases not found\n");
3699 3700 3701 3702 3703
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3704
    errorPrint(
3705 3706
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3707 3708 3709 3710 3711 3712 3713 3714
    goto PARSE_OVER;
  }

  g_Dbs.dbCount = dbSize;
  for (int i = 0; i < dbSize; ++i) {
    cJSON* dbinfos = cJSON_GetArrayItem(dbs, i);
    if (dbinfos == NULL) continue;

3715
    // dbinfo
3716 3717
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3718
      printf("ERROR: failed to read json, dbinfo not found\n");
3719 3720
      goto PARSE_OVER;
    }
3721

3722 3723
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3724
      printf("ERROR: failed to read json, db name not found\n");
3725 3726
      goto PARSE_OVER;
    }
3727
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, TSDB_DB_NAME_LEN);
3728 3729 3730

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3731 3732
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3733
      } else {
3734
        g_Dbs.db[i].drop = false;
3735
      }
3736
    } else if (!drop) {
3737
      g_Dbs.db[i].drop = g_args.drop_database;
3738
    } else {
3739 3740
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
              __func__, __LINE__);
3741 3742 3743 3744
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3745 3746 3747
    if (precision && precision->type == cJSON_String
            && precision->valuestring != NULL) {
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
3748
              8);
3749
    } else if (!precision) {
3750
      memset(g_Dbs.db[i].dbCfg.precision, 0, 8);
3751
    } else {
3752
      printf("ERROR: failed to read json, precision not found\n");
3753 3754 3755 3756 3757 3758 3759 3760 3761
      goto PARSE_OVER;
    }

    cJSON* update = cJSON_GetObjectItem(dbinfo, "update");
    if (update && update->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.update = update->valueint;
    } else if (!update) {
      g_Dbs.db[i].dbCfg.update = -1;
    } else {
3762
      printf("ERROR: failed to read json, update not found\n");
3763 3764 3765 3766 3767 3768 3769 3770 3771
      goto PARSE_OVER;
    }

    cJSON* replica = cJSON_GetObjectItem(dbinfo, "replica");
    if (replica && replica->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.replica = replica->valueint;
    } else if (!replica) {
      g_Dbs.db[i].dbCfg.replica = -1;
    } else {
3772
      printf("ERROR: failed to read json, replica not found\n");
3773 3774 3775 3776 3777 3778 3779 3780 3781
      goto PARSE_OVER;
    }

    cJSON* keep = cJSON_GetObjectItem(dbinfo, "keep");
    if (keep && keep->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.keep = keep->valueint;
    } else if (!keep) {
      g_Dbs.db[i].dbCfg.keep = -1;
    } else {
3782
     printf("ERROR: failed to read json, keep not found\n");
3783 3784
     goto PARSE_OVER;
    }
3785

3786 3787 3788 3789 3790 3791
    cJSON* days = cJSON_GetObjectItem(dbinfo, "days");
    if (days && days->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.days = days->valueint;
    } else if (!days) {
      g_Dbs.db[i].dbCfg.days = -1;
    } else {
3792
     printf("ERROR: failed to read json, days not found\n");
3793 3794
     goto PARSE_OVER;
    }
3795

3796 3797 3798 3799 3800 3801
    cJSON* cache = cJSON_GetObjectItem(dbinfo, "cache");
    if (cache && cache->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.cache = cache->valueint;
    } else if (!cache) {
      g_Dbs.db[i].dbCfg.cache = -1;
    } else {
3802
     printf("ERROR: failed to read json, cache not found\n");
3803 3804
     goto PARSE_OVER;
    }
3805

3806 3807 3808 3809 3810 3811
    cJSON* blocks= cJSON_GetObjectItem(dbinfo, "blocks");
    if (blocks && blocks->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.blocks = blocks->valueint;
    } else if (!blocks) {
      g_Dbs.db[i].dbCfg.blocks = -1;
    } else {
3812
     printf("ERROR: failed to read json, block not found\n");
3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829
     goto PARSE_OVER;
    }

    //cJSON* maxtablesPerVnode= cJSON_GetObjectItem(dbinfo, "maxtablesPerVnode");
    //if (maxtablesPerVnode && maxtablesPerVnode->type == cJSON_Number) {
    //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = maxtablesPerVnode->valueint;
    //} else if (!maxtablesPerVnode) {
    //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = TSDB_DEFAULT_TABLES;
    //} else {
    // printf("failed to read json, maxtablesPerVnode not found");
    // goto PARSE_OVER;
    //}

    cJSON* minRows= cJSON_GetObjectItem(dbinfo, "minRows");
    if (minRows && minRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.minRows = minRows->valueint;
    } else if (!minRows) {
3830
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3831
    } else {
3832
     printf("ERROR: failed to read json, minRows not found\n");
3833 3834 3835 3836 3837 3838 3839
     goto PARSE_OVER;
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3840
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3841
    } else {
3842
     printf("ERROR: failed to read json, maxRows not found\n");
3843 3844 3845 3846 3847 3848 3849 3850 3851
     goto PARSE_OVER;
    }

    cJSON* comp= cJSON_GetObjectItem(dbinfo, "comp");
    if (comp && comp->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.comp = comp->valueint;
    } else if (!comp) {
      g_Dbs.db[i].dbCfg.comp = -1;
    } else {
3852
     printf("ERROR: failed to read json, comp not found\n");
3853 3854 3855 3856 3857 3858 3859 3860 3861
     goto PARSE_OVER;
    }

    cJSON* walLevel= cJSON_GetObjectItem(dbinfo, "walLevel");
    if (walLevel && walLevel->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.walLevel = walLevel->valueint;
    } else if (!walLevel) {
      g_Dbs.db[i].dbCfg.walLevel = -1;
    } else {
3862
     printf("ERROR: failed to read json, walLevel not found\n");
3863 3864 3865
     goto PARSE_OVER;
    }

3866 3867 3868 3869 3870 3871
    cJSON* cacheLast= cJSON_GetObjectItem(dbinfo, "cachelast");
    if (cacheLast && cacheLast->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.cacheLast = cacheLast->valueint;
    } else if (!cacheLast) {
      g_Dbs.db[i].dbCfg.cacheLast = -1;
    } else {
3872
     printf("ERROR: failed to read json, cacheLast not found\n");
3873 3874 3875
     goto PARSE_OVER;
    }

3876 3877 3878 3879
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3880
      g_Dbs.db[i].dbCfg.quorum = 1;
3881
    } else {
3882
     printf("failed to read json, quorum input mistake");
3883 3884 3885 3886 3887 3888 3889 3890 3891
     goto PARSE_OVER;
    }

    cJSON* fsync= cJSON_GetObjectItem(dbinfo, "fsync");
    if (fsync && fsync->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.fsync = fsync->valueint;
    } else if (!fsync) {
      g_Dbs.db[i].dbCfg.fsync = -1;
    } else {
3892 3893 3894
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
              __func__, __LINE__);
      goto PARSE_OVER;
3895
    }
3896

3897
    // super_talbes
3898 3899
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3900 3901
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
              __func__, __LINE__);
3902
      goto PARSE_OVER;
3903 3904
    }

3905 3906
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3907
      errorPrint(
3908 3909
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3910 3911 3912 3913 3914 3915 3916
      goto PARSE_OVER;
    }

    g_Dbs.db[i].superTblCount = stbSize;
    for (int j = 0; j < stbSize; ++j) {
      cJSON* stbInfo = cJSON_GetArrayItem(stables, j);
      if (stbInfo == NULL) continue;
3917 3918

      // dbinfo
3919
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
3920 3921
      if (!stbName || stbName->type != cJSON_String
              || stbName->valuestring == NULL) {
3922 3923
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
                __func__, __LINE__);
3924 3925
        goto PARSE_OVER;
      }
3926
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring,
3927
              TSDB_TABLE_NAME_LEN);
3928

3929 3930
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3931
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3932 3933
        goto PARSE_OVER;
      }
3934
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring,
3935
              TSDB_TABLE_NAME_LEN - 20);
3936

3937
      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table");
3938 3939 3940
      if (autoCreateTbl
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3941 3942 3943 3944 3945 3946 3947 3948
          if ((0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3))
                  && (TBL_ALREADY_EXISTS != g_Dbs.db[i].superTbls[j].childTblExists)) {
              g_Dbs.db[i].superTbls[j].autoCreateTable = AUTO_CREATE_SUBTBL;
          } else if (0 == strncasecmp(autoCreateTbl->valuestring, "no", 2)) {
              g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
          } else {
              g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
          }
3949
      } else if (!autoCreateTbl) {
3950
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
3951
      } else {
3952 3953
          printf("ERROR: failed to read json, auto_create_table not found\n");
          goto PARSE_OVER;
3954
      }
3955

3956 3957 3958 3959
      cJSON* batchCreateTbl = cJSON_GetObjectItem(stbInfo, "batch_create_tbl_num");
      if (batchCreateTbl && batchCreateTbl->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = batchCreateTbl->valueint;
      } else if (!batchCreateTbl) {
3960
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3961
      } else {
3962
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3963
        goto PARSE_OVER;
3964
      }
3965 3966

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3967 3968 3969
      if (childTblExists
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3970 3971
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3972
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3973 3974
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
              || (g_Dbs.db[i].drop == true))) {
3975 3976 3977 3978 3979 3980 3981
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
        } else {
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
        }
      } else if (!childTblExists) {
        g_Dbs.db[i].superTbls[j].childTblExists = TBL_NO_EXISTS;
      } else {
3982 3983
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
                __func__, __LINE__);
3984 3985
        goto PARSE_OVER;
      }
3986

3987 3988 3989 3990
      if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
          g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
      }

3991 3992
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3993
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3994
                __func__, __LINE__);
3995 3996 3997 3998 3999
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
4000 4001 4002
      if (dataSource && dataSource->type == cJSON_String
              && dataSource->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
4003
                dataSource->valuestring, TSDB_DB_NAME_LEN);
4004
      } else if (!dataSource) {
4005
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", TSDB_DB_NAME_LEN);
4006
      } else {
4007 4008
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
            __func__, __LINE__);
4009 4010 4011
        goto PARSE_OVER;
      }

4012 4013 4014 4015 4016 4017 4018
      cJSON *stbIface = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest, stmt
      if (stbIface && stbIface->type == cJSON_String
              && stbIface->valuestring != NULL) {
        if (0 == strcasecmp(stbIface->valuestring, "taosc")) {
            g_Dbs.db[i].superTbls[j].iface= TAOSC_IFACE;
        } else if (0 == strcasecmp(stbIface->valuestring, "rest")) {
            g_Dbs.db[i].superTbls[j].iface= REST_IFACE;
4019
#if STMT_IFACE_ENABLED == 1
4020 4021
        } else if (0 == strcasecmp(stbIface->valuestring, "stmt")) {
            g_Dbs.db[i].superTbls[j].iface= STMT_IFACE;
4022
#endif
4023 4024 4025 4026 4027 4028 4029
        } else {
            errorPrint("%s() LN%d, failed to read json, insert_mode %s not recognized\n",
                    __func__, __LINE__, stbIface->valuestring);
            goto PARSE_OVER;
        }
      } else if (!stbIface) {
        g_Dbs.db[i].superTbls[j].iface = TAOSC_IFACE;
4030
      } else {
4031
        errorPrint("%s", "failed to read json, insert_mode not found\n");
4032 4033 4034
        goto PARSE_OVER;
      }

4035
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
4036 4037
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
4038 4039 4040 4041 4042 4043
        if (childTbl_limit->type != cJSON_Number) {
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
4044
        g_Dbs.db[i].superTbls[j].childTblLimit = -1;    // select ... limit -1 means all query result, drop = yes mean all table need recreate, limit value is invalid.
4045 4046 4047
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
4048 4049
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
4050 4051
        if ((childTbl_offset->type != cJSON_Number)
                || (0 > childTbl_offset->valueint)) {
4052 4053 4054 4055 4056 4057 4058 4059
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

4060 4061
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
4062
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
4063
                ts->valuestring, TSDB_DB_NAME_LEN);
4064
      } else if (!ts) {
4065
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
4066
                "now", TSDB_DB_NAME_LEN);
4067
      } else {
4068
        printf("ERROR: failed to read json, start_timestamp not found\n");
4069 4070
        goto PARSE_OVER;
      }
4071

4072 4073 4074 4075
      cJSON* timestampStep = cJSON_GetObjectItem(stbInfo, "timestamp_step");
      if (timestampStep && timestampStep->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].timeStampStep = timestampStep->valueint;
      } else if (!timestampStep) {
4076
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
4077
      } else {
4078
        printf("ERROR: failed to read json, timestamp_step not found\n");
4079 4080 4081 4082
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
4083 4084
      if (sampleFormat && sampleFormat->type
              == cJSON_String && sampleFormat->valuestring != NULL) {
4085
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
4086
                sampleFormat->valuestring, TSDB_DB_NAME_LEN);
4087
      } else if (!sampleFormat) {
4088
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", TSDB_DB_NAME_LEN);
4089
      } else {
4090
        printf("ERROR: failed to read json, sample_format not found\n");
4091
        goto PARSE_OVER;
4092
      }
4093

4094
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
4095 4096
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
4097 4098
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
4099 4100 4101
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
4102
        printf("ERROR: failed to read json, sample_file not found\n");
4103
        goto PARSE_OVER;
4104
      }
4105

4106
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
4107 4108
      if ((tagsFile && tagsFile->type == cJSON_String)
              && (tagsFile->valuestring != NULL)) {
4109 4110
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
4111 4112 4113 4114 4115 4116 4117 4118 4119
        if (0 == g_Dbs.db[i].superTbls[j].tagsFile[0]) {
          g_Dbs.db[i].superTbls[j].tagSource = 0;
        } else {
          g_Dbs.db[i].superTbls[j].tagSource = 1;
        }
      } else if (!tagsFile) {
        memset(g_Dbs.db[i].superTbls[j].tagsFile, 0, MAX_FILE_NAME_LEN);
        g_Dbs.db[i].superTbls[j].tagSource = 0;
      } else {
4120
        printf("ERROR: failed to read json, tags_file not found\n");
4121 4122
        goto PARSE_OVER;
      }
4123

4124 4125 4126
      cJSON* stbMaxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
      if (stbMaxSqlLen && stbMaxSqlLen->type == cJSON_Number) {
        int32_t len = stbMaxSqlLen->valueint;
4127 4128
        if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
          len = TSDB_MAX_ALLOWED_SQL_LEN;
4129 4130
        } else if (len < 5) {
          len = 5;
4131
        }
4132 4133
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
4134
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
4135
      } else {
4136
        errorPrint("%s() LN%d, failed to read json, stbMaxSqlLen input mistake\n",
4137
            __func__, __LINE__);
4138
        goto PARSE_OVER;
4139
      }
4140
/*
4141 4142 4143 4144 4145
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
4146 4147 4148 4149
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
4150
        }
4151 4152 4153
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
4154
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
4155 4156
        goto PARSE_OVER;
      }
4157
*/
4158 4159 4160
      cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) {
        if (stbInterlaceRows->valueint < 0) {
4161 4162 4163 4164
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
4165
        g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint;
4166 4167
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
4168 4169 4170 4171
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %u > num_of_records_per_req %u\n\n",
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows,
                  g_args.num_of_RPR);
          printf("        interlace rows value will be set to num_of_records_per_req %u\n\n",
4172
                  g_args.num_of_RPR);
4173
          prompt();
4174 4175
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
4176
      } else if (!stbInterlaceRows) {
4177
        g_Dbs.db[i].superTbls[j].interlaceRows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
4178
      } else {
4179 4180 4181
        errorPrint(
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
4182
        goto PARSE_OVER;
4183
      }
4184 4185 4186

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
4187 4188 4189 4190 4191 4192
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

        if (disorderRatio->valueint < 0)
          disorderRatio->valueint = 0;

4193 4194 4195 4196
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
4197
        printf("ERROR: failed to read json, disorderRatio not found\n");
4198
        goto PARSE_OVER;
4199
      }
4200 4201 4202 4203 4204 4205 4206

      cJSON* disorderRange = cJSON_GetObjectItem(stbInfo, "disorder_range");
      if (disorderRange && disorderRange->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].disorderRange = disorderRange->valueint;
      } else if (!disorderRange) {
        g_Dbs.db[i].superTbls[j].disorderRange = 1000;
      } else {
4207
        printf("ERROR: failed to read json, disorderRange not found\n");
4208 4209
        goto PARSE_OVER;
      }
4210

4211 4212
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
4213 4214 4215 4216 4217
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4218 4219 4220 4221
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
4222 4223
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
4224 4225 4226 4227 4228 4229
        goto PARSE_OVER;
      }

      cJSON* insertInterval = cJSON_GetObjectItem(stbInfo, "insert_interval");
      if (insertInterval && insertInterval->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].insertInterval = insertInterval->valueint;
4230 4231 4232 4233 4234
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4235
      } else if (!insertInterval) {
4236
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
4237 4238 4239
                __func__, __LINE__, g_args.insert_interval);
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
4240 4241
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
4242 4243 4244
        goto PARSE_OVER;
      }

4245 4246
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4247 4248
      if (false == retVal) {
        goto PARSE_OVER;
4249 4250
      }
    }
4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263
  }

  ret = true;

PARSE_OVER:
  return ret;
}

static bool getMetaFromQueryJsonFile(cJSON* root) {
  bool  ret = false;

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
4264
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4265 4266 4267 4268
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4269
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4270
  } else if (!host) {
4271
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4272
  } else {
4273
    printf("ERROR: failed to read json, host not found\n");
4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285
    goto PARSE_OVER;
  }

  cJSON* port = cJSON_GetObjectItem(root, "port");
  if (port && port->type == cJSON_Number) {
    g_queryInfo.port = port->valueint;
  } else if (!port) {
    g_queryInfo.port = 6030;
  }

  cJSON* user = cJSON_GetObjectItem(root, "user");
  if (user && user->type == cJSON_String && user->valuestring != NULL) {
4286
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4287
  } else if (!user) {
4288
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4289 4290 4291 4292
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4293
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4294
  } else if (!password) {
4295
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4296
  }
H
hzcheng 已提交
4297

4298
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4299 4300
  if (answerPrompt && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
4301 4302 4303 4304
    if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
      g_args.answer_yes = false;
    } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
      g_args.answer_yes = true;
H
hzcheng 已提交
4305
    } else {
4306
      g_args.answer_yes = false;
H
hzcheng 已提交
4307
    }
4308 4309 4310
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4311
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4312
    goto PARSE_OVER;
4313
  }
4314

4315 4316
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4317
    if (gQueryTimes->valueint <= 0) {
4318 4319
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4320 4321
      goto PARSE_OVER;
    }
4322 4323 4324 4325
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4326 4327
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4328 4329 4330
    goto PARSE_OVER;
  }

4331 4332
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4333
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, TSDB_DB_NAME_LEN);
4334
  } else if (!dbs) {
4335
    printf("ERROR: failed to read json, databases not found\n");
4336
    goto PARSE_OVER;
H
hzcheng 已提交
4337
  }
4338 4339 4340

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4341
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4342
  } else if (!queryMode) {
4343
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4344
  } else {
4345
    printf("ERROR: failed to read json, query_mode not found\n");
4346
    goto PARSE_OVER;
H
hzcheng 已提交
4347
  }
4348

4349
  // specified_table_query
4350 4351
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4352
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4353 4354
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4355
    printf("ERROR: failed to read json, super_table_query not found\n");
4356
    goto PARSE_OVER;
4357
  } else {
4358 4359 4360 4361 4362
    cJSON* queryInterval = cJSON_GetObjectItem(specifiedQuery, "query_interval");
    if (queryInterval && queryInterval->type == cJSON_Number) {
      g_queryInfo.specifiedQueryInfo.queryInterval = queryInterval->valueint;
    } else if (!queryInterval) {
      g_queryInfo.specifiedQueryInfo.queryInterval = 0;
4363 4364
    }

4365 4366
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
        "query_times");
4367
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4368
      if (specifiedQueryTimes->valueint <= 0) {
4369 4370
        errorPrint(
                "%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4371
          __func__, __LINE__, specifiedQueryTimes->valueint);
4372 4373 4374
        goto PARSE_OVER;

      }
4375 4376 4377 4378
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4379 4380
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4381
      goto PARSE_OVER;
4382
    }
4383

4384
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4385
    if (concurrent && concurrent->type == cJSON_Number) {
4386
      if (concurrent->valueint <= 0) {
4387
        errorPrint(
4388
                "%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n",
4389 4390
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4391 4392 4393
              g_queryInfo.specifiedQueryInfo.concurrent);
        goto PARSE_OVER;
      }
4394
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4395
    } else if (!concurrent) {
4396
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4397
    }
4398

4399 4400 4401 4402 4403 4404 4405
    cJSON* specifiedAsyncMode = cJSON_GetObjectItem(specifiedQuery, "mode");
    if (specifiedAsyncMode && specifiedAsyncMode->type == cJSON_String
        && specifiedAsyncMode->valuestring != NULL) {
      if (0 == strcmp("sync", specifiedAsyncMode->valuestring)) {
        g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
      } else if (0 == strcmp("async", specifiedAsyncMode->valuestring)) {
        g_queryInfo.specifiedQueryInfo.asyncMode = ASYNC_MODE;
4406
      } else {
4407
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4408
            __func__, __LINE__);
4409 4410 4411
        goto PARSE_OVER;
      }
    } else {
4412
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4413
    }
4414

4415
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4416
    if (interval && interval->type == cJSON_Number) {
4417
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4418
    } else if (!interval) {
4419 4420
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4421
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4422
    }
4423

4424
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4425
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4426
      if (0 == strcmp("yes", restart->valuestring)) {
4427
        g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4428
      } else if (0 == strcmp("no", restart->valuestring)) {
4429
        g_queryInfo.specifiedQueryInfo.subscribeRestart = false;
4430
      } else {
4431
        printf("ERROR: failed to read json, subscribe restart error\n");
4432 4433 4434
        goto PARSE_OVER;
      }
    } else {
4435
      g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4436
    }
4437

4438
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4439 4440 4441
    if (keepProgress
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4442
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4443
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4444
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4445
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4446
      } else {
4447
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4448 4449 4450
        goto PARSE_OVER;
      }
    } else {
4451
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4452 4453
    }

4454
    // sqls
4455 4456
    cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
    if (!specifiedSqls) {
4457
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4458
    } else if (specifiedSqls->type != cJSON_Array) {
4459 4460
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
          __func__, __LINE__);
4461
      goto PARSE_OVER;
4462
    } else {
4463 4464 4465 4466 4467 4468 4469 4470
      int superSqlSize = cJSON_GetArraySize(specifiedSqls);
      if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent
              > MAX_QUERY_SQL_COUNT) {
        errorPrint("%s() LN%d, failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n",
           __func__, __LINE__,
           superSqlSize,
           g_queryInfo.specifiedQueryInfo.concurrent,
           MAX_QUERY_SQL_COUNT);
4471 4472
        goto PARSE_OVER;
      }
4473

4474
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4475
      for (int j = 0; j < superSqlSize; ++j) {
4476
        cJSON* sql = cJSON_GetArrayItem(specifiedSqls, j);
4477
        if (sql == NULL) continue;
4478

4479 4480
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4481
          printf("ERROR: failed to read json, sql not found\n");
4482 4483
          goto PARSE_OVER;
        }
4484 4485 4486
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
                sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);

4487 4488
        // default value is -1, which mean infinite loop
        g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;
4489 4490 4491 4492 4493 4494 4495
        cJSON* endAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "endAfterConsume");
        if (endAfterConsume
                && endAfterConsume->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.endAfterConsume[j]
                = endAfterConsume->valueint;
        }
4496 4497
        if (g_queryInfo.specifiedQueryInfo.endAfterConsume[j] < -1)
            g_queryInfo.specifiedQueryInfo.endAfterConsume[j] = -1;
4498

4499
        g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;
4500 4501
        cJSON* resubAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
4502 4503 4504
        if ((resubAfterConsume)
                && (resubAfterConsume->type == cJSON_Number)
                && (resubAfterConsume->valueint >= 0)) {
4505 4506 4507
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
                = resubAfterConsume->valueint;
        }
H
hzcheng 已提交
4508

4509 4510 4511
        if (g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] < -1)
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = -1;

4512
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4513 4514 4515 4516
        if ((NULL != result) && (result->type == cJSON_String)
                && (result->valuestring != NULL)) {
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                  result->valuestring, MAX_FILE_NAME_LEN);
4517
        } else if (NULL == result) {
4518 4519
          memset(g_queryInfo.specifiedQueryInfo.result[j],
                  0, MAX_FILE_NAME_LEN);
4520
        } else {
4521
          printf("ERROR: failed to read json, super query result file not found\n");
4522
          goto PARSE_OVER;
4523
        }
4524 4525 4526
      }
    }
  }
4527

4528
  // super_table_query
4529 4530
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4531
    g_queryInfo.superQueryInfo.threadCnt = 1;
4532 4533
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4534
    printf("ERROR: failed to read json, sub_table_query not found\n");
4535 4536
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4537
  } else {
4538
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4539
    if (subrate && subrate->type == cJSON_Number) {
4540
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4541
    } else if (!subrate) {
4542
      g_queryInfo.superQueryInfo.queryInterval = 0;
4543 4544 4545 4546
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4547 4548 4549
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
          __func__, __LINE__, superQueryTimes->valueint);
4550 4551
        goto PARSE_OVER;
      }
4552 4553 4554 4555
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4556 4557
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4558
      goto PARSE_OVER;
4559
    }
4560

4561
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4562
    if (threads && threads->type == cJSON_Number) {
4563 4564 4565 4566 4567 4568
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4569
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4570
    } else if (!threads) {
4571
      g_queryInfo.superQueryInfo.threadCnt = 1;
4572
    }
4573

4574
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4575
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4576
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4577
    //} else if (!subTblCnt) {
4578
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4579
    //}
4580

4581
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4582 4583 4584
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4585
          TSDB_TABLE_NAME_LEN);
4586
    } else {
4587 4588
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
          __func__, __LINE__);
4589 4590
      goto PARSE_OVER;
    }
4591

4592 4593 4594 4595 4596 4597 4598
    cJSON* superAsyncMode = cJSON_GetObjectItem(superQuery, "mode");
    if (superAsyncMode && superAsyncMode->type == cJSON_String
        && superAsyncMode->valuestring != NULL) {
      if (0 == strcmp("sync", superAsyncMode->valuestring)) {
        g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
      } else if (0 == strcmp("async", superAsyncMode->valuestring)) {
        g_queryInfo.superQueryInfo.asyncMode = ASYNC_MODE;
4599
      } else {
4600
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4601
            __func__, __LINE__);
4602 4603 4604
        goto PARSE_OVER;
      }
    } else {
4605
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4606
    }
4607

4608 4609 4610 4611 4612 4613 4614 4615 4616
    cJSON* superInterval = cJSON_GetObjectItem(superQuery, "interval");
    if (superInterval && superInterval->type == cJSON_Number) {
      if (superInterval->valueint < 0) {
        errorPrint("%s() LN%d, failed to read json, interval input mistake\n",
            __func__, __LINE__);
        goto PARSE_OVER;
      }
      g_queryInfo.superQueryInfo.subscribeInterval = superInterval->valueint;
    } else if (!superInterval) {
4617 4618
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4619
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4620
    }
4621

4622
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4623 4624
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4625
      if (0 == strcmp("yes", subrestart->valuestring)) {
4626
        g_queryInfo.superQueryInfo.subscribeRestart = true;
4627
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4628
        g_queryInfo.superQueryInfo.subscribeRestart = false;
4629
      } else {
4630
        printf("ERROR: failed to read json, subscribe restart error\n");
4631 4632 4633
        goto PARSE_OVER;
      }
    } else {
4634
      g_queryInfo.superQueryInfo.subscribeRestart = true;
4635
    }
4636

4637 4638 4639 4640 4641
    cJSON* superkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
    if (superkeepProgress &&
            superkeepProgress->type == cJSON_String
            && superkeepProgress->valuestring != NULL) {
      if (0 == strcmp("yes", superkeepProgress->valuestring)) {
4642
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4643
      } else if (0 == strcmp("no", superkeepProgress->valuestring)) {
4644
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4645
      } else {
4646
        printf("ERROR: failed to read json, subscribe super table keepProgress error\n");
4647 4648 4649
        goto PARSE_OVER;
      }
    } else {
4650
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4651
    }
4652

4653 4654
    // default value is -1, which mean do not resub
    g_queryInfo.superQueryInfo.endAfterConsume = -1;
4655 4656 4657 4658 4659 4660 4661
    cJSON* superEndAfterConsume =
            cJSON_GetObjectItem(superQuery, "endAfterConsume");
    if (superEndAfterConsume
            && superEndAfterConsume->type == cJSON_Number) {
        g_queryInfo.superQueryInfo.endAfterConsume =
            superEndAfterConsume->valueint;
    }
4662 4663
    if (g_queryInfo.superQueryInfo.endAfterConsume < -1)
        g_queryInfo.superQueryInfo.endAfterConsume = -1;
4664

4665 4666
    // default value is -1, which mean do not resub
    g_queryInfo.superQueryInfo.resubAfterConsume = -1;
4667
    cJSON* superResubAfterConsume =
4668 4669 4670 4671 4672
            cJSON_GetObjectItem(superQuery, "resubAfterConsume");
    if ((superResubAfterConsume)
            && (superResubAfterConsume->type == cJSON_Number)
            && (superResubAfterConsume->valueint >= 0)) {
        g_queryInfo.superQueryInfo.resubAfterConsume =
4673 4674
            superResubAfterConsume->valueint;
    }
4675 4676
    if (g_queryInfo.superQueryInfo.resubAfterConsume < -1)
        g_queryInfo.superQueryInfo.resubAfterConsume = -1;
4677

4678 4679 4680
    // supert table sqls
    cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
    if (!superSqls) {
4681
      g_queryInfo.superQueryInfo.sqlCount = 0;
4682
    } else if (superSqls->type != cJSON_Array) {
4683 4684
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
          __func__, __LINE__);
4685
      goto PARSE_OVER;
4686
    } else {
4687
      int superSqlSize = cJSON_GetArraySize(superSqls);
4688
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4689 4690
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4691 4692
        goto PARSE_OVER;
      }
4693

4694
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4695
      for (int j = 0; j < superSqlSize; ++j) {
4696
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
4697
        if (sql == NULL) continue;
4698

4699
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4700 4701 4702 4703
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
              __func__, __LINE__);
4704 4705
          goto PARSE_OVER;
        }
4706 4707
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
            MAX_QUERY_SQL_LENGTH);
4708 4709

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4710 4711 4712 4713
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
              result->valuestring, MAX_FILE_NAME_LEN);
4714
        } else if (NULL == result) {
4715
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4716
        }  else {
4717 4718
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
              __func__, __LINE__);
4719
          goto PARSE_OVER;
4720
        }
4721 4722
      }
    }
H
hzcheng 已提交
4723 4724
  }

4725
  ret = true;
H
hzcheng 已提交
4726

4727 4728 4729
PARSE_OVER:
  return ret;
}
H
hzcheng 已提交
4730

4731
static bool getInfoFromJsonFile(char* file) {
4732
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4733

4734 4735 4736 4737 4738
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4739

4740
  bool  ret = false;
4741
  int   maxLen = 6400000;
4742 4743 4744 4745 4746 4747 4748
  char *content = calloc(1, maxLen + 1);
  int   len = fread(content, 1, maxLen, fp);
  if (len <= 0) {
    free(content);
    fclose(fp);
    printf("failed to read %s, content is null", file);
    return false;
H
hzcheng 已提交
4749
  }
H
Hui Li 已提交
4750

4751 4752 4753
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4754
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4755 4756
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4757

4758 4759 4760
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4761
      g_args.test_mode = INSERT_TEST;
4762
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4763
      g_args.test_mode = QUERY_TEST;
4764
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4765
      g_args.test_mode = SUBSCRIBE_TEST;
4766
    } else {
4767
      printf("ERROR: failed to read json, filetype not support\n");
4768 4769 4770
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4771
    g_args.test_mode = INSERT_TEST;
4772
  } else {
4773
    printf("ERROR: failed to read json, filetype not found\n");
4774 4775
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4776

4777
  if (INSERT_TEST == g_args.test_mode) {
4778
    ret = getMetaFromInsertJsonFile(root);
4779 4780
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4781 4782
    ret = getMetaFromQueryJsonFile(root);
  } else {
4783 4784
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4785
    goto PARSE_OVER;
4786
  }
4787 4788 4789 4790

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4791
  fclose(fp);
4792 4793
  return ret;
}
H
hzcheng 已提交
4794

4795
static int prepareSampleData() {
4796
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4797 4798
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) {
4799 4800 4801
        if (readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]) != 0) {
          return -1;
        }
S
Shuaiqiang Chang 已提交
4802
      }
4803 4804
    }
  }
4805 4806

  return 0;
4807 4808
}

4809
static void postFreeResource() {
4810
  tmfclose(g_fpOfInsertResult);
4811
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4812
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4813 4814 4815
      if (0 != g_Dbs.db[i].superTbls[j].colsOfCreateChildTable) {
        free(g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
        g_Dbs.db[i].superTbls[j].colsOfCreateChildTable = NULL;
S
Shuaiqiang Chang 已提交
4816
      }
4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828
      if (0 != g_Dbs.db[i].superTbls[j].sampleDataBuf) {
        free(g_Dbs.db[i].superTbls[j].sampleDataBuf);
        g_Dbs.db[i].superTbls[j].sampleDataBuf = NULL;
      }
      if (0 != g_Dbs.db[i].superTbls[j].tagDataBuf) {
        free(g_Dbs.db[i].superTbls[j].tagDataBuf);
        g_Dbs.db[i].superTbls[j].tagDataBuf = NULL;
      }
      if (0 != g_Dbs.db[i].superTbls[j].childTblName) {
        free(g_Dbs.db[i].superTbls[j].childTblName);
        g_Dbs.db[i].superTbls[j].childTblName = NULL;
      }
S
Shuaiqiang Chang 已提交
4829
    }
4830 4831
  }
}
S
Shuaiqiang Chang 已提交
4832

4833 4834
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860
      SSuperTable* superTblInfo, int64_t* sampleUsePos)
{
    if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
        /*    int ret = readSampleFromCsvFileToMem(superTblInfo);
              if (0 != ret) {
              tmfree(superTblInfo->sampleDataBuf);
              superTblInfo->sampleDataBuf = NULL;
              return -1;
              }
              */
        *sampleUsePos = 0;
    }

    int    dataLen = 0;

    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "(%" PRId64 ", ", timestamp);
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
            "%s",
            superTblInfo->sampleDataBuf
            + superTblInfo->lenOfOneRow * (*sampleUsePos));
    dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");

    (*sampleUsePos)++;

    return dataLen;
4861
}
S
Shuaiqiang Chang 已提交
4862

4863 4864 4865 4866
static int64_t generateStbRowData(
        SSuperTable* stbInfo,
        char* recBuf, int64_t timestamp)
{
4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883
    int64_t   dataLen = 0;
    char  *pstr = recBuf;
    int64_t maxLen = MAX_DATA_SIZE;

    dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
            "(%" PRId64 ",", timestamp);

    for (int i = 0; i < stbInfo->columnCount; i++) {
        if ((0 == strncasecmp(stbInfo->columns[i].dataType,
                        "BINARY", strlen("BINARY")))
                || (0 == strncasecmp(stbInfo->columns[i].dataType,
                        "NCHAR", strlen("NCHAR")))) {
            if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
                errorPrint( "binary or nchar length overflow, max size:%u\n",
                        (uint32_t)TSDB_MAX_BINARY_LEN);
                return -1;
            }
4884

4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943
            char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
            if (NULL == buf) {
                errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
                return -1;
            }
            rand_string(buf, stbInfo->columns[i].dataLen);
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
            tmfree(buf);
        } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "INT", strlen("INT"))) {
            if ((g_args.demo_mode) && (i == 1)) {
                dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                        "%d,", demo_voltage_int());
            } else {
                dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                        "%d,", rand_int());
            }
        } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "BIGINT", strlen("BIGINT"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%"PRId64",", rand_bigint());
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "FLOAT", strlen("FLOAT"))) {
            if (g_args.demo_mode) {
                if (i == 0) {
                    dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                            "%f,", demo_current_float());
                } else {
                    dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                            "%f,", demo_phase_float());
                }
            } else {
                dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                        "%f,", rand_float());
            }
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "DOUBLE", strlen("DOUBLE"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%f,", rand_double());
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "SMALLINT", strlen("SMALLINT"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%d,", rand_smallint());
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "TINYINT", strlen("TINYINT"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%d,", rand_tinyint());
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "BOOL", strlen("BOOL"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%d,", rand_bool());
        }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "TIMESTAMP", strlen("TIMESTAMP"))) {
            dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
                    "%"PRId64",", rand_bigint());
        }  else {
            errorPrint( "Not support data type: %s\n", stbInfo->columns[i].dataType);
            return -1;
        }
4944
    }
4945

4946 4947
    dataLen -= 1;
    dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4948

4949 4950
    verbosePrint("%s() LN%d, dataLen:%"PRId64"\n", __func__, __LINE__, dataLen);
    verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);
4951

4952
    return strlen(recBuf);
4953
}
S
Shuaiqiang Chang 已提交
4954

4955
static int64_t generateData(char *recBuf, char **data_type,
4956
        int64_t timestamp, int lenOfBinary) {
4957 4958
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4959 4960
  pstr += sprintf(pstr, "(%" PRId64, timestamp);

4961
  int columnCount = g_args.num_of_CPR;
4962

4963 4964
  for (int i = 0; i < columnCount; i++) {
    if (strcasecmp(data_type[i % columnCount], "TINYINT") == 0) {
4965
      pstr += sprintf(pstr, ",%d", rand_tinyint() );
4966
    } else if (strcasecmp(data_type[i % columnCount], "SMALLINT") == 0) {
4967
      pstr += sprintf(pstr, ",%d", rand_smallint());
4968
    } else if (strcasecmp(data_type[i % columnCount], "INT") == 0) {
4969
      pstr += sprintf(pstr, ",%d", rand_int());
4970
    } else if (strcasecmp(data_type[i % columnCount], "BIGINT") == 0) {
4971
      pstr += sprintf(pstr, ",%" PRId64, rand_bigint());
4972 4973 4974
    } else if (strcasecmp(data_type[i % columnCount], "TIMESTAMP") == 0) {
      pstr += sprintf(pstr, ",%" PRId64, rand_bigint());
    } else if (strcasecmp(data_type[i % columnCount], "FLOAT") == 0) {
4975
      pstr += sprintf(pstr, ",%10.4f", rand_float());
4976
    } else if (strcasecmp(data_type[i % columnCount], "DOUBLE") == 0) {
4977
      double t = rand_double();
4978
      pstr += sprintf(pstr, ",%20.8f", t);
4979
    } else if (strcasecmp(data_type[i % columnCount], "BOOL") == 0) {
4980
      bool b = rand_bool() & 1;
4981
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
4982
    } else if (strcasecmp(data_type[i % columnCount], "BINARY") == 0) {
4983 4984
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4985
      pstr += sprintf(pstr, ",\"%s\"", s);
4986
      free(s);
4987
    } else if (strcasecmp(data_type[i % columnCount], "NCHAR") == 0) {
4988 4989
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4990
      pstr += sprintf(pstr, ",\"%s\"", s);
4991 4992 4993
      free(s);
    }

4994
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4995 4996 4997 4998 4999 5000 5001
      perror("column length too long, abort");
      exit(-1);
    }
  }

  pstr += sprintf(pstr, ")");

5002 5003
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

5004
  return (int32_t)strlen(recBuf);
5005 5006
}

5007
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
5008 5009
  char* sampleDataBuf = NULL;

5010
  sampleDataBuf = calloc(
5011
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
5012
  if (sampleDataBuf == NULL) {
5013
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
5014
              __func__, __LINE__,
5015
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
5016
              strerror(errno));
5017
      return -1;
5018
  }
5019

5020 5021 5022 5023
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
5024 5025
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
5026
      tmfree(sampleDataBuf);
5027
      superTblInfo->sampleDataBuf = NULL;
5028
      return -1;
H
Hui Li 已提交
5029
  }
5030

5031 5032 5033
  return 0;
}

5034
static int32_t execInsert(threadInfo *pThreadInfo, uint32_t k)
5035
{
5036 5037
    int32_t affectedRows;
    SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5038

5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061
    verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, pThreadInfo->buffer);

    uint16_t iface;
    if (superTblInfo)
        iface = superTblInfo->iface;
    else
        iface = g_args.iface;

    debugPrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__,
            (g_args.iface==TAOSC_IFACE)?
            "taosc":(g_args.iface==REST_IFACE)?"rest":"stmt");

    switch(iface) {
        case TAOSC_IFACE:
            affectedRows = queryDbExec(
                    pThreadInfo->taos,
                    pThreadInfo->buffer, INSERT_TYPE, false);
            break;

        case REST_IFACE:
            if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
5062
                        pThreadInfo->buffer, pThreadInfo)) {
5063 5064 5065 5066 5067 5068 5069 5070
                affectedRows = -1;
                printf("========restful return fail, threadID[%d]\n",
                        pThreadInfo->threadID);
            } else {
                affectedRows = k;
            }
            break;

5071
#if STMT_IFACE_ENABLED == 1
5072 5073 5074 5075 5076 5077 5078 5079 5080
        case STMT_IFACE:
            debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt);
            if (0 != taos_stmt_execute(pThreadInfo->stmt)) {
                errorPrint("%s() LN%d, failied to execute insert statement\n",
                        __func__, __LINE__);
                exit(-1);
            }
            affectedRows = k;
            break;
5081
#endif
5082 5083 5084 5085 5086

        default:
            errorPrint("%s() LN%d: unknown insert mode: %d\n",
                    __func__, __LINE__, superTblInfo->iface);
            affectedRows = 0;
5087
    }
5088

5089
    return affectedRows;
5090 5091
}

5092 5093
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
5094
{
5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113
    SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
    if (superTblInfo) {
        if (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable) {
            if (superTblInfo->childTblLimit > 0) {
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
                        superTblInfo->childTblName +
                        (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
            } else {
                verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
                        pThreadInfo->threadID, __func__, __LINE__,
                        pThreadInfo->start_table_from,
                        pThreadInfo->ntables, tableSeq);
                snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
                        superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
            }
        } else {
            snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                    superTblInfo->childTblPrefix, tableSeq);
        }
5114
    } else {
5115 5116
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
                g_args.tb_prefix, tableSeq);
5117 5118 5119
    }
}

5120 5121 5122 5123 5124
static int32_t generateDataTailWithoutStb(
        uint32_t batch, char* buffer,
        int64_t remainderBufLen, int64_t insertRows,
        uint64_t recordFrom, int64_t startTime,
        /* int64_t *pSamplePos, */int64_t *dataLen) {
5125

5126
  uint64_t len = 0;
5127 5128
  char *pstr = buffer;

5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162
  verbosePrint("%s() LN%d batch=%d\n", __func__, __LINE__, batch);

  int32_t k = 0;
  for (k = 0; k < batch;) {
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);

    int64_t retLen = 0;

    char **data_type = g_args.datatype;
    int lenOfBinary = g_args.len_of_binary;

    retLen = generateData(data, data_type,
            startTime + getTSRandTail(
                (int64_t) DEFAULT_TIMESTAMP_STEP, k,
                g_args.disorderRatio,
                g_args.disorderRange),
            lenOfBinary);

    if (len > remainderBufLen)
        break;

    pstr += sprintf(pstr, "%s", data);
    k++;
    len += retLen;
    remainderBufLen -= retLen;

    verbosePrint("%s() LN%d len=%"PRIu64" k=%d \nbuffer=%s\n",
            __func__, __LINE__, len, k, buffer);

    recordFrom ++;

    if (recordFrom >= insertRows) {
      break;
5163
    }
5164 5165
  }

5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194
  *dataLen = len;
  return k;
}

static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
        int disorderRatio, int disorderRange)
{
    int64_t randTail = timeStampStep * seq;
    if (disorderRatio > 0) {
        int rand_num = taosRandom() % 100;
        if(rand_num < disorderRatio) {
            randTail = (randTail +
                    (taosRandom() % disorderRange + 1)) * (-1);
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
    }

    return randTail;
}

static int32_t generateStbDataTail(
        SSuperTable* superTblInfo,
        uint32_t batch, char* buffer,
        int64_t remainderBufLen, int64_t insertRows,
        uint64_t recordFrom, int64_t startTime,
        int64_t *pSamplePos, int64_t *dataLen) {
  uint64_t len = 0;

  char *pstr = buffer;
5195

5196
  bool tsRand;
5197 5198 5199 5200
  if (0 == strncasecmp(superTblInfo->dataSource, "rand", strlen("rand"))) {
      tsRand = true;
  } else {
      tsRand = false;
5201
  }
5202 5203
  verbosePrint("%s() LN%d batch=%u buflen=%"PRId64"\n",
          __func__, __LINE__, batch, remainderBufLen);
5204

5205
  int32_t k = 0;
5206
  for (k = 0; k < batch;) {
5207
    char data[MAX_DATA_SIZE];
5208 5209
    memset(data, 0, MAX_DATA_SIZE);

5210
    int64_t lenOfRow = 0;
5211

5212
    if (tsRand) {
5213
        lenOfRow = generateStbRowData(superTblInfo, data,
5214
                startTime + getTSRandTail(
5215 5216 5217 5218 5219
                    superTblInfo->timeStampStep, k,
                    superTblInfo->disorderRatio,
                    superTblInfo->disorderRange)
                );
    } else {
5220
        lenOfRow = getRowDataFromSample(
5221
                  data,
5222
                  (remainderBufLen < MAX_DATA_SIZE)?remainderBufLen:MAX_DATA_SIZE,
5223 5224 5225 5226
                  startTime + superTblInfo->timeStampStep * k,
                  superTblInfo,
                  pSamplePos);
    }
5227

5228
    if ((lenOfRow + 1) > remainderBufLen) {
5229
        break;
5230 5231
    }

5232
    pstr += snprintf(pstr , lenOfRow + 1, "%s", data);
5233
    k++;
5234 5235
    len += lenOfRow;
    remainderBufLen -= lenOfRow;
5236 5237

    verbosePrint("%s() LN%d len=%"PRIu64" k=%u \nbuffer=%s\n",
5238
            __func__, __LINE__, len, k, buffer);
5239

5240
    recordFrom ++;
5241

5242
    if (recordFrom >= insertRows) {
5243
      break;
5244
    }
5245
  }
5246

5247 5248 5249
  *dataLen = len;
  return k;
}
5250

5251 5252 5253

static int generateSQLHeadWithoutStb(char *tableName,
        char *dbName,
5254
        char *buffer, int remainderBufLen)
5255 5256
{
  int len;
5257 5258 5259

  char headBuf[HEAD_BUFF_LEN];

5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284
  len = snprintf(
          headBuf,
          HEAD_BUFF_LEN,
          "%s.%s values",
          dbName,
          tableName);

  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

  return len;
}

static int generateStbSQLHead(
        SSuperTable* superTblInfo,
        char *tableName, int32_t tableSeq,
        char *dbName,
        char *buffer, int remainderBufLen)
{
  int len;

  char headBuf[HEAD_BUFF_LEN];

5285
  if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
5286 5287
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
5288
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
5289 5290 5291 5292 5293 5294
      } else {
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
      }
      if (NULL == tagsValBuf) {
5295 5296
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
            __func__, __LINE__);
5297 5298 5299
        return -1;
      }

5300 5301 5302
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
5303
                  "%s.%s using %s.%s tags %s values",
5304
                  dbName,
5305
                  tableName,
5306
                  dbName,
5307 5308 5309 5310
                  superTblInfo->sTblName,
                  tagsValBuf);
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
5311 5312 5313
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
5314
                  "%s.%s values",
5315
                  dbName,
5316
                  tableName);
5317
    } else {
5318 5319 5320
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
5321
                  "%s.%s values",
5322
                  dbName,
5323 5324 5325
                  tableName);
  }

5326 5327 5328 5329 5330
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

5331 5332 5333
  return len;
}

5334 5335 5336 5337 5338
static int32_t generateStbInterlaceData(
        SSuperTable *superTblInfo,
        char *tableName, uint32_t batchPerTbl,
        uint64_t i,
        uint32_t batchPerTblTimes,
5339
        uint64_t tableSeq,
5340
        threadInfo *pThreadInfo, char *buffer,
5341
        int64_t insertRows,
5342
        int64_t startTime,
5343
        uint64_t *pRemainderBufLen)
5344
{
5345
  assert(buffer);
5346 5347
  char *pstr = buffer;

5348 5349 5350 5351
  int headLen = generateStbSQLHead(
          superTblInfo,
          tableName, tableSeq, pThreadInfo->db_name,
          pstr, *pRemainderBufLen);
5352 5353 5354 5355 5356

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
5357
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
5358 5359 5360 5361 5362
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5363
  int64_t dataLen = 0;
5364

5365
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%u batchPerTbl = %u\n",
5366 5367 5368
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);

5369
  if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5370 5371
      startTime = taosGetTimestamp(pThreadInfo->time_precision);
  }
5372

5373 5374 5375 5376 5377
  int32_t k = generateStbDataTail(
            superTblInfo,
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &(pThreadInfo->samplePos), &dataLen);
5378

5379
  if (k == batchPerTbl) {
5380 5381 5382
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5383
    debugPrint("%s() LN%d, generated data tail: %u, not equal batch per table: %u\n",
5384
            __func__, __LINE__, k, batchPerTbl);
5385 5386
    pstr -= headLen;
    pstr[0] = '\0';
5387
    k = 0;
5388 5389 5390 5391 5392
  }

  return k;
}

5393 5394 5395 5396 5397 5398 5399
static int64_t generateInterlaceDataWithoutStb(
        char *tableName, uint32_t batch,
        uint64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
        int64_t startTime,
        uint64_t *pRemainderBufLen)
5400
{
5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437
  assert(buffer);
  char *pstr = buffer;

  int headLen = generateSQLHeadWithoutStb(
          tableName, dbName,
            pstr, *pRemainderBufLen);

  if (headLen <= 0) {
    return 0;
  }

  pstr += headLen;
  *pRemainderBufLen -= headLen;

  int64_t dataLen = 0;

  int32_t k = generateDataTailWithoutStb(
            batch, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &dataLen);

  if (k == batch) {
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
    debugPrint("%s() LN%d, generated data tail: %d, not equal batch per table: %u\n",
            __func__, __LINE__, k, batch);
    pstr -= headLen;
    pstr[0] = '\0';
    k = 0;
  }

  return k;
}

#if STMT_IFACE_ENABLED == 1
static int32_t prepareStmtBindArrayByType(TAOS_BIND *bind,
5438
        char *dataType, int32_t dataLen, char **ptr, char *value)
5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449
{
    if (0 == strncasecmp(dataType,
                "BINARY", strlen("BINARY"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
            errorPrint( "binary length overflow, max size:%u\n",
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
        }
        char *bind_binary = (char *)*ptr;

        bind->buffer_type = TSDB_DATA_TYPE_BINARY;
5450 5451 5452 5453 5454 5455 5456 5457
        if (value) {
            strncpy(bind_binary, value, strlen(value));
            bind->buffer_length = strlen(bind_binary);
        } else {
            rand_string(bind_binary, dataLen);
            bind->buffer_length = dataLen;
        }

5458
        bind->length = &bind->buffer_length;
5459
        bind->buffer = bind_binary;
5460 5461 5462 5463 5464 5465 5466 5467 5468
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "NCHAR", strlen("NCHAR"))) {
        if (dataLen > TSDB_MAX_BINARY_LEN) {
            errorPrint( "nchar length overflow, max size:%u\n",
                    (uint32_t)TSDB_MAX_BINARY_LEN);
            return -1;
5469
        }
5470 5471 5472
        char *bind_nchar = (char *)*ptr;

        bind->buffer_type = TSDB_DATA_TYPE_NCHAR;
5473 5474 5475 5476 5477 5478
        if (value) {
            strncpy(bind_nchar, value, strlen(value));
        } else {
            rand_string(bind_nchar, dataLen);
        }

5479 5480 5481 5482 5483 5484 5485 5486 5487 5488
        bind->buffer_length = strlen(bind_nchar);
        bind->buffer = bind_nchar;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "INT", strlen("INT"))) {
        int32_t *bind_int = (int32_t *)*ptr;

5489 5490 5491 5492 5493
        if (value) {
            *bind_int = atoi(value);
        } else {
            *bind_int = rand_int();
        }
5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504
        bind->buffer_type = TSDB_DATA_TYPE_INT;
        bind->buffer_length = sizeof(int32_t);
        bind->buffer = bind_int;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    } else if (0 == strncasecmp(dataType,
                "BIGINT", strlen("BIGINT"))) {
        int64_t *bind_bigint = (int64_t *)*ptr;

5505 5506 5507 5508 5509
        if (value) {
            *bind_bigint = atoll(value);
        } else {
            *bind_bigint = rand_bigint();
        }
5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520
        bind->buffer_type = TSDB_DATA_TYPE_BIGINT;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_bigint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "FLOAT", strlen("FLOAT"))) {
        float   *bind_float = (float *) *ptr;

5521 5522 5523 5524 5525
        if (value) {
            *bind_float = (float)atof(value);
        } else {
            *bind_float = rand_float();
        }
5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536
        bind->buffer_type = TSDB_DATA_TYPE_FLOAT;
        bind->buffer_length = sizeof(float);
        bind->buffer = bind_float;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "DOUBLE", strlen("DOUBLE"))) {
        double  *bind_double = (double *)*ptr;

5537 5538 5539 5540 5541
        if (value) {
            *bind_double = atof(value);
        } else {
            *bind_double = rand_double();
        }
5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552
        bind->buffer_type = TSDB_DATA_TYPE_DOUBLE;
        bind->buffer_length = sizeof(double);
        bind->buffer = bind_double;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "SMALLINT", strlen("SMALLINT"))) {
        int16_t *bind_smallint = (int16_t *)*ptr;

5553 5554 5555 5556 5557
        if (value) {
            *bind_smallint = (int16_t)atoi(value);
        } else {
            *bind_smallint = rand_smallint();
        }
5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568
        bind->buffer_type = TSDB_DATA_TYPE_SMALLINT;
        bind->buffer_length = sizeof(int16_t);
        bind->buffer = bind_smallint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TINYINT", strlen("TINYINT"))) {
        int8_t  *bind_tinyint = (int8_t *)*ptr;

5569 5570 5571 5572 5573
        if (value) {
            *bind_tinyint = (int8_t)atoi(value);
        } else {
            *bind_tinyint = rand_tinyint();
        }
5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595
        bind->buffer_type = TSDB_DATA_TYPE_TINYINT;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_tinyint;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;
        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "BOOL", strlen("BOOL"))) {
        int8_t  *bind_bool = (int8_t *)*ptr;

        *bind_bool = rand_bool();
        bind->buffer_type = TSDB_DATA_TYPE_BOOL;
        bind->buffer_length = sizeof(int8_t);
        bind->buffer = bind_bool;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else if (0 == strncasecmp(dataType,
                "TIMESTAMP", strlen("TIMESTAMP"))) {
        int64_t *bind_ts2 = (int64_t *) *ptr;

5596 5597 5598 5599 5600
        if (value) {
            *bind_ts2 = atoll(value);
        } else {
            *bind_ts2 = rand_bigint();
        }
5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts2;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        *ptr += bind->buffer_length;
    }  else {
        errorPrint( "No support data type: %s\n",
                dataType);
        return -1;
5612 5613
    }

5614
    return 0;
5615 5616
}

5617 5618
static int32_t prepareStmtWithoutStb(
        TAOS_STMT *stmt,
5619
        char *tableName,
5620
        uint32_t batch,
5621
        int64_t insertRows,
5622 5623
        int64_t recordFrom,
        int64_t startTime)
5624
{
5625 5626 5627 5628 5629 5630
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
        errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
                tableName, ret, taos_errstr(NULL));
        return ret;
    }
5631

5632
    char **data_type = g_args.datatype;
5633

5634 5635 5636 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665
    char *bindArray = malloc(sizeof(TAOS_BIND) * (g_args.num_of_CPR + 1));
    if (bindArray == NULL) {
        errorPrint("Failed to allocate %d bind params\n",
                (g_args.num_of_CPR + 1));
        return -1;
    }

    int32_t k = 0;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */
        char data[MAX_DATA_SIZE];
        memset(data, 0, MAX_DATA_SIZE);

        char *ptr = data;
        TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0);

        int64_t *bind_ts;

        bind_ts = (int64_t *)ptr;
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
        *bind_ts = startTime + getTSRandTail(
                (int64_t)DEFAULT_TIMESTAMP_STEP, k,
                g_args.disorderRatio,
                g_args.disorderRange);
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        ptr += bind->buffer_length;

        for (int i = 0; i < g_args.num_of_CPR; i ++) {
5666 5667
            bind = (TAOS_BIND *)((char *)bindArray
                    + (sizeof(TAOS_BIND) * (i + 1)));
5668 5669 5670 5671
            if ( -1 == prepareStmtBindArrayByType(
                        bind,
                        data_type[i],
                        g_args.len_of_binary,
5672
                        &ptr, NULL)) {
5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686
                return -1;
            }
        }
        taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        // if msg > 3MB, break
        taos_stmt_add_batch(stmt);

        k++;
        recordFrom ++;
        if (recordFrom >= insertRows) {
            break;
        }
    }

5687
    free(bindArray);
5688 5689 5690
    return k;
}

5691 5692
static int32_t prepareStbStmt(
        SSuperTable *stbInfo,
5693 5694 5695 5696
        TAOS_STMT *stmt,
        char *tableName, uint32_t batch,
        uint64_t insertRows,
        uint64_t recordFrom,
5697 5698
        int64_t startTime,
        int64_t *pSamplePos)
5699 5700 5701 5702 5703 5704 5705 5706 5707 5708
{
    int ret = taos_stmt_set_tbname(stmt, tableName);
    if (ret != 0) {
        errorPrint("failed to execute taos_stmt_set_tbname(%s). return 0x%x. reason: %s\n",
                tableName, ret, taos_errstr(NULL));
        return ret;
    }

    char *bindArray = malloc(sizeof(TAOS_BIND) * (stbInfo->columnCount + 1));
    if (bindArray == NULL) {
5709 5710
        errorPrint("%s() LN%d, Failed to allocate %d bind params\n",
                __func__, __LINE__, (stbInfo->columnCount + 1));
5711
        return -1;
5712 5713
    }

5714
    bool sourceRand;
5715
    if (0 == strncasecmp(stbInfo->dataSource, "rand", strlen("rand"))) {
5716
        sourceRand = true;
5717
    } else {
5718 5719 5720 5721 5722 5723 5724 5725 5726
        sourceRand = false;     // from sample data file
    }

    char *bindBuffer = malloc(g_args.len_of_binary);
    if (bindBuffer == NULL) {
        errorPrint("%s() LN%d, Failed to allocate %d bind buffer\n",
                __func__, __LINE__, g_args.len_of_binary);
        free(bindArray);
        return -1;
5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741
    }

    uint32_t k;
    for (k = 0; k < batch;) {
        /* columnCount + 1 (ts) */
        char data[MAX_DATA_SIZE];
        memset(data, 0, MAX_DATA_SIZE);

        char *ptr = data;
        TAOS_BIND *bind = (TAOS_BIND *)(bindArray + 0);

        int64_t *bind_ts;

        bind_ts = (int64_t *)ptr;
        bind->buffer_type = TSDB_DATA_TYPE_TIMESTAMP;
5742
        if (sourceRand) {
5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756
            *bind_ts = startTime + getTSRandTail(
                    stbInfo->timeStampStep, k,
                    stbInfo->disorderRatio,
                    stbInfo->disorderRange);
        } else {
            *bind_ts = startTime + stbInfo->timeStampStep * k;
        }
        bind->buffer_length = sizeof(int64_t);
        bind->buffer = bind_ts;
        bind->length = &bind->buffer_length;
        bind->is_null = NULL;

        ptr += bind->buffer_length;

5757
        int cursor = 0;
5758 5759
        for (int i = 0; i < stbInfo->columnCount; i ++) {
            bind = (TAOS_BIND *)((char *)bindArray + (sizeof(TAOS_BIND) * (i + 1)));
5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796

            if (sourceRand) {
                if ( -1 == prepareStmtBindArrayByType(
                            bind,
                            stbInfo->columns[i].dataType,
                            stbInfo->columns[i].dataLen,
                            &ptr,
                            NULL)) {
                    free(bindArray);
                    free(bindBuffer);
                    return -1;
                }
            } else {
                char *restStr = stbInfo->sampleDataBuf + cursor;
                int lengthOfRest = strlen(restStr);

                int index = 0;
                for (index = 0; index < lengthOfRest; index ++) {
                    if (restStr[index] == ',') {
                        break;
                    }
                }

                memset(bindBuffer, 0, g_args.len_of_binary);
                strncpy(bindBuffer, restStr, index);
                cursor += index + 1; // skip ',' too

                if ( -1 == prepareStmtBindArrayByType(
                            bind,
                            stbInfo->columns[i].dataType,
                            stbInfo->columns[i].dataLen,
                            &ptr,
                            bindBuffer)) {
                    free(bindArray);
                    free(bindBuffer);
                    return -1;
                }
5797 5798 5799 5800 5801 5802 5803 5804
            }
        }
        taos_stmt_bind_param(stmt, (TAOS_BIND *)bindArray);
        // if msg > 3MB, break
        taos_stmt_add_batch(stmt);

        k++;
        recordFrom ++;
5805 5806 5807 5808

        if (!sourceRand) {
            (*pSamplePos) ++;
        }
5809 5810 5811 5812 5813
        if (recordFrom >= insertRows) {
            break;
        }
    }

5814
    free(bindBuffer);
5815
    free(bindArray);
5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828
    return k;
}
#endif

static int32_t generateStbProgressiveData(
        SSuperTable *superTblInfo,
        char *tableName,
        int64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
        uint64_t recordFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
{
5829
  assert(buffer != NULL);
5830
  char *pstr = buffer;
5831

5832
  memset(buffer, 0, *pRemainderBufLen);
5833

5834 5835 5836
  int64_t headLen = generateStbSQLHead(
              superTblInfo,
          tableName, tableSeq, dbName,
5837
          buffer, *pRemainderBufLen);
5838 5839 5840 5841

  if (headLen <= 0) {
    return 0;
  }
5842
  pstr += headLen;
5843
  *pRemainderBufLen -= headLen;
5844

5845
  int64_t dataLen;
5846 5847 5848 5849

  return generateStbDataTail(superTblInfo,
          g_args.num_of_RPR, pstr, *pRemainderBufLen,
          insertRows, recordFrom,
5850
          startTime,
5851
          pSamplePos, &dataLen);
5852
}
5853

5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882
static int32_t generateProgressiveDataWithoutStb(
        char *tableName,
        /* int64_t tableSeq, */
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
        uint64_t recordFrom, int64_t startTime, /*int64_t *pSamplePos, */
        int64_t *pRemainderBufLen)
{
  assert(buffer != NULL);
  char *pstr = buffer;

  memset(buffer, 0, *pRemainderBufLen);

  int64_t headLen = generateSQLHeadWithoutStb(
          tableName, pThreadInfo->db_name,
          buffer, *pRemainderBufLen);

  if (headLen <= 0) {
    return 0;
  }
  pstr += headLen;
  *pRemainderBufLen -= headLen;

  int64_t dataLen;

  return generateDataTailWithoutStb(
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, recordFrom,
          startTime,
          /*pSamplePos, */&dataLen);
5883
}
5884

5885 5886
static void printStatPerThread(threadInfo *pThreadInfo)
{
5887
    fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
5888 5889 5890 5891 5892 5893
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
          pThreadInfo->totalAffectedRows,
          (double)(pThreadInfo->totalAffectedRows / (pThreadInfo->totalDelay/1000.0)));
}

5894
// sync write interlace data
5895
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5896 5897
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
5898

5899
  int64_t insertRows;
5900 5901 5902 5903
  uint32_t interlaceRows;
  uint64_t maxSqlLen;
  int64_t nTimeStampStep;
  uint64_t insert_interval;
5904

5905
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5906

5907 5908 5909 5910 5911 5912 5913 5914 5915
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
5916 5917 5918
    maxSqlLen = superTblInfo->maxSqlLen;
    nTimeStampStep = superTblInfo->timeStampStep;
    insert_interval = superTblInfo->insertInterval;
5919 5920 5921
  } else {
    insertRows = g_args.num_of_DPT;
    interlaceRows = g_args.interlace_rows;
5922 5923 5924
    maxSqlLen = g_args.max_sql_len;
    nTimeStampStep = DEFAULT_TIMESTAMP_STEP;
    insert_interval = g_args.insert_interval;
5925
  }
5926

5927 5928 5929 5930 5931
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n",
          pThreadInfo->threadID, __func__, __LINE__,
          pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);

5932
  if (interlaceRows > insertRows)
5933
    interlaceRows = insertRows;
5934

5935 5936
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5937

5938 5939
  uint32_t batchPerTbl = interlaceRows;
  uint32_t batchPerTblTimes;
5940

5941 5942 5943
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
    batchPerTblTimes =
        g_args.num_of_RPR / interlaceRows;
5944
  } else {
5945
    batchPerTblTimes = 1;
5946 5947
  }

5948 5949
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
5950
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5951
              __func__, __LINE__, maxSqlLen, strerror(errno));
5952 5953 5954 5955 5956 5957
    return NULL;
  }

  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;

5958 5959
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5960

5961 5962 5963
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5964

5965
  uint64_t tableSeq = pThreadInfo->start_table_from;
5966 5967
  int64_t startTime = pThreadInfo->start_time;

5968
  uint64_t generatedRecPerTbl = 0;
5969
  bool flagSleep = true;
5970
  uint64_t sleepTimeTotal = 0;
5971

5972
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5973
    if ((flagSleep) && (insert_interval)) {
5974
        st = taosGetTimestampMs();
5975
        flagSleep = false;
5976 5977
    }
    // generate data
5978
    memset(pThreadInfo->buffer, 0, maxSqlLen);
5979
    uint64_t remainderBufLen = maxSqlLen;
5980

5981
    char *pstr = pThreadInfo->buffer;
5982

5983 5984
    int len = snprintf(pstr,
            strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
5985 5986 5987
    pstr += len;
    remainderBufLen -= len;

5988 5989 5990 5991
    uint32_t recOfBatch = 0;

    for (uint32_t i = 0; i < batchPerTblTimes; i ++) {
        char tableName[TSDB_TABLE_NAME_LEN];
5992

5993
      getTableName(tableName, pThreadInfo, tableSeq);
5994 5995 5996
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
5997
        free(pThreadInfo->buffer);
5998 5999
        return NULL;
      }
6000

6001
      uint64_t oldRemainderLen = remainderBufLen;
6002 6003 6004 6005 6006

      int32_t generated;
      if (superTblInfo) {
          if (superTblInfo->iface == STMT_IFACE) {
#if STMT_IFACE_ENABLED == 1
6007 6008
              generated = prepareStbStmt(
                      superTblInfo,
6009 6010 6011 6012 6013
                      pThreadInfo->stmt,
                      tableName,
                      batchPerTbl,
                      insertRows, i,
                      startTime,
6014
                      &(pThreadInfo->samplePos));
6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055
#else
              generated = -1;
#endif
          } else {
              generated = generateStbInterlaceData(
                      superTblInfo,
                      tableName, batchPerTbl, i,
                      batchPerTblTimes,
                      tableSeq,
                      pThreadInfo, pstr,
                      insertRows,
                      startTime,
                      &remainderBufLen);
          }
      } else {
          if (g_args.iface == STMT_IFACE) {
              debugPrint("[%d] %s() LN%d, tableName:%s, batch:%d startTime:%"PRId64"\n",
                      pThreadInfo->threadID,
                      __func__, __LINE__,
                      tableName, batchPerTbl, startTime);
#if STMT_IFACE_ENABLED == 1
              generated = prepareStmtWithoutStb(
                      pThreadInfo->stmt, tableName,
                      batchPerTbl,
                      insertRows, i,
                      startTime);
#else
              generated = -1;
#endif
          } else {
              generated = generateInterlaceDataWithoutStb(
                      tableName, batchPerTbl,
                      tableSeq,
                      pThreadInfo->db_name, pstr,
                      insertRows,
                      startTime,
                      &remainderBufLen);
          }
      }

      debugPrint("[%d] %s() LN%d, generated records is %d\n",
6056
                  pThreadInfo->threadID, __func__, __LINE__, generated);
6057
      if (generated < 0) {
6058
        errorPrint("[%d] %s() LN%d, generated records is %d\n",
6059
                  pThreadInfo->threadID, __func__, __LINE__, generated);
6060
        goto free_of_interlace;
6061 6062
      } else if (generated == 0) {
        break;
6063 6064
      }

6065
      tableSeq ++;
6066
      recOfBatch += batchPerTbl;
6067

6068
      pstr += (oldRemainderLen - remainderBufLen);
6069
      pThreadInfo->totalInsertRows += batchPerTbl;
6070 6071

      verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
6072 6073
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
6074

6075
      if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
6076 6077
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
6078
            generatedRecPerTbl += batchPerTbl;
6079 6080

            startTime = pThreadInfo->start_time
6081
              + generatedRecPerTbl * nTimeStampStep;
6082

6083 6084 6085 6086
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

6087
            int64_t remainRows = insertRows - generatedRecPerTbl;
6088 6089 6090
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;

6091 6092
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
6093 6094
      }

6095
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
6096 6097 6098 6099
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
6100 6101 6102
        break;
    }

6103
    verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRIu64"\n",
6104 6105 6106
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
6107
           pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer);
6108

6109
    startTs = taosGetTimestampMs();
6110

6111
    if (recOfBatch == 0) {
6112 6113 6114
        errorPrint("[%d] %s() LN%d Failed to insert records of batch %d\n",
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl);
6115 6116 6117 6118
        if (batchPerTbl > 0) {
          errorPrint("\tIf the batch is %d, the length of the SQL to insert a row must be less then %"PRId64"\n",
              batchPerTbl, maxSqlLen / batchPerTbl);
        }
6119 6120 6121
        errorPrint("\tPlease check if the buffer length(%"PRId64") or batch(%d) is set with proper value!\n",
                maxSqlLen, batchPerTbl);
        goto free_of_interlace;
6122
    }
6123
    int64_t affectedRows = execInsert(pThreadInfo, recOfBatch);
6124

6125
    endTs = taosGetTimestampMs();
6126 6127
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
6128
            __func__, __LINE__, delay);
6129 6130 6131
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
6132 6133 6134 6135 6136 6137

    if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
    if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
    pThreadInfo->cntDelay++;
    pThreadInfo->totalDelay += delay;

6138
    if (recOfBatch != affectedRows) {
6139
        errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %"PRId64"\n%s\n",
6140
                pThreadInfo->threadID, __func__, __LINE__,
6141
                recOfBatch, affectedRows, pThreadInfo->buffer);
6142
        goto free_of_interlace;
6143
    }
6144

6145
    pThreadInfo->totalAffectedRows += affectedRows;
6146

6147 6148
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
6149
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
6150 6151 6152
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
6153 6154
      lastPrintTime = currentPrintTime;
    }
6155

6156
    if ((insert_interval) && flagSleep) {
6157
      et = taosGetTimestampMs();
6158

6159
      if (insert_interval > (et - st) ) {
6160 6161
        uint64_t sleepTime = insert_interval - (et -st);
        performancePrint("%s() LN%d sleep: %"PRId64" ms for insert interval\n",
6162
                    __func__, __LINE__, sleepTime);
6163 6164 6165
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
6166
    }
6167 6168
  }

6169
free_of_interlace:
6170
  tmfree(pThreadInfo->buffer);
6171
  printStatPerThread(pThreadInfo);
6172 6173 6174
  return NULL;
}

6175
// sync insertion progressive data
6176
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
6177
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
6178

6179
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6180
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
6181 6182 6183 6184 6185 6186
  int64_t timeStampStep =
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
  int64_t insertRows =
        (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
  verbosePrint("%s() LN%d insertRows=%"PRId64"\n",
            __func__, __LINE__, insertRows);
6187

6188 6189
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
6190
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
6191
              maxSqlLen,
6192 6193 6194
              strerror(errno));
    return NULL;
  }
6195

6196 6197 6198
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
6199

6200 6201
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
6202

6203
  pThreadInfo->samplePos = 0;
6204

6205 6206 6207
  for (uint64_t tableSeq = pThreadInfo->start_table_from;
          tableSeq <= pThreadInfo->end_table_to;
          tableSeq ++) {
6208
    int64_t start_time = pThreadInfo->start_time;
6209

6210
    for (uint64_t i = 0; i < insertRows;) {
6211 6212
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
6213
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
6214 6215
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
6216 6217 6218 6219 6220 6221
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
        free(pThreadInfo->buffer);
        return NULL;
      }
6222

6223
      int64_t remainderBufLen = maxSqlLen;
6224
      char *pstr = pThreadInfo->buffer;
6225

6226 6227
      int len = snprintf(pstr,
              strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
6228 6229 6230 6231

      pstr += len;
      remainderBufLen -= len;

6232 6233 6234 6235 6236 6237 6238 6239 6240
      int32_t generated;
      if (superTblInfo) {
          if (superTblInfo->iface == STMT_IFACE) {
#if STMT_IFACE_ENABLED == 1
              generated = prepareStbStmt(
                      superTblInfo,
                      pThreadInfo->stmt,
                      tableName,
                      g_args.num_of_RPR,
6241 6242
                      insertRows, i, start_time,
                      &(pThreadInfo->samplePos));
6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275
#else
              generated = -1;
#endif
          } else {
              generated = generateStbProgressiveData(
                      superTblInfo,
                      tableName, tableSeq, pThreadInfo->db_name, pstr,
                      insertRows, i, start_time,
                      &(pThreadInfo->samplePos),
                      &remainderBufLen);
          }
      } else {
          if (g_args.iface == STMT_IFACE) {
#if STMT_IFACE_ENABLED == 1
              generated = prepareStmtWithoutStb(
                      pThreadInfo->stmt,
                      tableName,
                      g_args.num_of_RPR,
                      insertRows, i,
                      start_time);
#else
              generated = -1;
#endif
          } else {
              generated = generateProgressiveDataWithoutStb(
                      tableName,
                      /*  tableSeq, */
                      pThreadInfo, pstr, insertRows,
                      i, start_time,
                      /* &(pThreadInfo->samplePos), */
                      &remainderBufLen);
          }
      }
6276 6277 6278
      if (generated > 0)
        i += generated;
      else
6279
        goto free_of_progressive;
6280

6281
      start_time +=  generated * timeStampStep;
6282
      pThreadInfo->totalInsertRows += generated;
6283

6284
      startTs = taosGetTimestampMs();
6285

6286
      int32_t affectedRows = execInsert(pThreadInfo, generated);
6287

6288
      endTs = taosGetTimestampMs();
6289
      uint64_t delay = endTs - startTs;
6290 6291
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
              __func__, __LINE__, delay);
6292
      verbosePrint("[%d] %s() LN%d affectedRows=%d\n",
6293 6294
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
6295

6296 6297 6298 6299
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
6300

6301
      if (affectedRows < 0) {
6302
        errorPrint("%s() LN%d, affected rows: %d\n",
6303 6304 6305
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
6306 6307 6308

      pThreadInfo->totalAffectedRows += affectedRows;

6309 6310
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
6311
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
6312 6313 6314
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
6315 6316 6317
        lastPrintTime = currentPrintTime;
      }

6318
      if (i >= insertRows)
6319 6320 6321
        break;
    }   // num_of_DPT

6322 6323
    if ((g_args.verbose_print) &&
      (tableSeq == pThreadInfo->ntables - 1) && (superTblInfo) &&
6324 6325
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
6326
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
6327
                  __func__, __LINE__, pThreadInfo->samplePos);
6328
    }
6329
  } // tableSeq
6330

6331
free_of_progressive:
6332
  tmfree(pThreadInfo->buffer);
6333
  printStatPerThread(pThreadInfo);
6334
  return NULL;
H
Hui Li 已提交
6335 6336
}

6337 6338
static void* syncWrite(void *sarg) {

6339 6340
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6341

6342
  uint32_t interlaceRows;
6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353

  if (superTblInfo) {
    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
  } else {
    interlaceRows = g_args.interlace_rows;
  }
6354

6355
  if (interlaceRows > 0) {
6356
    // interlace mode
6357
    return syncWriteInterlace(pThreadInfo);
6358 6359
  } else {
    // progressive mode
6360
    return syncWriteProgressive(pThreadInfo);
6361 6362 6363
  }
}

6364
static void callBack(void *param, TAOS_RES *res, int code) {
6365 6366
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6367

6368 6369
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
6370
  if (insert_interval) {
6371 6372 6373
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
6374
    }
H
Hui Li 已提交
6375
  }
6376

6377
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
6378
  char data[MAX_DATA_SIZE];
6379
  char *pstr = buffer;
6380 6381
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
6382 6383 6384 6385 6386 6387 6388 6389
          pThreadInfo->start_table_from);
//  if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
  if (pThreadInfo->counter >= g_args.num_of_RPR) {
    pThreadInfo->start_table_from++;
    pThreadInfo->counter = 0;
  }
  if (pThreadInfo->start_table_from > pThreadInfo->end_table_to) {
    tsem_post(&pThreadInfo->lock_sem);
6390 6391 6392 6393
    free(buffer);
    taos_free_result(res);
    return;
  }
6394

6395
  for (int i = 0; i < g_args.num_of_RPR; i++) {
6396
    int rand_num = taosRandom() % 100;
6397 6398
    if (0 != pThreadInfo->superTblInfo->disorderRatio
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
6399 6400
      int64_t d = pThreadInfo->lastTs
          - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
6401
      generateStbRowData(pThreadInfo->superTblInfo, data, d);
6402
    } else {
6403 6404
      generateStbRowData(pThreadInfo->superTblInfo,
              data, pThreadInfo->lastTs += 1000);
H
Hui Li 已提交
6405
    }
6406
    pstr += sprintf(pstr, "%s", data);
6407
    pThreadInfo->counter++;
H
Hui Li 已提交
6408

6409
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
6410
      break;
H
Hui Li 已提交
6411 6412
    }
  }
6413

6414
  if (insert_interval) {
6415
    pThreadInfo->st = taosGetTimestampMs();
6416
  }
6417
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
6418
  free(buffer);
H
Hui Li 已提交
6419

6420
  taos_free_result(res);
H
Hui Li 已提交
6421 6422
}

6423
static void *asyncWrite(void *sarg) {
6424 6425
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
6426

6427 6428 6429
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
6430

6431
  int insert_interval =
6432
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
6433
  if (insert_interval) {
6434
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
6435
  }
6436
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
6437

6438
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
6439 6440 6441 6442

  return NULL;
}

6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468
static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in *serv_addr)
{
  uint16_t rest_port = port + TSDB_PORT_HTTP;
  struct hostent *server = gethostbyname(host);
  if ((server == NULL) || (server->h_addr == NULL)) {
    errorPrint("%s", "ERROR, no such host");
    return -1;
  }

  debugPrint("h_name: %s\nh_addr=%p\nh_addretype: %s\nh_length: %d\n",
            server->h_name,
            server->h_addr,
            (server->h_addrtype == AF_INET)?"ipv4":"ipv6",
            server->h_length);

  memset(serv_addr, 0, sizeof(struct sockaddr_in));
  serv_addr->sin_family = AF_INET;
  serv_addr->sin_port = htons(rest_port);
#ifdef WINDOWS
  serv_addr->sin_addr.s_addr = inet_addr(host);
#else
  memcpy(&(serv_addr->sin_addr.s_addr), server->h_addr, server->h_length);
#endif
  return 0;
}

6469 6470
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
6471

6472 6473 6474 6475 6476 6477 6478
  int32_t timePrec = TSDB_TIME_PRECISION_MILLI;
  if (0 != precision[0]) {
    if (0 == strncasecmp(precision, "ms", 2)) {
      timePrec = TSDB_TIME_PRECISION_MILLI;
    }  else if (0 == strncasecmp(precision, "us", 2)) {
      timePrec = TSDB_TIME_PRECISION_MICRO;
    }  else {
6479
      errorPrint("Not support precision: %s\n", precision);
6480 6481 6482 6483
      exit(-1);
    }
  }

6484
  int64_t start_time;
6485 6486 6487
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
6488
    } else {
6489 6490 6491 6492 6493
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
6494
          ERROR_EXIT("failed to parse time!\n");
6495
      }
6496
    }
6497 6498
  } else {
     start_time = 1500000000000;
6499 6500
  }

6501
  int64_t start = taosGetTimestampMs();
6502

6503
  // read sample data from file first
6504
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
6505
              "sample", strlen("sample")))) {
6506
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
6507 6508
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
6509 6510 6511 6512
      exit(-1);
    }
  }

6513
  TAOS* taos0 = taos_connect(
6514 6515
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
6516
  if (NULL == taos0) {
6517 6518
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
                __func__, __LINE__, taos_errstr(NULL));
6519 6520 6521
    exit(-1);
  }

6522
  int64_t ntables = 0;
6523
  uint64_t tableFrom;
6524

6525
  if (superTblInfo) {
6526 6527
    int64_t limit;
    uint64_t offset;
6528

6529
    if ((NULL != g_args.sqlFile) && (superTblInfo->childTblExists == TBL_NO_EXISTS) &&
6530
            ((superTblInfo->childTblOffset != 0) || (superTblInfo->childTblLimit >= 0))) {
6531
      printf("WARNING: offset and limit will not be used since the child tables not exists!\n");
6532 6533
    }

6534
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
6535 6536
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
6537
            > (superTblInfo->childTblCount))) {
6538 6539 6540 6541 6542 6543
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
6544
    } else {
6545 6546
      limit = superTblInfo->childTblCount;
      offset = 0;
6547 6548
    }

6549
    ntables = limit;
6550
    tableFrom = offset;
6551

6552 6553 6554 6555
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
6556
      prompt();
6557 6558 6559 6560 6561
    }

    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
            && (0 == superTblInfo->childTblLimit)) {
      printf("WARNING: specified limit = 0, which cannot find table name to insert or query! \n");
6562
      prompt();
6563 6564
    }

6565 6566 6567
    superTblInfo->childTblName = (char*)calloc(1,
        limit * TSDB_TABLE_NAME_LEN);
    if (superTblInfo->childTblName == NULL) {
6568
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
6569
      taos_close(taos0);
6570 6571 6572
      exit(-1);
    }

6573
    int64_t childTblCount;
6574
    getChildNameOfSuperTableWithLimitAndOffset(
6575
        taos0,
6576 6577 6578 6579
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
6580 6581
  } else {
    ntables = g_args.num_of_tables;
6582
    tableFrom = 0;
6583
  }
6584

6585
  taos_close(taos0);
6586

6587
  int64_t a = ntables / threads;
6588 6589 6590 6591 6592
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

6593
  int64_t b = 0;
6594 6595 6596 6597
  if (threads != 0) {
    b = ntables % threads;
  }

6598
  if ((superTblInfo)
6599 6600 6601 6602 6603
      && (superTblInfo->iface == REST_IFACE)) {
      if (convertHostToServAddr(
                  g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0) {
        exit(-1);
      }
6604 6605
  }

6606
  pthread_t *pids = calloc(1, threads * sizeof(pthread_t));
6607 6608 6609 6610 6611 6612 6613 6614
  assert(pids != NULL);

  threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
  assert(infos != NULL);

  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));

H
Hui Li 已提交
6615
  for (int i = 0; i < threads; i++) {
6616 6617
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
6618
    tstrncpy(pThreadInfo->db_name, db_name, TSDB_DB_NAME_LEN);
6619 6620
    pThreadInfo->time_precision = timePrec;
    pThreadInfo->superTblInfo = superTblInfo;
6621

6622 6623
    pThreadInfo->start_time = start_time;
    pThreadInfo->minDelay = UINT64_MAX;
6624

6625
    if ((NULL == superTblInfo) ||
6626 6627
            (superTblInfo->iface != REST_IFACE)) {
      //t_info->taos = taos;
6628
      pThreadInfo->taos = taos_connect(
6629
              g_Dbs.host, g_Dbs.user,
6630
              g_Dbs.password, db_name, g_Dbs.port);
6631
      if (NULL == pThreadInfo->taos) {
6632
        errorPrint(
6633 6634
                "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n",
                __func__, __LINE__,
6635
                taos_errstr(NULL));
6636
        free(infos);
6637 6638
        exit(-1);
      }
6639

6640
#if STMT_IFACE_ENABLED == 1
6641 6642 6643 6644 6645 6646 6647 6648 6649 6650 6651 6652 6653 6654 6655 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679
      if ((g_args.iface == STMT_IFACE)
          || ((superTblInfo) && (superTblInfo->iface == STMT_IFACE))) {

          int columnCount;
          if (superTblInfo) {
              columnCount = superTblInfo->columnCount;
          } else {
              columnCount = g_args.num_of_CPR;
          }

        pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos);
        if (NULL == pThreadInfo->stmt) {
            errorPrint(
                "%s() LN%d, failed init stmt, reason: %s\n",
                __func__, __LINE__,
                taos_errstr(NULL));
            free(pids);
            free(infos);
            exit(-1);
        }

        char buffer[3000];
        char *pstr = buffer;
        pstr += sprintf(pstr, "INSERT INTO ? values(?");

        for (int col = 0; col < columnCount; col ++) {
            pstr += sprintf(pstr, ",?");
        }
        pstr += sprintf(pstr, ")");

        int ret = taos_stmt_prepare(pThreadInfo->stmt, buffer, 0);
        if (ret != 0){
            errorPrint("failed to execute taos_stmt_prepare. return 0x%x. reason: %s\n",
                    ret, taos_errstr(NULL));
            free(pids);
            free(infos);
            exit(-1);
        }
      }
6680
#endif
6681
    } else {
6682
      pThreadInfo->taos = NULL;
6683 6684
    }

6685
/*    if ((NULL == superTblInfo)
6686
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
6687
            */
6688
      pThreadInfo->start_table_from = tableFrom;
6689
      pThreadInfo->ntables = i<b?a+1:a;
6690 6691
      pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
      tableFrom = pThreadInfo->end_table_to + 1;
6692
/*    } else {
6693 6694 6695
      pThreadInfo->start_table_from = 0;
      pThreadInfo->ntables = superTblInfo->childTblCount;
      pThreadInfo->start_time = pThreadInfo->start_time + rand_int() % 10000 - rand_tinyint();
6696
    }
6697
*/
6698
    tsem_init(&(pThreadInfo->lock_sem), 0, 0);
6699
    if (ASYNC_MODE == g_Dbs.asyncMode) {
6700
      pthread_create(pids + i, NULL, asyncWrite, pThreadInfo);
6701
    } else {
6702
      pthread_create(pids + i, NULL, syncWrite, pThreadInfo);
6703
    }
H
Hui Li 已提交
6704
  }
6705

H
Hui Li 已提交
6706 6707 6708 6709
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

6710 6711 6712 6713
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
6714 6715
  double  avgDelay = 0;

H
Hui Li 已提交
6716
  for (int i = 0; i < threads; i++) {
6717
    threadInfo *pThreadInfo = infos + i;
6718

6719 6720
    tsem_destroy(&(pThreadInfo->lock_sem));

6721
#if STMT_IFACE_ENABLED == 1
6722 6723 6724
    if (pThreadInfo->stmt) {
      taos_stmt_close(pThreadInfo->stmt);
    }
6725
#endif
6726 6727
    tsem_destroy(&(pThreadInfo->lock_sem));
    taos_close(pThreadInfo->taos);
6728

6729
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
6730
            __func__, __LINE__,
6731 6732
            pThreadInfo->threadID, pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows);
6733
    if (superTblInfo) {
6734 6735
        superTblInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
        superTblInfo->totalInsertRows += pThreadInfo->totalInsertRows;
6736
    } else {
6737 6738
        g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
        g_args.totalInsertRows += pThreadInfo->totalInsertRows;
6739
    }
6740

6741 6742 6743 6744
    totalDelay  += pThreadInfo->totalDelay;
    cntDelay   += pThreadInfo->cntDelay;
    if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
    if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
H
Hui Li 已提交
6745
  }
6746
  cntDelay -= 1;
H
Hui Li 已提交
6747

6748
  if (cntDelay == 0)    cntDelay = 1;
6749 6750
  avgDelay = (double)totalDelay / cntDelay;

6751 6752
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
6753 6754

  if (superTblInfo) {
6755
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
6756
          t / 1000.0, superTblInfo->totalInsertRows,
6757 6758
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
6759
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6760 6761 6762 6763

    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
          "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
6764
          t / 1000.0, superTblInfo->totalInsertRows,
6765 6766
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
6767
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6768
    }
6769
  } else {
6770
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
6771
          t / 1000.0, g_args.totalInsertRows,
6772 6773
          g_args.totalAffectedRows,
          threads, db_name,
6774
          (double)g_args.totalInsertRows / (t / 1000.0));
6775 6776 6777
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
          "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
6778
          t * 1000.0, g_args.totalInsertRows,
6779 6780
          g_args.totalAffectedRows,
          threads, db_name,
6781
          (double)g_args.totalInsertRows / (t / 1000.0));
6782
    }
6783
  }
6784

6785
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6786
          avgDelay, maxDelay, minDelay);
6787 6788
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6789
          avgDelay, maxDelay, minDelay);
6790
  }
6791

6792 6793
  //taos_close(taos);

H
Hui Li 已提交
6794
  free(pids);
6795
  free(infos);
H
Hui Li 已提交
6796 6797
}

6798
static void *readTable(void *sarg) {
6799
#if 1
6800 6801
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6802
  char command[BUFFER_SIZE] = "\0";
6803 6804 6805
  uint64_t sTime = pThreadInfo->start_time;
  char *tb_prefix = pThreadInfo->tb_prefix;
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6806
  if (NULL == fp) {
6807
    errorPrint( "fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6808 6809
    return NULL;
  }
6810

6811
  int64_t num_of_DPT;
6812 6813
/*  if (pThreadInfo->superTblInfo) {
    num_of_DPT = pThreadInfo->superTblInfo->insertRows; //  nrecords_per_table;
6814
  } else {
6815
  */
6816
      num_of_DPT = g_args.num_of_DPT;
6817
//  }
6818

6819
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
6820
  int64_t totalData = num_of_DPT * num_of_tables;
6821
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6822 6823 6824 6825 6826

  int n = do_aggreFunc ? (sizeof(aggreFunc) / sizeof(aggreFunc[0])) : 2;
  if (!do_aggreFunc) {
    printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n");
  }
6827
  printf("%"PRId64" records:\n", totalData);
H
hzcheng 已提交
6828 6829
  fprintf(fp, "| QFunctions |    QRecords    |   QSpeed(R/s)   |  QLatency(ms) |\n");

6830
  for (int j = 0; j < n; j++) {
H
hzcheng 已提交
6831
    double totalT = 0;
6832
    uint64_t count = 0;
6833 6834
    for (int64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
6835
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
6836

6837
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
6838 6839
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
6840

S
Shuaiqiang Chang 已提交
6841
      if (code != 0) {
6842
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6843
        taos_free_result(pSql);
H
hzcheng 已提交
6844
        taos_close(taos);
6845
        fclose(fp);
6846
        return NULL;
H
hzcheng 已提交
6847 6848
      }

6849
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6850 6851 6852
        count++;
      }

6853
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6854 6855
      totalT += t;

S
Shuaiqiang Chang 已提交
6856
      taos_free_result(pSql);
H
hzcheng 已提交
6857 6858
    }

6859
    fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
6860
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
6861
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
6862
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
6863 6864 6865
  }
  fprintf(fp, "\n");
  fclose(fp);
6866
#endif
H
hzcheng 已提交
6867 6868 6869
  return NULL;
}

6870
static void *readMetric(void *sarg) {
6871
#if 1
6872 6873
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6874
  char command[BUFFER_SIZE] = "\0";
6875
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6876
  if (NULL == fp) {
6877
    printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6878 6879
    return NULL;
  }
6880

6881 6882
  int64_t num_of_DPT = pThreadInfo->superTblInfo->insertRows;
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
6883
  int64_t totalData = num_of_DPT * num_of_tables;
6884
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6885 6886 6887 6888 6889

  int n = do_aggreFunc ? (sizeof(aggreFunc) / sizeof(aggreFunc[0])) : 2;
  if (!do_aggreFunc) {
    printf("\nThe first field is either Binary or Bool. Aggregation functions are not supported.\n");
  }
6890 6891
  printf("%"PRId64" records:\n", totalData);
  fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
6892 6893

  for (int j = 0; j < n; j++) {
6894
    char condition[COND_BUF_LEN] = "\0";
B
Bomin Zhang 已提交
6895
    char tempS[64] = "\0";
H
hzcheng 已提交
6896

6897
    int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
6898

6899
    for (int64_t i = 1; i <= m; i++) {
H
hzcheng 已提交
6900
      if (i == 1) {
6901
        sprintf(tempS, "t1 = %"PRId64"", i);
H
hzcheng 已提交
6902
      } else {
6903
        sprintf(tempS, " or t1 = %"PRId64" ", i);
H
hzcheng 已提交
6904
      }
6905
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6906

L
liu0x54 已提交
6907
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6908 6909 6910 6911

      printf("Where condition: %s\n", condition);
      fprintf(fp, "%s\n", command);

6912
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6913

S
Shuaiqiang Chang 已提交
6914 6915 6916 6917
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6918
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6919
        taos_free_result(pSql);
H
hzcheng 已提交
6920
        taos_close(taos);
6921
        fclose(fp);
6922
        return NULL;
H
hzcheng 已提交
6923 6924
      }
      int count = 0;
6925
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6926 6927
        count++;
      }
6928
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6929

6930
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6931 6932
              num_of_tables * num_of_DPT / (t * 1000.0), t);
      printf("select %10s took %.6f second(s)\n\n", aggreFunc[j], t * 1000.0);
H
hzcheng 已提交
6933

S
Shuaiqiang Chang 已提交
6934
      taos_free_result(pSql);
H
hzcheng 已提交
6935 6936 6937 6938
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6939
#endif
H
hzcheng 已提交
6940 6941 6942
  return NULL;
}

6943 6944 6945
static void prompt()
{
  if (!g_args.answer_yes) {
6946
    printf("         Press enter key to continue or Ctrl-C to stop\n\n");
6947 6948 6949 6950
    (void)getchar();
  }
}

6951
static int insertTestProcess() {
6952

6953 6954 6955
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6956

6957 6958 6959
  if (ret == -1)
    exit(EXIT_FAILURE);

6960
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6961 6962
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6963
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6964 6965
    return -1;
  }
6966

6967 6968
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6969

6970
  prompt();
6971

6972 6973 6974
  init_rand_data();

  // create database and super tables
6975
  if(createDatabasesAndStables() != 0) {
6976 6977
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6978 6979
    return -1;
  }
6980 6981

  // pretreatement
6982 6983 6984 6985 6986
  if (prepareSampleData() != 0) {
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
    return -1;
  }
6987

6988 6989 6990 6991
  double start;
  double end;

  // create child tables
6992
  start = taosGetTimestampMs();
6993
  createChildTables();
6994
  end = taosGetTimestampMs();
6995

6996
  if (g_totalChildTables > 0) {
6997
    fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6998
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6999 7000
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
7001
            "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
7002
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
7003
    }
7004
  }
7005

7006
  // create sub threads for inserting data
7007
  //start = taosGetTimestampMs();
7008
  for (int i = 0; i < g_Dbs.dbCount; i++) {
7009 7010
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
7011
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
7012 7013 7014 7015 7016 7017 7018 7019 7020 7021

          SSuperTable* superTblInfo = &g_Dbs.db[i].superTbls[j];

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
          }
7022
        }
7023
      }
7024 7025
    } else {
        startMultiThreadInsertData(
7026 7027 7028
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
7029
          NULL);
H
Hui Li 已提交
7030
    }
7031
  }
7032
  //end = taosGetTimestampMs();
7033

7034
  //int64_t    totalInsertRows = 0;
7035
  //int64_t    totalAffectedRows = 0;
7036
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
7037
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
7038
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
7039 7040
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
7041
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
7042
  postFreeResource();
7043

7044 7045 7046
  return 0;
}

7047 7048
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
7049

7050
  if (pThreadInfo->taos == NULL) {
7051 7052 7053 7054 7055 7056 7057 7058
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
7059
            pThreadInfo->threadID, taos_errstr(NULL));
7060 7061
      return NULL;
    } else {
7062
      pThreadInfo->taos = taos;
7063 7064 7065
    }
  }

7066
  char sqlStr[TSDB_DB_NAME_LEN + 5];
7067
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
7068 7069
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
7070 7071 7072 7073
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
7074

7075 7076
  uint64_t st = 0;
  uint64_t et = 0;
7077

7078
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
7079

7080 7081 7082
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
7083

7084
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
7085
    sprintf(pThreadInfo->filePath, "%s-%d",
7086 7087 7088 7089
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }

7090
  while(queryTimes --) {
7091 7092 7093
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
7094 7095
    }

7096 7097 7098
    st = taosGetTimestampMs();

    selectAndGetResult(pThreadInfo,
7099
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
7100

7101 7102 7103 7104
    et = taosGetTimestampMs();
    printf("=thread[%"PRId64"] use %s complete one sql, Spent %10.3f s\n",
              taosGetSelfPthreadId(), g_queryInfo.queryMode, (et - st)/1000.0);

7105 7106
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
7107

7108 7109
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
7110
    if (currentPrintTime - lastPrintTime > 30*1000) {
7111
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
7112
          __func__, __LINE__, endTs, startTs);
7113
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
7114 7115
                    pThreadInfo->threadID,
                    totalQueried,
7116
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
7117
      lastPrintTime = currentPrintTime;
7118
    }
H
Hui Li 已提交
7119
  }
7120 7121
  return NULL;
}
H
Hui Li 已提交
7122

7123
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
7124 7125
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
7126 7127
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
7128
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
7129 7130

  //printf("inSql: %s\n", inSql);
7131

7132 7133
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
7134
    return;
H
Hui Li 已提交
7135
  }
7136

7137
  tstrncpy(outSql, inSql, pos - inSql + 1);
7138
  //printf("1: %s\n", outSql);
7139
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
7140
  //printf("2: %s\n", outSql);
7141
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
7142
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
7143 7144
}

7145
static void *superTableQuery(void *sarg) {
7146
  char sqlstr[MAX_QUERY_SQL_LENGTH];
7147
  threadInfo *pThreadInfo = (threadInfo *)sarg;
7148

7149
  if (pThreadInfo->taos == NULL) {
7150 7151 7152 7153 7154 7155 7156 7157
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
7158
            pThreadInfo->threadID, taos_errstr(NULL));
7159 7160
      return NULL;
    } else {
7161
      pThreadInfo->taos = taos;
7162 7163 7164
    }
  }

7165 7166
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
7167

7168 7169 7170
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
7171

7172
  uint64_t  lastPrintTime = taosGetTimestampMs();
7173
  while(queryTimes --) {
7174 7175 7176
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
7177
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
7178
    }
H
Hui Li 已提交
7179

7180
    st = taosGetTimestampMs();
7181
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
7182
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
7183
        memset(sqlstr,0,sizeof(sqlstr));
7184
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
7185
        if (g_queryInfo.superQueryInfo.result[j][0] != '\0') {
7186
          sprintf(pThreadInfo->filePath, "%s-%d",
7187
                  g_queryInfo.superQueryInfo.result[j],
7188
                  pThreadInfo->threadID);
7189
        }
7190
        selectAndGetResult(pThreadInfo, sqlstr);
7191 7192 7193 7194 7195 7196 7197

        totalQueried++;
        g_queryInfo.superQueryInfo.totalQueried ++;

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
7198
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
7199 7200
                    pThreadInfo->threadID,
                    totalQueried,
7201
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
7202
          lastPrintTime = currentPrintTime;
7203
        }
7204
      }
H
Hui Li 已提交
7205
    }
7206
    et = taosGetTimestampMs();
7207
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
7208
            taosGetSelfPthreadId(),
7209 7210
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
7211
            (double)(et - st)/1000.0);
7212
  }
7213

7214 7215 7216
  return NULL;
}

7217
static int queryTestProcess() {
7218 7219 7220 7221

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
7222 7223 7224 7225 7226 7227

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
7228
          g_queryInfo.port);
7229
  if (taos == NULL) {
7230 7231
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7232 7233 7234
    exit(-1);
  }

7235
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
7236 7237
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
7238 7239 7240
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
7241
  }
7242

7243
  prompt();
7244

7245 7246 7247
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
7248

7249 7250 7251 7252 7253 7254
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

7255 7256 7257
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
7258
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
7259
  uint64_t nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
7260

7261
  uint64_t startTs = taosGetTimestampMs();
7262

7263 7264
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

7265 7266
    pids  = calloc(1, nConcurrent * nSqlCount * sizeof(pthread_t));
    infos = calloc(1, nConcurrent * nSqlCount * sizeof(threadInfo));
7267 7268

    if ((NULL == pids) || (NULL == infos)) {
7269
      taos_close(taos);
7270
      ERROR_EXIT("memory allocation failed for create threads\n");
7271
    }
7272

7273 7274 7275
    for (uint64_t i = 0; i < nSqlCount; i++) {
        for (int j = 0; j < nConcurrent; j++) {
            uint64_t seq = i * nConcurrent + j;
7276 7277 7278
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 7289 7290 7291 7292

            if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) {

                char sqlStr[MAX_TB_NAME_SIZE*2];
                sprintf(sqlStr, "use %s", g_queryInfo.dbName);
                if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
                    taos_close(taos);
                    free(infos);
                    free(pids);
                    errorPrint( "use database %s failed!\n\n",
                        g_queryInfo.dbName);
                    return -1;
                }
            }
7293

7294
            pThreadInfo->taos = NULL;// TODO: workaround to use separate taos connection;
7295

7296
            pthread_create(pids + seq, NULL, specifiedTableQuery,
7297
                pThreadInfo);
7298
        }
7299
    }
7300
  } else {
7301
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
7302
  }
7303

7304 7305
  taos_close(taos);

7306 7307 7308
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
7309 7310
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
7311 7312
    pidsOfSub  = calloc(1, g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t));
    infosOfSub = calloc(1, g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo));
7313 7314

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
7315 7316
      free(infos);
      free(pids);
7317

7318
      ERROR_EXIT("memory allocation failed for create threads\n");
7319
    }
7320

7321
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
7322
    int threads = g_queryInfo.superQueryInfo.threadCnt;
7323

7324
    int64_t a = ntables / threads;
7325 7326 7327 7328
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
7329

7330
    int64_t b = 0;
7331 7332 7333
    if (threads != 0) {
      b = ntables % threads;
    }
7334

7335
    uint64_t tableFrom = 0;
7336
    for (int i = 0; i < threads; i++) {
7337 7338
      threadInfo *pThreadInfo = infosOfSub + i;
      pThreadInfo->threadID = i;
7339

7340
      pThreadInfo->start_table_from = tableFrom;
7341
      pThreadInfo->ntables = i<b?a+1:a;
7342 7343
      pThreadInfo->end_table_to = i < b ? tableFrom + a : tableFrom + a - 1;
      tableFrom = pThreadInfo->end_table_to + 1;
7344 7345
      pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
      pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
7346 7347
    }

7348
    g_queryInfo.superQueryInfo.threadCnt = threads;
7349
  } else {
7350
    g_queryInfo.superQueryInfo.threadCnt = 0;
7351
  }
7352

7353 7354 7355 7356 7357 7358
  if ((nSqlCount > 0) && (nConcurrent > 0)) {
    for (int i = 0; i < nConcurrent; i++) {
      for (int j = 0; j < nSqlCount; j++) {
        pthread_join(pids[i * nSqlCount + j], NULL);
      }
    }
7359
  }
S
Shuaiqiang Chang 已提交
7360

7361
  tmfree((char*)pids);
7362
  tmfree((char*)infos);
7363

7364
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
7365
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
7366
  }
H
Hui Li 已提交
7367

7368
  tmfree((char*)pidsOfSub);
7369
  tmfree((char*)infosOfSub);
7370

7371
//  taos_close(taos);// TODO: workaround to use separate taos connection;
7372
  uint64_t endTs = taosGetTimestampMs();
7373

7374
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
7375 7376
    g_queryInfo.superQueryInfo.totalQueried;

7377
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
7378
          totalQueried,
7379
          (double)(totalQueried/((endTs-startTs)/1000.0)));
7380 7381 7382
  return 0;
}

7383 7384 7385 7386 7387 7388 7389 7390 7391
static void stable_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
  if (res == NULL || taos_errno(res) != 0) {
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
    return;
  }

  if (param)
7392
    fetchResult(res, (threadInfo *)param);
7393 7394 7395 7396 7397
  // tao_unscribe() will free result.
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
7398
  if (res == NULL || taos_errno(res) != 0) {
7399 7400
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
7401 7402
    return;
  }
7403

7404
  if (param)
7405
    fetchResult(res, (threadInfo *)param);
7406
  // tao_unscribe() will free result.
H
hzcheng 已提交
7407 7408
}

7409
static TAOS_SUB* subscribeImpl(
7410
        QUERY_CLASS class,
7411
        threadInfo *pThreadInfo,
7412
        char *sql, char* topic, bool restart, uint64_t interval)
7413
{
7414
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
7415

7416 7417
  if ((SPECIFIED_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode)) {
7418 7419
    tsub = taos_subscribe(
            pThreadInfo->taos,
7420
            restart,
7421
            topic, sql, specified_sub_callback, (void*)pThreadInfo,
7422
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
7423 7424
  } else if ((STABLE_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode)) {
7425 7426 7427 7428 7429
    tsub = taos_subscribe(
            pThreadInfo->taos,
            restart,
            topic, sql, stable_sub_callback, (void*)pThreadInfo,
            g_queryInfo.superQueryInfo.subscribeInterval);
7430
  } else {
7431 7432
    tsub = taos_subscribe(
            pThreadInfo->taos,
7433
            restart,
7434
            topic, sql, NULL, NULL, interval);
7435
  }
7436

7437
  if (tsub == NULL) {
7438 7439
      errorPrint("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
      return NULL;
7440
  }
7441

7442 7443
  return tsub;
}
H
hzcheng 已提交
7444

7445
static void *superSubscribe(void *sarg) {
7446 7447 7448 7449 7450 7451 7452 7453 7454 7455
    threadInfo *pThreadInfo = (threadInfo *)sarg;
    char subSqlstr[MAX_QUERY_SQL_LENGTH];
    TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
    uint64_t tsubSeq;

    if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
        errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
                pThreadInfo->ntables, MAX_QUERY_SQL_COUNT);
        exit(-1);
    }
7456

7457
    if (pThreadInfo->taos == NULL) {
7458 7459 7460 7461 7462 7463 7464 7465 7466 7467
        pThreadInfo->taos = taos_connect(g_queryInfo.host,
                g_queryInfo.user,
                g_queryInfo.password,
                g_queryInfo.dbName,
                g_queryInfo.port);
        if (pThreadInfo->taos == NULL) {
            errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
                    pThreadInfo->threadID, taos_errstr(NULL));
            return NULL;
        }
7468 7469
    }

7470 7471 7472 7473 7474
    char sqlStr[MAX_TB_NAME_SIZE*2];
    sprintf(sqlStr, "use %s", g_queryInfo.dbName);
    if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
        taos_close(pThreadInfo->taos);
        errorPrint( "use database %s failed!\n\n",
7475
                g_queryInfo.dbName);
7476 7477
        return NULL;
    }
7478

7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498
    char topic[32] = {0};
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
        tsubSeq = i - pThreadInfo->start_table_from;
        verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n",
                __func__, __LINE__,
                pThreadInfo->threadID,
                pThreadInfo->start_table_from,
                pThreadInfo->end_table_to, i);
        sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"",
                i, pThreadInfo->querySeq);
        memset(subSqlstr, 0, sizeof(subSqlstr));
        replaceChildTblName(
                g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
                subSqlstr, i);
        if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
            sprintf(pThreadInfo->filePath, "%s-%d",
                    g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                    pThreadInfo->threadID);
        }
7499

7500
        verbosePrint("%s() LN%d, [%d] subSqlstr: %s\n",
7501 7502 7503 7504 7505 7506 7507 7508 7509 7510 7511
                __func__, __LINE__, pThreadInfo->threadID, subSqlstr);
        tsub[tsubSeq] = subscribeImpl(
                STABLE_CLASS,
                pThreadInfo, subSqlstr, topic,
                g_queryInfo.superQueryInfo.subscribeRestart,
                g_queryInfo.superQueryInfo.subscribeInterval);
        if (NULL == tsub[tsubSeq]) {
            taos_close(pThreadInfo->taos);
            return NULL;
        }
    }
7512

7513 7514 7515 7516 7517 7518
    // start loop to consume result
    int consumed[MAX_QUERY_SQL_COUNT];
    for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
        consumed[i] = 0;
    }
    TAOS_RES* res = NULL;
7519

7520
    uint64_t st = 0, et = 0;
7521

7522 7523 7524 7525
    while ((g_queryInfo.superQueryInfo.endAfterConsume == -1)
            || (g_queryInfo.superQueryInfo.endAfterConsume >
                consumed[pThreadInfo->end_table_to
                - pThreadInfo->start_table_from])) {
7526

7527 7528 7529 7530 7531 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 7547 7548 7549 7550 7551 7552 7553 7554 7555 7556 7557 7558 7559 7560 7561 7562 7563 7564 7565 7566 7567 7568 7569 7570 7571 7572 7573 7574 7575 7576 7577 7578 7579 7580 7581
        verbosePrint("super endAfterConsume: %d, consumed: %d\n",
                g_queryInfo.superQueryInfo.endAfterConsume,
                consumed[pThreadInfo->end_table_to
                - pThreadInfo->start_table_from]);
        for (uint64_t i = pThreadInfo->start_table_from;
                i <= pThreadInfo->end_table_to; i++) {
            tsubSeq = i - pThreadInfo->start_table_from;
            if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
                continue;
            }

            st = taosGetTimestampMs();
            performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
            res = taos_consume(tsub[tsubSeq]);
            et = taosGetTimestampMs();
            performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));

            if (res) {
                if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
                    sprintf(pThreadInfo->filePath, "%s-%d",
                            g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                            pThreadInfo->threadID);
                    fetchResult(res, pThreadInfo);
                }
                consumed[tsubSeq] ++;

                if ((g_queryInfo.superQueryInfo.resubAfterConsume != -1)
                        && (consumed[tsubSeq] >=
                            g_queryInfo.superQueryInfo.resubAfterConsume)) {
                    verbosePrint("%s() LN%d, keepProgress:%d, resub super table query: %"PRIu64"\n",
                            __func__, __LINE__,
                            g_queryInfo.superQueryInfo.subscribeKeepProgress,
                            pThreadInfo->querySeq);
                    taos_unsubscribe(tsub[tsubSeq],
                            g_queryInfo.superQueryInfo.subscribeKeepProgress);
                    consumed[tsubSeq]= 0;
                    tsub[tsubSeq] = subscribeImpl(
                            STABLE_CLASS,
                            pThreadInfo, subSqlstr, topic,
                            g_queryInfo.superQueryInfo.subscribeRestart,
                            g_queryInfo.superQueryInfo.subscribeInterval
                            );
                    if (NULL == tsub[tsubSeq]) {
                        taos_close(pThreadInfo->taos);
                        return NULL;
                    }
                }
            }
        }
    }
    verbosePrint("%s() LN%d, super endAfterConsume: %d, consumed: %d\n",
            __func__, __LINE__,
            g_queryInfo.superQueryInfo.endAfterConsume,
            consumed[pThreadInfo->end_table_to - pThreadInfo->start_table_from]);
    taos_free_result(res);
7582

7583 7584
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
7585 7586
        tsubSeq = i - pThreadInfo->start_table_from;
        taos_unsubscribe(tsub[tsubSeq], 0);
H
hzcheng 已提交
7587
    }
7588

7589 7590
    taos_close(pThreadInfo->taos);
    return NULL;
H
hzcheng 已提交
7591 7592
}

7593 7594
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
7595
//  TAOS_SUB*  tsub = NULL;
7596

7597
  if (pThreadInfo->taos == NULL) {
7598
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
7599 7600 7601 7602
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
7603
    if (pThreadInfo->taos == NULL) {
7604
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
7605
            pThreadInfo->threadID, taos_errstr(NULL));
7606 7607 7608 7609
      return NULL;
    }
  }

7610 7611
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
7612 7613
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
7614 7615
    return NULL;
  }
7616

7617 7618 7619 7620
  sprintf(g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
          "taosdemo-subscribe-%"PRIu64"-%d",
          pThreadInfo->querySeq,
          pThreadInfo->threadID);
7621
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != '\0') {
7622
      sprintf(pThreadInfo->filePath, "%s-%d",
7623
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
7624
                pThreadInfo->threadID);
7625
  }
7626 7627
  g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
          SPECIFIED_CLASS, pThreadInfo,
7628
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
7629
          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
7630 7631
          g_queryInfo.specifiedQueryInfo.subscribeRestart,
          g_queryInfo.specifiedQueryInfo.subscribeInterval);
7632
  if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
7633 7634
      taos_close(pThreadInfo->taos);
      return NULL;
7635
  }
7636

7637
  // start loop to consume result
7638

7639
  g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
7640 7641 7642 7643
  while((g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq] == -1)
          || (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] <
              g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq])) {

7644 7645 7646 7647 7648
      printf("consumed[%d]: %d, endAfterConsum[%"PRId64"]: %d\n",
              pThreadInfo->threadID,
              g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID],
              pThreadInfo->querySeq,
              g_queryInfo.specifiedQueryInfo.endAfterConsume[pThreadInfo->querySeq]);
7649
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
7650
          continue;
7651
      }
7652

7653 7654 7655
      g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]);
      if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) {
7656 7657
          if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0]
                  != 0) {
7658
              sprintf(pThreadInfo->filePath, "%s-%d",
7659 7660 7661
                      g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
          }
7662 7663 7664
          fetchResult(
                  g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID],
                  pThreadInfo);
7665

7666
          g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++;
7667
          if ((g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq] != -1)
7668
                && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >=
7669 7670 7671 7672
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) {
              printf("keepProgress:%d, resub specified query: %"PRIu64"\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress,
                    pThreadInfo->querySeq);
7673 7674
              g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
              taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID],
7675
                      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
7676 7677 7678 7679 7680 7681 7682 7683
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] =
                  subscribeImpl(
                          SPECIFIED_CLASS,
                          pThreadInfo,
                          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
                          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
                          g_queryInfo.specifiedQueryInfo.subscribeRestart,
                          g_queryInfo.specifiedQueryInfo.subscribeInterval);
7684
              if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
7685 7686
                  taos_close(pThreadInfo->taos);
                  return NULL;
7687 7688
              }
          }
7689 7690
      }
  }
7691
  taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
7692
  taos_close(pThreadInfo->taos);
7693

H
hzcheng 已提交
7694 7695 7696
  return NULL;
}

7697
static int subscribeTestProcess() {
7698
  setupForAnsiEscape();
7699
  printfQueryMeta();
7700
  resetAfterAnsiEscape();
7701

7702
  prompt();
7703

7704 7705 7706 7707 7708
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
7709
          g_queryInfo.port);
7710
  if (taos == NULL) {
7711 7712
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7713 7714 7715
    exit(-1);
  }

7716
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
7717 7718
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
7719 7720 7721
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
7722 7723
  }

7724 7725
  taos_close(taos); // TODO: workaround to use separate taos connection;

7726 7727
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
7728 7729 7730 7731 7732

  pthread_t  *pidsOfStable  = NULL;
  threadInfo *infosOfStable = NULL;

  //==== create threads for query for specified table
7733
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
7734
    debugPrint("%s() LN%d, sepcified query sqlCount %d.\n",
7735
              __func__, __LINE__,
7736 7737 7738
              g_queryInfo.specifiedQueryInfo.sqlCount);
  } else {
    if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
7739
        errorPrint("%s() LN%d, sepcified query sqlCount %d.\n",
7740 7741 7742 7743
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount);
        exit(-1);
    }
7744

7745 7746
    pids  = calloc(
            1,
7747 7748 7749
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(pthread_t));
7750 7751
    infos = calloc(
            1,
7752 7753 7754
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(threadInfo));
7755 7756 7757 7758
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
7759

7760 7761 7762
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
            uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
7763 7764 7765 7766 7767
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
            pThreadInfo->taos = NULL;  // TODO: workaround to use separate taos connection;
            pthread_create(pids + seq, NULL, specifiedSubscribe, pThreadInfo);
7768
        }
7769
    }
H
hzcheng 已提交
7770
  }
7771

7772
  //==== create threads for super table query
7773
  if (g_queryInfo.superQueryInfo.sqlCount <= 0) {
7774
    debugPrint("%s() LN%d, super table query sqlCount %d.\n",
7775
              __func__, __LINE__,
7776
              g_queryInfo.superQueryInfo.sqlCount);
7777 7778
  } else {
    if ((g_queryInfo.superQueryInfo.sqlCount > 0)
7779
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
7780 7781
        pidsOfStable  = calloc(
                1,
7782 7783
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7784
            sizeof(pthread_t));
7785 7786
        infosOfStable = calloc(
                1,
7787 7788
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7789
            sizeof(threadInfo));
7790 7791
        if ((NULL == pidsOfStable) || (NULL == infosOfStable)) {
            errorPrint("%s() LN%d, malloc failed for create threads\n",
7792
              __func__, __LINE__);
7793 7794 7795
            // taos_close(taos);
            exit(-1);
        }
7796

7797 7798
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
7799

7800 7801 7802 7803 7804
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
7805

7806 7807 7808 7809
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
7810

7811
        for (uint64_t i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
7812
            uint64_t tableFrom = 0;
7813 7814
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
7815 7816 7817 7818
                threadInfo *pThreadInfo = infosOfStable + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;

7819
                pThreadInfo->start_table_from = tableFrom;
7820
                pThreadInfo->ntables = j<b?a+1:a;
7821 7822
                pThreadInfo->end_table_to = j<b?tableFrom+a:tableFrom+a-1;
                tableFrom = pThreadInfo->end_table_to + 1;
7823
                pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
7824
                pthread_create(pidsOfStable + seq,
7825
                        NULL, superSubscribe, pThreadInfo);
7826 7827
            }
        }
7828

7829
        g_queryInfo.superQueryInfo.threadCnt = threads;
7830

7831 7832 7833 7834 7835 7836
        for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
                pthread_join(pidsOfStable[seq], NULL);
            }
        }
7837
    }
H
hzcheng 已提交
7838
  }
7839

7840 7841 7842 7843 7844
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
    for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
        uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
        pthread_join(pids[seq], NULL);
    }
7845
  }
H
hzcheng 已提交
7846

7847
  tmfree((char*)pids);
7848
  tmfree((char*)infos);
H
hzcheng 已提交
7849

7850 7851
  tmfree((char*)pidsOfStable);
  tmfree((char*)infosOfStable);
7852
//   taos_close(taos);
7853
  return 0;
H
hzcheng 已提交
7854 7855
}

7856
static void initOfInsertMeta() {
7857
  memset(&g_Dbs, 0, sizeof(SDbs));
7858

7859
  // set default values
7860
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7861
  g_Dbs.port = 6030;
7862 7863
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
7864
  g_Dbs.threadCount = 2;
7865 7866

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
7867 7868
}

7869
static void initOfQueryMeta() {
7870
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
7871

7872
  // set default values
7873
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7874
  g_queryInfo.port = 6030;
7875 7876
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
7877 7878
}

7879
static void setParaFromArg(){
7880
  if (g_args.host) {
7881
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
7882
  } else {
7883
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7884
  }
L
Liu Tao 已提交
7885

7886
  if (g_args.user) {
7887
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
7888
  }
7889 7890

  if (g_args.password) {
7891
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
7892 7893
  }

7894 7895
  if (g_args.port) {
    g_Dbs.port = g_args.port;
7896
  }
L
Liu Tao 已提交
7897

7898 7899 7900
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

7901
  g_Dbs.dbCount = 1;
7902
  g_Dbs.db[0].drop = true;
7903

7904
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, TSDB_DB_NAME_LEN);
7905
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
7906
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", 8);
L
Liu Tao 已提交
7907

7908
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
7909 7910 7911 7912 7913

  g_Dbs.use_metric = g_args.use_metric;
  g_Dbs.insert_only = g_args.insert_only;

  g_Dbs.do_aggreFunc = true;
L
Liu Tao 已提交
7914

7915 7916
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
7917

7918
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
7919

7920 7921
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
7922
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
7923
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
7924
  }
H
hzcheng 已提交
7925

7926 7927
  if (g_args.use_metric) {
    g_Dbs.db[0].superTblCount = 1;
7928
    tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", TSDB_TABLE_NAME_LEN);
7929 7930
    g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
    g_Dbs.threadCount = g_args.num_of_threads;
7931
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
7932
    g_Dbs.asyncMode = g_args.async_mode;
7933

7934 7935 7936 7937
    g_Dbs.db[0].superTbls[0].autoCreateTable = PRE_CREATE_SUBTBL;
    g_Dbs.db[0].superTbls[0].childTblExists = TBL_NO_EXISTS;
    g_Dbs.db[0].superTbls[0].disorderRange = g_args.disorderRange;
    g_Dbs.db[0].superTbls[0].disorderRatio = g_args.disorderRatio;
7938
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
7939
            g_args.tb_prefix, TSDB_TABLE_NAME_LEN - 20);
7940
    tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE);
7941
    g_Dbs.db[0].superTbls[0].iface = g_args.iface;
7942
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
7943
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
7944
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
7945

7946
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
7947
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
7948

7949 7950 7951 7952 7953
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
7954

7955
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7956
              data_type[i], strlen(data_type[i]) + 1);
7957
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
7958 7959
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
7960

7961 7962 7963
    if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) {
      g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR;
    } else {
7964 7965 7966
      for (int i = g_Dbs.db[0].superTbls[0].columnCount;
              i < g_args.num_of_CPR; i++) {
        tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7967
                "INT", strlen("INT") + 1);
7968
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
7969 7970 7971
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
7972

7973
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
7974
            "INT", strlen("INT") + 1);
7975
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
7976

7977
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
7978
            "BINARY", strlen("BINARY") + 1);
7979 7980
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
7981
  } else {
7982 7983
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
7984
  }
7985 7986 7987 7988 7989 7990
}

/* Function to do regular expression check */
static int regexMatch(const char *s, const char *reg, int cflags) {
  regex_t regex;
  char    msgbuf[100] = {0};
H
hzcheng 已提交
7991

7992 7993 7994
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
7995 7996 7997
    exit(-1);
  }

7998 7999 8000 8001 8002 8003 8004 8005 8006 8007 8008 8009 8010 8011 8012 8013 8014 8015 8016 8017 8018 8019 8020 8021
  /* Execute regular expression */
  int reti = regexec(&regex, s, 0, NULL, 0);
  if (!reti) {
    regfree(&regex);
    return 1;
  } else if (reti == REG_NOMATCH) {
    regfree(&regex);
    return 0;
  } else {
    regerror(reti, &regex, msgbuf, sizeof(msgbuf));
    printf("Regex match failed: %s\n", msgbuf);
    regfree(&regex);
    exit(-1);
  }

  return 0;
}

static int isCommentLine(char *line) {
  if (line == NULL) return 1;

  return regexMatch(line, "^\\s*#.*", REG_EXTENDED);
}

8022
static void querySqlFile(TAOS* taos, char* sqlFile)
8023 8024 8025 8026 8027 8028
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
8029

8030 8031 8032 8033 8034 8035
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

8036
  double t = taosGetTimestampMs();
8037

8038
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
8039 8040 8041 8042 8043 8044 8045 8046 8047 8048 8049 8050
    if (read_len >= MAX_SQL_SIZE) continue;
    line[--read_len] = '\0';

    if (read_len == 0 || isCommentLine(line)) {  // line starts with #
      continue;
    }

    if (line[read_len - 1] == '\\') {
      line[read_len - 1] = ' ';
      memcpy(cmd + cmd_len, line, read_len);
      cmd_len += read_len;
      continue;
8051
    }
8052 8053

    memcpy(cmd + cmd_len, line, read_len);
8054 8055 8056
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
8057 8058 8059 8060 8061
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
8062 8063
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
8064 8065
  }

8066
  t = taosGetTimestampMs() - t;
8067
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
8068

8069 8070 8071 8072
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
8073 8074
}

8075
static void testMetaFile() {
8076
    if (INSERT_TEST == g_args.test_mode) {
8077 8078
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
8079

8080
      insertTestProcess();
8081

8082
    } else if (QUERY_TEST == g_args.test_mode) {
8083 8084
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
8085

8086
      queryTestProcess();
8087

8088
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
8089 8090
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
8091

8092
      subscribeTestProcess();
8093

8094 8095 8096
    }  else {
      ;
    }
8097
}
8098

8099
static void queryResult() {
8100
  // query data
8101

8102
  pthread_t read_id;
8103
  threadInfo *pThreadInfo = calloc(1, sizeof(threadInfo));
8104 8105 8106
  assert(pThreadInfo);
  pThreadInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  pThreadInfo->start_table_from = 0;
8107

8108
  //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
8109
  if (g_args.use_metric) {
8110 8111 8112 8113
    pThreadInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    pThreadInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    pThreadInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(pThreadInfo->tb_prefix,
8114
          g_Dbs.db[0].superTbls[0].childTblPrefix, TSDB_TABLE_NAME_LEN - 20);
8115
  } else {
8116 8117
    pThreadInfo->ntables = g_args.num_of_tables;
    pThreadInfo->end_table_to = g_args.num_of_tables -1;
8118
    tstrncpy(pThreadInfo->tb_prefix, g_args.tb_prefix, TSDB_TABLE_NAME_LEN);
8119 8120
  }

8121
  pThreadInfo->taos = taos_connect(
8122 8123 8124 8125 8126
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
          g_Dbs.port);
8127
  if (pThreadInfo->taos == NULL) {
8128 8129
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
8130
    free(pThreadInfo);
8131 8132 8133
    exit(-1);
  }

8134
  tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
8135 8136

  if (!g_Dbs.use_metric) {
8137
    pthread_create(&read_id, NULL, readTable, pThreadInfo);
8138
  } else {
8139
    pthread_create(&read_id, NULL, readMetric, pThreadInfo);
8140 8141
  }
  pthread_join(read_id, NULL);
8142 8143
  taos_close(pThreadInfo->taos);
  free(pThreadInfo);
8144 8145
}

8146 8147
static void testCmdLine() {

8148 8149 8150 8151 8152 8153 8154 8155 8156 8157
  if (strlen(configDir)) {
    wordexp_t full_path;
    if (wordexp(configDir, &full_path, 0) != 0) {
      errorPrint( "Invalid path %s\n", configDir);
      return;
    }
    taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
    wordfree(&full_path);
  }

8158 8159
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
8160

8161
  if (false == g_Dbs.insert_only)
8162
    queryResult();
8163 8164
}

8165 8166 8167
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

8168
  debugPrint("meta file: %s\n", g_args.metaFile);
8169 8170 8171

  if (g_args.metaFile) {
    initOfInsertMeta();
8172
    initOfQueryMeta();
8173 8174 8175 8176 8177 8178 8179 8180 8181 8182 8183 8184 8185

    if (false == getInfoFromJsonFile(g_args.metaFile)) {
      printf("Failed to read %s\n", g_args.metaFile);
      return 1;
    }

    testMetaFile();
  } else {
    memset(&g_Dbs, 0, sizeof(SDbs));
    setParaFromArg();

    if (NULL != g_args.sqlFile) {
      TAOS* qtaos = taos_connect(
8186 8187 8188 8189
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
8190
          g_Dbs.port);
8191
      querySqlFile(qtaos, g_args.sqlFile);
8192 8193 8194 8195 8196
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
8197 8198 8199

    if (g_dupstr)
        free(g_dupstr);
H
hzcheng 已提交
8200
  }
8201 8202

  return 0;
H
hzcheng 已提交
8203
}
8204