taosdemo.c 231.1 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>
S
slguan 已提交
22
#define _GNU_SOURCE
23 24
#define CURL_STATICLIB

S
TD-1057  
Shengliang Guan 已提交
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
#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>
41
#else
S
TD-1057  
Shengliang Guan 已提交
42 43
  #include <regex.h>
  #include <stdio.h>
44
#endif
H
hzcheng 已提交
45

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

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

55 56 57
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

S
slguan 已提交
58 59
extern char configDir[];

60 61 62 63
#define INSERT_JSON_NAME      "insert.json"
#define QUERY_JSON_NAME       "query.json"
#define SUBSCRIBE_JSON_NAME   "subscribe.json"

64 65 66 67 68 69
enum TEST_MODE {
    INSERT_TEST,            // 0
    QUERY_TEST,             // 1
    SUBSCRIBE_TEST,         // 2
    INVAID_TEST
};
70

71 72 73 74 75 76
enum QUERY_MODE {
  SYNC_QUERY_MODE,          // 0
  ASYNC_QUERY_MODE,         // 1
  INVALID_MODE
};

77 78
#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
79 80
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
81
#define MAX_DB_NAME_SIZE   64
82
#define MAX_HOSTNAME_SIZE  64
83
#define MAX_TB_NAME_SIZE   64
84
#define MAX_DATA_SIZE      (16*1024)
85 86 87 88 89 90 91 92 93 94
#define MAX_NUM_DATATYPE   10
#define OPT_ABORT          1 /* –abort */
#define STRING_LEN         60000
#define MAX_PREPARED_RAND  1000000
#define MAX_FILE_NAME_LEN  256

#define   MAX_SAMPLES_ONCE_FROM_FILE   10000
#define   MAX_NUM_DATATYPE 10

#define   MAX_DB_COUNT           8
95
#define   MAX_SUPER_TABLE_COUNT  200
96 97 98
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

99
#define   MAX_QUERY_SQL_COUNT    100
100
#define   MAX_QUERY_SQL_LENGTH   1024
101 102

#define   MAX_DATABASE_COUNT     256
103
#define INPUT_BUF_LEN   256
104

105
#define DEFAULT_TIMESTAMP_STEP  1
106

107

108 109 110 111 112
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
113

114 115
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
116
  TBL_ALREADY_EXISTS,
117 118 119 120
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

enum MODE {
121
  SYNC,
122 123 124
  ASYNC,
  MODE_BUT
};
125

126 127 128 129 130 131
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

132
typedef enum enumQUERY_TYPE {
133
  NO_INSERT_TYPE,
134
  INSERT_TYPE,
135
  QUERY_TYPE_BUT
136
} QUERY_TYPE;
137 138 139 140 141 142 143

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,
144
  TSDB_SHOW_DB_QUORUM_INDEX,
145 146 147 148 149 150 151 152 153 154
  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,
155
  TSDB_SHOW_DB_PRECISION_INDEX,
156 157 158 159 160 161 162 163 164 165
  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,
166 167
  TSDB_SHOW_STABLES_METRIC_INDEX,
  TSDB_SHOW_STABLES_UID_INDEX,
168
  TSDB_SHOW_STABLES_TID_INDEX,
169
  TSDB_SHOW_STABLES_VGID_INDEX,
170
  TSDB_MAX_SHOW_STABLES
171 172
};

173 174 175 176 177 178 179 180 181 182 183 184 185 186
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
};

typedef struct {
  char field[TSDB_COL_NAME_LEN + 1];
  char type[16];
  int length;
  char note[128];
} SColDes;
H
hzcheng 已提交
187 188

/* Used by main to communicate with parse_opt. */
189 190
typedef struct SArguments_S {
  char *   metaFile;
191
  int      test_mode;
192 193 194 195 196 197 198 199 200
  char *   host;
  uint16_t port;
  char *   user;
  char *   password;
  char *   database;
  int      replica;
  char *   tb_prefix;
  char *   sqlFile;
  bool     use_metric;
201
  bool     drop_database;
202
  bool     insert_only;
203
  bool     answer_yes;
204
  bool     debug_print;
205
  bool     verbose_print;
206
  bool     performance_print;
207
  char *   output_file;
208
  int      query_mode;
209 210 211 212
  char *   datatype[MAX_NUM_DATATYPE + 1];
  int      len_of_binary;
  int      num_of_CPR;
  int      num_of_threads;
213 214 215 216 217 218 219
  int64_t  insert_interval;
  int64_t  query_times;
  int64_t  interlace_rows;
  int64_t  num_of_RPR;                  // num_of_records_per_req
  int64_t  max_sql_len;
  int64_t  num_of_tables;
  int64_t  num_of_DPT;
220
  int      abort;
221 222
  int      disorderRatio;               // 0: no disorder, >0: x%
  int      disorderRange;               // ms or us by database precision
223 224
  int      method_of_delete;
  char **  arg_list;
225 226
  int64_t  totalInsertRows;
  int64_t  totalAffectedRows;
227 228 229 230 231 232
} SArguments;

typedef struct SColumn_S {
  char  field[TSDB_COL_NAME_LEN + 1];
  char  dataType[MAX_TB_NAME_SIZE];
  int   dataLen;
233
  char  note[128];
234 235 236
} StrColumn;

typedef struct SSuperTable_S {
237
  char         sTblName[MAX_TB_NAME_SIZE+1];
238
  int64_t      childTblCount;
239
  bool         childTblExists;          // 0: no, 1: yes
240
  int64_t      batchCreateTableNum;     // 0: no batch,  > 0: batch table number in one sql
241
  int8_t       autoCreateTable;         // 0: create sub table, 1: auto create sub table
242
  char         childTblPrefix[MAX_TB_NAME_SIZE];
243
  char         dataSource[MAX_TB_NAME_SIZE+1];  // rand_gen or sample
244
  char         insertMode[MAX_TB_NAME_SIZE];    // taosc, rest
245 246
  int64_t      childTblLimit;
  int64_t      childTblOffset;
247

248 249
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
  int64_t      interlaceRows;           //
250 251
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
252
  int64_t      maxSqlLen;               //
253

254
  int64_t      insertInterval;          // insert interval, will override global insert interval
255
  int64_t      insertRows;
256
  int64_t      timeStampStep;
257
  char         startTimestamp[MAX_TB_NAME_SIZE];
258
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
259 260
  char         sampleFile[MAX_FILE_NAME_LEN+1];
  char         tagsFile[MAX_FILE_NAME_LEN+1];
261 262 263 264 265 266 267

  int          columnCount;
  StrColumn    columns[MAX_COLUMN_COUNT];
  int          tagCount;
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
268
  char*        colsOfCreateChildTable;
269 270
  int64_t      lenOfOneRow;
  int64_t      lenOfTagOfOneRow;
271 272 273 274 275 276 277 278 279 280

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

  int          tagSource;    // 0: rand, 1: tag sample
  char*        tagDataBuf;
  int          tagSampleCount;
  int          tagUsePos;

281
  // statistics
282 283
  int64_t       totalInsertRows;
  int64_t       totalAffectedRows;
284 285 286 287 288 289
} SSuperTable;

typedef struct {
  char     name[TSDB_DB_NAME_LEN + 1];
  char     create_time[32];
  int32_t  ntables;
290
  int32_t  vgroups;
291 292
  int16_t  replica;
  int16_t  quorum;
293
  int16_t  days;
294 295 296 297 298 299 300 301 302 303 304 305 306 307
  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;

308
typedef struct SDbCfg_S {
309
//  int       maxtablesPerVnode;
310
  int       minRows;
311 312 313
  int       maxRows;
  int       comp;
  int       walLevel;
314
  int       cacheLast;
315
  int       fsync;
316 317 318 319 320 321 322
  int       replica;
  int       update;
  int       keep;
  int       days;
  int       cache;
  int       blocks;
  int       quorum;
323
  char      precision[MAX_TB_NAME_SIZE];
324 325 326 327
} SDbCfg;

typedef struct SDataBase_S {
  char         dbName[MAX_DB_NAME_SIZE];
328
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
329
  SDbCfg       dbCfg;
330
  int64_t      superTblCount;
331 332 333 334
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
335
  char         cfgDir[MAX_FILE_NAME_LEN+1];
336
  char         host[MAX_HOSTNAME_SIZE];
337 338
  struct sockaddr_in serv_addr;

339
  uint16_t     port;
340 341
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
342
  char         resultFile[MAX_FILE_NAME_LEN+1];
343 344 345 346
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
  bool         queryMode;
347

348 349 350 351 352 353
  int          threadCount;
  int          threadCountByCreateTbl;
  int          dbCount;
  SDataBase    db[MAX_DB_COUNT];

  // statistics
354 355
  int64_t       totalInsertRows;
  int64_t       totalAffectedRows;
356

357 358
} SDbs;

359
typedef struct SpecifiedQueryInfo_S {
360 361 362
  int64_t      queryInterval;  // 0: unlimit  > 0   loop/s
  int64_t      concurrent;
  int64_t      sqlCount;
363
  int          mode; // 0: sync, 1: async
364 365
  int64_t      subscribeInterval; // ms
  int64_t      queryTimes;
366 367
  int          subscribeRestart;
  int          subscribeKeepProgress;
368
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
369
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
370
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
371
  int64_t      totalQueried;
372
} SpecifiedQueryInfo;
373

374
typedef struct SuperQueryInfo_S {
375
  char         sTblName[MAX_TB_NAME_SIZE+1];
376
  int64_t      queryInterval;  // 0: unlimit  > 0   loop/s
377
  int          threadCnt;
378
  int          mode; // 0: sync, 1: async
379
  int64_t      subscribeInterval; // ms
380 381
  int          subscribeRestart;
  int          subscribeKeepProgress;
382 383
  int64_t      queryTimes;
  int64_t      childTblCount;
384
  char         childTblPrefix[MAX_TB_NAME_SIZE];
385
  int64_t      sqlCount;
386
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
387
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
388
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
389

390
  char*        childTblName;
391
  int64_t      totalQueried;
392
} SuperQueryInfo;
393 394

typedef struct SQueryMetaInfo_S {
395
  char         cfgDir[MAX_FILE_NAME_LEN+1];
396
  char         host[MAX_HOSTNAME_SIZE];
397
  uint16_t     port;
398
  struct sockaddr_in serv_addr;
399 400
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
401
  char         dbName[MAX_DB_NAME_SIZE+1];
402
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
403

404 405
  SpecifiedQueryInfo  specifiedQueryInfo;
  SuperQueryInfo    superQueryInfo;
406
  int64_t      totalQueried;
407 408 409 410 411
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
  TAOS *taos;
  int threadID;
412
  char db_name[MAX_DB_NAME_SIZE+1];
413
  uint32_t time_precision;
414 415
  char fp[4096];
  char tb_prefix[MAX_TB_NAME_SIZE];
416 417 418 419 420
  int64_t start_table_from;
  int64_t end_table_to;
  int64_t ntables;
  int64_t data_of_rate;
  int64_t start_time;
421 422
  char* cols;
  bool  use_metric;
423 424 425 426
  SSuperTable* superTblInfo;

  // for async insert
  tsem_t lock_sem;
427
  int64_t  counter;
428 429
  uint64_t  st;
  uint64_t  et;
430 431
  int64_t  lastTs;

432
  // sample data
433
  int64_t samplePos;
434
  // statistics
435
  int64_t totalInsertRows;
436
  int64_t totalAffectedRows;
437 438 439 440 441 442 443

  // insert delay statistics
  int64_t cntDelay;
  int64_t totalDelay;
  int64_t avgDelay;
  int64_t maxDelay;
  int64_t minDelay;
444

445
  // query
446
  int64_t querySeq;   // sequence number of sql command
447 448
} threadInfo;

449
#ifdef WINDOWS
450 451
#define _CRT_RAND_S

452
#include <windows.h>
453 454 455 456 457
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
458 459
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
460 461
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
462 463 464 465

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

466
static void setupForAnsiEscape(void) {
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
  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());
485
  }
486 487
}

488
static void resetAfterAnsiEscape(void) {
489
  // Reset colors
490
  printf("\x1b[0m");
491 492 493 494 495 496

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

498
static int taosRandom()
499 500 501 502 503 504
{
    int number;
    rand_s(&number);

    return number;
}
505
#else   // Not windows
506
static void setupForAnsiEscape(void) {}
507

508
static void resetAfterAnsiEscape(void) {
509 510 511
  // Reset colors
  printf("\x1b[0m");
}
512

513 514
#include <time.h>

515
static int taosRandom()
516
{
517
  return rand();
518 519
}

520
#endif // ifdef Windows
521

522
static int createDatabasesAndStables();
523
static void createChildTables();
524
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
525 526 527 528 529 530 531

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

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

535
SArguments g_args = {
536 537
                     NULL,            // metaFile
                     0,               // test_mode
538 539 540
                     "127.0.0.1",     // host
                     6030,            // port
                     "root",          // user
541
                     #ifdef _TD_POWER_
542 543 544 545 546 547 548 549
                     "powerdb",      // password
                     #else
                     "taosdata",      // password
                     #endif
                     "test",          // database
                     1,               // replica
                     "t",             // tb_prefix
                     NULL,            // sqlFile
550
                     true,            // use_metric
551
                     true,            // drop_database
552
                     true,            // insert_only
553
                     false,           // debug_print
554
                     false,           // verbose_print
555
                     false,           // performance statistic print
556 557 558 559
                     false,           // answer_yes;
                     "./output.txt",  // output_file
                     0,               // mode : sync or async
                     {
560 561 562 563
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
564 565
                     },
                     16,              // len_of_binary
566
                     4,               // num_of_CPR
567 568
                     10,              // num_of_connections/thread
                     0,               // insert_interval
569
                     1,               // query_times
570
                     0,               // interlace_rows;
571 572
                     30000,           // num_of_RPR
                     1024000,         // max_sql_len
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
                     10000,           // num_of_tables
                     10000,           // num_of_DPT
                     0,               // abort
                     0,               // disorderRatio
                     1000,            // disorderRange
                     1,               // method_of_delete
                     NULL             // arg_list
};



static SDbs            g_Dbs;
static int             g_totalChildTables = 0;
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

#define debugPrint(fmt, ...) \
590
    do { if (g_args.debug_print || g_args.verbose_print) \
591
      fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
592

593
#define verbosePrint(fmt, ...) \
594 595
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
596

597 598 599 600
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

601 602 603 604
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


605
///////////////////////////////////////////////////
H
hzcheng 已提交
606

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

609 610 611 612 613 614 615 616
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

617
#ifndef TAOSDEMO_STATUS
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634
#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);
    }
}

635
static void printHelp() {
636
  char indent[10] = "        ";
637
  printf("%s%s%s%s\n", indent, "-f", indent,
638
          "The meta file to the execution procedure. Default is './meta.json'.");
639
  printf("%s%s%s%s\n", indent, "-u", indent,
640 641
          "The TDengine user name to use when connecting to the server. Default is 'root'.");
#ifdef _TD_POWER_
642
  printf("%s%s%s%s\n", indent, "-P", indent,
643
          "The password to use when connecting to the server. Default is 'powerdb'.");
644
  printf("%s%s%s%s\n", indent, "-c", indent,
645 646
          "Configuration directory. Default is '/etc/power/'.");
#else
647
  printf("%s%s%s%s\n", indent, "-P", indent,
648
          "The password to use when connecting to the server. Default is 'taosdata'.");
649
  printf("%s%s%s%s\n", indent, "-c", indent,
650
          "Configuration directory. Default is '/etc/taos/'.");
651
#endif
652
  printf("%s%s%s%s\n", indent, "-h", indent,
653
          "The host to connect to TDengine. Default is localhost.");
654
  printf("%s%s%s%s\n", indent, "-p", indent,
655
          "The TCP/IP port number to use for the connection. Default is 0.");
656
  printf("%s%s%s%s\n", indent, "-d", indent,
657
          "Destination database. Default is 'test'.");
658
  printf("%s%s%s%s\n", indent, "-a", indent,
659
          "Set the replica parameters of the database, Default 1, min: 1, max: 3.");
660
  printf("%s%s%s%s\n", indent, "-m", indent,
661 662
          "Table prefix name. Default is 't'.");
  printf("%s%s%s%s\n", indent, "-s", indent, "The select sql file.");
663
  printf("%s%s%s%s\n", indent, "-N", indent, "Use normal table flag.");
664
  printf("%s%s%s%s\n", indent, "-o", indent,
665
          "Direct output to the named file. Default is './output.txt'.");
666
  printf("%s%s%s%s\n", indent, "-q", indent,
667
          "Query mode -- 0: SYNC, 1: ASYNC. Default is SYNC.");
668
  printf("%s%s%s%s\n", indent, "-b", indent,
669
          "The data_type of columns, default: TINYINT,SMALLINT,INT,BIGINT,FLOAT,DOUBLE,BINARY,NCHAR,BOOL,TIMESTAMP.");
670
  printf("%s%s%s%s\n", indent, "-w", indent,
671
          "The length of data_type 'BINARY' or 'NCHAR'. Default is 16");
672
  printf("%s%s%s%s\n", indent, "-l", indent,
673
          "The number of columns per record. Default is 10.");
674
  printf("%s%s%s%s\n", indent, "-T", indent,
675
          "The number of threads. Default is 10.");
676
  printf("%s%s%s%s\n", indent, "-i", indent,
677
          "The sleep time (ms) between insertion. Default is 0.");
678
  printf("%s%s%s%s\n", indent, "-r", indent,
679
          "The number of records per request. Default is 30000.");
680
  printf("%s%s%s%s\n", indent, "-t", indent,
681
          "The number of tables. Default is 10000.");
682
  printf("%s%s%s%s\n", indent, "-n", indent,
683 684 685
          "The number of records per table. Default is 10000.");
  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.");
686
  printf("%s%s%s%s\n", indent, "-O", indent,
687
          "Insert mode--0: In order, 1 ~ 50: disorder ratio. Default is in order.");
688
  printf("%s%s%s%s\n", indent, "-R", indent,
689
          "Out of order data's range, ms, default is 1000.");
690
  printf("%s%s%s%s\n", indent, "-g", indent,
691
          "Print debug info.");
692
  printf("%s%s%s\n", indent, "-V, --version\t",
693
          "Print version info.");
694 695
  printf("%s%s%s%s\n", indent, "--help\t", indent,
          "Print command line arguments list info.");
696
/*    printf("%s%s%s%s\n", indent, "-D", indent,
697 698 699 700
          "if elete database if exists. 0: no, 1: yes, default is 1");
          */
}

701 702 703 704 705 706 707 708 709 710 711 712 713 714 715
static bool isStringNumber(char *input)
{
  int len = strlen(input);
  if (0 == len) {
    return false;
  }

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

  return true;
}

716
static void parse_args(int argc, char *argv[], SArguments *arguments) {
717
  char **sptr;
718 719 720 721 722

  for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-f") == 0) {
      arguments->metaFile = argv[++i];
    } else if (strcmp(argv[i], "-c") == 0) {
723 724 725 726 727
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
728
      tstrncpy(configDir, argv[++i], MAX_FILE_NAME_LEN);
729

730
    } else if (strcmp(argv[i], "-h") == 0) {
731 732 733 734 735
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-h need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
736 737
      arguments->host = argv[++i];
    } else if (strcmp(argv[i], "-p") == 0) {
738 739 740 741 742 743
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-p need a number following!\n");
        exit(EXIT_FAILURE);
      }
744 745
      arguments->port = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-u") == 0) {
746 747 748 749 750
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-u need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
751 752
      arguments->user = argv[++i];
    } else if (strcmp(argv[i], "-P") == 0) {
753 754 755 756 757
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-P need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
758 759
      arguments->password = argv[++i];
    } else if (strcmp(argv[i], "-o") == 0) {
760 761 762 763 764
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-o need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
765 766
      arguments->output_file = argv[++i];
    } else if (strcmp(argv[i], "-s") == 0) {
767 768 769 770 771
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-s need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
772 773
      arguments->sqlFile = argv[++i];
    } else if (strcmp(argv[i], "-q") == 0) {
774 775 776
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
777
        errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, 1: ASYNC. Default is SYNC.\n");
778 779
        exit(EXIT_FAILURE);
      }
780
      arguments->query_mode = atoi(argv[++i]);
781
    } else if (strcmp(argv[i], "-T") == 0) {
782 783 784 785 786 787
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-T need a number following!\n");
        exit(EXIT_FAILURE);
      }
788 789
      arguments->num_of_threads = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-i") == 0) {
790 791 792 793 794 795
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-i need a number following!\n");
        exit(EXIT_FAILURE);
      }
796
      arguments->insert_interval = atoi(argv[++i]);
797
    } else if (strcmp(argv[i], "-qt") == 0) {
798 799 800 801 802 803
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-qt need a number following!\n");
        exit(EXIT_FAILURE);
      }
804
      arguments->query_times = atoi(argv[++i]);
805
    } else if (strcmp(argv[i], "-B") == 0) {
806 807 808 809 810 811
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-B need a number following!\n");
        exit(EXIT_FAILURE);
      }
812
      arguments->interlace_rows = atoi(argv[++i]);
813
    } else if (strcmp(argv[i], "-r") == 0) {
814 815 816 817 818 819
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-r need a number following!\n");
        exit(EXIT_FAILURE);
      }
820 821
      arguments->num_of_RPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-t") == 0) {
822 823 824 825 826 827
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-t need a number following!\n");
        exit(EXIT_FAILURE);
      }
828 829
      arguments->num_of_tables = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-n") == 0) {
830 831 832 833 834 835
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-n need a number following!\n");
        exit(EXIT_FAILURE);
      }
836 837
      arguments->num_of_DPT = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-d") == 0) {
838 839 840 841 842
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-d need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
843 844
      arguments->database = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0) {
845 846 847 848 849 850
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-l need a number following!\n");
        exit(EXIT_FAILURE);
      }
851 852
      arguments->num_of_CPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-b") == 0) {
853
      sptr = arguments->datatype;
854 855
      ++i;
      if (strstr(argv[i], ",") == NULL) {
856
        // only one col
857 858 859 860 861 862 863
        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")
864
                && strcasecmp(argv[i], "BINARY")
865 866
                && strcasecmp(argv[i], "NCHAR")) {
          printHelp();
867
          errorPrint("%s", "-b: Invalid data_type!\n");
868
          exit(EXIT_FAILURE);
869
        }
870
        sptr[0] = argv[i];
871
      } else {
872
        // more than one col
873
        int index = 0;
874
        char *dupstr = strdup(argv[i]);
875 876
        char *running = dupstr;
        char *token = strsep(&running, ",");
877
        while(token != NULL) {
878 879 880 881 882 883 884 885 886 887
          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, "NCHAR")) {
            printHelp();
888
            free(dupstr);
889
            errorPrint("%s", "-b: Invalid data_type!\n");
890
            exit(EXIT_FAILURE);
H
hzcheng 已提交
891
          }
892 893 894
          sptr[index++] = token;
          token = strsep(&running, ",");
          if (index >= MAX_NUM_DATATYPE) break;
S
TD-1057  
Shengliang Guan 已提交
895
        }
896
        free(dupstr);
897
        sptr[index] = NULL;
898
      }
899
    } else if (strcmp(argv[i], "-w") == 0) {
900 901 902 903 904 905
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-w need a number following!\n");
        exit(EXIT_FAILURE);
      }
906 907
      arguments->len_of_binary = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-m") == 0) {
908 909 910 911 912 913
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-m need a number following!\n");
        exit(EXIT_FAILURE);
      }
914
      arguments->tb_prefix = argv[++i];
915 916
    } else if (strcmp(argv[i], "-N") == 0) {
      arguments->use_metric = false;
917
    } else if (strcmp(argv[i], "-x") == 0) {
918
      arguments->insert_only = false;
919
    } else if (strcmp(argv[i], "-y") == 0) {
920
      arguments->answer_yes = true;
921 922
    } else if (strcmp(argv[i], "-g") == 0) {
      arguments->debug_print = true;
923 924
    } else if (strcmp(argv[i], "-gg") == 0) {
      arguments->verbose_print = true;
925 926
    } else if (strcmp(argv[i], "-pp") == 0) {
      arguments->performance_print = true;
927
    } else if (strcmp(argv[i], "-O") == 0) {
928 929 930 931 932 933
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-O need a number following!\n");
        exit(EXIT_FAILURE);
      }
934

935
      arguments->disorderRatio = atoi(argv[++i]);
936

937
      if (arguments->disorderRatio > 50) {
938
        arguments->disorderRatio = 50;
939
      }
940

941
      if (arguments->disorderRatio < 0) {
942
        arguments->disorderRatio = 0;
943
      }
944

945
    } else if (strcmp(argv[i], "-R") == 0) {
946 947 948 949 950 951
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
952

953
      arguments->disorderRange = atoi(argv[++i]);
954 955 956
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

957
    } else if (strcmp(argv[i], "-a") == 0) {
958 959 960 961 962 963
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-a need a number following!\n");
        exit(EXIT_FAILURE);
      }
964 965 966
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
967
      }
968 969 970 971 972
    } else if (strcmp(argv[i], "-D") == 0) {
      arguments->method_of_delete = atoi(argv[++i]);
      if (arguments->method_of_delete < 0
              || arguments->method_of_delete > 3) {
        arguments->method_of_delete = 0;
S
TD-1057  
Shengliang Guan 已提交
973
      }
974 975 976 977
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
978 979 980 981 982
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
983
      errorPrint("%s", "ERROR: wrong options\n");
984
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
985 986
    }
  }
987

988 989
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
          || arguments->verbose_print) {
990
    printf("###################################################################\n");
991
    printf("# meta file:                         %s\n", arguments->metaFile);
992
    printf("# Server IP:                         %s:%hu\n",
993 994 995 996 997
            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");
998 999 1000 1001 1002 1003 1004 1005 1006
    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");
    }
1007 1008 1009 1010 1011 1012
    printf("# Insertion interval:                %"PRId64"\n",
            arguments->insert_interval);
    printf("# Number of records per req:         %"PRId64"\n",
            arguments->num_of_RPR);
    printf("# Max SQL length:                    %"PRId64"\n",
            arguments->max_sql_len);
1013
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1014
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1015 1016 1017 1018
    printf("# Number of Tables:                  %"PRId64"\n",
            arguments->num_of_tables);
    printf("# Number of Data per Table:          %"PRId64"\n",
            arguments->num_of_DPT);
1019 1020 1021 1022 1023
    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);
1024

1025 1026 1027 1028
    }
    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);
1029
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1030 1031 1032 1033 1034 1035
    printf("###################################################################\n");
    if (!arguments->answer_yes) {
        printf("Press enter key to continue\n\n");
        (void) getchar();
    }
  }
1036
}
H
hzcheng 已提交
1037

1038 1039 1040 1041
static bool getInfoFromJsonFile(char* file);
//static int generateOneRowDataForStb(SSuperTable* stbInfo);
//static int getDataIntoMemForStb(SSuperTable* stbInfo);
static void init_rand_data();
1042
static void tmfclose(FILE *fp) {
1043 1044 1045 1046
  if (NULL != fp) {
    fclose(fp);
  }
}
1047

1048
static void tmfree(char *buf) {
1049 1050
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1051
  }
1052
}
H
Hui Li 已提交
1053

1054
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1055 1056 1057
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1058

1059 1060 1061 1062
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1063
    }
1064

1065 1066 1067 1068
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1069
    }
H
hzcheng 已提交
1070 1071
  }

1072
  if (code != 0) {
1073 1074 1075 1076
    if (!quiet) {
      debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
      errorPrint("Failed to run %s, reason: %s\n", command, taos_errstr(res));
    }
1077 1078 1079
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1080
  }
H
hzcheng 已提交
1081

1082 1083 1084 1085
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1086
  }
1087

1088
  taos_free_result(res);
1089 1090
  return 0;
}
H
hzcheng 已提交
1091

1092
static void getResult(TAOS_RES *res, char* resultFileName) {
1093 1094 1095 1096 1097 1098 1099 1100 1101
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

  FILE *fp = NULL;
  if (resultFileName[0] != 0) {
    fp = fopen(resultFileName, "at");
    if (fp == NULL) {
1102 1103
      errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFileName);
1104 1105
    }
  }
1106

1107 1108
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1109 1110
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1111 1112
    if (fp)
        fclose(fp);
1113 1114
    return ;
  }
H
hzcheng 已提交
1115

1116 1117
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1118

1119
  // fetch the records row by row
1120
  while((row = taos_fetch_row(res))) {
1121 1122 1123 1124
    if (totalLen >= 100*1024*1024 - 32000) {
      if (fp) fprintf(fp, "%s", databuf);
      totalLen = 0;
      memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1125
    }
1126 1127 1128 1129 1130 1131
    num_rows++;
    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;
H
hzcheng 已提交
1132 1133
  }

1134 1135 1136 1137
  if (fp) fprintf(fp, "%s", databuf);
  tmfclose(fp);
  free(databuf);
}
H
hzcheng 已提交
1138

1139 1140 1141
static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) {
  TAOS_RES *res = taos_query(taos, command);
  if (res == NULL || taos_errno(res) != 0) {
1142 1143
    errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n",
       __func__, __LINE__, command, taos_errstr(res));
1144 1145
    taos_free_result(res);
    return;
H
hzcheng 已提交
1146
  }
1147

1148 1149 1150
  getResult(res, resultFileName);
  taos_free_result(res);
}
H
hzcheng 已提交
1151

1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
static int32_t rand_bool(){
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
  return randint[cursor] % 2;
}

static int32_t rand_tinyint(){
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
  return randint[cursor] % 128;
}

static int32_t rand_smallint(){
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
  return randint[cursor] % 32767;
}

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

static int64_t rand_bigint(){
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
  return randbigint[cursor];
}

static float rand_float(){
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
1191
  return randfloat[cursor];
1192 1193 1194
}

static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1195
static void rand_string(char *str, int size) {
1196 1197 1198 1199
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1200
    for (n = 0; n < size - 1; n++) {
1201
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217
      str[n] = charset[key];
    }
    str[n] = 0;
  }
}

static double rand_double() {
  static int cursor;
  cursor++;
  cursor = cursor % MAX_PREPARED_RAND;
  return randdouble[cursor];

}

static void init_rand_data() {
  for (int i = 0; i < MAX_PREPARED_RAND; i++){
1218 1219 1220 1221
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1222 1223 1224
  }
}

1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
#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)

1245
static int printfInsertMeta() {
1246 1247
    SHOW_PARSE_RESULT_START();

1248 1249 1250
  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);
1251
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1252 1253 1254
  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);
1255 1256 1257 1258 1259 1260
  printf("top insert interval:        \033[33m%"PRId64"\033[0m\n",
          g_args.insert_interval);
  printf("number of records per req:  \033[33m%"PRId64"\033[0m\n",
          g_args.num_of_RPR);
  printf("max sql length:             \033[33m%"PRId64"\033[0m\n",
          g_args.max_sql_len);
1261 1262

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

1264 1265
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1266
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1267
    if (0 == g_Dbs.db[i].drop) {
1268 1269 1270
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309
    }

    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) {
1310 1311
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1312 1313
        printf("  precision:             \033[33m%s\033[0m\n",
            g_Dbs.db[i].dbCfg.precision);
1314
      } else {
1315 1316 1317
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                g_Dbs.db[i].dbCfg.precision);
        return -1;
1318 1319 1320
      }
    }

1321
    printf("  super table count:     \033[33m%"PRId64"\033[0m\n",
1322
        g_Dbs.db[i].superTblCount);
1323 1324
    for (int64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRId64"\033[0m]:\n", j);
1325

1326 1327
      printf("      stbName:           \033[33m%s\033[0m\n",
          g_Dbs.db[i].superTbls[j].sTblName);
1328 1329 1330 1331 1332 1333 1334 1335

      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");
      }
1336

1337 1338 1339 1340 1341 1342 1343
      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");
      }
1344

1345
      printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
1346 1347 1348 1349 1350 1351 1352
              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("      insertMode:        \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].insertMode);
1353
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1354
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1355
                g_Dbs.db[i].superTbls[j].childTblLimit);
1356
      }
1357
      if (g_Dbs.db[i].superTbls[j].childTblOffset >= 0) {
1358
        printf("      childTblOffset:    \033[33m%"PRId64"\033[0m\n",
1359
                g_Dbs.db[i].superTbls[j].childTblOffset);
1360
      }
1361 1362
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
              g_Dbs.db[i].superTbls[j].insertRows);
1363
/*
1364
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1365
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1366
      }else {
1367
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1368
      }
1369 1370
      */
      printf("      interlaceRows:     \033[33m%"PRId64"\033[0m\n",
1371
              g_Dbs.db[i].superTbls[j].interlaceRows);
1372 1373

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

1378 1379 1380 1381
      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);
1382
      printf("      maxSqlLen:         \033[33m%"PRId64"\033[0m\n",
1383
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1384
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1385 1386 1387 1388 1389 1390 1391 1392 1393
              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);
1394
      printf("      columnCount:       \033[33m%d\033[0m\n",
1395
              g_Dbs.db[i].superTbls[j].columnCount);
1396 1397
      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);
1398 1399 1400 1401
        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))) {
1402
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1403 1404
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1405
        } else {
1406 1407
          printf("column[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1408 1409 1410
        }
      }
      printf("\n");
1411 1412 1413

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1414 1415
      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);
1416 1417 1418 1419
        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")))) {
1420
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1421 1422
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1423
        } else {
1424 1425
          printf("tag[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1426
        }
1427 1428 1429 1430 1431
      }
      printf("\n");
    }
    printf("\n");
  }
1432 1433

  SHOW_PARSE_RESULT_END();
1434 1435

  return 0;
1436 1437 1438
}

static void printfInsertMetaToFile(FILE* fp) {
1439 1440

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1441

1442 1443
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1444
  fprintf(fp, "configDir:                  %s\n", configDir);
1445 1446 1447
  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);
1448 1449
  fprintf(fp, "number of records per req:  %"PRId64"\n", g_args.num_of_RPR);
  fprintf(fp, "max sql length:             %"PRId64"\n", g_args.max_sql_len);
1450
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1451

1452 1453
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1454
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1455
    if (0 == g_Dbs.db[i].drop) {
1456
      fprintf(fp, "  drop:                  no\n");
1457
    }else {
1458
      fprintf(fp, "  drop:                  yes\n");
1459 1460 1461 1462 1463 1464 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
    }

    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) {
1498 1499
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1500 1501 1502 1503 1504 1505
        fprintf(fp, "  precision:             %s\n", g_Dbs.db[i].dbCfg.precision);
      } else {
        fprintf(fp, "  precision error:       %s\n", g_Dbs.db[i].dbCfg.precision);
      }
    }

1506
    fprintf(fp, "  super table count:     %"PRId64"\n", g_Dbs.db[i].superTblCount);
1507 1508
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1509 1510

      fprintf(fp, "      stbName:           %s\n",  g_Dbs.db[i].superTbls[j].sTblName);
1511 1512 1513 1514 1515 1516 1517 1518

      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");
      }
1519

1520 1521 1522 1523 1524 1525 1526
      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");
      }
1527

1528
      fprintf(fp, "      childTblCount:     %"PRId64"\n",
1529 1530 1531 1532 1533 1534 1535 1536 1537
              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, "      insertMode:        %s\n",
              g_Dbs.db[i].superTbls[j].insertMode);
      fprintf(fp, "      insertRows:        %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].insertRows);
1538
      fprintf(fp, "      interlace rows:    %"PRId64"\n",
1539
              g_Dbs.db[i].superTbls[j].interlaceRows);
1540
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1541
        fprintf(fp, "      stable insert interval:   %"PRId64"\n",
1542
                g_Dbs.db[i].superTbls[j].insertInterval);
1543
      }
1544
/*
1545
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1546
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1547
      }else {
1548
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1549
      }
1550 1551
      */
      fprintf(fp, "      interlaceRows:     %"PRId64"\n",
1552
              g_Dbs.db[i].superTbls[j].interlaceRows);
1553
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1554
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1555 1556
      fprintf(fp, "      maxSqlLen:         %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1557

1558 1559 1560 1561
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1562
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1563 1564 1565
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

1566 1567 1568
      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);
1569 1570 1571 1572 1573 1574 1575 1576
        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);
1577 1578 1579 1580 1581
        } else {
          fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
        }
      }
      fprintf(fp, "\n");
1582 1583 1584

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1585 1586
      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);
1587 1588 1589 1590 1591 1592
        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);
1593 1594
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1595
        }
1596 1597 1598 1599 1600
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1601

1602
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1603 1604 1605
}

static void printfQueryMeta() {
1606

1607
  SHOW_PARSE_RESULT_START();
1608

1609 1610
  printf("host:                    \033[33m%s:%u\033[0m\n",
          g_queryInfo.host, g_queryInfo.port);
1611 1612 1613 1614
  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");
1615
  printf("specified table query info:                   \n");
1616
  printf("query interval: \033[33m%"PRId64" ms\033[0m\n",
1617
      g_queryInfo.specifiedQueryInfo.queryInterval);
1618 1619
  printf("top query times:\033[33m%"PRId64"\033[0m\n", g_args.query_times);
  printf("concurrent:     \033[33m%"PRId64"\033[0m\n",
1620
      g_queryInfo.specifiedQueryInfo.concurrent);
1621
  printf("sqlCount:       \033[33m%"PRId64"\033[0m\n",
1622
      g_queryInfo.specifiedQueryInfo.sqlCount);
1623
  printf("specified tbl query times:\n");
1624
  printf("                \033[33m%"PRId64"\033[0m\n",
1625
      g_queryInfo.specifiedQueryInfo.queryTimes);
1626

1627
  if (SUBSCRIBE_TEST == g_args.test_mode) {
1628 1629
    printf("mod:            \033[33m%d\033[0m\n",
        g_queryInfo.specifiedQueryInfo.mode);
1630
    printf("interval:       \033[33m%"PRId64"\033[0m\n",
1631 1632 1633 1634 1635
        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);
1636 1637
  }

1638 1639
  for (int64_t i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
    printf("  sql[%"PRId64"]: \033[33m%s\033[0m\n",
1640
        i, g_queryInfo.specifiedQueryInfo.sql[i]);
1641 1642
  }
  printf("\n");
1643
  printf("super table query info:\n");
1644
  printf("query interval: \033[33m%"PRId64"\033[0m\n",
1645
      g_queryInfo.superQueryInfo.queryInterval);
1646 1647
  printf("threadCnt:      \033[33m%d\033[0m\n",
      g_queryInfo.superQueryInfo.threadCnt);
1648
  printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
1649 1650 1651
      g_queryInfo.superQueryInfo.childTblCount);
  printf("stable name:    \033[33m%s\033[0m\n",
      g_queryInfo.superQueryInfo.sTblName);
1652
  printf("stb query times:\033[33m%"PRId64"\033[0m\n",
1653
      g_queryInfo.superQueryInfo.queryTimes);
1654

1655
  if (SUBSCRIBE_TEST == g_args.test_mode) {
1656 1657
    printf("mod:            \033[33m%d\033[0m\n",
        g_queryInfo.superQueryInfo.mode);
1658
    printf("interval:       \033[33m%"PRId64"\033[0m\n",
1659 1660 1661 1662 1663 1664 1665
        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);
  }

1666
  printf("sqlCount:       \033[33m%"PRId64"\033[0m\n",
1667
      g_queryInfo.superQueryInfo.sqlCount);
1668
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
1669 1670
    printf("  sql[%d]: \033[33m%s\033[0m\n",
        i, g_queryInfo.superQueryInfo.sql[i]);
1671
  }
1672
  printf("\n");
1673

1674
  SHOW_PARSE_RESULT_END();
1675 1676
}

1677
static char* formatTimestamp(char* buf, int64_t val, int precision) {
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
  time_t tt;
  if (precision == TSDB_TIME_PRECISION_MICRO) {
    tt = (time_t)(val / 1000000);
  } else {
    tt = (time_t)(val / 1000);
  }

/* 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;
  }
  */

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

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

  if (precision == TSDB_TIME_PRECISION_MICRO) {
    sprintf(buf + pos, ".%06d", (int)(val % 1000000));
  } else {
    sprintf(buf + pos, ".%03d", (int)(val % 1000));
  }

  return buf;
}

1709 1710 1711
static void xDumpFieldToFile(FILE* fp, const char* val,
        TAOS_FIELD* field, int32_t length, int precision) {

1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746
  if (val == NULL) {
    fprintf(fp, "%s", TSDB_DATA_NULL_STR);
    return;
  }

  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:
1747
      formatTimestamp(buf, *(int64_t*)val, precision);
1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
      fprintf(fp, "'%s'", buf);
      break;
    default:
      break;
  }
}

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

  FILE* fp = fopen(fname, "at");
  if (fp == NULL) {
1763
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777
    return -1;
  }

  int num_fields = taos_num_fields(tres);
  TAOS_FIELD *fields = taos_fetch_fields(tres);
  int precision = taos_result_precision(tres);

  for (int col = 0; col < num_fields; col++) {
    if (col > 0) {
      fprintf(fp, ",");
    }
    fprintf(fp, "%s", fields[col].name);
  }
  fputc('\n', fp);
1778

1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798
  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);

  fclose(fp);

  return numOfRows;
}

1799 1800
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1801 1802
  TAOS_ROW row = NULL;
  int count = 0;
1803 1804

  res = taos_query(taos, "show databases;");
1805
  int32_t code = taos_errno(res);
1806

1807
  if (code != 0) {
1808
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1809 1810 1811 1812 1813
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1814
  while((row = taos_fetch_row(res)) != NULL) {
1815
    // sys database name : 'log'
1816 1817 1818 1819
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
      continue;
    }
1820 1821 1822

    dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo));
    if (dbInfos[count] == NULL) {
1823
      errorPrint( "failed to allocate memory for some dbInfo[%d]\n", count);
1824 1825 1826
      return -1;
    }

1827 1828
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1829
    formatTimestamp(dbInfos[count]->create_time,
1830 1831
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1832
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1833
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1834 1835
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1836
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1837

1838
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1839
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1840 1841 1842 1843 1844 1845 1846
    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]));
1847 1848
    dbInfos[count]->cachelast =
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1849

1850
    tstrncpy(dbInfos[count]->precision,
1851
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
1852
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1853
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1854
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1855
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1856

1857 1858
    count++;
    if (count > MAX_DATABASE_COUNT) {
1859 1860
      errorPrint("%s() LN%d, The database count overflow than %d\n",
         __func__, __LINE__, MAX_DATABASE_COUNT);
1861 1862 1863 1864 1865 1866 1867
      break;
    }
  }

  return count;
}

1868 1869
static void printfDbInfoForQueryToFile(
        char* filename, SDbInfo* dbInfos, int index) {
1870

1871
  if (filename[0] == 0)
1872
      return;
1873 1874 1875

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1876
    errorPrint( "failed to open file: %s\n", filename);
1877
    return;
1878 1879 1880 1881 1882 1883
  }

  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: %d\n", dbInfos->ntables);
1884
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1885 1886
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1887 1888
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1889 1890 1891 1892 1893 1894 1895
  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);
1896 1897
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
1898
  fprintf(fp, "update: %d\n", dbInfos->update);
1899
  fprintf(fp, "status: %s\n", dbInfos->status);
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913
  fprintf(fp, "\n");

  fclose(fp);
}

static void printfQuerySystemInfo(TAOS * taos) {
  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);
1914 1915 1916 1917
  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);

1918 1919 1920 1921 1922 1923 1924 1925 1926
  // show variables
  res = taos_query(taos, "show variables;");
  //getResult(res, filename);
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
  //getResult(res, filename);
1927

1928 1929 1930 1931
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
1932
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
1933 1934 1935
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
1936 1937 1938 1939
  if (dbCount <= 0) {
      free(dbInfos);
      return;
  }
1940 1941

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

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

1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960
    // 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]);
  }

  free(dbInfos);
}

1961
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port, char* sqlstr)
1962
{
1963
    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";
1964 1965 1966

    char *url = "/rest/sql";

1967
    int bytes, sent, received, req_str_len, resp_len;
1968 1969 1970
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
1971

1972 1973 1974
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

    request_buf = malloc(req_buf_len);
1975 1976 1977 1978
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
1979

1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990
    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', '+', '/'};
1991

1992 1993 1994 1995 1996 1997
    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];
1998
#ifdef WINDOWS
1999
    WSADATA wsaData;
2000
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2001 2002 2003 2004
    SOCKET sockfd;
#else
    int sockfd;
#endif
2005
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
2006
    if (sockfd < 0) {
2007
#ifdef WINDOWS
2008
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2009
#endif
2010
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
2011
        free(request_buf);
2012
        ERROR_EXIT("ERROR opening socket");
2013
    }
2014

2015
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2016 2017
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
2018
        free(request_buf);
2019
        ERROR_EXIT("ERROR connecting");
2020
    }
2021

2022 2023 2024
    memset(base64_buf, 0, INPUT_BUF_LEN);

    for (int n = 0, m = 0; n < userpass_buf_len;) {
2025
      uint32_t oct_a = n < userpass_buf_len ?
2026
        (unsigned char) userpass_buf[n++]:0;
2027
      uint32_t oct_b = n < userpass_buf_len ?
2028
        (unsigned char) userpass_buf[n++]:0;
2029
      uint32_t oct_c = n < userpass_buf_len ?
2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041
        (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] = '=';

2042 2043
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
2044 2045
    char *auth = base64_buf;

2046 2047 2048
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
2049 2050 2051 2052 2053
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
2054
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
2055

2056
    req_str_len = strlen(request_buf);
2057 2058
    sent = 0;
    do {
2059 2060 2061
#ifdef WINDOWS
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
#else
2062
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2063
#endif
2064
        if (bytes < 0)
2065
            ERROR_EXIT("ERROR writing message to socket");
2066 2067 2068
        if (bytes == 0)
            break;
        sent+=bytes;
2069
    } while(sent < req_str_len);
2070

2071 2072
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
2073 2074
    received = 0;
    do {
2075 2076 2077
#ifdef WINDOWS
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
#else
2078
        bytes = read(sockfd, response_buf + received, resp_len - received);
2079
#endif
2080 2081
        if (bytes < 0) {
            free(request_buf);
2082
            ERROR_EXIT("ERROR reading response from socket");
2083
        }
2084 2085
        if (bytes == 0)
            break;
2086
        received += bytes;
2087
    } while(received < resp_len);
2088

2089 2090
    if (received == resp_len) {
        free(request_buf);
2091
        ERROR_EXIT("ERROR storing complete response from socket");
2092
    }
2093

2094
    response_buf[RESP_BUF_LEN - 1] = '\0';
2095 2096 2097
    printf("Response:\n%s\n", response_buf);

    free(request_buf);
2098 2099 2100 2101
#ifdef WINDOWS
    closesocket(sockfd);
    WSACleanup();
#else
2102
    close(sockfd);
2103
#endif
2104 2105 2106 2107

    return 0;
}

2108
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2109 2110
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2111 2112
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2113 2114
    return NULL;
  }
2115

2116
  int    dataLen = 0;
2117 2118 2119
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);

2120 2121 2122
  return dataBuf;
}

2123
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2124 2125 2126 2127 2128 2129 2130 2131 2132
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
    printf("calloc failed! size:%d\n", TSDB_MAX_SQL_LEN+1);
    return NULL;
  }

  int    dataLen = 0;
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, "(");
  for (int i = 0; i < stbInfo->tagCount; i++) {
2133 2134
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2135
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2136 2137
        printf("binary or nchar length overflow, max size:%u\n",
                (uint32_t)TSDB_MAX_BINARY_LEN);
2138 2139 2140
        tmfree(dataBuf);
        return NULL;
      }
2141

2142 2143
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2144 2145 2146 2147 2148
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2149 2150 2151 2152 2153 2154 2155

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2156 2157
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
              "\'%s\', ", buf);
2158
      tmfree(buf);
2159 2160 2161
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                "int", strlen("int"))) {
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2162
              "%d, ", tableSeq);
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 2190
    } 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());
2191 2192 2193 2194 2195 2196
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2197

2198
  dataLen -= 2;
2199
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2200 2201 2202
  return dataBuf;
}

2203
static int calcRowLen(SSuperTable*  superTbls) {
2204 2205
  int colIndex;
  int  lenOfOneRow = 0;
2206

2207 2208
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2209

2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225
    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;
2226
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2227
      lenOfOneRow += 42;
2228
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
      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;
2242

2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258
    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;
2259
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2260 2261 2262 2263 2264 2265 2266 2267
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2268

2269 2270 2271 2272
  return 0;
}


2273 2274
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2275
        int64_t* childTblCountOfSuperTbl, int64_t limit, int64_t offset) {
2276

2277
  char command[BUFFER_SIZE] = "\0";
2278 2279
  char limitBuf[100] = "\0";

2280
  TAOS_RES * res;
2281 2282 2283
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2284 2285

  if (offset >= 0) {
2286 2287
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRId64"",
            limit, offset);
2288 2289
  }

2290
  //get all child table name use cmd: select tbname from superTblName;
2291 2292
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
          dbName, sTblName, limitBuf);
2293

2294
  res = taos_query(taos, command);
2295 2296 2297 2298
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2299 2300
    errorPrint("%s() LN%d, failed to run command %s\n",
           __func__, __LINE__, command);
2301 2302 2303
    exit(-1);
  }

2304
  int childTblCount = (limit < 0)?10000:limit;
2305
  int count = 0;
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315
  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);
    }
  }

2316
  char* pTblName = childTblName;
2317
  while((row = taos_fetch_row(res)) != NULL) {
2318
    int32_t* len = taos_fetch_lengths(res);
2319
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2320 2321 2322
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2323 2324
      char *tmp = realloc(childTblName,
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2325 2326 2327
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2328 2329
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2330 2331
      } else {
        // exit, if allocate more memory failed
2332 2333
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
               __func__, __LINE__, dbName, sTblName);
2334 2335 2336 2337 2338 2339
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2340
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2341
  }
2342

2343 2344 2345 2346 2347 2348 2349
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2350 2351
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
        char* sTblName, char** childTblNameOfSuperTbl,
2352
        int64_t* childTblCountOfSuperTbl) {
2353 2354 2355 2356 2357 2358

    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
            -1, -1);
}

2359 2360
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2361

2362
  char command[BUFFER_SIZE] = "\0";
2363
  TAOS_RES * res;
2364 2365
  TAOS_ROW row = NULL;
  int count = 0;
2366

2367
  //get schema use cmd: describe superTblName;
2368
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2369
  res = taos_query(taos, command);
2370 2371 2372
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2373
    taos_free_result(res);
2374 2375 2376 2377 2378 2379
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2380
  while((row = taos_fetch_row(res)) != NULL) {
2381 2382 2383
    if (0 == count) {
      count++;
      continue;
2384
    }
2385 2386

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397
      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],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
      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);
2398
      tagIndex++;
2399
    } else {
2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410
      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],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
      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);
2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2422
/*
2423
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2424
    //get all child table name use cmd: select tbname from superTblName;
2425 2426 2427
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2428
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2429 2430
      return -1;
    }
2431
    getAllChildNameOfSuperTable(taos, dbName,
2432 2433 2434
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2435
  }
2436
  */
2437 2438 2439
  return 0;
}

2440 2441
static int createSuperTable(
        TAOS * taos, char* dbName,
2442
        SSuperTable*  superTbl) {
2443

2444
  char command[BUFFER_SIZE] = "\0";
2445

2446 2447 2448 2449 2450
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2451 2452 2453 2454 2455 2456 2457 2458 2459

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

  for (colIndex = 0; colIndex < superTbl->columnCount; colIndex++) {
    char* dataType = superTbl->columns[colIndex].dataType;
2460

2461
    if (strcasecmp(dataType, "BINARY") == 0) {
2462 2463
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "BINARY",
2464 2465
          superTbl->columns[colIndex].dataLen);
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2466
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2467 2468
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "NCHAR",
2469 2470
          superTbl->columns[colIndex].dataLen);
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488
    } else if (strcasecmp(dataType, "INT") == 0)  {
      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) {
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "FLOAT");
      lenOfOneRow += 22;
2489
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2490 2491
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2492
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2493 2494 2495 2496
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2497 2498
      errorPrint("%s() LN%d, config error data type : %s\n",
         __func__, __LINE__, dataType);
2499 2500 2501 2502
      exit(-1);
    }
  }

2503 2504
  superTbl->lenOfOneRow = lenOfOneRow + 20; // timestamp
  //printf("%s.%s column count:%d, column length:%d\n\n", g_Dbs.db[i].dbName, g_Dbs.db[i].superTbl[j].sTblName, g_Dbs.db[i].superTbl[j].columnCount, lenOfOneRow);
2505 2506

  // save for creating child table
2507 2508 2509 2510
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
           __func__, __LINE__, len+1);
2511 2512 2513 2514
    taos_close(taos);
    exit(-1);
  }

2515
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2516 2517
  verbosePrint("%s() LN%d: %s\n",
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2518

2519 2520 2521 2522 2523
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
            __func__, __LINE__, superTbl->tagCount);
    return -1;
  }
2524

2525 2526 2527
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2528

2529 2530 2531 2532
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2533

2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
              "BINARY", superTbl->tags[tagIndex].dataLen);
      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)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "INT");
      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);
2572 2573
      errorPrint("%s() LN%d, config error tag type : %s\n",
         __func__, __LINE__, dataType);
2574
      exit(-1);
2575 2576
    }
  }
2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

  snprintf(command, BUFFER_SIZE,
          "create table if not exists %s.%s (ts timestamp%s) tags %s",
          dbName, superTbl->sTblName, cols, tags);
  verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, command);

  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);
2594 2595 2596
  return 0;
}

2597
static int createDatabasesAndStables() {
2598 2599 2600 2601
  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) {
2602
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2603
    return -1;
2604 2605 2606
  }
  char command[BUFFER_SIZE] = "\0";

2607
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2608 2609
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2610
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2611
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2612 2613 2614 2615
        taos_close(taos);
        return -1;
      }

2616
      int dataLen = 0;
2617
      dataLen += snprintf(command + dataLen,
2618
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2619

2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689
      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);
      }

      debugPrint("%s() %d command: %s\n", __func__, __LINE__, command);
      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);
2690 2691
    }

2692
    debugPrint("%s() LN%d supertbl count:%"PRId64"\n",
2693
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2694 2695 2696

    int validStbCount = 0;

2697
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2698 2699 2700 2701 2702 2703 2704
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);

      ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);

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

2708
        if (0 != ret) {
2709 2710
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2711 2712 2713
        }
      }

2714
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2715
                &g_Dbs.db[i].superTbls[j]);
2716 2717 2718
      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);
2719
        continue;
2720
      }
2721 2722

      validStbCount ++;
2723
    }
2724 2725

    g_Dbs.db[i].superTblCount = validStbCount;
2726 2727 2728 2729 2730 2731
  }

  taos_close(taos);
  return 0;
}

2732 2733
static void* createTable(void *sarg)
{
2734 2735
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2736 2737 2738

  int64_t  lastPrintTime = taosGetTimestampMs();

2739
  int buff_len;
2740
  buff_len = BUFFER_SIZE / 8;
2741

2742
  char *buffer = calloc(buff_len, 1);
2743
  if (buffer == NULL) {
2744
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2745 2746
    exit(-1);
  }
2747 2748 2749

  int len = 0;
  int batchNum = 0;
2750

2751
  verbosePrint("%s() LN%d: Creating table from %"PRId64" to %"PRId64"\n",
2752
          __func__, __LINE__,
2753
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2754

2755 2756
  for (int64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
2757
    if (0 == g_Dbs.use_metric) {
2758
      snprintf(buffer, buff_len,
2759
              "create table if not exists %s.%s%"PRId64" %s;",
2760
              pThreadInfo->db_name,
2761
              g_args.tb_prefix, i,
2762
              pThreadInfo->cols);
2763
    } else {
2764 2765 2766
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
                  __func__, __LINE__);
2767
        free(buffer);
2768 2769 2770 2771 2772 2773 2774 2775 2776 2777
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
          memset(buffer, 0, buff_len);
          len += snprintf(buffer + len,
                  buff_len - len, "create table ");
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
2778
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2779 2780 2781 2782 2783 2784 2785 2786 2787 2788
        } else {
          tagsValBuf = getTagValueFromTagSample(
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
        len += snprintf(buffer + len,
2789
                buff_len - len,
2790
                "if not exists %s.%s%"PRId64" using %s.%s tags %s ",
2791 2792
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
2793 2794 2795 2796
                superTblInfo->sTblName, tagsValBuf);
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2797
                && ((buff_len - len)
2798 2799 2800
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
          continue;
        }
2801 2802 2803 2804
      }
    }

    len = 0;
2805
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2806
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2807
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2808
      free(buffer);
2809 2810 2811 2812 2813
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2814
      printf("thread[%d] already create %"PRId64" - %"PRId64" tables\n",
2815
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2816 2817 2818
      lastPrintTime = currentPrintTime;
    }
  }
2819

2820
  if (0 != len) {
2821
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2822
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2823
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2824
    }
2825
  }
2826

2827 2828 2829 2830
  free(buffer);
  return NULL;
}

2831
static int startMultiThreadCreateChildTable(
2832
        char* cols, int threads, int64_t startFrom, int64_t ntables,
2833
        char* db_name, SSuperTable* superTblInfo) {
2834

2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  threadInfo *infos = malloc(threads * sizeof(threadInfo));

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

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

2847
  int64_t a = ntables / threads;
2848 2849 2850 2851 2852
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2853
  int64_t b = 0;
2854
  b = ntables % threads;
2855

2856
  for (int64_t i = 0; i < threads; i++) {
2857 2858
    threadInfo *t_info = infos + i;
    t_info->threadID = i;
H
Hui Li 已提交
2859
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
2860
    t_info->superTblInfo = superTblInfo;
2861
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
2862 2863 2864 2865 2866 2867
    t_info->taos = taos_connect(
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
2868
    if (t_info->taos == NULL) {
2869 2870
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
         __func__, __LINE__, taos_errstr(NULL));
2871
      free(pids);
2872
      free(infos);
2873 2874
      return -1;
    }
2875 2876 2877 2878 2879

    t_info->start_table_from = startFrom;
    t_info->ntables = i<b?a+1:a;
    t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
    startFrom = t_info->end_table_to + 1;
2880
    t_info->use_metric = true;
2881
    t_info->cols = cols;
2882
    t_info->minDelay = INT64_MAX;
2883 2884
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2885

2886 2887 2888 2889 2890 2891 2892 2893 2894 2895
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

  for (int i = 0; i < threads; i++) {
    threadInfo *t_info = infos + i;
    taos_close(t_info->taos);
  }

  free(pids);
2896
  free(infos);
2897 2898

  return 0;
2899 2900
}

2901 2902 2903 2904
static void createChildTables() {
    char tblColsBuf[MAX_SQL_SIZE];
    int len;

2905
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2906 2907 2908 2909 2910 2911 2912 2913
    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;
          }
2914

2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
          int startFrom = 0;
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

          verbosePrint("%s() LN%d: create %d child tables from %d\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]));
        }
2929 2930
      }
    } else {
2931 2932
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
2933
      for (int j = 0; j < g_args.num_of_CPR; j++) {
2934 2935 2936 2937
          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,
2938
                      ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary);
2939 2940 2941 2942 2943 2944
          } else {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                      ", COL%d %s", j, g_args.datatype[j]);
          }
          len = strlen(tblColsBuf);
      }
2945

2946
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
2947

2948
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
2949 2950 2951 2952 2953 2954 2955 2956 2957
              __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);
2958
    }
2959 2960 2961 2962 2963 2964
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
2965
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
2966 2967 2968
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
2969

2970 2971
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
2972 2973
    printf("Failed to open tags file: %s, reason:%s\n",
            superTblInfo->tagsFile, strerror(errno));
2974 2975 2976 2977 2978 2979 2980
    return -1;
  }

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

2982 2983 2984 2985 2986 2987 2988 2989 2990
  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;
  }

2991
  while((readLen = tgetline(&line, &n, fp)) != -1) {
2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003
    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) {
3004 3005
      char *tmp = realloc(tagDataBuf,
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3006 3007 3008
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3009 3010
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037
      } 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;
}

int readSampleFromJsonFileToMem(SSuperTable  * superTblInfo) {
  // TODO
  return 0;
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3038 3039
static int readSampleFromCsvFileToMem(
        SSuperTable* superTblInfo) {
3040 3041 3042 3043
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3044

3045 3046
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3047
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
3048 3049 3050
              superTblInfo->sampleFile, strerror(errno));
      return -1;
  }
3051

3052
  assert(superTblInfo->sampleDataBuf);
3053 3054
  memset(superTblInfo->sampleDataBuf, 0,
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3055
  while(1) {
3056
    readLen = tgetline(&line, &n, fp);
3057 3058
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3059
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3060
                superTblInfo->sampleFile, strerror(errno));
3061
        fclose(fp);
3062 3063 3064 3065
        return -1;
      }
      continue;
    }
3066

3067 3068 3069 3070 3071 3072 3073 3074 3075
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3076
      printf("sample row len[%d] overflow define schema len[%"PRId64"], so discard this row\n",
3077
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3078 3079 3080
      continue;
    }

3081 3082
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
          line, readLen);
3083 3084 3085 3086 3087 3088 3089
    getRows++;

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

3090
  fclose(fp);
3091 3092 3093 3094
  tmfree(line);
  return 0;
}

3095 3096
static bool getColumnAndTagTypeFromInsertJsonFile(
        cJSON* stbInfo, SSuperTable* superTbls) {
3097
  bool  ret = false;
3098

3099
  // columns
3100 3101
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3102
    printf("ERROR: failed to read json, columns not found\n");
3103 3104 3105 3106 3107 3108
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3109

3110
  int columnSize = cJSON_GetArraySize(columns);
3111
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3112 3113
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
            __func__, __LINE__, MAX_COLUMN_COUNT);
3114 3115 3116 3117 3118 3119
    goto PARSE_OVER;
  }

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

3121
  //superTbls->columnCount = columnSize;
3122 3123 3124 3125 3126 3127 3128
  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) {
3129
      count = countObj->valueint;
3130
    } else if (countObj && countObj->type != cJSON_Number) {
3131 3132
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
          __func__, __LINE__);
3133 3134 3135 3136 3137
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3138
    // column info
3139 3140
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3141 3142 3143 3144
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
          __func__, __LINE__);
3145 3146
      goto PARSE_OVER;
    }
3147 3148
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3149

3150 3151
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3152
      columnCase.dataLen = dataLen->valueint;
3153
    } else if (dataLen && dataLen->type != cJSON_Number) {
3154 3155
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
          __func__, __LINE__);
3156 3157 3158 3159
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3160

3161
    for (int n = 0; n < count; ++n) {
3162 3163 3164
      tstrncpy(superTbls->columns[index].dataType,
              columnCase.dataType, MAX_TB_NAME_SIZE);
      superTbls->columns[index].dataLen = columnCase.dataLen;
3165 3166
      index++;
    }
3167
  }
3168

3169 3170
  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",
3171 3172 3173 3174
            __func__, __LINE__, MAX_COLUMN_COUNT);
    goto PARSE_OVER;
  }

3175
  superTbls->columnCount = index;
3176

3177 3178
  count = 1;
  index = 0;
3179
  // tags
3180 3181
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3182 3183
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
        __func__, __LINE__);
3184 3185
    goto PARSE_OVER;
  }
3186

3187 3188
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3189 3190
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
        __func__, __LINE__, MAX_TAG_COUNT);
3191 3192
    goto PARSE_OVER;
  }
3193 3194

  //superTbls->tagCount = tagSize;
3195 3196 3197
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3198

3199 3200 3201
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3202
      count = countObj->valueint;
3203
    } else if (countObj && countObj->type != cJSON_Number) {
3204
      printf("ERROR: failed to read json, column count not found\n");
3205 3206 3207 3208 3209
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3210
    // column info
3211 3212
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3213 3214 3215 3216
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
          __func__, __LINE__);
3217 3218
      goto PARSE_OVER;
    }
3219
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3220

3221 3222
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3223
      columnCase.dataLen = dataLen->valueint;
3224
    } else if (dataLen && dataLen->type != cJSON_Number) {
3225 3226
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
          __func__, __LINE__);
3227 3228 3229
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3230 3231
    }

3232
    for (int n = 0; n < count; ++n) {
3233 3234
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
          MAX_TB_NAME_SIZE);
3235
      superTbls->tags[index].dataLen = columnCase.dataLen;
3236 3237
      index++;
    }
3238
  }
3239 3240

  if (index > MAX_TAG_COUNT) {
3241
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3242 3243 3244 3245
        __func__, __LINE__, MAX_TAG_COUNT);
    goto PARSE_OVER;
  }

3246 3247
  superTbls->tagCount = index;

3248 3249 3250
  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);
3251 3252
    goto PARSE_OVER;
  }
3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263
  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) {
3264
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3265 3266 3267 3268
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3269
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3270
  } else if (!host) {
3271
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3272
  } else {
3273
    printf("ERROR: failed to read json, host not found\n");
3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
    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) {
3286
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3287
  } else if (!user) {
3288
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3289 3290 3291 3292
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3293
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3294
  } else if (!password) {
3295
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3296 3297 3298 3299
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3300
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3301
  } else if (!resultfile) {
3302
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3303 3304 3305 3306 3307 3308 3309 3310
  }

  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 {
3311
    printf("ERROR: failed to read json, threads not found\n");
3312
    goto PARSE_OVER;
3313 3314
  }

3315 3316 3317 3318
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
3319
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
3320
  } else {
3321 3322
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
            __func__, __LINE__);
3323
    goto PARSE_OVER;
3324
  }
3325

3326 3327 3328 3329 3330 3331
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3332 3333
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
        __func__, __LINE__);
3334 3335
    goto PARSE_OVER;
  }
3336

3337 3338 3339
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
    g_args.interlace_rows = interlaceRows->valueint;
3340 3341 3342

    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
3343
      printf("NOTICE: interlace rows value %"PRId64" > num_of_records_per_req %"PRId64"\n\n",
3344
              g_args.interlace_rows, g_args.num_of_RPR);
3345
      printf("        interlace rows value will be set to num_of_records_per_req %"PRId64"\n\n",
3346
              g_args.num_of_RPR);
3347
      printf("        press Enter key to continue or Ctrl-C to stop.");
3348 3349 3350
      (void)getchar();
      g_args.interlace_rows = g_args.num_of_RPR;
    }
3351
  } else if (!interlaceRows) {
3352
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3353
  } else {
3354 3355
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
3356
    goto PARSE_OVER;
3357
  }
3358

3359 3360 3361 3362
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
3363
    g_args.max_sql_len = 1024000;
3364
  } else {
3365 3366
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
3367 3368 3369 3370 3371 3372 3373
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3374
    g_args.num_of_RPR = INT64_MAX;
3375
  } else {
3376 3377
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
        __func__, __LINE__);
3378 3379 3380
    goto PARSE_OVER;
  }

3381
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3382
  if (answerPrompt
3383 3384
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3385 3386 3387 3388 3389 3390 3391 3392 3393 3394
    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) {
    g_args.answer_yes = false;
  } else {
3395
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3396
    goto PARSE_OVER;
3397
  }
3398 3399 3400

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3401
    printf("ERROR: failed to read json, databases not found\n");
3402 3403 3404 3405 3406
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3407
    errorPrint(
3408 3409
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3410 3411 3412 3413 3414 3415 3416 3417
    goto PARSE_OVER;
  }

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

3418
    // dbinfo
3419 3420
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3421
      printf("ERROR: failed to read json, dbinfo not found\n");
3422 3423
      goto PARSE_OVER;
    }
3424

3425 3426
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3427
      printf("ERROR: failed to read json, db name not found\n");
3428 3429
      goto PARSE_OVER;
    }
3430
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3431 3432 3433

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3434 3435
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3436
      } else {
3437
        g_Dbs.db[i].drop = false;
3438
      }
3439
    } else if (!drop) {
3440
      g_Dbs.db[i].drop = g_args.drop_database;
3441
    } else {
3442 3443
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
              __func__, __LINE__);
3444 3445 3446 3447
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3448 3449 3450 3451
    if (precision && precision->type == cJSON_String
            && precision->valuestring != NULL) {
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
              MAX_DB_NAME_SIZE);
3452
    } else if (!precision) {
3453
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3454 3455
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3456
      printf("ERROR: failed to read json, precision not found\n");
3457 3458 3459 3460 3461 3462 3463 3464 3465
      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 {
3466
      printf("ERROR: failed to read json, update not found\n");
3467 3468 3469 3470 3471 3472 3473 3474 3475
      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 {
3476
      printf("ERROR: failed to read json, replica not found\n");
3477 3478 3479 3480 3481 3482 3483 3484 3485
      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 {
3486
     printf("ERROR: failed to read json, keep not found\n");
3487 3488
     goto PARSE_OVER;
    }
3489

3490 3491 3492 3493 3494 3495
    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 {
3496
     printf("ERROR: failed to read json, days not found\n");
3497 3498
     goto PARSE_OVER;
    }
3499

3500 3501 3502 3503 3504 3505
    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 {
3506
     printf("ERROR: failed to read json, cache not found\n");
3507 3508
     goto PARSE_OVER;
    }
3509

3510 3511 3512 3513 3514 3515
    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 {
3516
     printf("ERROR: failed to read json, block not found\n");
3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535
     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) {
      g_Dbs.db[i].dbCfg.minRows = -1;
    } else {
3536
     printf("ERROR: failed to read json, minRows not found\n");
3537 3538 3539 3540 3541 3542 3543 3544 3545
     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) {
      g_Dbs.db[i].dbCfg.maxRows = -1;
    } else {
3546
     printf("ERROR: failed to read json, maxRows not found\n");
3547 3548 3549 3550 3551 3552 3553 3554 3555
     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 {
3556
     printf("ERROR: failed to read json, comp not found\n");
3557 3558 3559 3560 3561 3562 3563 3564 3565
     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 {
3566
     printf("ERROR: failed to read json, walLevel not found\n");
3567 3568 3569
     goto PARSE_OVER;
    }

3570 3571 3572 3573 3574 3575
    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 {
3576
     printf("ERROR: failed to read json, cacheLast not found\n");
3577 3578 3579
     goto PARSE_OVER;
    }

3580 3581 3582 3583
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3584
      g_Dbs.db[i].dbCfg.quorum = 1;
3585
    } else {
3586
     printf("failed to read json, quorum input mistake");
3587 3588 3589 3590 3591 3592 3593 3594 3595
     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 {
3596 3597 3598
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
              __func__, __LINE__);
      goto PARSE_OVER;
3599
    }
3600

3601
    // super_talbes
3602 3603
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3604 3605
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
              __func__, __LINE__);
3606
      goto PARSE_OVER;
3607 3608
    }

3609 3610
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3611
      errorPrint(
3612 3613
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3614 3615 3616 3617 3618 3619 3620
      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;
3621 3622

      // dbinfo
3623 3624
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3625 3626
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
                __func__, __LINE__);
3627 3628
        goto PARSE_OVER;
      }
3629
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3630

3631 3632
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3633
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3634 3635
        goto PARSE_OVER;
      }
3636
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3637 3638

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3639 3640 3641
      if (autoCreateTbl
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3642 3643 3644 3645 3646 3647 3648 3649 3650 3651
        if (0 == strncasecmp(autoCreateTbl->valuestring, "yes", 3)) {
          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;
        }
      } else if (!autoCreateTbl) {
        g_Dbs.db[i].superTbls[j].autoCreateTable = PRE_CREATE_SUBTBL;
      } else {
3652
        printf("ERROR: failed to read json, auto_create_table not found\n");
3653 3654
        goto PARSE_OVER;
      }
3655

3656 3657 3658 3659
      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) {
3660
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3661
      } else {
3662
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3663
        goto PARSE_OVER;
3664
      }
3665 3666

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3667 3668 3669
      if (childTblExists
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3670 3671
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3672
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3673 3674
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
              || (g_Dbs.db[i].drop == true))) {
3675 3676 3677 3678 3679 3680 3681
          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 {
3682 3683
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
                __func__, __LINE__);
3684 3685
        goto PARSE_OVER;
      }
3686

3687 3688
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3689 3690
        errorPrint("%s() LN%d, failed to read json, childtable_count not found\n",
                __func__, __LINE__);
3691 3692 3693 3694 3695
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3696 3697 3698 3699
      if (dataSource && dataSource->type == cJSON_String
              && dataSource->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3700
      } else if (!dataSource) {
3701
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3702
      } else {
3703 3704
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
            __func__, __LINE__);
3705 3706 3707
        goto PARSE_OVER;
      }

3708
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3709 3710 3711 3712
      if (insertMode && insertMode->type == cJSON_String
              && insertMode->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3713
      } else if (!insertMode) {
3714
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3715
      } else {
3716
        printf("ERROR: failed to read json, insert_mode not found\n");
3717 3718 3719
        goto PARSE_OVER;
      }

3720
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3721 3722
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3723 3724 3725 3726 3727 3728
        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 {
3729
        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.
3730 3731 3732
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3733 3734
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3735 3736 3737 3738 3739 3740 3741 3742 3743
        if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) {
            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;
      }

3744 3745
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3746 3747
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                ts->valuestring, MAX_DB_NAME_SIZE);
3748
      } else if (!ts) {
3749 3750
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                "now", MAX_DB_NAME_SIZE);
3751
      } else {
3752
        printf("ERROR: failed to read json, start_timestamp not found\n");
3753 3754
        goto PARSE_OVER;
      }
3755

3756 3757 3758 3759
      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) {
3760
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3761
      } else {
3762
        printf("ERROR: failed to read json, timestamp_step not found\n");
3763 3764 3765 3766
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3767 3768
      if (sampleFormat && sampleFormat->type
              == cJSON_String && sampleFormat->valuestring != NULL) {
3769 3770
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3771
      } else if (!sampleFormat) {
3772
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3773
      } else {
3774
        printf("ERROR: failed to read json, sample_format not found\n");
3775
        goto PARSE_OVER;
3776
      }
3777

3778
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
3779 3780
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
3781 3782
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3783 3784 3785
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3786
        printf("ERROR: failed to read json, sample_file not found\n");
3787
        goto PARSE_OVER;
3788
      }
3789

3790 3791
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3792 3793
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3794 3795 3796 3797 3798 3799 3800 3801 3802
        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 {
3803
        printf("ERROR: failed to read json, tags_file not found\n");
3804 3805
        goto PARSE_OVER;
      }
3806

3807 3808 3809 3810 3811
      cJSON* maxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
      if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
        int32_t len = maxSqlLen->valueint;
        if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
          len = TSDB_MAX_ALLOWED_SQL_LEN;
3812 3813
        } else if (len < 5) {
          len = 5;
3814
        }
3815 3816
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
3817
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
3818
      } else {
3819 3820
        errorPrint("%s() LN%d, failed to read json, maxSqlLen input mistake\n",
            __func__, __LINE__);
3821
        goto PARSE_OVER;
3822
      }
3823
/*
3824 3825 3826 3827 3828
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
3829 3830 3831 3832
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
3833
        }
3834 3835 3836
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
3837
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
3838 3839
        goto PARSE_OVER;
      }
3840
*/
3841 3842 3843
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3844 3845
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
3846
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %"PRId64" > num_of_records_per_req %"PRId64"\n\n",
3847
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
3848
          printf("        interlace rows value will be set to num_of_records_per_req %"PRId64"\n\n",
3849
                  g_args.num_of_RPR);
3850
          printf("        press Enter key to continue or Ctrl-C to stop.");
3851 3852 3853
          (void)getchar();
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
3854 3855
      } else if (!interlaceRows) {
        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
3856
      } else {
3857 3858 3859
        errorPrint(
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3860
        goto PARSE_OVER;
3861
      }
3862 3863 3864

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3865 3866 3867 3868 3869 3870
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

3871 3872 3873 3874
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3875
        printf("ERROR: failed to read json, disorderRatio not found\n");
3876
        goto PARSE_OVER;
3877
      }
3878 3879 3880 3881 3882 3883 3884

      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 {
3885
        printf("ERROR: failed to read json, disorderRange not found\n");
3886 3887
        goto PARSE_OVER;
      }
3888

3889 3890 3891 3892 3893 3894
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
3895 3896
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
3897 3898 3899 3900 3901 3902 3903
        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;
      } else if (!insertInterval) {
3904
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRId64".\n",
3905 3906 3907
                __func__, __LINE__, g_args.insert_interval);
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
3908 3909
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
3910 3911 3912
        goto PARSE_OVER;
      }

3913 3914
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
              stbInfo, &g_Dbs.db[i].superTbls[j]);
3915 3916
      if (false == retVal) {
        goto PARSE_OVER;
3917 3918
      }
    }
3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931
  }

  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) {
3932
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3933 3934 3935 3936
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3937
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
3938
  } else if (!host) {
3939
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3940
  } else {
3941
    printf("ERROR: failed to read json, host not found\n");
3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953
    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) {
3954
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
3955
  } else if (!user) {
3956
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
3957 3958 3959 3960
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3961
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
3962
  } else if (!password) {
3963
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
3964
  }
H
hzcheng 已提交
3965

3966
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3967 3968
  if (answerPrompt && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3969 3970 3971 3972
    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 已提交
3973
    } else {
3974
      g_args.answer_yes = false;
H
hzcheng 已提交
3975
    }
3976 3977 3978
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
3979
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3980
    goto PARSE_OVER;
3981
  }
3982

3983 3984 3985 3986 3987 3988
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
3989 3990
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
3991 3992 3993
    goto PARSE_OVER;
  }

3994 3995
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
3996
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
3997
  } else if (!dbs) {
3998
    printf("ERROR: failed to read json, databases not found\n");
3999
    goto PARSE_OVER;
H
hzcheng 已提交
4000
  }
4001 4002 4003

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4004
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4005
  } else if (!queryMode) {
4006
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4007
  } else {
4008
    printf("ERROR: failed to read json, query_mode not found\n");
4009
    goto PARSE_OVER;
H
hzcheng 已提交
4010
  }
4011

4012
  // super_table_query
4013 4014 4015 4016 4017
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4018
    printf("ERROR: failed to read json, super_table_query not found\n");
4019
    goto PARSE_OVER;
4020
  } else {
4021 4022 4023 4024 4025
    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;
4026 4027
    }

4028 4029
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
        "query_times");
4030 4031 4032 4033 4034
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4035 4036
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4037
      goto PARSE_OVER;
4038
    }
4039

4040
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4041
    if (concurrent && concurrent->type == cJSON_Number) {
4042
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4043
      if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
4044
        errorPrint("%s() LN%d, query sqlCount %"PRId64" or concurrent %"PRId64" is not correct.\n",
4045 4046 4047 4048
              __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount,
              g_queryInfo.specifiedQueryInfo.concurrent);
        goto PARSE_OVER;
      }
4049
    } else if (!concurrent) {
4050
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4051
    }
4052

4053 4054 4055 4056
    cJSON* mode = cJSON_GetObjectItem(specifiedQuery, "mode");
    if (mode && mode->type == cJSON_String
        && mode->valuestring != NULL) {
      if (0 == strcmp("sync", mode->valuestring)) {
4057
        g_queryInfo.specifiedQueryInfo.mode = SYNC_QUERY_MODE;
4058
      } else if (0 == strcmp("async", mode->valuestring)) {
4059
        g_queryInfo.specifiedQueryInfo.mode = ASYNC_QUERY_MODE;
4060
      } else {
4061 4062
        errorPrint("%s() LN%d, failed to read json, query mode input error\n",
            __func__, __LINE__);
4063 4064 4065
        goto PARSE_OVER;
      }
    } else {
4066
      g_queryInfo.specifiedQueryInfo.mode = SYNC_QUERY_MODE;
4067
    }
4068

4069
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4070
    if (interval && interval->type == cJSON_Number) {
4071
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4072
    } else if (!interval) {
4073 4074
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4075
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4076
    }
4077

4078
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4079
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4080
      if (0 == strcmp("yes", restart->valuestring)) {
4081
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4082
      } else if (0 == strcmp("no", restart->valuestring)) {
4083
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
4084
      } else {
4085
        printf("ERROR: failed to read json, subscribe restart error\n");
4086 4087 4088
        goto PARSE_OVER;
      }
    } else {
4089
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4090
    }
4091

4092
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4093 4094 4095
    if (keepProgress
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4096
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4097
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4098
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4099
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4100
      } else {
4101
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4102 4103 4104
        goto PARSE_OVER;
      }
    } else {
4105
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4106 4107
    }

4108
    // sqls
4109
    cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
4110
    if (!superSqls) {
4111
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4112
    } else if (superSqls->type != cJSON_Array) {
4113 4114
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
          __func__, __LINE__);
4115
      goto PARSE_OVER;
4116
    } else {
4117 4118
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4119 4120
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4121 4122
        goto PARSE_OVER;
      }
4123

4124
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4125 4126 4127
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4128

4129 4130
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4131
          printf("ERROR: failed to read json, sql not found\n");
4132 4133
          goto PARSE_OVER;
        }
4134
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4135

4136 4137
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
4138
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4139
        } else if (NULL == result) {
4140
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4141
        } else {
4142
          printf("ERROR: failed to read json, super query result file not found\n");
4143
          goto PARSE_OVER;
4144
        }
4145 4146 4147
      }
    }
  }
4148

4149
  // sub_table_query
4150 4151 4152 4153 4154
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
    g_queryInfo.superQueryInfo.threadCnt = 0;
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4155
    printf("ERROR: failed to read json, sub_table_query not found\n");
4156 4157
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4158
  } else {
4159
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4160
    if (subrate && subrate->type == cJSON_Number) {
4161
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4162
    } else if (!subrate) {
4163
      g_queryInfo.superQueryInfo.queryInterval = 0;
4164 4165 4166 4167 4168 4169 4170 4171
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4172 4173
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4174
      goto PARSE_OVER;
4175
    }
4176

4177
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4178
    if (threads && threads->type == cJSON_Number) {
4179
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4180
    } else if (!threads) {
4181
      g_queryInfo.superQueryInfo.threadCnt = 1;
4182
    }
4183

4184
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4185
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4186
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4187
    //} else if (!subTblCnt) {
4188
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4189
    //}
4190

4191
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4192 4193 4194 4195
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
          MAX_TB_NAME_SIZE);
4196
    } else {
4197 4198
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
          __func__, __LINE__);
4199 4200
      goto PARSE_OVER;
    }
4201

4202
    cJSON* submode = cJSON_GetObjectItem(superQuery, "mode");
4203 4204
    if (submode && submode->type == cJSON_String
        && submode->valuestring != NULL) {
4205
      if (0 == strcmp("sync", submode->valuestring)) {
4206
        g_queryInfo.superQueryInfo.mode = SYNC_QUERY_MODE;
4207
      } else if (0 == strcmp("async", submode->valuestring)) {
4208
        g_queryInfo.superQueryInfo.mode = ASYNC_QUERY_MODE;
4209
      } else {
4210 4211
        errorPrint("%s() LN%d, failed to read json, query mode input error\n",
            __func__, __LINE__);
4212 4213 4214
        goto PARSE_OVER;
      }
    } else {
4215
      g_queryInfo.superQueryInfo.mode = SYNC_QUERY_MODE;
4216
    }
4217

4218
    cJSON* subinterval = cJSON_GetObjectItem(superQuery, "interval");
4219
    if (subinterval && subinterval->type == cJSON_Number) {
4220
      g_queryInfo.superQueryInfo.subscribeInterval = subinterval->valueint;
4221
    } else if (!subinterval) {
4222 4223
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4224
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4225
    }
4226

4227
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4228 4229
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4230
      if (0 == strcmp("yes", subrestart->valuestring)) {
4231
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
4232
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4233
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
4234
      } else {
4235
        printf("ERROR: failed to read json, subscribe restart error\n");
4236 4237 4238
        goto PARSE_OVER;
      }
    } else {
4239
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
4240
    }
4241

4242
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
4243 4244 4245
    if (subkeepProgress &&
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
4246
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
4247
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4248
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
4249
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4250
      } else {
4251
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4252 4253 4254
        goto PARSE_OVER;
      }
    } else {
4255
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4256
    }
4257

4258
    // sqls
4259
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
4260
    if (!subsqls) {
4261
      g_queryInfo.superQueryInfo.sqlCount = 0;
4262
    } else if (subsqls->type != cJSON_Array) {
4263 4264
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
          __func__, __LINE__);
4265
      goto PARSE_OVER;
4266
    } else {
4267 4268
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4269 4270
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4271 4272
        goto PARSE_OVER;
      }
4273

4274
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4275
      for (int j = 0; j < superSqlSize; ++j) {
4276 4277
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4278

4279
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4280 4281 4282 4283
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
              __func__, __LINE__);
4284 4285
          goto PARSE_OVER;
        }
4286 4287
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
            MAX_QUERY_SQL_LENGTH);
4288 4289

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4290 4291 4292 4293
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
              result->valuestring, MAX_FILE_NAME_LEN);
4294
        } else if (NULL == result) {
4295
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4296
        }  else {
4297 4298
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
              __func__, __LINE__);
4299
          goto PARSE_OVER;
4300
        }
4301 4302
      }
    }
H
hzcheng 已提交
4303 4304
  }

4305
  ret = true;
H
hzcheng 已提交
4306

4307 4308 4309
PARSE_OVER:
  return ret;
}
H
hzcheng 已提交
4310

4311
static bool getInfoFromJsonFile(char* file) {
4312
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4313

4314 4315 4316 4317 4318
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4319

4320
  bool  ret = false;
4321
  int   maxLen = 6400000;
4322 4323 4324 4325 4326 4327 4328
  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 已提交
4329
  }
H
Hui Li 已提交
4330

4331 4332 4333
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4334
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4335 4336
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4337

4338 4339 4340
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4341
      g_args.test_mode = INSERT_TEST;
4342
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4343
      g_args.test_mode = QUERY_TEST;
4344
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4345
      g_args.test_mode = SUBSCRIBE_TEST;
4346
    } else {
4347
      printf("ERROR: failed to read json, filetype not support\n");
4348 4349 4350
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4351
    g_args.test_mode = INSERT_TEST;
4352
  } else {
4353
    printf("ERROR: failed to read json, filetype not found\n");
4354 4355
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4356

4357
  if (INSERT_TEST == g_args.test_mode) {
4358
    ret = getMetaFromInsertJsonFile(root);
4359 4360
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4361 4362
    ret = getMetaFromQueryJsonFile(root);
  } else {
4363 4364
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4365
    goto PARSE_OVER;
4366
  }
4367 4368 4369 4370

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4371
  fclose(fp);
4372 4373
  return ret;
}
H
hzcheng 已提交
4374

4375
static void prepareSampleData() {
4376
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4377 4378 4379
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      if (g_Dbs.db[i].superTbls[j].tagsFile[0] != 0) {
        (void)readTagFromCsvFileToMem(&g_Dbs.db[i].superTbls[j]);
S
Shuaiqiang Chang 已提交
4380
      }
4381 4382 4383 4384
    }
  }
}

4385
static void postFreeResource() {
4386
  tmfclose(g_fpOfInsertResult);
4387
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4388
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4389 4390 4391
      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 已提交
4392
      }
4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404
      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 已提交
4405
    }
4406 4407
  }
}
S
Shuaiqiang Chang 已提交
4408

4409 4410 4411
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4412
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4413
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4414
    if (0 != ret) {
4415
      tmfree(superTblInfo->sampleDataBuf);
4416
      superTblInfo->sampleDataBuf = NULL;
4417 4418
      return -1;
    }
4419
*/
4420 4421
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4422

4423
  int    dataLen = 0;
4424

4425 4426 4427 4428
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "(%" PRId64 ", ", timestamp);
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4429
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4430

4431
  (*sampleUsePos)++;
4432

4433 4434
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4435

4436 4437
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4438
  char  *pstr = recBuf;
4439
  int64_t maxLen = MAX_DATA_SIZE;
4440 4441 4442

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

4443
  for (int i = 0; i < stbInfo->columnCount; i++) {
4444 4445
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) {
4446
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4447
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4448
                (uint32_t)TSDB_MAX_BINARY_LEN);
4449
        return -1;
4450
      }
4451

4452 4453
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4454
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4455
        return -1;
4456 4457
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4458
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\', ", buf);
4459
      tmfree(buf);
4460 4461
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "int", 3)) {
4462
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4463 4464 4465
              "%d, ", rand_int());
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "bigint", 6)) {
4466
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4467 4468 4469
              "%"PRId64", ", rand_bigint());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "float", 5)) {
4470
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4471 4472 4473
              "%f, ", rand_float());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "double", 6)) {
4474
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4475 4476 4477
              "%f, ", rand_double());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "smallint", 8)) {
4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491
      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());
4492
    }  else {
4493
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4494
      return -1;
4495
    }
S
Shuaiqiang Chang 已提交
4496
  }
4497

4498
  dataLen -= 2;
4499
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4500

4501 4502 4503
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4504
}
S
Shuaiqiang Chang 已提交
4505

4506
static int64_t generateData(char *recBuf, char **data_type,
4507
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4508 4509
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523
  pstr += sprintf(pstr, "(%" PRId64, timestamp);
  int c = 0;

  for (; c < MAX_NUM_DATATYPE; c++) {
    if (data_type[c] == NULL) {
      break;
    }
  }

  if (0 == c) {
    perror("data type error!");
    exit(-1);
  }

4524
  for (int i = 0; i < c; i++) {
4525 4526 4527 4528 4529
    if (strcasecmp(data_type[i % c], "tinyint") == 0) {
      pstr += sprintf(pstr, ", %d", rand_tinyint() );
    } else if (strcasecmp(data_type[i % c], "smallint") == 0) {
      pstr += sprintf(pstr, ", %d", rand_smallint());
    } else if (strcasecmp(data_type[i % c], "int") == 0) {
4530
      pstr += sprintf(pstr, ", %d", rand_int());
4531 4532 4533 4534 4535 4536 4537 4538
    } else if (strcasecmp(data_type[i % c], "bigint") == 0) {
      pstr += sprintf(pstr, ", %" PRId64, rand_bigint());
    } else if (strcasecmp(data_type[i % c], "float") == 0) {
      pstr += sprintf(pstr, ", %10.4f", rand_float());
    } else if (strcasecmp(data_type[i % c], "double") == 0) {
      double t = rand_double();
      pstr += sprintf(pstr, ", %20.8f", t);
    } else if (strcasecmp(data_type[i % c], "bool") == 0) {
4539
      bool b = taosRandom() & 1;
4540 4541
      pstr += sprintf(pstr, ", %s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "binary") == 0) {
4542 4543
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4544 4545
      pstr += sprintf(pstr, ", \"%s\"", s);
      free(s);
4546
    } else if (strcasecmp(data_type[i % c], "nchar") == 0) {
4547 4548
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4549 4550 4551 4552
      pstr += sprintf(pstr, ", \"%s\"", s);
      free(s);
    }

4553
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4554 4555 4556 4557 4558 4559 4560
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4563
  return (int32_t)strlen(recBuf);
4564 4565
}

4566
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4567 4568
  char* sampleDataBuf = NULL;

4569
  sampleDataBuf = calloc(
4570
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4571
  if (sampleDataBuf == NULL) {
4572
      errorPrint("%s() LN%d, Failed to calloc %"PRId64" Bytes, reason:%s\n",
4573
              __func__, __LINE__,
4574
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
4575
              strerror(errno));
4576
      return -1;
4577
  }
4578

4579 4580 4581 4582
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4583 4584
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
4585
      tmfree(sampleDataBuf);
4586
      superTblInfo->sampleDataBuf = NULL;
4587
      return -1;
H
Hui Li 已提交
4588
  }
4589

4590 4591 4592
  return 0;
}

4593
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, int k)
4594 4595
{
  int affectedRows;
4596
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4597

4598 4599
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, buffer);
4600
  if (superTblInfo) {
4601
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4602
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4603 4604
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port, buffer)) {
4605
        affectedRows = -1;
4606 4607
        printf("========restful return fail, threadID[%d]\n",
            pThreadInfo->threadID);
4608 4609 4610
      } else {
        affectedRows = k;
      }
4611 4612 4613 4614
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4615
    }
4616
  } else {
4617
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4618 4619 4620 4621 4622
  }

  return affectedRows;
}

4623
static void getTableName(char *pTblName, threadInfo* pThreadInfo, int64_t tableSeq)
4624 4625
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4626 4627 4628 4629
  if (superTblInfo) {
    if ((superTblInfo->childTblOffset >= 0)
            && (superTblInfo->childTblLimit > 0)) {
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
4630 4631
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4632
    } else {
4633

4634
        verbosePrint("[%d] %s() LN%d: from=%"PRId64" count=%"PRId64" seq=%"PRId64"\n",
4635 4636
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
4637 4638 4639 4640 4641
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
    }
  } else {
4642
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRId64"",
4643
        g_args.tb_prefix, tableSeq);
4644 4645 4646
  }
}

4647
static int64_t generateDataTail(
4648
        SSuperTable* superTblInfo,
4649 4650 4651
        int64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
  int64_t len = 0;
4652 4653
  int ncols_per_record = 1; // count first col ts

4654 4655
  char *pstr = buffer;

4656
  if (superTblInfo == NULL) {
4657 4658 4659 4660 4661
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
4662 4663
  }

4664
  verbosePrint("%s() LN%d batch=%"PRId64"\n", __func__, __LINE__, batch);
4665

4666
  int64_t k = 0;
4667
  for (k = 0; k < batch;) {
4668
    char data[MAX_DATA_SIZE];
4669 4670
    memset(data, 0, MAX_DATA_SIZE);

4671
    int64_t retLen = 0;
4672

4673 4674
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4675 4676
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
4677 4678
                    data,
                    remainderBufLen,
4679
                    startTime + superTblInfo->timeStampStep * k,
4680
                    superTblInfo,
4681
                    pSamplePos);
4682
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4683
                   "rand", strlen("rand"))) {
4684

4685
        int64_t randTail = superTblInfo->timeStampStep * k;
4686 4687 4688 4689
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4690
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4691
          }
4692 4693
        }

4694
        int64_t d = startTime
4695 4696
                + randTail;
        retLen = generateRowData(
4697
                      data,
4698
                      d,
4699
                      superTblInfo);
4700
      }
4701

4702 4703 4704
      if (retLen > remainderBufLen) {
        break;
      }
4705

4706
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4707 4708 4709
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4710
    } else {
4711 4712
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4713

4714 4715 4716 4717 4718 4719
      int64_t randTail = DEFAULT_TIMESTAMP_STEP * k;

      if (g_args.disorderRatio != 0) {
        int rand_num = taosRandom() % 100;
        if (rand_num < g_args.disorderRatio) {
          randTail = (randTail + (taosRandom() % g_args.disorderRange + 1)) * (-1);
4720

4721 4722
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4723
      } else {
4724 4725 4726 4727
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4728
                  ncols_per_record,
4729
                  startTime + randTail,
4730
                  lenOfBinary);
4731

4732 4733 4734
      if (len > remainderBufLen)
        break;

4735
      pstr += sprintf(pstr, "%s", data);
4736 4737 4738
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4739 4740
    }

4741
    verbosePrint("%s() LN%d len=%"PRId64" k=%"PRId64" \nbuffer=%s\n",
4742
            __func__, __LINE__, len, k, buffer);
4743 4744

    startFrom ++;
4745

4746
    if (startFrom >= insertRows) {
4747
      break;
4748
    }
4749
  }
4750

4751 4752 4753
  *dataLen = len;
  return k;
}
4754

4755
static int generateSQLHead(char *tableName, int32_t tableSeq,
4756 4757
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4758 4759
{
  int len;
4760 4761 4762 4763

#define HEAD_BUFF_LEN    1024*24  // 16*1024 + (192+32)*2 + insert into ..
  char headBuf[HEAD_BUFF_LEN];

4764 4765 4766 4767
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4768
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4769 4770 4771 4772 4773 4774
      } else {
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
      }
      if (NULL == tagsValBuf) {
4775 4776
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
            __func__, __LINE__);
4777 4778 4779
        return -1;
      }

4780 4781 4782
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4783
                  "%s.%s using %s.%s tags %s values",
4784 4785 4786 4787 4788 4789 4790
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
4791 4792 4793
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4794
                  "%s.%s values",
4795
                  pThreadInfo->db_name,
4796
                  tableName);
4797
    } else {
4798 4799 4800
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4801
                  "%s.%s values",
4802 4803 4804 4805
                  pThreadInfo->db_name,
                  tableName);
    }
  } else {
4806 4807 4808
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4809
                  "%s.%s values",
4810 4811 4812 4813
                  pThreadInfo->db_name,
                  tableName);
  }

4814 4815 4816 4817 4818
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

4819 4820 4821
  return len;
}

4822 4823 4824
static int64_t generateInterlaceDataBuffer(
        char *tableName, int64_t batchPerTbl, int64_t i, int64_t batchPerTblTimes,
        int64_t tableSeq,
4825 4826 4827
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
        int64_t startTime,
4828
        int64_t *pRemainderBufLen)
4829
{
4830
  assert(buffer);
4831 4832 4833 4834 4835 4836 4837 4838 4839 4840
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
            superTblInfo, pstr, *pRemainderBufLen);

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
4841
  verbosePrint("[%d] %s() LN%d i=%"PRId64" buffer:\n%s\n",
4842 4843 4844 4845 4846
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);

  pstr += headLen;
  *pRemainderBufLen -= headLen;

4847
  int64_t dataLen = 0;
4848

4849
  verbosePrint("[%d] %s() LN%d i=%"PRId64" batchPerTblTimes=%"PRId64" batchPerTbl = %"PRId64"\n",
4850 4851 4852 4853 4854 4855 4856 4857 4858 4859
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);

  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
      startTime = taosGetTimestamp(pThreadInfo->time_precision);
    }
  } else {
      startTime = 1500000000000;
  }
4860

4861
  int64_t k = generateDataTail(
4862
    superTblInfo,
4863 4864 4865 4866
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);

4867
  if (k == batchPerTbl) {
4868 4869 4870
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
4871
    debugPrint("%s() LN%d, generated data tail: %"PRId64", not equal batch per table: %"PRId64"\n",
4872
            __func__, __LINE__, k, batchPerTbl);
4873 4874
    pstr -= headLen;
    pstr[0] = '\0';
4875
    k = 0;
4876 4877 4878 4879 4880 4881 4882
  }

  return k;
}

static int generateProgressiveDataBuffer(
        char *tableName,
4883
        int64_t tableSeq,
4884 4885
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
4886 4887
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

  if (superTblInfo == NULL) {
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
  }

  assert(buffer != NULL);
4902
  char *pstr = buffer;
4903

4904
  int64_t k = 0;
4905

4906
  memset(buffer, 0, *pRemainderBufLen);
4907

4908
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
4909
          buffer, *pRemainderBufLen);
4910 4911 4912 4913

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

4917
  int64_t dataLen;
4918
  k = generateDataTail(superTblInfo,
4919
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
4920
          startTime,
4921
          pSamplePos, &dataLen);
4922

4923 4924
  return k;
}
4925

4926
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
4927 4928
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
4929

4930
  int64_t insertRows;
4931
  int64_t interlaceRows;
4932

4933
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4934

4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

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

4949
  if (interlaceRows > insertRows)
4950
    interlaceRows = insertRows;
4951

4952 4953
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
4954

4955 4956 4957 4958 4959 4960 4961 4962 4963 4964
  int insertMode;

  if (interlaceRows > 0) {
    insertMode = INTERLACE_INSERT_MODE;
  } else {
    insertMode = PROGRESSIVE_INSERT_MODE;
  }

  // TODO: prompt tbl count multple interlace rows and batch
  //
4965

4966
  int64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
4967
  char* buffer = calloc(maxSqlLen, 1);
4968
  if (NULL == buffer) {
4969
    errorPrint( "%s() LN%d, Failed to alloc %"PRId64" Bytes, reason:%s\n",
4970
              __func__, __LINE__, maxSqlLen, strerror(errno));
4971 4972 4973
    return NULL;
  }

4974
  char tableName[TSDB_TABLE_NAME_LEN];
4975 4976 4977 4978

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

4979
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
4980

4981 4982
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4983 4984
  int64_t st = 0;
  int64_t et = 0xffffffff;
4985 4986

  int64_t lastPrintTime = taosGetTimestampMs();
4987
  int64_t startTs = taosGetTimestampMs();
4988 4989
  int64_t endTs;

4990
  int64_t tableSeq = pThreadInfo->start_table_from;
4991

4992
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRId64" ntables=%"PRId64" insertRows=%"PRId64"\n",
4993
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
4994 4995 4996 4997
          pThreadInfo->ntables, insertRows);

  int64_t startTime = pThreadInfo->start_time;

4998 4999
  assert(pThreadInfo->ntables > 0);

5000
  int64_t batchPerTbl = interlaceRows;
5001

5002
  int64_t batchPerTblTimes;
5003
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5004
    batchPerTblTimes =
5005
        g_args.num_of_RPR / interlaceRows;
5006 5007 5008 5009
  } else {
    batchPerTblTimes = 1;
  }

5010
  int64_t generatedRecPerTbl = 0;
5011
  bool flagSleep = true;
5012
  int64_t sleepTimeTotal = 0;
5013

5014 5015 5016
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5017
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5018
    if ((flagSleep) && (insert_interval)) {
5019
        st = taosGetTimestampMs();
5020
        flagSleep = false;
5021 5022
    }
    // generate data
5023
    memset(buffer, 0, maxSqlLen);
5024
    int64_t remainderBufLen = maxSqlLen;
5025

5026
    char *pstr = buffer;
5027 5028 5029 5030 5031

    int len = snprintf(pstr, nInsertBufLen + 1, "%s", strInsertInto);
    pstr += len;
    remainderBufLen -= len;

5032
    int64_t recOfBatch = 0;
5033

5034
    for (int64_t i = 0; i < batchPerTblTimes; i ++) {
5035
      getTableName(tableName, pThreadInfo, tableSeq);
5036 5037 5038
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
5039
        free(buffer);
5040 5041
        return NULL;
      }
5042

5043 5044
      int64_t oldRemainderLen = remainderBufLen;
      int64_t generated = generateInterlaceDataBuffer(
5045 5046 5047 5048
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
5049
        startTime,
5050
        &remainderBufLen);
5051

5052
      if (generated < 0) {
5053
        debugPrint("[%d] %s() LN%d, generated data is %"PRId64"\n",
5054 5055
                  pThreadInfo->threadID, __func__, __LINE__, generated);
        goto free_and_statistics_interlace;
5056 5057
      } else if (generated == 0) {
        break;
5058 5059
      }

5060
      tableSeq ++;
5061
      recOfBatch += batchPerTbl;
5062
      pstr += (oldRemainderLen - remainderBufLen);
5063
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5064
      pThreadInfo->totalInsertRows += batchPerTbl;
5065
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5066 5067
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5068

5069 5070 5071 5072
      if (insertMode == INTERLACE_INSERT_MODE) {
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
5073
            generatedRecPerTbl += batchPerTbl;
5074 5075

            startTime = pThreadInfo->start_time
5076
              + generatedRecPerTbl * nTimeStampStep;
5077

5078 5079 5080 5081
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

5082 5083 5084 5085
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;

5086 5087
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
5088
          }
5089 5090
      }

5091
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5092 5093 5094 5095
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5096 5097 5098
        break;
    }

5099
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRId64" totalInsertRows=%"PRId64"\n",
5100 5101 5102 5103 5104
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
           pThreadInfo->threadID, __func__, __LINE__, buffer);

5105
    startTs = taosGetTimestampMs();
5106

5107
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5108

5109
    endTs = taosGetTimestampMs();
5110
    int64_t delay = endTs - startTs;
5111 5112
    performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
            __func__, __LINE__, delay);
5113 5114 5115 5116 5117 5118

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

5119 5120
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
5121
            __func__, __LINE__, affectedRows);
5122
    if ((affectedRows < 0) || (recOfBatch != affectedRows)) {
5123
        errorPrint("[%d] %s() LN%d execInsert insert %"PRId64", affected rows: %"PRId64"\n%s\n",
5124
                pThreadInfo->threadID, __func__, __LINE__,
5125
                recOfBatch, affectedRows, buffer);
5126
        goto free_and_statistics_interlace;
5127
    }
5128

5129
    pThreadInfo->totalAffectedRows += affectedRows;
5130

5131 5132 5133
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
      printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5134 5135 5136
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5137 5138
      lastPrintTime = currentPrintTime;
    }
5139

5140
    if ((insert_interval) && flagSleep) {
5141
      et = taosGetTimestampMs();
5142

5143 5144
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5145 5146
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleepTime);
5147 5148 5149
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5150
    }
5151 5152 5153 5154 5155
  }

free_and_statistics_interlace:
  tmfree(buffer);

5156 5157 5158
  printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n",
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
5159 5160 5161 5162
          pThreadInfo->totalAffectedRows);
  return NULL;
}

5163 5164 5165 5166 5167 5168 5169 5170
// sync insertion
/*
   1 thread: 100 tables * 2000  rows/s
   1 thread: 10  tables * 20000 rows/s
   6 thread: 300 tables * 2000  rows/s

   2 taosinsertdata , 1 thread:  10  tables * 20000 rows/s
*/
5171
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5172
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5173

5174
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5175
  int maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5176

5177
  char* buffer = calloc(maxSqlLen, 1);
5178
  if (NULL == buffer) {
5179
    errorPrint( "Failed to alloc %d Bytes, reason:%s\n",
5180
              maxSqlLen,
5181 5182 5183
              strerror(errno));
    return NULL;
  }
5184

5185
  int64_t lastPrintTime = taosGetTimestampMs();
5186
  int64_t startTs = taosGetTimestampMs();
5187 5188
  int64_t endTs;

5189
  int64_t timeStampStep =
5190
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5191
/*  int insert_interval =
5192
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5193 5194
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5195
  */
5196

5197 5198
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5199

5200
  pThreadInfo->samplePos = 0;
5201

5202
  for (int64_t tableSeq =
5203
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
5204
        tableSeq ++) {
5205
    int64_t start_time = pThreadInfo->start_time;
5206 5207 5208 5209 5210

    int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
    verbosePrint("%s() LN%d insertRows=%"PRId64"\n", __func__, __LINE__, insertRows);

    for (int64_t i = 0; i < insertRows;) {
5211
        /*
5212
      if (insert_interval) {
5213
            st = taosGetTimestampMs();
5214
      }
5215
      */
5216

5217 5218
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5219
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5220 5221 5222
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);

5223
      int64_t remainderBufLen = maxSqlLen;
5224 5225 5226 5227 5228 5229 5230 5231
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

      int len = snprintf(pstr, nInsertBufLen + 1, "%s", "insert into ");

      pstr += len;
      remainderBufLen -= len;

5232
      int generated = generateProgressiveDataBuffer(
5233
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
5234
            i, start_time,
5235 5236
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5237 5238 5239 5240 5241
      if (generated > 0)
        i += generated;
      else
        goto free_and_statistics_2;

5242
      start_time +=  generated * timeStampStep;
5243
      pThreadInfo->totalInsertRows += generated;
5244

5245
      startTs = taosGetTimestampMs();
5246

5247
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5248

5249
      endTs = taosGetTimestampMs();
5250
      int64_t delay = endTs - startTs;
5251 5252
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
              __func__, __LINE__, delay);
5253

5254 5255 5256 5257
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5258

5259 5260 5261 5262 5263
      if (affectedRows < 0)
        goto free_and_statistics_2;

      pThreadInfo->totalAffectedRows += affectedRows;

5264 5265
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5266
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5267 5268 5269
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5270 5271 5272
        lastPrintTime = currentPrintTime;
      }

5273
      if (i >= insertRows)
5274
        break;
5275
/*
5276
      if (insert_interval) {
5277
        et = taosGetTimestampMs();
5278

5279 5280
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5281 5282
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5283 5284
            taosMsleep(sleep_time); // ms
        }
5285
      }
5286
      */
5287 5288
    }   // num_of_DPT

5289 5290
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5291 5292
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5293
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5294
                  __func__, __LINE__, pThreadInfo->samplePos);
5295
      }
5296
    }
5297
  } // tableSeq
5298

5299
free_and_statistics_2:
5300 5301
  tmfree(buffer);

5302 5303 5304
  printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n",
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
5305
          pThreadInfo->totalAffectedRows);
5306
  return NULL;
H
Hui Li 已提交
5307 5308
}

5309 5310
static void* syncWrite(void *sarg) {

5311 5312
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5313

5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325
  int interlaceRows;

  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;
  }
5326

5327
  if (interlaceRows > 0) {
5328
    // interlace mode
5329
    return syncWriteInterlace(pThreadInfo);
5330 5331
  } else {
    // progressive mode
5332
    return syncWriteProgressive(pThreadInfo);
5333 5334 5335
  }
}

5336
static void callBack(void *param, TAOS_RES *res, int code) {
5337 5338
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5339

5340 5341
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5342
  if (insert_interval) {
5343 5344 5345
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5346
    }
H
Hui Li 已提交
5347
  }
5348

5349
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5350
  char data[MAX_DATA_SIZE];
5351
  char *pstr = buffer;
5352 5353
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5354 5355 5356 5357 5358 5359 5360 5361
          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);
5362 5363 5364 5365
    free(buffer);
    taos_free_result(res);
    return;
  }
5366

5367
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5368
    int rand_num = taosRandom() % 100;
5369 5370 5371 5372
    if (0 != pThreadInfo->superTblInfo->disorderRatio
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
      int64_t d = pThreadInfo->lastTs - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateRowData(data, d, pThreadInfo->superTblInfo);
5373
    } else {
5374
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5375
    }
5376
    pstr += sprintf(pstr, "%s", data);
5377
    pThreadInfo->counter++;
H
Hui Li 已提交
5378

5379
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5380
      break;
H
Hui Li 已提交
5381 5382
    }
  }
5383

5384
  if (insert_interval) {
5385
    pThreadInfo->st = taosGetTimestampMs();
5386
  }
5387
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5388
  free(buffer);
H
Hui Li 已提交
5389

5390
  taos_free_result(res);
H
Hui Li 已提交
5391 5392
}

5393
static void *asyncWrite(void *sarg) {
5394 5395
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5396

5397 5398 5399
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5400

5401
  int insert_interval =
5402
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5403
  if (insert_interval) {
5404
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5405
  }
5406
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5407

5408
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5409 5410 5411 5412

  return NULL;
}

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 5438
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;
}

5439 5440
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
5441

5442 5443
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5444

5445 5446
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5447

5448 5449
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466

  //TAOS* taos;
  //if (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5)) {
  //  taos = taos_connect(g_Dbs.host, g_Dbs.user, g_Dbs.password, db_name, g_Dbs.port);
  //  if (NULL == taos) {
  //    printf("connect to server fail, reason: %s\n", taos_errstr(NULL));
  //    exit(-1);
  //  }
  //}

  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 {
5467
      errorPrint("Not support precision: %s\n", precision);
5468 5469 5470 5471
      exit(-1);
    }
  }

5472
  int64_t start_time;
5473 5474 5475
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
5476
    } else {
5477 5478 5479 5480 5481
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
5482
          ERROR_EXIT("failed to parse time!\n");
5483
      }
5484
    }
5485 5486
  } else {
     start_time = 1500000000000;
5487 5488
  }

5489
  int64_t start = taosGetTimestampMs();
5490

5491
  // read sample data from file first
5492
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5493
              "sample", strlen("sample")))) {
5494
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5495 5496
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5497 5498 5499 5500
      exit(-1);
    }
  }

5501
  // read sample data from file first
5502
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5503 5504
              "sample", strlen("sample")))) {
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5505 5506
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5507 5508 5509 5510 5511 5512 5513 5514
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
  if (NULL == taos) {
5515 5516
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
                __func__, __LINE__, taos_errstr(NULL));
5517 5518 5519
    exit(-1);
  }

5520 5521
  int ntables = 0;
  int startFrom;
5522

5523
  if (superTblInfo) {
5524
    int limit, offset;
5525

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

5531 5532
    if ((superTblInfo->childTblExists == TBL_ALREADY_EXISTS)
            && (superTblInfo->childTblOffset >= 0)) {
5533 5534
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5535
            > (superTblInfo->childTblCount))) {
5536 5537 5538 5539 5540 5541
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5542
    } else {
5543 5544
      limit = superTblInfo->childTblCount;
      offset = 0;
5545 5546
    }

5547 5548 5549
    ntables = limit;
    startFrom = offset;

5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
      if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
      }
    }

    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
            && (0 == superTblInfo->childTblLimit)) {
      printf("WARNING: specified limit = 0, which cannot find table name to insert or query! \n");
      if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
      }
    }

5569 5570 5571
    superTblInfo->childTblName = (char*)calloc(1,
        limit * TSDB_TABLE_NAME_LEN);
    if (superTblInfo->childTblName == NULL) {
5572
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5573 5574 5575 5576
      taos_close(taos);
      exit(-1);
    }

5577
    int64_t childTblCount;
5578 5579 5580 5581 5582 5583
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5584 5585 5586
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5587
  }
5588

5589 5590
  taos_close(taos);

5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601
  int a = ntables / threads;
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

  int b = 0;
  if (threads != 0) {
    b = ntables % threads;
  }

5602 5603 5604 5605 5606 5607
  if ((superTblInfo)
      && (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest")))) {
    if (convertHostToServAddr(g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0)
      exit(-1);
  }

H
Hui Li 已提交
5608
  for (int i = 0; i < threads; i++) {
5609
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5610 5611
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5612
    t_info->time_precision = timePrec;
5613 5614 5615
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5616
    t_info->minDelay = INT64_MAX;
5617

5618 5619
    if ((NULL == superTblInfo) ||
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5620
      //t_info->taos = taos;
5621
      t_info->taos = taos_connect(
5622
              g_Dbs.host, g_Dbs.user,
5623
              g_Dbs.password, db_name, g_Dbs.port);
5624
      if (NULL == t_info->taos) {
5625 5626
        errorPrint(
                "connect to server fail from insert sub thread, reason: %s\n",
5627
                taos_errstr(NULL));
5628 5629 5630 5631 5632 5633
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5634
/*    if ((NULL == superTblInfo)
5635
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5636
            */
5637 5638 5639 5640
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
5641
/*    } else {
5642 5643
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5644 5645
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5646
*/
5647 5648
    tsem_init(&(t_info->lock_sem), 0, 0);
    if (SYNC == g_Dbs.queryMode) {
5649
      pthread_create(pids + i, NULL, syncWrite, t_info);
5650
    } else {
5651 5652
      pthread_create(pids + i, NULL, asyncWrite, t_info);
    }
H
Hui Li 已提交
5653
  }
5654

H
Hui Li 已提交
5655 5656 5657 5658
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5659 5660
  int64_t totalDelay = 0;
  int64_t maxDelay = 0;
5661
  int64_t minDelay = INT64_MAX;
5662
  int64_t cntDelay = 1;
5663 5664
  double  avgDelay = 0;

H
Hui Li 已提交
5665
  for (int i = 0; i < threads; i++) {
5666 5667
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5668
    tsem_destroy(&(t_info->lock_sem));
5669 5670
    taos_close(t_info->taos);

5671 5672 5673 5674
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRId64" totalAffected=%"PRId64"\n",
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5675 5676
    if (superTblInfo) {
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
5677
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5678 5679 5680
    } else {
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5681
    }
5682 5683 5684 5685

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5686
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5687
  }
5688
  cntDelay -= 1;
H
Hui Li 已提交
5689

5690
  if (cntDelay == 0)    cntDelay = 1;
5691 5692
  avgDelay = (double)totalDelay / cntDelay;

5693 5694
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5695 5696

  if (superTblInfo) {
5697 5698
    printf("Spent %.2f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
          t / 1000.0, superTblInfo->totalInsertRows,
5699 5700
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5701
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5702
    fprintf(g_fpOfInsertResult,
5703 5704
          "Spent %.2f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
          t / 1000.0, superTblInfo->totalInsertRows,
5705 5706
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5707
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5708
  } else {
5709 5710
    printf("Spent %.2f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n",
          t / 1000.0, g_args.totalInsertRows,
5711 5712
          g_args.totalAffectedRows,
          threads, db_name,
5713
          (double)g_args.totalInsertRows / (t / 1000.0));
5714
    fprintf(g_fpOfInsertResult,
5715 5716
          "Spent %.2f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n",
          t * 1000.0, g_args.totalInsertRows,
5717 5718
          g_args.totalAffectedRows,
          threads, db_name,
5719
          (double)g_args.totalInsertRows / (t / 1000.0));
5720
  }
5721

5722 5723 5724 5725
  printf("insert delay, avg: %10.2fms, max: %"PRId64"ms, min: %"PRId64"ms\n\n",
          avgDelay, maxDelay, minDelay);
  fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRId64"ms, min: %"PRId64"ms\n\n",
          avgDelay, maxDelay, minDelay);
5726

5727 5728
  //taos_close(taos);

H
Hui Li 已提交
5729
  free(pids);
5730
  free(infos);
H
Hui Li 已提交
5731 5732
}

5733
static void *readTable(void *sarg) {
5734
#if 1
5735
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5736 5737
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5738
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5739 5740
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5741
  if (NULL == fp) {
5742
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5743 5744
    return NULL;
  }
5745

5746
    int num_of_DPT;
5747
/*  if (rinfo->superTblInfo) {
5748 5749
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5750
  */
5751
      num_of_DPT = g_args.num_of_DPT;
5752
//  }
5753

5754
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5755
  int totalData = num_of_DPT * num_of_tables;
5756
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768

  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");
  }
  printf("%d records:\n", totalData);
  fprintf(fp, "| QFunctions |    QRecords    |   QSpeed(R/s)   |  QLatency(ms) |\n");

  for (int j = 0; j < n; j++) {
    double totalT = 0;
    int count = 0;
    for (int i = 0; i < num_of_tables; i++) {
5769 5770
      sprintf(command, "select %s from %s%d where ts>= %" PRId64,
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5771

5772
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5773 5774
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5775

S
Shuaiqiang Chang 已提交
5776
      if (code != 0) {
5777
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5778
        taos_free_result(pSql);
H
hzcheng 已提交
5779
        taos_close(taos);
5780
        fclose(fp);
5781
        return NULL;
H
hzcheng 已提交
5782 5783
      }

5784
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5785 5786 5787
        count++;
      }

5788
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5789 5790
      totalT += t;

S
Shuaiqiang Chang 已提交
5791
      taos_free_result(pSql);
H
hzcheng 已提交
5792 5793 5794
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5795
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5796
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
5797
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
5798 5799 5800
  }
  fprintf(fp, "\n");
  fclose(fp);
5801
#endif
H
hzcheng 已提交
5802 5803 5804
  return NULL;
}

5805
static void *readMetric(void *sarg) {
5806
#if 1
5807
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5808 5809 5810
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5811 5812 5813 5814
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5815 5816

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5817
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5818
  int totalData = num_of_DPT * num_of_tables;
5819
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5820 5821 5822 5823 5824 5825 5826 5827 5828

  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");
  }
  printf("%d records:\n", totalData);
  fprintf(fp, "Querying On %d records:\n", totalData);

  for (int j = 0; j < n; j++) {
sangshuduo's avatar
sangshuduo 已提交
5829
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5830
    char tempS[64] = "\0";
H
hzcheng 已提交
5831 5832 5833 5834 5835

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5836
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5837
      } else {
5838
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5839 5840 5841
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5842
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5843 5844 5845 5846

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

5847
      double t = taosGetTimestampMs();
H
hzcheng 已提交
5848

S
Shuaiqiang Chang 已提交
5849 5850 5851 5852
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
5853
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5854
        taos_free_result(pSql);
H
hzcheng 已提交
5855
        taos_close(taos);
5856
        fclose(fp);
5857
        return NULL;
H
hzcheng 已提交
5858 5859
      }
      int count = 0;
5860
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5861 5862
        count++;
      }
5863
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5864

5865
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
5866 5867
              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 已提交
5868

S
Shuaiqiang Chang 已提交
5869
      taos_free_result(pSql);
H
hzcheng 已提交
5870 5871 5872 5873
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5874
#endif
H
hzcheng 已提交
5875 5876 5877
  return NULL;
}

H
Hui Li 已提交
5878

5879
static int insertTestProcess() {
5880

5881 5882 5883
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5884

5885 5886 5887
  if (ret == -1)
    exit(EXIT_FAILURE);

5888
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5889 5890
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
5891
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
5892 5893
    return -1;
  }
5894

5895 5896
  printfInsertMetaToFile(g_fpOfInsertResult);

5897 5898 5899 5900
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5901

5902 5903 5904
  init_rand_data();

  // create database and super tables
5905
  if(createDatabasesAndStables() != 0) {
5906 5907 5908
    fclose(g_fpOfInsertResult);
    return -1;
  }
5909 5910

  // pretreatement
5911
  prepareSampleData();
5912

5913 5914 5915 5916
  double start;
  double end;

  // create child tables
5917
  start = taosGetTimestampMs();
5918
  createChildTables();
5919
  end = taosGetTimestampMs();
5920

5921
  if (g_totalChildTables > 0) {
5922
    printf("Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5923
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5924 5925
    fprintf(g_fpOfInsertResult,
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5926
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5927
  }
5928

5929
  taosMsleep(1000);
5930
  // create sub threads for inserting data
5931
  //start = taosGetTimestampMs();
5932
  for (int i = 0; i < g_Dbs.dbCount; i++) {
5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {

          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);
          }
5946
        }
5947
      }
5948 5949
    } else {
        startMultiThreadInsertData(
5950 5951 5952
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
5953
          NULL);
H
Hui Li 已提交
5954
    }
5955
  }
5956
  //end = taosGetTimestampMs();
5957

5958
  //int64_t    totalInsertRows = 0;
5959
  //int64_t    totalAffectedRows = 0;
5960
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
5961
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
5962
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
5963 5964
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
5965
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
5966
  postFreeResource();
5967

5968 5969 5970
  return 0;
}

5971 5972
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
5973

5974
  if (pThreadInfo->taos == NULL) {
5975 5976 5977 5978 5979 5980 5981 5982
    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",
5983
            pThreadInfo->threadID, taos_errstr(NULL));
5984 5985
      return NULL;
    } else {
5986
      pThreadInfo->taos = taos;
5987 5988 5989
    }
  }

5990 5991
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5992 5993
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
5994 5995 5996 5997
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
5998

5999 6000
  int64_t st = 0;
  int64_t et = 0;
6001

6002
  int queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6003

6004 6005 6006 6007
  int totalQueried = 0;
  int64_t  lastPrintTime = taosGetTimestampMs();
  int64_t  startTs = taosGetTimestampMs();

6008
  while(queryTimes --) {
6009 6010 6011
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6012 6013
    }

6014
    st = taosGetTimestampMs();
6015

6016
    if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
6017
      int64_t t1 = taosGetTimestampMs();
6018
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6019
      if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6020
        sprintf(tmpFile, "%s-%d",
6021 6022
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6023
      }
6024 6025
      selectAndGetResult(pThreadInfo->taos,
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], tmpFile);
6026 6027 6028
      int64_t t2 = taosGetTimestampMs();
      printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6029
    } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
6030
      int64_t t1 = taosGetTimestampMs();
6031
      int retCode = postProceSql(g_queryInfo.host, &(g_queryInfo.serv_addr),
6032
              g_queryInfo.port,
6033 6034 6035 6036 6037
              g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
      if (0 != retCode) {
        printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
        return NULL;
      }
6038 6039 6040
      int64_t t2 = taosGetTimestampMs();
      printf("=[restful] thread[%"PRId64"] complete one sql, Spent %10.3f s\n",
              taosGetSelfPthreadId(), (t2 - t1)/1000.0);
6041

6042 6043 6044 6045
    } else {
      errorPrint("%s() LN%d, unknown query mode: %s\n",
        __func__, __LINE__, g_queryInfo.queryMode);
      return NULL;
6046
    }
6047 6048
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6049

6050
    et = taosGetTimestampMs();
6051 6052 6053 6054

    int64_t  currentPrintTime = taosGetTimestampMs();
    int64_t  endTs = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
6055 6056 6057
      debugPrint("%s() LN%d, endTs=%"PRId64"ms, startTs=%"PRId64"ms\n",
          __func__, __LINE__, endTs, startTs);
      printf("thread[%d] has currently completed queries: %d, QPS: %10.6f\n",
6058 6059
                    pThreadInfo->threadID,
                    totalQueried,
6060
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6061
      lastPrintTime = currentPrintTime;
6062
    }
H
Hui Li 已提交
6063
  }
6064 6065
  return NULL;
}
H
Hui Li 已提交
6066

6067
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6068 6069
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6070 6071
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6072
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6073 6074

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

6076 6077
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6078
    return;
H
Hui Li 已提交
6079
  }
6080

6081
  tstrncpy(outSql, inSql, pos - inSql + 1);
6082
  //printf("1: %s\n", outSql);
6083 6084 6085 6086
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6087 6088
}

6089
static void *superTableQuery(void *sarg) {
6090
  char sqlstr[1024];
6091
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6092

6093
  if (pThreadInfo->taos == NULL) {
6094 6095 6096 6097 6098 6099 6100 6101
    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",
6102
            pThreadInfo->threadID, taos_errstr(NULL));
6103 6104
      return NULL;
    } else {
6105
      pThreadInfo->taos = taos;
6106 6107 6108
    }
  }

6109
  int64_t st = 0;
6110
  int64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6111 6112

  int queryTimes = g_queryInfo.superQueryInfo.queryTimes;
6113 6114
  int totalQueried = 0;
  int64_t  startTs = taosGetTimestampMs();
6115

6116
  int64_t  lastPrintTime = taosGetTimestampMs();
6117
  while(queryTimes --) {
6118 6119 6120
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6121
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6122
    }
H
Hui Li 已提交
6123

6124
    st = taosGetTimestampMs();
6125
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6126
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6127
        memset(sqlstr,0,sizeof(sqlstr));
6128
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6129
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6130
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6131
          sprintf(tmpFile, "%s-%d",
6132
                  g_queryInfo.superQueryInfo.result[j],
6133
                  pThreadInfo->threadID);
6134
        }
6135 6136 6137 6138 6139 6140 6141 6142
        selectAndGetResult(pThreadInfo->taos, sqlstr, tmpFile);

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6143
          printf("thread[%d] has currently completed queries: %d, QPS: %10.3f\n",
6144 6145
                    pThreadInfo->threadID,
                    totalQueried,
6146
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6147
          lastPrintTime = currentPrintTime;
6148
        }
6149
      }
H
Hui Li 已提交
6150
    }
6151
    et = taosGetTimestampMs();
6152
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRId64" - %"PRId64"] once queries duration:%.4fs\n\n",
6153
            taosGetSelfPthreadId(),
6154 6155
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6156
            (double)(et - st)/1000.0);
6157
  }
6158

6159 6160 6161
  return NULL;
}

6162
static int queryTestProcess() {
6163 6164 6165 6166

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6167 6168 6169 6170 6171 6172

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6173
          g_queryInfo.port);
6174
  if (taos == NULL) {
6175 6176
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6177 6178 6179
    exit(-1);
  }

6180
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6181 6182
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6183 6184 6185
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6186
  }
6187

6188 6189 6190 6191
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6192

6193
  printfQuerySystemInfo(taos);
6194

6195 6196 6197 6198 6199 6200
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6201 6202 6203
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6204 6205
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6206

6207 6208
  int64_t startTs = taosGetTimestampMs();

6209 6210 6211 6212 6213 6214
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

    pids  = malloc(nConcurrent * nSqlCount * sizeof(pthread_t));
    infos = malloc(nConcurrent * nSqlCount * sizeof(threadInfo));

    if ((NULL == pids) || (NULL == infos)) {
6215
      taos_close(taos);
6216
      ERROR_EXIT("memory allocation failed for create threads\n");
6217
    }
6218

6219 6220 6221 6222 6223
    for (int i = 0; i < nConcurrent; i++) {
      for (int j = 0; j < nSqlCount; j++) {
        threadInfo *t_info = infos + i * nSqlCount + j;
        t_info->threadID = i * nSqlCount + j;
        t_info->querySeq = j;
6224

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

6227 6228 6229 6230
          char sqlStr[MAX_TB_NAME_SIZE*2];
          sprintf(sqlStr, "use %s", g_queryInfo.dbName);
          verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
          if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
6231
            taos_close(taos);
6232 6233
            free(infos);
            free(pids);
6234 6235 6236
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6237
          }
6238
        }
6239

6240
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6241

6242
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6243 6244
            t_info);
      }
6245
    }
6246
  } else {
6247
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6248
  }
6249

6250 6251
  taos_close(taos);

6252 6253 6254
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6255 6256 6257 6258
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t));
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo));
6259 6260

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6261 6262
      free(infos);
      free(pids);
6263

6264
      ERROR_EXIT("memory allocation failed for create threads\n");
6265
    }
6266

6267 6268
    int ntables = g_queryInfo.superQueryInfo.childTblCount;
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6269

6270 6271 6272 6273 6274
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6275

6276 6277 6278 6279
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
6280

6281
    int startFrom = 0;
6282
    for (int i = 0; i < threads; i++) {
6283 6284
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6285

6286 6287 6288 6289
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6290
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6291
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6292 6293
    }

6294
    g_queryInfo.superQueryInfo.threadCnt = threads;
6295
  } else {
6296
    g_queryInfo.superQueryInfo.threadCnt = 0;
6297
  }
6298

6299 6300 6301 6302 6303 6304
  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);
      }
    }
6305
  }
S
Shuaiqiang Chang 已提交
6306

6307
  tmfree((char*)pids);
6308
  tmfree((char*)infos);
6309

6310
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6311
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6312
  }
H
Hui Li 已提交
6313

6314
  tmfree((char*)pidsOfSub);
6315
  tmfree((char*)infosOfSub);
6316

6317
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6318 6319 6320 6321 6322
  int64_t endTs = taosGetTimestampMs();

  int totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
    g_queryInfo.superQueryInfo.totalQueried;

6323
  printf("==== completed total queries: %d, the QPS of all threads: %10.3f====\n",
6324
          totalQueried,
6325
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6326 6327 6328
  return 0;
}

6329
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6330
  if (res == NULL || taos_errno(res) != 0) {
6331 6332
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6333 6334
    return;
  }
6335

6336 6337
  getResult(res, (char*)param);
  taos_free_result(res);
H
hzcheng 已提交
6338 6339
}

6340
static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) {
6341
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6342

6343
  if (g_queryInfo.specifiedQueryInfo.mode) {
6344
    tsub = taos_subscribe(taos,
6345
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6346
            topic, sql, subscribe_callback, (void*)resultFileName,
6347
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6348
  } else {
6349
    tsub = taos_subscribe(taos,
6350
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6351
            topic, sql, NULL, NULL, 0);
6352
  }
6353

6354 6355 6356
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6357
  }
6358

6359 6360
  return tsub;
}
H
hzcheng 已提交
6361

6362 6363
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6364
  char subSqlstr[1024];
6365
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6366

6367
  if (pThreadInfo->taos == NULL) {
6368 6369 6370 6371 6372 6373 6374 6375
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6376
            pThreadInfo->threadID, taos_errstr(NULL));
6377 6378
      return NULL;
    } else {
6379
      pThreadInfo->taos = taos;
6380 6381 6382
    }
  }

6383 6384
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6385 6386
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6387 6388
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6389 6390
    return NULL;
  }
6391

6392 6393 6394
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6395 6396
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6397
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6398 6399 6400 6401
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6402
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6403 6404
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
6405
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i);
6406
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6407
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6408
        sprintf(tmpFile, "%s-%d",
6409
                g_queryInfo.superQueryInfo.result[i], pThreadInfo->threadID);
6410
      }
6411
      tsub[i] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic, tmpFile);
6412
      if (NULL == tsub[i]) {
6413
        taos_close(pThreadInfo->taos);
6414 6415 6416 6417
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6418
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6419
  } while(0);
6420 6421 6422

  // start loop to consume result
  TAOS_RES* res = NULL;
6423
  while(1) {
6424
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6425
      if (1 == g_queryInfo.superQueryInfo.mode) {
6426 6427
        continue;
      }
6428

6429
      res = taos_consume(tsub[i]);
6430 6431
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6432
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6433
          sprintf(tmpFile, "%s-%d",
6434
                  g_queryInfo.superQueryInfo.result[i],
6435
                  pThreadInfo->threadID);
6436 6437
        }
        getResult(res, tmpFile);
H
hzcheng 已提交
6438 6439 6440
      }
    }
  }
6441
  taos_free_result(res);
6442

6443
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6444
    taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress);
6445
  }
6446

6447
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6448 6449 6450
  return NULL;
}

6451 6452
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6453
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6454

6455
  if (pThreadInfo->taos == NULL) {
6456 6457 6458 6459 6460 6461 6462 6463
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6464
            pThreadInfo->threadID, taos_errstr(NULL));
6465 6466
      return NULL;
    } else {
6467
      pThreadInfo->taos = taos;
6468 6469 6470
    }
  }

6471 6472
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6473
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6474 6475
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6476 6477
    return NULL;
  }
6478

6479 6480 6481
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6482 6483
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6484
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6485 6486 6487 6488
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6489
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6490 6491
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6492
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6493
        sprintf(tmpFile, "%s-%d",
6494
                g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6495
      }
6496
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6497
          g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile);
6498
      if (NULL == tsub[i]) {
6499
        taos_close(pThreadInfo->taos);
6500 6501 6502 6503
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6504
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6505
  } while(0);
6506 6507 6508

  // start loop to consume result
  TAOS_RES* res = NULL;
6509
  while(1) {
6510
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6511
      if (SYNC_QUERY_MODE == g_queryInfo.specifiedQueryInfo.mode) {
6512 6513
        continue;
      }
6514

6515
      res = taos_consume(tsub[i]);
6516 6517
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6518
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6519
          sprintf(tmpFile, "%s-%d",
6520
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6521 6522 6523 6524 6525 6526
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
6527

6528
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6529 6530
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6531
  }
6532

6533
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6534 6535 6536
  return NULL;
}

6537
static int subscribeTestProcess() {
6538
  setupForAnsiEscape();
6539
  printfQueryMeta();
6540
  resetAfterAnsiEscape();
6541

6542 6543
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6544
    (void) getchar();
Y
yihaoDeng 已提交
6545
  }
6546

6547 6548 6549 6550 6551
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6552
          g_queryInfo.port);
6553
  if (taos == NULL) {
6554 6555
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6556 6557 6558
    exit(-1);
  }

6559
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6560 6561
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6562 6563 6564
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6565 6566
  }

6567 6568
  taos_close(taos); // TODO: workaround to use separate taos connection;

6569 6570 6571
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6572 6573
  if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) {
6574
    errorPrint("%s() LN%d, query sqlCount %"PRId64" or concurrent %"PRId64" is not correct.\n",
6575 6576
              __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount,
              g_queryInfo.specifiedQueryInfo.concurrent);
6577 6578 6579
    exit(-1);
  }

6580 6581
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6582
  if ((NULL == pids) || (NULL == infos)) {
6583
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6584
      exit(-1);
6585
  }
6586

6587
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6588 6589
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6590
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6591
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
H
hzcheng 已提交
6592
  }
6593

6594
  //==== create sub threads for query from sub table
6595 6596
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6597 6598 6599
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6600
            sizeof(pthread_t));
6601
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6602
            sizeof(threadInfo));
6603
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6604 6605 6606
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6607
      exit(-1);
S
Shuaiqiang Chang 已提交
6608
    }
6609

6610 6611
    int ntables = g_queryInfo.superQueryInfo.childTblCount;
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6612

6613 6614 6615 6616 6617
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6618

6619 6620 6621 6622
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
6623

6624
    int startFrom = 0;
6625
    for (int i = 0; i < threads; i++) {
6626 6627
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6628

6629 6630 6631 6632
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6633
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6634
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6635
    }
6636

6637
    g_queryInfo.superQueryInfo.threadCnt = threads;
6638

6639
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6640 6641
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6642
  }
6643

6644
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6645
    pthread_join(pids[i], NULL);
6646
  }
H
hzcheng 已提交
6647

6648
  tmfree((char*)pids);
6649
  tmfree((char*)infos);
H
hzcheng 已提交
6650

6651
  tmfree((char*)pidsOfSub);
6652
  tmfree((char*)infosOfSub);
6653
//   taos_close(taos);
6654
  return 0;
H
hzcheng 已提交
6655 6656
}

6657
static void initOfInsertMeta() {
6658
  memset(&g_Dbs, 0, sizeof(SDbs));
6659

6660
  // set default values
6661
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6662
  g_Dbs.port = 6030;
6663 6664
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6665
  g_Dbs.threadCount = 2;
6666 6667

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6668 6669
}

6670
static void initOfQueryMeta() {
6671
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6672

6673
  // set default values
6674
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6675
  g_queryInfo.port = 6030;
6676 6677
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6678 6679
}

6680
static void setParaFromArg(){
6681
  if (g_args.host) {
6682
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6683
  } else {
6684
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6685
  }
L
Liu Tao 已提交
6686

6687
  if (g_args.user) {
6688
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6689
  }
6690 6691

  if (g_args.password) {
6692
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6693 6694
  }

6695 6696
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6697
  }
L
Liu Tao 已提交
6698

6699 6700 6701
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6702 6703
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6704

6705
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6706
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6707
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6708

6709
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6710 6711 6712 6713 6714

  g_Dbs.use_metric = g_args.use_metric;
  g_Dbs.insert_only = g_args.insert_only;

  g_Dbs.do_aggreFunc = true;
L
Liu Tao 已提交
6715

6716 6717
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6718

6719
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6720

6721 6722
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6723
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6724
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6725
  }
H
hzcheng 已提交
6726

6727 6728 6729 6730 6731
  if (g_args.use_metric) {
    g_Dbs.db[0].superTblCount = 1;
    tstrncpy(g_Dbs.db[0].superTbls[0].sTblName, "meters", MAX_TB_NAME_SIZE);
    g_Dbs.db[0].superTbls[0].childTblCount = g_args.num_of_tables;
    g_Dbs.threadCount = g_args.num_of_threads;
6732
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6733
    g_Dbs.queryMode = g_args.query_mode;
6734

6735 6736 6737 6738
    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;
6739
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6740 6741 6742
            g_args.tb_prefix, MAX_TB_NAME_SIZE);
    tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE);
    tstrncpy(g_Dbs.db[0].superTbls[0].insertMode, "taosc", MAX_TB_NAME_SIZE);
6743
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6744
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6745
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6746

6747
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6748
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6749

6750 6751 6752 6753 6754
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6755

6756
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6757
              data_type[i], MAX_TB_NAME_SIZE);
6758
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6759 6760
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6761

6762 6763 6764 6765 6766
    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 {
      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, "INT", MAX_TB_NAME_SIZE);
6767
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6768 6769 6770
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6771

6772
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6773
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6774

6775
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6776 6777
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6778
  } else {
6779 6780
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6781
  }
6782 6783 6784 6785 6786 6787
}

/* 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 已提交
6788

6789 6790 6791
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6792 6793 6794
    exit(-1);
  }

6795 6796 6797 6798 6799 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818
  /* 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);
}

6819
static void querySqlFile(TAOS* taos, char* sqlFile)
6820 6821 6822 6823 6824 6825
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6826

6827 6828 6829 6830 6831 6832
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

6833
  double t = taosGetTimestampMs();
6834

6835
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847
    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;
6848
    }
6849 6850

    memcpy(cmd + cmd_len, line, read_len);
6851
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
6852 6853 6854
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
6855 6856 6857 6858 6859
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
6860 6861
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
6862 6863
  }

6864
  t = taosGetTimestampMs() - t;
6865
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6866

6867 6868 6869 6870
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6871 6872
}

6873
static void testMetaFile() {
6874
    if (INSERT_TEST == g_args.test_mode) {
6875 6876
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6877

6878
      insertTestProcess();
6879

6880
    } else if (QUERY_TEST == g_args.test_mode) {
6881 6882
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6883

6884
      queryTestProcess();
6885

6886
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
6887 6888
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6889

6890
      subscribeTestProcess();
6891

6892 6893 6894
    }  else {
      ;
    }
6895
}
6896

6897
static void queryResult() {
6898
  // query data
6899

6900 6901 6902 6903 6904
  pthread_t read_id;
  threadInfo *rInfo = malloc(sizeof(threadInfo));
  assert(rInfo);
  rInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  rInfo->start_table_from = 0;
6905

6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 6917 6918 6919 6920 6921 6922 6923 6924 6925 6926 6927 6928 6929 6930 6931 6932 6933 6934 6935 6936 6937 6938 6939 6940 6941
  //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
  if (g_args.use_metric) {
    rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(rInfo->tb_prefix,
          g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
  } else {
    rInfo->ntables = g_args.num_of_tables;
    rInfo->end_table_to = g_args.num_of_tables -1;
    tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
  }

  rInfo->taos = taos_connect(
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
          g_Dbs.port);
  if (rInfo->taos == NULL) {
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
    free(rInfo);
    exit(-1);
  }

  tstrncpy(rInfo->fp, g_Dbs.resultFile, MAX_FILE_NAME_LEN);

  if (!g_Dbs.use_metric) {
    pthread_create(&read_id, NULL, readTable, rInfo);
  } else {
    pthread_create(&read_id, NULL, readMetric, rInfo);
  }
  pthread_join(read_id, NULL);
  taos_close(rInfo->taos);
  free(rInfo);
6942 6943
}

6944 6945
static void testCmdLine() {

6946 6947 6948 6949 6950 6951 6952 6953 6954 6955
  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);
  }

6956 6957
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
6958

6959
  if (false == g_Dbs.insert_only)
6960
    queryResult();
6961 6962
}

6963 6964 6965
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

6966
  debugPrint("meta file: %s\n", g_args.metaFile);
6967 6968 6969

  if (g_args.metaFile) {
    initOfInsertMeta();
6970
    initOfQueryMeta();
6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983

    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(
6984 6985 6986 6987
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
6988
          g_Dbs.port);
6989
      querySqlFile(qtaos, g_args.sqlFile);
6990 6991 6992 6993 6994
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
6995
  }
6996 6997

  return 0;
H
hzcheng 已提交
6998
}
6999