taosdemo.c 214.5 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.
*/

S
slguan 已提交
21
#define _GNU_SOURCE
22 23
#define CURL_STATICLIB

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

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

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

54 55 56
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

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

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

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

#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
72 73
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
74
#define MAX_DB_NAME_SIZE   64
75
#define MAX_HOSTNAME_SIZE  64
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
#define MAX_TB_NAME_SIZE   64
#define MAX_DATA_SIZE      16000
#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
#define   MAX_SUPER_TABLE_COUNT  8
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

92
#define   MAX_QUERY_SQL_COUNT    100
93 94 95
#define   MAX_QUERY_SQL_LENGTH   256

#define   MAX_DATABASE_COUNT     256
96
#define INPUT_BUF_LEN   256
97

98
#define DEFAULT_TIMESTAMP_STEP  1
99

100

101 102 103 104 105
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
106

107 108
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
109
  TBL_ALREADY_EXISTS,
110 111 112 113
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

enum MODE {
114
  SYNC,
115 116 117
  ASYNC,
  MODE_BUT
};
118

119 120 121 122 123 124
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

125
typedef enum enumQUERY_TYPE {
126 127 128
  NO_INSERT_TYPE,
  INSERT_TYPE, 
  QUERY_TYPE_BUT
129
} QUERY_TYPE;
130 131 132 133 134 135 136

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,
137
  TSDB_SHOW_DB_QUORUM_INDEX,
138 139 140 141 142 143 144 145 146 147
  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,
148
  TSDB_SHOW_DB_PRECISION_INDEX,
149 150 151 152 153 154 155 156 157 158
  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,
159 160
  TSDB_SHOW_STABLES_METRIC_INDEX,
  TSDB_SHOW_STABLES_UID_INDEX,
161
  TSDB_SHOW_STABLES_TID_INDEX,
162
  TSDB_SHOW_STABLES_VGID_INDEX,
163
  TSDB_MAX_SHOW_STABLES
164 165
};

166 167 168 169 170 171 172 173 174 175 176 177 178 179
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 已提交
180 181

/* Used by main to communicate with parse_opt. */
182 183
typedef struct SArguments_S {
  char *   metaFile;
184
  int      test_mode;
185 186 187 188 189 190 191 192 193
  char *   host;
  uint16_t port;
  char *   user;
  char *   password;
  char *   database;
  int      replica;
  char *   tb_prefix;
  char *   sqlFile;
  bool     use_metric;
194
  bool     drop_database;
195
  bool     insert_only;
196
  bool     answer_yes;
197
  bool     debug_print;
198
  bool     verbose_print;
199
  bool     performance_print;
200 201 202 203 204 205
  char *   output_file;
  int      mode;
  char *   datatype[MAX_NUM_DATATYPE + 1];
  int      len_of_binary;
  int      num_of_CPR;
  int      num_of_threads;
206
  int      insert_interval;
207
  int      query_times;
208
  int      interlace_rows;
209
  int      num_of_RPR;
210
  int      max_sql_len;
211 212 213
  int      num_of_tables;
  int      num_of_DPT;
  int      abort;
214 215
  int      disorderRatio;
  int      disorderRange;
216 217
  int      method_of_delete;
  char **  arg_list;
218 219
  int64_t  totalInsertRows;
  int64_t  totalAffectedRows;
220 221 222 223 224 225
} SArguments;

typedef struct SColumn_S {
  char  field[TSDB_COL_NAME_LEN + 1];
  char  dataType[MAX_TB_NAME_SIZE];
  int   dataLen;
226
  char  note[128];
227 228 229
} StrColumn;

typedef struct SSuperTable_S {
230
  char         sTblName[MAX_TB_NAME_SIZE+1];
231 232 233 234 235
  int          childTblCount;
  bool         childTblExists;    // 0: no, 1: yes  
  int          batchCreateTableNum;  // 0: no batch,  > 0: batch table number in one sql
  int8_t       autoCreateTable;                  // 0: create sub table, 1: auto create sub table
  char         childTblPrefix[MAX_TB_NAME_SIZE];
236
  char         dataSource[MAX_TB_NAME_SIZE+1];  // rand_gen or sample
237
  char         insertMode[MAX_TB_NAME_SIZE];  // taosc, restful
238 239
  int           childTblLimit;
  int           childTblOffset;
240 241

  int          multiThreadWriteOneTbl;   // 0: no, 1: yes
242
  int          interlaceRows;            // 
243 244 245
  int          disorderRatio;            // 0: no disorder, >0: x%
  int          disorderRange;            // ms or us by database precision
  int          maxSqlLen;                // 
246 247

  int          insertInterval;          // insert interval, will override global insert interval
248 249 250 251
  int64_t      insertRows;               // 0: no limit
  int          timeStampStep;
  char         startTimestamp[MAX_TB_NAME_SIZE];  // 
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
252 253
  char         sampleFile[MAX_FILE_NAME_LEN+1];
  char         tagsFile[MAX_FILE_NAME_LEN+1];
254 255 256 257 258 259 260

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

  char*        childTblName;
261
  char*        colsOfCreateChildTable;
262 263 264 265 266 267 268 269 270 271 272 273 274
  int          lenOfOneRow;
  int          lenOfTagOfOneRow;

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

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

275
  // statistics
276
  int64_t    totalInsertRows;
277 278 279 280 281 282 283
  int64_t    totalAffectedRows;
} SSuperTable;

typedef struct {
  char     name[TSDB_DB_NAME_LEN + 1];
  char     create_time[32];
  int32_t  ntables;
284
  int32_t  vgroups;
285 286
  int16_t  replica;
  int16_t  quorum;
287
  int16_t  days;
288 289 290 291 292 293 294 295 296 297 298 299 300 301
  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;

302
typedef struct SDbCfg_S {
303
//  int       maxtablesPerVnode;
304
  int       minRows;
305 306 307
  int       maxRows;
  int       comp;
  int       walLevel;
308
  int       cacheLast;
309
  int       fsync;
310 311 312 313 314 315 316
  int       replica;
  int       update;
  int       keep;
  int       days;
  int       cache;
  int       blocks;
  int       quorum;
317
  char      precision[MAX_TB_NAME_SIZE];
318 319 320 321
} SDbCfg;

typedef struct SDataBase_S {
  char         dbName[MAX_DB_NAME_SIZE];
322
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
323 324 325 326 327 328
  SDbCfg       dbCfg;
  int          superTblCount;
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
329
  char         cfgDir[MAX_FILE_NAME_LEN+1];
330
  char         host[MAX_HOSTNAME_SIZE];
331
  uint16_t     port;
332 333
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
334
  char         resultFile[MAX_FILE_NAME_LEN+1];
335 336 337 338
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
  bool         queryMode;
339

340 341 342 343 344 345
  int          threadCount;
  int          threadCountByCreateTbl;
  int          dbCount;
  SDataBase    db[MAX_DB_COUNT];

  // statistics
346
  int64_t    totalInsertRows;
347
  int64_t    totalAffectedRows;
348

349 350 351 352 353 354 355 356 357 358
} SDbs;

typedef struct SuperQueryInfo_S {
  int          rate;  // 0: unlimit  > 0   loop/s
  int          concurrent;
  int          sqlCount;
  int          subscribeMode; // 0: sync, 1: async
  int          subscribeInterval; // ms
  int          subscribeRestart;
  int          subscribeKeepProgress;
359
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
360
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
361 362 363 364
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
} SuperQueryInfo;

typedef struct SubQueryInfo_S {
365
  char         sTblName[MAX_TB_NAME_SIZE+1];
366
  int          rate;  // 0: unlimit  > 0   loop/s
367
  int          threadCnt;
368 369 370 371 372 373 374
  int          subscribeMode; // 0: sync, 1: async
  int          subscribeInterval; // ms
  int          subscribeRestart;
  int          subscribeKeepProgress;
  int          childTblCount;
  char         childTblPrefix[MAX_TB_NAME_SIZE];
  int          sqlCount;
375
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
376
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
377
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
378

379 380 381 382
  char*        childTblName;
} SubQueryInfo;

typedef struct SQueryMetaInfo_S {
383
  char         cfgDir[MAX_FILE_NAME_LEN+1];
384
  char         host[MAX_HOSTNAME_SIZE];
385
  uint16_t     port;
386 387
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
388
  char         dbName[MAX_DB_NAME_SIZE+1];
389 390 391
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, restful

  SuperQueryInfo  superQueryInfo;
392
  SubQueryInfo    subQueryInfo;
393 394 395 396 397
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
  TAOS *taos;
  int threadID;
398
  char db_name[MAX_DB_NAME_SIZE+1];
399
  uint32_t time_precision;
400 401
  char fp[4096];
  char tb_prefix[MAX_TB_NAME_SIZE];
402 403 404
  int start_table_from;
  int end_table_to;
  int ntables;
405
  int data_of_rate;
406 407 408
  uint64_t start_time;
  char* cols;
  bool  use_metric;
409 410 411 412
  SSuperTable* superTblInfo;

  // for async insert
  tsem_t lock_sem;
413
  int64_t  counter;
414 415
  uint64_t  st;
  uint64_t  et;
416 417
  int64_t  lastTs;

418 419
  // sample data
  int samplePos;
420
  // statistics
421
  int64_t totalInsertRows;
422
  int64_t totalAffectedRows;
423 424 425 426 427 428 429

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

431 432
} threadInfo;

433
#ifdef WINDOWS
434 435
#define _CRT_RAND_S

436
#include <windows.h>
437 438 439 440 441
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
442 443
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
444 445
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
446 447 448 449

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

450
static void setupForAnsiEscape(void) {
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
  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());
469
  }
470 471
}

472
static void resetAfterAnsiEscape(void) {
473
  // Reset colors
474
  printf("\x1b[0m");
475 476 477 478 479 480

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

482
static int taosRandom()
483 484 485 486 487 488
{
    int number;
    rand_s(&number);

    return number;
}
489
#else
490
static void setupForAnsiEscape(void) {}
491

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

497 498
#include <time.h>

499
static int taosRandom()
500
{
501 502
  srand(time(NULL));
  return rand();
503 504
}

505 506
#endif

507 508
static int createDatabases();
static void createChildTables();
509
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
510 511 512 513 514 515 516

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

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

520
SArguments g_args = {
521 522
                     NULL,            // metaFile
                     0,               // test_mode
523 524 525
                     "127.0.0.1",     // host
                     6030,            // port
                     "root",          // user
526
                     #ifdef _TD_POWER_
527 528 529 530 531 532 533 534
                     "powerdb",      // password
                     #else
                     "taosdata",      // password
                     #endif
                     "test",          // database
                     1,               // replica
                     "t",             // tb_prefix
                     NULL,            // sqlFile
535
                     true,            // use_metric
536
                     true,            // drop_database
537
                     true,            // insert_only
538
                     false,           // debug_print
539
                     false,           // verbose_print
540
                     false,           // performance statistic print 
541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559
                     false,           // answer_yes;
                     "./output.txt",  // output_file
                     0,               // mode : sync or async
                     {
                     "TINYINT",           // datatype
                     "SMALLINT",
                     "INT",
                     "BIGINT",
                     "FLOAT",
                     "DOUBLE",
                     "BINARY",
                     "NCHAR",
                     "BOOL",
                     "TIMESTAMP"
                     },
                     16,              // len_of_binary
                     10,              // num_of_CPR
                     10,              // num_of_connections/thread
                     0,               // insert_interval
560
                     1,               // query_times
561
                     0,               // interlace_rows;
562
                     100,             // num_of_RPR
563
                     TSDB_PAYLOAD_SIZE,  // max_sql_len
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
                     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, ...) \
581
    do { if (g_args.debug_print || g_args.verbose_print) \
582
      fprintf(stderr, "DEBG: "fmt, __VA_ARGS__); } while(0)
583

584
#define verbosePrint(fmt, ...) \
585 586
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
587

588 589 590 591
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

592 593 594 595
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


596
///////////////////////////////////////////////////
H
hzcheng 已提交
597

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

600 601 602 603 604 605 606 607
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

608
#ifndef TAOSDEMO_STATUS
609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
#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);
    }
}

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

690
static void parse_args(int argc, char *argv[], SArguments *arguments) {
691
  char **sptr;
692 693 694 695 696 697 698 699
  wordexp_t full_path;

  for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-f") == 0) {
      arguments->metaFile = argv[++i];
    } else if (strcmp(argv[i], "-c") == 0) {
        char *configPath = argv[++i];
      if (wordexp(configPath, &full_path, 0) != 0) {
700
          errorPrint( "Invalid path %s\n", configPath);
701 702 703 704
          return;
      }
      taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
      wordfree(&full_path);
705

706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723
    } else if (strcmp(argv[i], "-h") == 0) {
      arguments->host = argv[++i];
    } else if (strcmp(argv[i], "-p") == 0) {
      arguments->port = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-u") == 0) {
      arguments->user = argv[++i];
    } else if (strcmp(argv[i], "-P") == 0) {
      arguments->password = argv[++i];
    } else if (strcmp(argv[i], "-o") == 0) {
      arguments->output_file = argv[++i];
    } else if (strcmp(argv[i], "-s") == 0) {
      arguments->sqlFile = argv[++i];
    } else if (strcmp(argv[i], "-q") == 0) {
      arguments->mode = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-T") == 0) {
      arguments->num_of_threads = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-i") == 0) {
      arguments->insert_interval = atoi(argv[++i]);
724 725
    } else if (strcmp(argv[i], "-qt") == 0) {
      arguments->query_times = atoi(argv[++i]);
726
    } else if (strcmp(argv[i], "-B") == 0) {
727
      arguments->interlace_rows = atoi(argv[++i]);
728 729 730 731 732 733 734 735 736 737 738
    } else if (strcmp(argv[i], "-r") == 0) {
      arguments->num_of_RPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-t") == 0) {
      arguments->num_of_tables = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-n") == 0) {
      arguments->num_of_DPT = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-d") == 0) {
      arguments->database = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0) {
      arguments->num_of_CPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-b") == 0) {
739
      sptr = arguments->datatype;
740 741
      ++i;
      if (strstr(argv[i], ",") == NULL) {
742
        // only one col
743 744 745 746 747 748 749 750 751 752
        if (strcasecmp(argv[i], "INT")
                && strcasecmp(argv[i], "FLOAT")
                && strcasecmp(argv[i], "TINYINT")
                && strcasecmp(argv[i], "BOOL")
                && strcasecmp(argv[i], "SMALLINT")
                && strcasecmp(argv[i], "BIGINT")
                && strcasecmp(argv[i], "DOUBLE")
                && strcasecmp(argv[i], "BINARY") 
                && strcasecmp(argv[i], "NCHAR")) {
          printHelp();
753
          ERROR_EXIT( "Invalid data_type!\n");
754
          exit(EXIT_FAILURE);
755
        }
756
        sptr[0] = argv[i];
757
      } else {
758
        // more than one col
759
        int index = 0;
760
        char *dupstr = strdup(argv[i]);
761 762 763
        char *running = dupstr;
        char *token = strsep(&running, ",");
        while (token != NULL) {
764 765 766 767 768 769 770 771 772 773
          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();
774
            ERROR_EXIT("Invalid data_type!\n");
775
            exit(EXIT_FAILURE);
H
hzcheng 已提交
776
          }
777 778 779
          sptr[index++] = token;
          token = strsep(&running, ",");
          if (index >= MAX_NUM_DATATYPE) break;
S
TD-1057  
Shengliang Guan 已提交
780
        }
781
        sptr[index] = NULL;
782
      }
783 784 785 786
    } else if (strcmp(argv[i], "-w") == 0) {
      arguments->len_of_binary = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-m") == 0) {
      arguments->tb_prefix = argv[++i];
787 788
    } else if (strcmp(argv[i], "-N") == 0) {
      arguments->use_metric = false;
789
    } else if (strcmp(argv[i], "-x") == 0) {
790
      arguments->insert_only = false;
791
    } else if (strcmp(argv[i], "-y") == 0) {
792
      arguments->answer_yes = true;
793 794
    } else if (strcmp(argv[i], "-g") == 0) {
      arguments->debug_print = true;
795 796
    } else if (strcmp(argv[i], "-gg") == 0) {
      arguments->verbose_print = true;
797 798
    } else if (strcmp(argv[i], "-pp") == 0) {
      arguments->performance_print = true;
799 800 801 802
    } else if (strcmp(argv[i], "-c") == 0) {
      strcpy(configDir, argv[++i]);
    } else if (strcmp(argv[i], "-O") == 0) {
      arguments->disorderRatio = atoi(argv[++i]);
803
      if (arguments->disorderRatio > 1
804 805 806 807
              || arguments->disorderRatio < 0) {
        arguments->disorderRatio = 0;
      } else if (arguments->disorderRatio == 1) {
        arguments->disorderRange = 10;
808
      }
809 810
    } else if (strcmp(argv[i], "-R") == 0) {
      arguments->disorderRange = atoi(argv[++i]);
811 812
      if (arguments->disorderRange == 1
              && (arguments->disorderRange > 50
813 814
              || arguments->disorderRange <= 0)) {
        arguments->disorderRange = 10;
815
      }
816 817 818 819
    } else if (strcmp(argv[i], "-a") == 0) {
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
820
      }
821 822 823 824 825
    } 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 已提交
826
      }
827 828 829 830
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
831 832 833 834 835
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
836
      ERROR_EXIT("ERROR: wrong options\n");
837
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
838 839
    }
  }
840

841 842
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
          || arguments->verbose_print) {
843
    printf("###################################################################\n");
844
    printf("# meta file:                         %s\n", arguments->metaFile);
845
    printf("# Server IP:                         %s:%hu\n",
846 847 848 849 850
            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");
851 852 853 854 855 856 857 858 859
    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");
    }
860
    printf("# Insertion interval:                %d\n", arguments->insert_interval);
861
    printf("# Number of records per req:         %d\n", arguments->num_of_RPR);
862
    printf("# Max SQL length:                    %d\n", arguments->max_sql_len);
863
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
864 865 866 867 868 869 870 871
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
    printf("# Number of Tables:                  %d\n", arguments->num_of_tables);
    printf("# Number of Data per Table:          %d\n", arguments->num_of_DPT);
    printf("# Database name:                     %s\n", arguments->database);
    printf("# Table prefix:                      %s\n", arguments->tb_prefix);
    if (arguments->disorderRatio) {
      printf("# Data order:                        %d\n", arguments->disorderRatio);
      printf("# Data out of order rate:            %d\n", arguments->disorderRange);
872

873 874 875 876
    }
    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);
877
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
878 879 880 881 882 883
    printf("###################################################################\n");
    if (!arguments->answer_yes) {
        printf("Press enter key to continue\n\n");
        (void) getchar();
    }
  }
884
}
H
hzcheng 已提交
885

886 887 888 889
static bool getInfoFromJsonFile(char* file);
//static int generateOneRowDataForStb(SSuperTable* stbInfo);
//static int getDataIntoMemForStb(SSuperTable* stbInfo);
static void init_rand_data();
890
static void tmfclose(FILE *fp) {
891 892 893 894
  if (NULL != fp) {
    fclose(fp);
  }
}
895

896
static void tmfree(char *buf) {
897 898
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
899
  }
900
}
H
Hui Li 已提交
901

902
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
903 904 905
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
906

907 908 909 910
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
911
    }
912

913 914 915 916
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
917
    }
H
hzcheng 已提交
918 919
  }

920
  if (code != 0) {
921 922 923 924
    if (!quiet) {
      debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
      errorPrint("Failed to run %s, reason: %s\n", command, taos_errstr(res));
    }
925 926 927
    taos_free_result(res);
    //taos_close(taos);
    return -1;
928
  }
H
hzcheng 已提交
929

930 931 932 933
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
934
  }
935

936
  taos_free_result(res);
937 938
  return 0;
}
H
hzcheng 已提交
939

940
static void getResult(TAOS_RES *res, char* resultFileName) {
941 942 943 944 945 946 947 948 949
  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) {
950 951
      errorPrint("%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFileName);
952 953
    }
  }
954

955 956
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
957 958
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
959 960
    if (fp)
        fclose(fp);
961 962
    return ;
  }
H
hzcheng 已提交
963

964 965
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
966

967 968 969 970 971 972
  // fetch the records row by row
  while ((row = taos_fetch_row(res))) {
    if (totalLen >= 100*1024*1024 - 32000) {
      if (fp) fprintf(fp, "%s", databuf);
      totalLen = 0;
      memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
973
    }
974 975 976 977 978 979
    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 已提交
980 981
  }

982 983 984 985
  if (fp) fprintf(fp, "%s", databuf);
  tmfclose(fp);
  free(databuf);
}
H
hzcheng 已提交
986

987 988 989 990 991 992
static void selectAndGetResult(TAOS *taos, char *command, char* resultFileName) {
  TAOS_RES *res = taos_query(taos, command);
  if (res == NULL || taos_errno(res) != 0) {
    printf("failed to sql:%s, reason:%s\n", command, taos_errstr(res));
    taos_free_result(res);
    return;
H
hzcheng 已提交
993
  }
994

995 996 997
  getResult(res, resultFileName);
  taos_free_result(res);
}
H
hzcheng 已提交
998

999
static double getCurrentTime() {
1000 1001 1002 1003
  struct timeval tv;
  if (gettimeofday(&tv, NULL) != 0) {
    perror("Failed to get current time in ms");
    return 0.0;
H
hzcheng 已提交
1004
  }
S
Shuduo Sang 已提交
1005

1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047
  return tv.tv_sec + tv.tv_usec / 1E6;
}

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;
1048
  return randfloat[cursor];
1049 1050 1051
}

static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1052
static void rand_string(char *str, int size) {
1053 1054 1055 1056
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1057
    for (n = 0; n < size - 1; n++) {
1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
      int key = rand_tinyint() % (int)(sizeof(charset) - 1);
      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++){
1075 1076 1077 1078
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1079 1080 1081
  }
}

1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101
#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)

1102
static int printfInsertMeta() {
1103 1104
    SHOW_PARSE_RESULT_START();

1105 1106 1107 1108 1109 1110
  printf("host:                       \033[33m%s:%u\033[0m\n", g_Dbs.host, g_Dbs.port);
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
  printf("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);
1111 1112
  printf("insert interval:            \033[33m%d\033[0m\n", g_args.insert_interval);
  printf("number of records per req:  \033[33m%d\033[0m\n", g_args.num_of_RPR);
1113
  printf("max sql length:             \033[33m%d\033[0m\n", g_args.max_sql_len);
1114 1115

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

1117 1118
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1119
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1120
    if (0 == g_Dbs.db[i].drop) {
1121 1122 1123
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162
    }

    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) {
1163 1164
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1165 1166
        printf("  precision:             \033[33m%s\033[0m\n", g_Dbs.db[i].dbCfg.precision);
      } else {
1167 1168 1169
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                g_Dbs.db[i].dbCfg.precision);
        return -1;
1170 1171 1172 1173 1174 1175
      }
    }

    printf("  super table count:     \033[33m%d\033[0m\n", g_Dbs.db[i].superTblCount);
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%d\033[0m]:\n", j);
1176 1177

      printf("      stbName:           \033[33m%s\033[0m\n",  g_Dbs.db[i].superTbls[j].sTblName);
1178 1179 1180 1181 1182 1183 1184 1185

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

1187 1188 1189 1190 1191 1192 1193
      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");
      }
1194 1195 1196 1197 1198 1199 1200 1201

      printf("      childTblCount:     \033[33m%d\033[0m\n",  g_Dbs.db[i].superTbls[j].childTblCount);
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",  g_Dbs.db[i].superTbls[j].childTblPrefix);
      printf("      dataSource:        \033[33m%s\033[0m\n",  g_Dbs.db[i].superTbls[j].dataSource);
      printf("      insertMode:        \033[33m%s\033[0m\n",  g_Dbs.db[i].superTbls[j].insertMode);
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
        printf("      childTblLimit:     \033[33m%d\033[0m\n",  g_Dbs.db[i].superTbls[j].childTblLimit);
      }
1202
      if (g_Dbs.db[i].superTbls[j].childTblOffset >= 0) {
1203 1204 1205
        printf("      childTblOffset:    \033[33m%d\033[0m\n",  g_Dbs.db[i].superTbls[j].childTblOffset);
      }
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n", g_Dbs.db[i].superTbls[j].insertRows);
1206 1207

      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1208
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1209
      }else {
1210
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1211
      }
1212 1213
      printf("      interlaceRows:     \033[33m%d\033[0m\n",
              g_Dbs.db[i].superTbls[j].interlaceRows);
1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231
      printf("      disorderRange:     \033[33m%d\033[0m\n",
              g_Dbs.db[i].superTbls[j].disorderRange);
      printf("      disorderRatio:     \033[33m%d\033[0m\n",
              g_Dbs.db[i].superTbls[j].disorderRatio);
      printf("      maxSqlLen:         \033[33m%d\033[0m\n",
              g_Dbs.db[i].superTbls[j].maxSqlLen);
      printf("      timeStampStep:     \033[33m%d\033[0m\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      printf("      startTimestamp:    \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
      printf("      sampleFormat:      \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].sampleFormat);
      printf("      sampleFile:        \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].sampleFile);
      printf("      tagsFile:          \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].tagsFile);
      printf("      columnCount:       \033[33m%d\033[0m\n        ",
              g_Dbs.db[i].superTbls[j].columnCount);
1232 1233
      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);
1234 1235 1236 1237
        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))) {
1238
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1239 1240
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1241
        } else {
1242 1243
          printf("column[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1244 1245 1246
        }
      }
      printf("\n");
1247 1248 1249

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1250 1251
      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);
1252 1253 1254
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "binary", 6))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType, "nchar", 5))) {
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1255 1256
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1257
        } else {
1258 1259
          printf("tag[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1260
        }
1261 1262 1263 1264 1265
      }
      printf("\n");
    }
    printf("\n");
  }
1266 1267

  SHOW_PARSE_RESULT_END();
1268 1269

  return 0;
1270 1271 1272
}

static void printfInsertMetaToFile(FILE* fp) {
1273 1274

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1275

1276 1277 1278 1279 1280
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
  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);
1281 1282
  fprintf(fp, "number of records per req:  %d\n", g_args.num_of_RPR);
  fprintf(fp, "max sql length:             %d\n", g_args.max_sql_len);
1283
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1284

1285 1286
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1287
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1288
    if (0 == g_Dbs.db[i].drop) {
1289
      fprintf(fp, "  drop:                  no\n");
1290
    }else {
1291
      fprintf(fp, "  drop:                  yes\n");
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330
    }

    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) {
1331 1332
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1333 1334 1335 1336 1337 1338 1339 1340 1341
        fprintf(fp, "  precision:             %s\n", g_Dbs.db[i].dbCfg.precision);
      } else {
        fprintf(fp, "  precision error:       %s\n", g_Dbs.db[i].dbCfg.precision);
      }
    }

    fprintf(fp, "  super table count:     %d\n", g_Dbs.db[i].superTblCount);
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1342 1343

      fprintf(fp, "      stbName:           %s\n",  g_Dbs.db[i].superTbls[j].sTblName);
1344 1345 1346 1347 1348 1349 1350 1351

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

1353 1354 1355 1356 1357 1358 1359
      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");
      }
1360 1361 1362 1363 1364 1365

      fprintf(fp, "      childTblCount:     %d\n",  g_Dbs.db[i].superTbls[j].childTblCount);
      fprintf(fp, "      childTblPrefix:    %s\n",  g_Dbs.db[i].superTbls[j].childTblPrefix);
      fprintf(fp, "      dataSource:        %s\n",  g_Dbs.db[i].superTbls[j].dataSource);
      fprintf(fp, "      insertMode:        %s\n",  g_Dbs.db[i].superTbls[j].insertMode);
      fprintf(fp, "      insertRows:        %"PRId64"\n", g_Dbs.db[i].superTbls[j].insertRows);
1366 1367 1368 1369
      fprintf(fp, "      interlace rows:    %d\n", g_Dbs.db[i].superTbls[j].interlaceRows);
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
        fprintf(fp, "      insert interval:   %d\n", g_Dbs.db[i].superTbls[j].insertInterval);
      }
1370 1371

      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1372
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1373
      }else {
1374
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1375
      }
1376 1377
      fprintf(fp, "      interlaceRows:     %d\n",  g_Dbs.db[i].superTbls[j].interlaceRows);
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1378
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1379 1380 1381 1382
      fprintf(fp, "      maxSqlLen:         %d\n",  g_Dbs.db[i].superTbls[j].maxSqlLen);

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

1387 1388 1389
      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);
1390 1391 1392 1393 1394 1395 1396 1397
        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);
1398 1399 1400 1401 1402
        } else {
          fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
        }
      }
      fprintf(fp, "\n");
1403 1404 1405

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1406 1407
      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);
1408 1409 1410 1411 1412 1413
        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);
1414 1415
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1416
        }
1417 1418 1419 1420 1421
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1422

1423
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1424 1425 1426
}

static void printfQueryMeta() {
1427

1428
  SHOW_PARSE_RESULT_START();
1429

1430 1431
  printf("host:                    \033[33m%s:%u\033[0m\n",
          g_queryInfo.host, g_queryInfo.port);
1432 1433 1434 1435
  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");
1436
  printf("specified table query info:                   \n");
1437
  printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.rate);
1438
  printf("query times:    \033[33m%d\033[0m\n", g_args.query_times);
1439
  printf("concurrent:     \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.concurrent);
1440
  printf("sqlCount:       \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount);
1441

1442
  if (SUBSCRIBE_TEST == g_args.test_mode) {
1443 1444 1445 1446 1447 1448 1449 1450 1451 1452
    printf("mod:            \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeMode);
    printf("interval:       \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeInterval);
    printf("restart:        \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeRestart);
    printf("keepProgress:   \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.subscribeKeepProgress);
  }

  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
    printf("  sql[%d]: \033[33m%s\033[0m\n", i, g_queryInfo.superQueryInfo.sql[i]);
  }
  printf("\n");
1453
  printf("super table query info:                   \n");
1454 1455 1456 1457 1458
  printf("query interval: \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.rate);
  printf("threadCnt:      \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.threadCnt);
  printf("childTblCount:  \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.childTblCount);
  printf("stable name:    \033[33m%s\033[0m\n", g_queryInfo.subQueryInfo.sTblName);

1459
  if (SUBSCRIBE_TEST == g_args.test_mode) {
1460 1461 1462 1463 1464
    printf("mod:            \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeMode);
    printf("interval:       \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeInterval);
    printf("restart:        \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeRestart);
    printf("keepProgress:   \033[33m%d\033[0m\n", g_queryInfo.subQueryInfo.subscribeKeepProgress);
  }
1465 1466

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

1472
  SHOW_PARSE_RESULT_END();
1473 1474
}

1475
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506
  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;
}

1507 1508 1509
static void xDumpFieldToFile(FILE* fp, const char* val,
        TAOS_FIELD* field, int32_t length, int precision) {

1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544
  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:
1545
      formatTimestamp(buf, *(int64_t*)val, precision);
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560
      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) {
1561
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575
    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);
1576

1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596
  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;
}

1597 1598
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1599 1600
  TAOS_ROW row = NULL;
  int count = 0;
1601 1602

  res = taos_query(taos, "show databases;");
1603
  int32_t code = taos_errno(res);
1604

1605
  if (code != 0) {
1606
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

  while ((row = taos_fetch_row(res)) != NULL) {
    // sys database name : 'log'
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log", fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) continue;

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

1622 1623
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1624
    formatTimestamp(dbInfos[count]->create_time,
1625 1626
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1627
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1628
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1629 1630
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1631
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1632

1633
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1634
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1635 1636 1637 1638 1639 1640 1641 1642 1643
    dbInfos[count]->cache = *((int32_t *)row[TSDB_SHOW_DB_CACHE_INDEX]);
    dbInfos[count]->blocks = *((int32_t *)row[TSDB_SHOW_DB_BLOCKS_INDEX]);
    dbInfos[count]->minrows = *((int32_t *)row[TSDB_SHOW_DB_MINROWS_INDEX]);
    dbInfos[count]->maxrows = *((int32_t *)row[TSDB_SHOW_DB_MAXROWS_INDEX]);
    dbInfos[count]->wallevel = *((int8_t *)row[TSDB_SHOW_DB_WALLEVEL_INDEX]);
    dbInfos[count]->fsync = *((int32_t *)row[TSDB_SHOW_DB_FSYNC_INDEX]);
    dbInfos[count]->comp = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX]));
    dbInfos[count]->cachelast = (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));

1644
    tstrncpy(dbInfos[count]->precision,
1645
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
1646
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1647
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1648
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1649
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1650

1651 1652
    count++;
    if (count > MAX_DATABASE_COUNT) {
1653
      errorPrint( "The database count overflow than %d\n", MAX_DATABASE_COUNT);
1654 1655 1656 1657 1658 1659 1660 1661
      break;
    }
  }

  return count;
}

static void printfDbInfoForQueryToFile(char* filename, SDbInfo* dbInfos, int index) {
1662
  if (filename[0] == 0)
1663
      return;
1664 1665 1666

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1667
    errorPrint( "failed to open file: %s\n", filename);
1668
    return;
1669 1670 1671 1672 1673 1674
  }

  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);
1675
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1676 1677
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1678 1679
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1680 1681 1682 1683 1684 1685 1686
  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);
1687 1688
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
1689
  fprintf(fp, "update: %d\n", dbInfos->update);
1690
  fprintf(fp, "status: %s\n", dbInfos->status);
1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
  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);
1705 1706 1707 1708
  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);

1709 1710 1711 1712 1713 1714 1715 1716 1717
  // 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);
1718

1719 1720 1721 1722
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
1723
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
1724 1725 1726
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
1727 1728 1729 1730
  if (dbCount <= 0) {
      free(dbInfos);
      return;
  }
1731 1732 1733 1734

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

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

1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
    // 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);
}

1752
static int postProceSql(char* host, uint16_t port, char* sqlstr)
1753
{
1754
    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";
1755 1756 1757 1758 1759

    char *url = "/rest/sql";

    struct hostent *server;
    struct sockaddr_in serv_addr;
1760
    int bytes, sent, received, req_str_len, resp_len;
1761 1762 1763
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
1764

1765 1766 1767 1768
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

    request_buf = malloc(req_buf_len);
    if (NULL == request_buf)
1769
        ERROR_EXIT("ERROR, cannot allocate memory.");
1770

1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781
    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', '+', '/'};
1782

1783 1784 1785 1786 1787 1788
    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];
1789
#ifdef WINDOWS
1790
    WSADATA wsaData;
1791
    WSAStartup(MAKEWORD(2, 2), &wsaData);
1792 1793 1794 1795
    SOCKET sockfd;
#else
    int sockfd;
#endif
1796
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
1797
    if (sockfd < 0) {
1798
#ifdef WINDOWS
1799
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
1800
#endif
1801
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
1802
        free(request_buf);
1803
        ERROR_EXIT("ERROR opening socket");
1804
    }
1805 1806

    server = gethostbyname(host);
1807 1808
    if (server == NULL) {
        free(request_buf);
1809
        ERROR_EXIT("ERROR, no such host");
1810
    }
1811

1812
    debugPrint("h_name: %s\nh_addretype: %s\nh_length: %d\n",
1813 1814 1815 1816
            server->h_name,
            (server->h_addrtype == AF_INET)?"ipv4":"ipv6",
            server->h_length);

1817
    memset(&serv_addr, 0, sizeof(serv_addr));
1818
    serv_addr.sin_family = AF_INET;
1819
    serv_addr.sin_port = htons(rest_port);
1820 1821 1822
#ifdef WINDOWS
    serv_addr.sin_addr.s_addr = inet_addr(host);
#else
1823
    memcpy(&serv_addr.sin_addr.s_addr,server->h_addr,server->h_length);
1824
#endif
1825

1826 1827 1828
    int retConn = connect(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
1829
        free(request_buf);
1830
        ERROR_EXIT("ERROR connecting");
1831
    }
1832

1833 1834 1835
    memset(base64_buf, 0, INPUT_BUF_LEN);

    for (int n = 0, m = 0; n < userpass_buf_len;) {
1836
      uint32_t oct_a = n < userpass_buf_len ?
1837
        (unsigned char) userpass_buf[n++]:0;
1838
      uint32_t oct_b = n < userpass_buf_len ?
1839
        (unsigned char) userpass_buf[n++]:0;
1840
      uint32_t oct_c = n < userpass_buf_len ?
1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
        (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] = '=';

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

1856 1857 1858
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
1859 1860 1861 1862 1863
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
1864
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
1865

1866
    req_str_len = strlen(request_buf);
1867 1868
    sent = 0;
    do {
1869 1870 1871
#ifdef WINDOWS
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
#else
1872
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
1873
#endif
1874
        if (bytes < 0)
1875
            ERROR_EXIT("ERROR writing message to socket");
1876 1877 1878
        if (bytes == 0)
            break;
        sent+=bytes;
1879
    } while (sent < req_str_len);
1880

1881 1882
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
1883 1884
    received = 0;
    do {
1885 1886 1887
#ifdef WINDOWS
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
#else
1888
        bytes = read(sockfd, response_buf + received, resp_len - received);
1889
#endif
1890 1891
        if (bytes < 0) {
            free(request_buf);
1892
            ERROR_EXIT("ERROR reading response from socket");
1893
        }
1894 1895
        if (bytes == 0)
            break;
1896 1897
        received += bytes;
    } while (received < resp_len);
1898

1899 1900
    if (received == resp_len) {
        free(request_buf);
1901
        ERROR_EXIT("ERROR storing complete response from socket");
1902
    }
1903

1904
    response_buf[RESP_BUF_LEN - 1] = '\0';
1905 1906 1907
    printf("Response:\n%s\n", response_buf);

    free(request_buf);
1908 1909 1910 1911
#ifdef WINDOWS
    closesocket(sockfd);
    WSACleanup();
#else
1912
    close(sockfd);
1913
#endif
1914 1915 1916 1917

    return 0;
}

1918
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
1919 1920
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
1921
    errorPrint("%s() LN%d, calloc failed! size:%d\n", __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
1922 1923
    return NULL;
  }
1924

1925
  int    dataLen = 0;
1926 1927 1928
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);

1929 1930 1931
  return dataBuf;
}

1932
static char* generateTagVaulesForStb(SSuperTable* stbInfo) {
1933 1934 1935 1936 1937 1938 1939 1940 1941
  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++) {
1942 1943
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
1944
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
1945 1946
        printf("binary or nchar length overflow, max size:%u\n",
                (uint32_t)TSDB_MAX_BINARY_LEN);
1947 1948 1949
        tmfree(dataBuf);
        return NULL;
      }
1950

1951 1952 1953 1954 1955 1956 1957
      char* buf = (char*)calloc(stbInfo->tags[i].dataLen+1, 1);
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
      rand_string(buf, stbInfo->tags[i].dataLen);
1958 1959
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
              "\'%s\', ", buf);
1960
      tmfree(buf);
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                "int", strlen("int"))) {
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
              "%d, ", rand_int());
    } 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());
1993 1994 1995 1996 1997 1998
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
1999

2000
  dataLen -= 2;
2001
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2002 2003 2004
  return dataBuf;
}

2005
static int calcRowLen(SSuperTable*  superTbls) {
2006 2007
  int colIndex;
  int  lenOfOneRow = 0;
2008

2009 2010
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2011

2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027
    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;
2028
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2029
      lenOfOneRow += 42;
2030
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043
      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;
2044

2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069
    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;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) { 
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2070

2071 2072 2073 2074
  return 0;
}


2075 2076 2077 2078
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
        int* childTblCountOfSuperTbl, int limit, int offset) {

2079
  char command[BUFFER_SIZE] = "\0";
2080 2081
  char limitBuf[100] = "\0";

2082
  TAOS_RES * res;
2083 2084 2085
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2086 2087 2088 2089 2090

  if (offset >= 0) {
    snprintf(limitBuf, 100, " limit %d offset %d", limit, offset);
  }

2091
  //get all child table name use cmd: select tbname from superTblName;
2092 2093
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s", dbName, sTblName, limitBuf);

2094
  res = taos_query(taos, command);
2095 2096 2097 2098
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2099 2100
    errorPrint("%s() LN%d, failed to run command %s\n",
           __func__, __LINE__, command);
2101 2102 2103
    exit(-1);
  }

2104
  int childTblCount = (limit < 0)?10000:limit;
2105
  int count = 0;
2106 2107 2108 2109 2110 2111 2112 2113 2114 2115
  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);
    }
  }

2116 2117 2118
  char* pTblName = childTblName;
  while ((row = taos_fetch_row(res)) != NULL) {
    int32_t* len = taos_fetch_lengths(res);
2119
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2120 2121 2122
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2123 2124
      char *tmp = realloc(childTblName,
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2125 2126 2127
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2128 2129
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2130 2131
      } else {
        // exit, if allocate more memory failed
2132 2133
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
               __func__, __LINE__, dbName, sTblName);
2134 2135 2136 2137 2138 2139
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2140
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2141
  }
2142

2143 2144 2145 2146 2147 2148 2149
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2150 2151
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
        char* sTblName, char** childTblNameOfSuperTbl,
2152
        int* childTblCountOfSuperTbl) {
2153 2154 2155 2156 2157 2158

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

2159 2160
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2161

2162
  char command[BUFFER_SIZE] = "\0";
2163
  TAOS_RES * res;
2164 2165
  TAOS_ROW row = NULL;
  int count = 0;
2166

2167
  //get schema use cmd: describe superTblName;
2168
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2169
  res = taos_query(taos, command);
2170 2171 2172
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2173
    taos_free_result(res);
2174 2175 2176 2177 2178 2179 2180 2181 2182 2183
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
  while ((row = taos_fetch_row(res)) != NULL) {
    if (0 == count) {
      count++;
      continue;
2184
    }
2185 2186

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197
      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);
2198
      tagIndex++;
2199
    } else {
2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210
      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);
2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2222
/*
2223 2224
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
    //get all child table name use cmd: select tbname from superTblName;  
2225 2226 2227
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2228
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2229 2230
      return -1;
    }
2231
    getAllChildNameOfSuperTable(taos, dbName,
2232 2233 2234
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2235
  }
2236
  */
2237 2238 2239
  return 0;
}

2240
static int createSuperTable(TAOS * taos, char* dbName, SSuperTable*  superTbls, bool use_metric) {
2241
  char command[BUFFER_SIZE] = "\0";
2242

2243 2244 2245 2246 2247 2248 2249
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2250
 
2251
    if (strcasecmp(dataType, "BINARY") == 0) {
2252 2253 2254
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbls->columns[colIndex].dataLen);
2255 2256
      lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2257 2258 2259
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbls->columns[colIndex].dataLen);
2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278
      lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
    } 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;
2279
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2280 2281
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2282
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
      printf("config error data type : %s\n", dataType);
      exit(-1);
    }
  }

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

  // save for creating child table
2296 2297
  superTbls->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbls->colsOfCreateChildTable) {
2298 2299 2300 2301
    printf("Failed when calloc, size:%d", len+1);
    taos_close(taos);
    exit(-1);
  }
2302
  snprintf(superTbls->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2303
  verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, superTbls->colsOfCreateChildTable);
2304 2305 2306 2307 2308 2309 2310 2311 2312 2313

  if (use_metric) {
    char tags[STRING_LEN] = "\0";
    int tagIndex;
    len = 0;

    int lenOfTagOfOneRow = 0;
    len += snprintf(tags + len, STRING_LEN - len, "(");
    for (tagIndex = 0; tagIndex < superTbls->tagCount; tagIndex++) {
      char* dataType = superTbls->tags[tagIndex].dataType;
2314

2315
      if (strcasecmp(dataType, "BINARY") == 0) {
2316 2317
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
                "BINARY", superTbls->tags[tagIndex].dataLen);
2318 2319
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
      } else if (strcasecmp(dataType, "NCHAR") == 0) {
2320 2321
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
                "NCHAR", superTbls->tags[tagIndex].dataLen);
2322 2323
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
      } else if (strcasecmp(dataType, "INT") == 0)  {
2324 2325
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "INT");
2326 2327
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 11;
      } else if (strcasecmp(dataType, "BIGINT") == 0)  {
2328 2329
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "BIGINT");
2330 2331
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 21;
      } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
2332 2333
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "SMALLINT");
2334 2335
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
      } else if (strcasecmp(dataType, "TINYINT") == 0)  {
2336 2337
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "TINYINT");
2338 2339
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 4;
      } else if (strcasecmp(dataType, "BOOL") == 0)  {
2340 2341
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "BOOL");
2342 2343
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
      } else if (strcasecmp(dataType, "FLOAT") == 0) {
2344 2345
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "FLOAT");
2346 2347
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22;
      } else if (strcasecmp(dataType, "DOUBLE") == 0) { 
2348 2349
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "DOUBLE");
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
      } else {
        taos_close(taos);
        printf("config error tag type : %s\n", dataType);
        exit(-1);
      }
    }
    len -= 2;
    len += snprintf(tags + len, STRING_LEN - len, ")");

    superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2361 2362 2363 2364

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

2367
    if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2368
        errorPrint( "create supertable %s failed!\n\n",
2369
                superTbls->sTblName);
2370
        return -1;
2371
    }
2372
    debugPrint("create supertable %s success!\n\n", superTbls->sTblName);
2373 2374 2375 2376
  }
  return 0;
}

2377
static int createDatabases() {
2378 2379 2380 2381
  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) {
2382
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2383
    return -1;
2384 2385 2386
  }
  char command[BUFFER_SIZE] = "\0";

2387
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2388 2389
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2390
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2391
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2392 2393 2394 2395
        taos_close(taos);
        return -1;
      }
    }
2396

2397
    int dataLen = 0;
2398
    dataLen += snprintf(command + dataLen,
2399
        BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2400 2401

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
2402
      dataLen += snprintf(command + dataLen,
2403
          BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
2404 2405
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
2406
      dataLen += snprintf(command + dataLen,
2407
          BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
2408 2409
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
2410
      dataLen += snprintf(command + dataLen,
2411
          BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
2412 2413
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
2414
      dataLen += snprintf(command + dataLen,
2415
          BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
2416
    }
2417 2418
    if (g_Dbs.db[i].dbCfg.quorum > 1) {
      dataLen += snprintf(command + dataLen,
2419
          BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
2420 2421
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
2422
      dataLen += snprintf(command + dataLen,
2423
          BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
2424 2425
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
2426
      dataLen += snprintf(command + dataLen,
2427
          BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
2428 2429
    }
    //if (g_Dbs.db[i].dbCfg.maxtablesPerVnode > 0) {
2430 2431
    //  dataLen += snprintf(command + dataLen,
    //  BUFFER_SIZE - dataLen, "tables %d ", g_Dbs.db[i].dbCfg.maxtablesPerVnode);
2432 2433
    //}
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
2434
      dataLen += snprintf(command + dataLen,
2435
          BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
2436 2437
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
2438
      dataLen += snprintf(command + dataLen,
2439
          BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
2440 2441
    }
    if (g_Dbs.db[i].dbCfg.comp > 0) {
2442
      dataLen += snprintf(command + dataLen,
2443
          BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
2444 2445
    }
    if (g_Dbs.db[i].dbCfg.walLevel > 0) {
2446
      dataLen += snprintf(command + dataLen,
2447
          BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
2448
    }
2449
    if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
2450
      dataLen += snprintf(command + dataLen,
2451
          BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
2452
    }
2453
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
2454 2455
      dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
              " fsync %d", g_Dbs.db[i].dbCfg.fsync);
2456
    }
2457
    if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
2458 2459
            || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                    "us", strlen("us")))) {
2460
      dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2461
              " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
2462
    }
2463

2464
    debugPrint("%s() %d command: %s\n", __func__, __LINE__, command);
2465
    if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2466
      taos_close(taos);
2467
      errorPrint( "\ncreate database %s failed!\n\n", g_Dbs.db[i].dbName);
2468 2469 2470 2471
      return -1;
    }
    printf("\ncreate database %s success!\n\n", g_Dbs.db[i].dbName);

2472 2473
    debugPrint("%s() %d supertbl count:%d\n",
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2474
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2475 2476 2477 2478 2479 2480 2481
      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)) {
2482 2483
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
                &g_Dbs.db[i].superTbls[j], g_Dbs.use_metric);
2484

2485 2486 2487 2488 2489 2490 2491
        if (0 != ret) {
          errorPrint("\ncreate super table %d failed!\n\n", j);
          taos_close(taos);
          return -1;
        }
      }

2492
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2493
                &g_Dbs.db[i].superTbls[j]);
2494 2495 2496 2497 2498 2499
      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);
        taos_close(taos);
        return -1;
      }
2500
    }
2501 2502 2503 2504 2505 2506
  }

  taos_close(taos);
  return 0;
}

2507 2508 2509
static void* createTable(void *sarg)
{
  threadInfo *winfo = (threadInfo *)sarg;
2510 2511 2512 2513
  SSuperTable* superTblInfo = winfo->superTblInfo;

  int64_t  lastPrintTime = taosGetTimestampMs();

2514 2515 2516 2517 2518 2519
  int buff_len;
  if (superTblInfo)
    buff_len = superTblInfo->maxSqlLen;
  else
    buff_len = BUFFER_SIZE;

2520
  char *buffer = calloc(buff_len, 1);
2521
  if (buffer == NULL) {
2522
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2523 2524
    exit(-1);
  }
2525 2526 2527

  int len = 0;
  int batchNum = 0;
2528

2529
  verbosePrint("%s() LN%d: Creating table from %d to %d\n",
2530 2531 2532 2533
          __func__, __LINE__,
          winfo->start_table_from, winfo->end_table_to);

  for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) {
2534
    if (0 == g_Dbs.use_metric) {
2535
      snprintf(buffer, buff_len,
2536 2537
              "create table if not exists %s.%s%d %s;",
              winfo->db_name,
2538 2539
              g_args.tb_prefix, i,
              winfo->cols);
2540
    } else {
2541 2542 2543
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
                  __func__, __LINE__);
2544
        free(buffer);
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 2572 2573 2574 2575 2576 2577 2578 2579 2580
        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) {
          tagsValBuf = generateTagVaulesForStb(superTblInfo);
        } else {
          tagsValBuf = getTagValueFromTagSample(
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
  
        len += snprintf(buffer + len,
                superTblInfo->maxSqlLen - len,
                "if not exists %s.%s%d using %s.%s tags %s ",
                winfo->db_name, superTblInfo->childTblPrefix,
                i, winfo->db_name,
                superTblInfo->sTblName, tagsValBuf);
        free(tagsValBuf);
        batchNum++;
  
        if ((batchNum < superTblInfo->batchCreateTableNum)
                && ((superTblInfo->maxSqlLen - len)
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
          continue;
        }
2581 2582 2583 2584
      }
    }

    len = 0;
2585
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2586
    if (0 != queryDbExec(winfo->taos, buffer, NO_INSERT_TYPE, false)){
2587
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2588
      free(buffer);
2589 2590 2591 2592 2593
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2594
      printf("thread[%d] already create %d - %d tables\n",
2595
              winfo->threadID, winfo->start_table_from, i);
2596 2597 2598 2599 2600
      lastPrintTime = currentPrintTime;
    }
  }
  
  if (0 != len) {
2601
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2602
    if (0 != queryDbExec(winfo->taos, buffer, NO_INSERT_TYPE, false)) {
2603
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2604
    }
2605
  }
2606

2607 2608 2609 2610
  free(buffer);
  return NULL;
}

2611
static int startMultiThreadCreateChildTable(
2612
        char* cols, int threads, int startFrom, int ntables,
2613
        char* db_name, SSuperTable* superTblInfo) {
2614

2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634
  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;
  }

  int a = ntables / threads;
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

  int b = 0;
  b = ntables % threads;
2635

2636 2637 2638
  for (int i = 0; i < threads; i++) {
    threadInfo *t_info = infos + i;
    t_info->threadID = i;
H
Hui Li 已提交
2639
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
2640
    t_info->superTblInfo = superTblInfo;
2641
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
2642 2643 2644 2645 2646 2647
    t_info->taos = taos_connect(
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
2648
    if (t_info->taos == NULL) {
2649
      errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2650
      free(pids);
2651
      free(infos);
2652 2653
      return -1;
    }
2654 2655 2656 2657 2658

    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;
2659
    t_info->use_metric = true;
2660
    t_info->cols = cols;
2661
    t_info->minDelay = INT16_MAX;
2662 2663
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2664
 
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
  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);
2675
  free(infos);
2676 2677

  return 0;
2678 2679
}

2680 2681 2682 2683
static void createChildTables() {
    char tblColsBuf[MAX_SQL_SIZE];
    int len;

2684
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2685
    if (g_Dbs.db[i].superTblCount > 0) {
2686
        // with super table
2687 2688
      for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
        if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
2689
              || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
2690 2691 2692
          continue;
        }

2693
        verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
2694
                g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
2695 2696
        int startFrom = 0;
        g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;
2697

2698 2699
        verbosePrint("%s() LN%d: create %d child tables from %d\n",
                __func__, __LINE__, g_totalChildTables, startFrom);
2700
        startMultiThreadCreateChildTable(
2701
              g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
2702
              g_Dbs.threadCountByCreateTbl,
2703
              startFrom,
2704
              g_Dbs.db[i].superTbls[j].childTblCount,
2705
              g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
2706 2707
      }
    } else {
2708 2709
        // normal table
        len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
2710 2711 2712
        int j = 0;
        while (g_args.datatype[j]) {
            if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0)
2713 2714
                    || (strncasecmp(g_args.datatype[j],
                        "NCHAR", strlen("NCHAR")) == 0)) {
2715
                snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
2716
                        ", COL%d %s(60)", j, g_args.datatype[j]);
2717
            } else {
2718
                snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
2719
                        ", COL%d %s", j, g_args.datatype[j]);
2720 2721
            }
            len = strlen(tblColsBuf);
2722
            j++;
2723 2724
        }

2725
        len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
2726

2727 2728
        verbosePrint("%s() LN%d: dbName: %s num of tb: %d schema: %s\n",
                __func__, __LINE__,
2729
                g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
2730
        startMultiThreadCreateChildTable(
2731
              tblColsBuf,
2732
              g_Dbs.threadCountByCreateTbl,
2733
              0,
2734
              g_args.num_of_tables,
2735 2736 2737
              g_Dbs.db[i].dbName,
              NULL);
    }
2738 2739 2740 2741 2742 2743
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
2744
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
2745 2746 2747
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
2748

2749 2750
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
2751 2752
    printf("Failed to open tags file: %s, reason:%s\n",
            superTblInfo->tagsFile, strerror(errno));
2753 2754 2755 2756 2757 2758 2759
    return -1;
  }

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

2761 2762 2763 2764 2765 2766 2767 2768 2769
  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;
  }

2770
  while ((readLen = tgetline(&line, &n, fp)) != -1) {
2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782
    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) {
2783 2784
      char *tmp = realloc(tagDataBuf,
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
2785 2786 2787
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
2788 2789
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816
      } 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
*/
2817 2818
static int readSampleFromCsvFileToMem(
        SSuperTable* superTblInfo) {
2819 2820 2821 2822
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
2823

2824 2825
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
2826
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
2827 2828 2829
              superTblInfo->sampleFile, strerror(errno));
      return -1;
  }
2830

2831
  assert(superTblInfo->sampleDataBuf);
2832 2833
  memset(superTblInfo->sampleDataBuf, 0,
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
2834
  while (1) {
2835
    readLen = tgetline(&line, &n, fp);
2836 2837
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
2838
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
2839
                superTblInfo->sampleFile, strerror(errno));
2840
        fclose(fp);
2841 2842 2843 2844
        return -1;
      }
      continue;
    }
2845

2846 2847 2848 2849 2850 2851 2852 2853 2854
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
2855 2856
      printf("sample row len[%d] overflow define schema len[%d], so discard this row\n",
              (int32_t)readLen, superTblInfo->lenOfOneRow);
2857 2858 2859
      continue;
    }

sangshuduo's avatar
sangshuduo 已提交
2860
    verbosePrint("readLen=%ld stb->lenOfOneRow=%d getRows=%d\n", (long)readLen,
2861
            superTblInfo->lenOfOneRow, getRows);
2862

2863 2864
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
          line, readLen);
2865 2866 2867 2868 2869 2870 2871
    getRows++;

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

2872
  fclose(fp);
2873 2874 2875 2876
  tmfree(line);
  return 0;
}

2877 2878
static bool getColumnAndTagTypeFromInsertJsonFile(
        cJSON* stbInfo, SSuperTable* superTbls) {
2879
  bool  ret = false;
2880

2881 2882 2883
  // columns 
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
2884
    printf("ERROR: failed to read json, columns not found\n");
2885 2886 2887 2888 2889 2890
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
2891
 
2892 2893
  int columnSize = cJSON_GetArraySize(columns);
  if (columnSize > MAX_COLUMN_COUNT) {
2894 2895
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
            __func__, __LINE__, MAX_COLUMN_COUNT);
2896 2897 2898 2899 2900 2901
    goto PARSE_OVER;
  }

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

2903
  //superTbls->columnCount = columnSize;
2904 2905 2906 2907 2908 2909 2910
  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) {
2911
      count = countObj->valueint;
2912
    } else if (countObj && countObj->type != cJSON_Number) {
2913
      errorPrint("%s() LN%d, failed to read json, column count not found\n", __func__, __LINE__);
2914 2915 2916 2917 2918 2919 2920 2921 2922
      goto PARSE_OVER;
    } else {
      count = 1;
    }

    // column info 
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
    if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) {
2923
      errorPrint("%s() LN%d: failed to read json, column type not found\n", __func__, __LINE__);
2924 2925
      goto PARSE_OVER;
    }
2926 2927
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
2928

2929 2930
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
2931
      columnCase.dataLen = dataLen->valueint;
2932
    } else if (dataLen && dataLen->type != cJSON_Number) {
2933
      debugPrint("%s() LN%d: failed to read json, column len not found\n", __func__, __LINE__);
2934 2935 2936 2937
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
2938

2939
    for (int n = 0; n < count; ++n) {
2940 2941 2942
      tstrncpy(superTbls->columns[index].dataType,
              columnCase.dataType, MAX_TB_NAME_SIZE);
      superTbls->columns[index].dataLen = columnCase.dataLen;
2943 2944
      index++;
    }
2945 2946 2947
  }
  superTbls->columnCount = index;
 
2948 2949 2950 2951 2952
  count = 1;
  index = 0;
  // tags 
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
2953
    debugPrint("%s() LN%d, failed to read json, tags not found\n", __func__, __LINE__);
2954 2955
    goto PARSE_OVER;
  }
2956

2957 2958
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
2959
    debugPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n", __func__, __LINE__, MAX_TAG_COUNT);
2960 2961
    goto PARSE_OVER;
  }
2962 2963

  //superTbls->tagCount = tagSize;
2964 2965 2966
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
2967

2968 2969 2970
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
2971
      count = countObj->valueint;
2972
    } else if (countObj && countObj->type != cJSON_Number) {
2973
      printf("ERROR: failed to read json, column count not found\n");
2974 2975 2976 2977 2978 2979 2980 2981 2982
      goto PARSE_OVER;
    } else {
      count = 1;
    }

    // column info 
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
    if (!dataType || dataType->type != cJSON_String || dataType->valuestring == NULL) {
2983
      printf("ERROR: failed to read json, tag type not found\n");
2984 2985
      goto PARSE_OVER;
    }
2986
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
2987

2988 2989
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
2990
      columnCase.dataLen = dataLen->valueint;
2991
    } else if (dataLen && dataLen->type != cJSON_Number) {
2992
      printf("ERROR: failed to read json, column len not found\n");
2993 2994 2995
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
2996 2997
    }

2998
    for (int n = 0; n < count; ++n) {
2999
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE);
3000
      superTbls->tags[index].dataLen = columnCase.dataLen;
3001 3002
      index++;
    }
3003
  }
3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019
  superTbls->tagCount = index;

  ret = true;

PARSE_OVER:
  //free(content);
  //cJSON_Delete(root);
  //fclose(fp);
  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) {
3020
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3021 3022 3023 3024
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3025
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3026
  } else if (!host) {
3027
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3028
  } else {
3029
    printf("ERROR: failed to read json, host not found\n");
3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041
    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) {
3042
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3043
  } else if (!user) {
3044
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3045 3046 3047 3048
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3049
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3050
  } else if (!password) {
3051
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3052 3053 3054 3055
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3056
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3057
  } else if (!resultfile) {
3058
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3059 3060 3061 3062 3063 3064 3065 3066
  }

  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 {
3067
    printf("ERROR: failed to read json, threads not found\n");
3068
    goto PARSE_OVER;
3069 3070
  }

3071 3072 3073 3074
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
3075
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
3076
  } else {
3077 3078
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
            __func__, __LINE__);
3079
    goto PARSE_OVER;
3080
  }
3081

3082 3083 3084 3085 3086 3087 3088 3089 3090
  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 {
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n", __func__, __LINE__);
    goto PARSE_OVER;
  }
3091

3092 3093 3094
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
    g_args.interlace_rows = interlaceRows->valueint;
3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105

    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
      printf("NOTICE: interlace rows value %d > num_of_records_per_request %d\n\n",
              g_args.interlace_rows, g_args.num_of_RPR);
      printf("        interlace rows value will be set to num_of_records_per_request %d\n\n",
              g_args.num_of_RPR);
      printf("        press Enter key to continue or Ctrl+C to stop.");
      (void)getchar();
      g_args.interlace_rows = g_args.num_of_RPR;
    }
3106
  } else if (!interlaceRows) {
3107
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3108
  } else {
3109
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n", __func__, __LINE__);
3110
    goto PARSE_OVER;
3111
  }
3112

3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
    g_args.max_sql_len = TSDB_PAYLOAD_SIZE;
  } else {
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n", __func__, __LINE__);
    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) {
    g_args.num_of_RPR = 100;
  } else {
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n", __func__, __LINE__);
    goto PARSE_OVER;
  }

3133
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3134
  if (answerPrompt
3135 3136
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3137 3138 3139 3140 3141 3142 3143 3144 3145 3146
    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 {
3147
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3148
    goto PARSE_OVER;
3149
  }
3150 3151 3152

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3153
    printf("ERROR: failed to read json, databases not found\n");
3154 3155 3156 3157 3158
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3159
    errorPrint(
3160 3161
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172
    goto PARSE_OVER;
  }

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

    // dbinfo 
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3173
      printf("ERROR: failed to read json, dbinfo not found\n");
3174 3175
      goto PARSE_OVER;
    }
3176

3177 3178
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3179
      printf("ERROR: failed to read json, db name not found\n");
3180 3181
      goto PARSE_OVER;
    }
3182
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3183 3184 3185

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3186 3187
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3188
      } else {
3189
        g_Dbs.db[i].drop = false;
3190
      }
3191
    } else if (!drop) {
3192
      g_Dbs.db[i].drop = g_args.drop_database;
3193
    } else {
3194 3195
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
              __func__, __LINE__);
3196 3197 3198 3199
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3200 3201 3202 3203
    if (precision && precision->type == cJSON_String
            && precision->valuestring != NULL) {
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
              MAX_DB_NAME_SIZE);
3204
    } else if (!precision) {
3205
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3206 3207
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3208
      printf("ERROR: failed to read json, precision not found\n");
3209 3210 3211 3212 3213 3214 3215 3216 3217
      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 {
3218
      printf("ERROR: failed to read json, update not found\n");
3219 3220 3221 3222 3223 3224 3225 3226 3227
      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 {
3228
      printf("ERROR: failed to read json, replica not found\n");
3229 3230 3231 3232 3233 3234 3235 3236 3237
      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 {
3238
     printf("ERROR: failed to read json, keep not found\n");
3239 3240
     goto PARSE_OVER;
    }
3241

3242 3243 3244 3245 3246 3247
    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 {
3248
     printf("ERROR: failed to read json, days not found\n");
3249 3250
     goto PARSE_OVER;
    }
3251

3252 3253 3254 3255 3256 3257
    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 {
3258
     printf("ERROR: failed to read json, cache not found\n");
3259 3260
     goto PARSE_OVER;
    }
3261

3262 3263 3264 3265 3266 3267
    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 {
3268
     printf("ERROR: failed to read json, block not found\n");
3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287
     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 {
3288
     printf("ERROR: failed to read json, minRows not found\n");
3289 3290 3291 3292 3293 3294 3295 3296 3297
     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 {
3298
     printf("ERROR: failed to read json, maxRows not found\n");
3299 3300 3301 3302 3303 3304 3305 3306 3307
     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 {
3308
     printf("ERROR: failed to read json, comp not found\n");
3309 3310 3311 3312 3313 3314 3315 3316 3317
     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 {
3318
     printf("ERROR: failed to read json, walLevel not found\n");
3319 3320 3321
     goto PARSE_OVER;
    }

3322 3323 3324 3325 3326 3327
    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 {
3328
     printf("ERROR: failed to read json, cacheLast not found\n");
3329 3330 3331
     goto PARSE_OVER;
    }

3332 3333 3334 3335
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3336
      g_Dbs.db[i].dbCfg.quorum = 1;
3337
    } else {
3338
     printf("failed to read json, quorum input mistake");
3339 3340 3341 3342 3343 3344 3345 3346 3347
     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 {
3348
     printf("ERROR: failed to read json, fsync not found\n");
3349
     goto PARSE_OVER;
3350
    }
3351

3352
    // super_talbes
3353 3354
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3355
      printf("ERROR: failed to read json, super_tables not found\n");
3356
      goto PARSE_OVER;
3357 3358
    }

3359 3360
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3361
      errorPrint(
3362 3363
              "ERROR: failed to read json, databases size overflow, max database is %d\n",
              MAX_SUPER_TABLE_COUNT);
3364 3365 3366 3367 3368 3369 3370
      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;
3371 3372

      // dbinfo
3373 3374
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3375
        printf("ERROR: failed to read json, stb name not found\n");
3376 3377
        goto PARSE_OVER;
      }
3378
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3379

3380 3381
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3382
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3383 3384
        goto PARSE_OVER;
      }
3385
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3386 3387

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3388 3389 3390
      if (autoCreateTbl
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3391 3392 3393 3394 3395 3396 3397 3398 3399 3400
        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 {
3401
        printf("ERROR: failed to read json, auto_create_table not found\n");
3402 3403
        goto PARSE_OVER;
      }
3404

3405 3406 3407 3408
      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) {
3409
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3410
      } else {
3411
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3412
        goto PARSE_OVER;
3413
      }
3414 3415

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3416 3417 3418
      if (childTblExists
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3419 3420 3421 3422 3423 3424 3425 3426 3427 3428
        if (0 == strncasecmp(childTblExists->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
        } else if (0 == strncasecmp(childTblExists->valuestring, "no", 2)) {
          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 {
3429 3430
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
                __func__, __LINE__);
3431 3432
        goto PARSE_OVER;
      }
3433

3434 3435
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3436 3437
        errorPrint("%s() LN%d, failed to read json, childtable_count not found\n",
                __func__, __LINE__);
3438 3439 3440 3441 3442
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3443 3444 3445 3446
      if (dataSource && dataSource->type == cJSON_String
              && dataSource->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3447
      } else if (!dataSource) {
3448
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3449
      } else {
3450
        errorPrint("%s() LN%d, failed to read json, data_source not found\n", __func__, __LINE__);
3451 3452 3453 3454
        goto PARSE_OVER;
      }

      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , restful
3455 3456 3457 3458
      if (insertMode && insertMode->type == cJSON_String
              && insertMode->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3459
      } else if (!insertMode) {
3460
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3461
      } else {
3462
        printf("ERROR: failed to read json, insert_mode not found\n");
3463 3464 3465
        goto PARSE_OVER;
      }

3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
      if (childTbl_limit) {
        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 {
        g_Dbs.db[i].superTbls[j].childTblLimit = -1;    // select ... limit -1 means all query result
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
      if (childTbl_offset) {
        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;
      }

3488 3489
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3490 3491
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                ts->valuestring, MAX_DB_NAME_SIZE);
3492
      } else if (!ts) {
3493 3494
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                "now", MAX_DB_NAME_SIZE);
3495
      } else {
3496
        printf("ERROR: failed to read json, start_timestamp not found\n");
3497 3498
        goto PARSE_OVER;
      }
3499

3500 3501 3502 3503
      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) {
3504
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3505
      } else {
3506
        printf("ERROR: failed to read json, timestamp_step not found\n");
3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518
        goto PARSE_OVER;
      }

      cJSON* sampleDataBufSize = cJSON_GetObjectItem(stbInfo, "sample_buf_size");
      if (sampleDataBufSize && sampleDataBufSize->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].sampleDataBufSize = sampleDataBufSize->valueint;
        if (g_Dbs.db[i].superTbls[j].sampleDataBufSize < 1024*1024) {
          g_Dbs.db[i].superTbls[j].sampleDataBufSize = 1024*1024 + 1024;
        }
      } else if (!sampleDataBufSize) {
        g_Dbs.db[i].superTbls[j].sampleDataBufSize = 1024*1024 + 1024;
      } else {
3519
        printf("ERROR: failed to read json, sample_buf_size not found\n");
3520
        goto PARSE_OVER;
3521
      }
3522

3523
      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3524 3525
      if (sampleFormat && sampleFormat->type
              == cJSON_String && sampleFormat->valuestring != NULL) {
3526 3527
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3528
      } else if (!sampleFormat) {
3529
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3530
      } else {
3531
        printf("ERROR: failed to read json, sample_format not found\n");
3532
        goto PARSE_OVER;
3533
      }
3534

3535 3536
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
      if (sampleFile && sampleFile->type == cJSON_String && sampleFile->valuestring != NULL) {
3537 3538
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3539 3540 3541
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3542
        printf("ERROR: failed to read json, sample_file not found\n");
3543
        goto PARSE_OVER;
3544
      }
3545

3546 3547
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3548 3549
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3550 3551 3552 3553 3554 3555 3556 3557 3558
        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 {
3559
        printf("ERROR: failed to read json, tags_file not found\n");
3560 3561
        goto PARSE_OVER;
      }
3562

3563 3564 3565 3566 3567 3568 3569
      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;
        } else if (len < TSDB_MAX_SQL_LEN) {
          len = TSDB_MAX_SQL_LEN;
3570
        }
3571 3572 3573 3574
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
        g_Dbs.db[i].superTbls[j].maxSqlLen = TSDB_MAX_SQL_LEN;
      } else {
3575
        printf("ERROR: failed to read json, maxSqlLen not found\n");
3576
        goto PARSE_OVER;
3577
      }
3578

3579 3580 3581 3582 3583
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
3584 3585 3586 3587
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
3588
        }
3589 3590 3591
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
3592
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
3593 3594
        goto PARSE_OVER;
      }
3595

3596 3597 3598
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3599 3600 3601 3602 3603 3604 3605 3606 3607 3608
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %d > num_of_records_per_request %d\n\n",
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
          printf("        interlace rows value will be set to num_of_records_per_request %d\n\n",
                  g_args.num_of_RPR);
          printf("        press Enter key to continue or Ctrl+C to stop.");
          (void)getchar();
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
3609 3610
      } 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
3611
      } else {
3612 3613 3614
        errorPrint(
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3615
        goto PARSE_OVER;
3616
      }
3617 3618 3619 3620 3621 3622 3623

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3624
        printf("ERROR: failed to read json, disorderRatio not found\n");
3625
        goto PARSE_OVER;
3626
      }
3627 3628 3629 3630 3631 3632 3633

      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 {
3634
        printf("ERROR: failed to read json, disorderRange not found\n");
3635 3636
        goto PARSE_OVER;
      }
3637

3638 3639 3640 3641 3642 3643
      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 {
3644 3645
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656
        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) {
        debugPrint("%s() LN%d: stable insert interval be overrided by global %d.\n",
                __func__, __LINE__, g_args.insert_interval);
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
3657 3658
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
3659 3660 3661
        goto PARSE_OVER;
      }

3662 3663
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
              stbInfo, &g_Dbs.db[i].superTbls[j]);
3664 3665
      if (false == retVal) {
        goto PARSE_OVER;
3666 3667
      }
    }
3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683
  }

  ret = true;

PARSE_OVER:
  //free(content);
  //cJSON_Delete(root);
  //fclose(fp);
  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) {
3684
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3685 3686 3687 3688
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3689
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
3690
  } else if (!host) {
3691
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3692
  } else {
3693
    printf("ERROR: failed to read json, host not found\n");
3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705
    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) {
3706
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);   
3707
  } else if (!user) {
3708
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
3709 3710 3711 3712
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3713
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
3714
  } else if (!password) {
3715
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
3716
  }
H
hzcheng 已提交
3717

3718
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3719 3720
  if (answerPrompt && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3721 3722 3723 3724
    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 已提交
3725
    } else {
3726
      g_args.answer_yes = false;
H
hzcheng 已提交
3727
    }
3728 3729 3730
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
3731
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3732
    goto PARSE_OVER;
3733
  }
3734

3735 3736 3737 3738 3739 3740 3741 3742 3743 3744
  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 {
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__);
    goto PARSE_OVER;
  }

3745 3746
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
3747
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
3748
  } else if (!dbs) {
3749
    printf("ERROR: failed to read json, databases not found\n");
3750
    goto PARSE_OVER;
H
hzcheng 已提交
3751
  }
3752 3753 3754

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
3755
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
3756
  } else if (!queryMode) {
3757
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
3758
  } else {
3759
    printf("ERROR: failed to read json, query_mode not found\n");
3760
    goto PARSE_OVER;
H
hzcheng 已提交
3761
  }
3762

3763 3764 3765 3766 3767 3768
  // super_table_query 
  cJSON *superQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!superQuery) {
    g_queryInfo.superQueryInfo.concurrent = 0;
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
3769
    printf("ERROR: failed to read json, super_table_query not found\n");
3770
    goto PARSE_OVER;
3771
  } else {
3772 3773 3774 3775 3776 3777
    cJSON* rate = cJSON_GetObjectItem(superQuery, "query_interval");
    if (rate && rate->type == cJSON_Number) {
      g_queryInfo.superQueryInfo.rate = rate->valueint;
    } else if (!rate) {
      g_queryInfo.superQueryInfo.rate = 0;
    }
3778

3779 3780 3781 3782 3783 3784
    cJSON* concurrent = cJSON_GetObjectItem(superQuery, "concurrent");
    if (concurrent && concurrent->type == cJSON_Number) {
      g_queryInfo.superQueryInfo.concurrent = concurrent->valueint;
    } else if (!concurrent) {
      g_queryInfo.superQueryInfo.concurrent = 1;
    }
3785

3786 3787
    cJSON* mode = cJSON_GetObjectItem(superQuery, "mode");
    if (mode && mode->type == cJSON_String && mode->valuestring != NULL) {
3788
      if (0 == strcmp("sync", mode->valuestring)) {
3789
        g_queryInfo.superQueryInfo.subscribeMode = 0;
3790
      } else if (0 == strcmp("async", mode->valuestring)) {
3791 3792
        g_queryInfo.superQueryInfo.subscribeMode = 1;
      } else {
3793
        printf("ERROR: failed to read json, subscribe mod error\n");
3794 3795 3796 3797 3798
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.superQueryInfo.subscribeMode = 0;
    }
3799

3800 3801 3802
    cJSON* interval = cJSON_GetObjectItem(superQuery, "interval");
    if (interval && interval->type == cJSON_Number) {
      g_queryInfo.superQueryInfo.subscribeInterval = interval->valueint;
3803
    } else if (!interval) {
3804 3805 3806 3807
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
    }
3808

3809 3810
    cJSON* restart = cJSON_GetObjectItem(superQuery, "restart");
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
3811
      if (0 == strcmp("yes", restart->valuestring)) {
3812
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
3813
      } else if (0 == strcmp("no", restart->valuestring)) {
3814 3815
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
      } else {
3816
        printf("ERROR: failed to read json, subscribe restart error\n");
3817 3818 3819 3820 3821
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
    }
3822

3823
    cJSON* keepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
3824 3825 3826
    if (keepProgress
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
3827
      if (0 == strcmp("yes", keepProgress->valuestring)) {
3828
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
3829
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
3830 3831
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
      } else {
3832
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
3833 3834 3835 3836 3837 3838
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
    }

3839
    // sqls
3840 3841 3842 3843
    cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
    if (!superSqls) {
      g_queryInfo.superQueryInfo.sqlCount = 0;
    } else if (superSqls->type != cJSON_Array) {
3844
      printf("ERROR: failed to read json, super sqls not found\n");
3845
      goto PARSE_OVER;
3846
    } else {
3847 3848
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
3849
        printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT);
3850 3851
        goto PARSE_OVER;
      }
3852

3853 3854 3855 3856
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
3857

3858 3859
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
3860
          printf("ERROR: failed to read json, sql not found\n");
3861 3862
          goto PARSE_OVER;
        }
3863
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
3864

3865 3866
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
3867
          tstrncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
3868 3869 3870
        } else if (NULL == result) {
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
        } else {
3871
          printf("ERROR: failed to read json, super query result file not found\n");
3872
          goto PARSE_OVER;
3873
        }
3874 3875 3876
      }
    }
  }
3877

3878 3879 3880 3881 3882 3883
  // sub_table_query 
  cJSON *subQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!subQuery) {
    g_queryInfo.subQueryInfo.threadCnt = 0;
    g_queryInfo.subQueryInfo.sqlCount = 0;
  } else if (subQuery->type != cJSON_Object) {
3884
    printf("ERROR: failed to read json, sub_table_query not found\n");
3885 3886
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
3887
  } else {
3888 3889 3890 3891 3892 3893
    cJSON* subrate = cJSON_GetObjectItem(subQuery, "query_interval");
    if (subrate && subrate->type == cJSON_Number) {
      g_queryInfo.subQueryInfo.rate = subrate->valueint;
    } else if (!subrate) {
      g_queryInfo.subQueryInfo.rate = 0;
    }
3894

3895 3896 3897 3898 3899 3900
    cJSON* threads = cJSON_GetObjectItem(subQuery, "threads");
    if (threads && threads->type == cJSON_Number) {
      g_queryInfo.subQueryInfo.threadCnt = threads->valueint;
    } else if (!threads) {
      g_queryInfo.subQueryInfo.threadCnt = 1;
    }
3901

3902 3903 3904 3905 3906 3907
    //cJSON* subTblCnt = cJSON_GetObjectItem(subQuery, "childtable_count");
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
    //  g_queryInfo.subQueryInfo.childTblCount = subTblCnt->valueint;
    //} else if (!subTblCnt) {
    //  g_queryInfo.subQueryInfo.childTblCount = 0;
    //}
3908

3909 3910
    cJSON* stblname = cJSON_GetObjectItem(subQuery, "stblname");
    if (stblname && stblname->type == cJSON_String && stblname->valuestring != NULL) {
3911
      tstrncpy(g_queryInfo.subQueryInfo.sTblName, stblname->valuestring, MAX_TB_NAME_SIZE);
3912
    } else {
3913
      printf("ERROR: failed to read json, super table name not found\n");
3914 3915
      goto PARSE_OVER;
    }
3916

3917 3918
    cJSON* submode = cJSON_GetObjectItem(subQuery, "mode");
    if (submode && submode->type == cJSON_String && submode->valuestring != NULL) {
3919
      if (0 == strcmp("sync", submode->valuestring)) {
3920
        g_queryInfo.subQueryInfo.subscribeMode = 0;
3921
      } else if (0 == strcmp("async", submode->valuestring)) {
3922 3923
        g_queryInfo.subQueryInfo.subscribeMode = 1;
      } else {
3924
        printf("ERROR: failed to read json, subscribe mod error\n");
3925 3926 3927 3928 3929
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.subQueryInfo.subscribeMode = 0;
    }
3930

3931 3932 3933 3934 3935 3936 3937 3938
    cJSON* subinterval = cJSON_GetObjectItem(subQuery, "interval");
    if (subinterval && subinterval->type == cJSON_Number) {
      g_queryInfo.subQueryInfo.subscribeInterval = subinterval->valueint;
    } else if (!subinterval) {    
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
      g_queryInfo.subQueryInfo.subscribeInterval = 10000;
    }
3939

3940 3941
    cJSON* subrestart = cJSON_GetObjectItem(subQuery, "restart");
    if (subrestart && subrestart->type == cJSON_String && subrestart->valuestring != NULL) {
3942
      if (0 == strcmp("yes", subrestart->valuestring)) {
3943
        g_queryInfo.subQueryInfo.subscribeRestart = 1;
3944
      } else if (0 == strcmp("no", subrestart->valuestring)) {
3945 3946
        g_queryInfo.subQueryInfo.subscribeRestart = 0;
      } else {
3947
        printf("ERROR: failed to read json, subscribe restart error\n");
3948 3949 3950 3951 3952
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.subQueryInfo.subscribeRestart = 1;
    }
3953

3954
    cJSON* subkeepProgress = cJSON_GetObjectItem(subQuery, "keepProgress");
3955 3956 3957
    if (subkeepProgress &&
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
3958
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
3959
        g_queryInfo.subQueryInfo.subscribeKeepProgress = 1;
3960
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
3961 3962
        g_queryInfo.subQueryInfo.subscribeKeepProgress = 0;
      } else {
3963
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
3964 3965 3966 3967
        goto PARSE_OVER;
      }
    } else {
      g_queryInfo.subQueryInfo.subscribeKeepProgress = 0;
3968
    }
3969

3970
    // sqls
3971 3972 3973 3974
    cJSON* subsqls = cJSON_GetObjectItem(subQuery, "sqls");
    if (!subsqls) {
      g_queryInfo.subQueryInfo.sqlCount = 0;
    } else if (subsqls->type != cJSON_Array) {
3975
      printf("ERROR: failed to read json, super sqls not found\n");
3976
      goto PARSE_OVER;
3977
    } else {
3978 3979
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
3980
        printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT);
3981 3982
        goto PARSE_OVER;
      }
3983

3984
      g_queryInfo.subQueryInfo.sqlCount = superSqlSize;
3985
      for (int j = 0; j < superSqlSize; ++j) {
3986 3987
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
3988

3989 3990
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
3991
          printf("ERROR: failed to read json, sql not found\n");
3992 3993
          goto PARSE_OVER;
        }
3994
        tstrncpy(g_queryInfo.subQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
3995 3996 3997

        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (result != NULL && result->type == cJSON_String && result->valuestring != NULL){
3998
          tstrncpy(g_queryInfo.subQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
3999 4000 4001
        } else if (NULL == result) {
          memset(g_queryInfo.subQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
        }  else {
4002
          printf("ERROR: failed to read json, sub query result file not found\n");
4003
          goto PARSE_OVER;
4004
        }
4005 4006
      }
    }
H
hzcheng 已提交
4007 4008
  }

4009
  ret = true;
H
hzcheng 已提交
4010

4011 4012 4013 4014 4015 4016
PARSE_OVER:
  //free(content);
  //cJSON_Delete(root);
  //fclose(fp);
  return ret;
}
H
hzcheng 已提交
4017

4018
static bool getInfoFromJsonFile(char* file) {
4019
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4020

4021 4022 4023 4024 4025
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4026

4027 4028 4029 4030 4031 4032 4033 4034 4035
  bool  ret = false;
  int   maxLen = 64000;
  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 已提交
4036
  }
H
Hui Li 已提交
4037

4038 4039 4040
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4041
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4042 4043
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4044

4045 4046 4047
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4048
      g_args.test_mode = INSERT_TEST;
4049
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4050
      g_args.test_mode = QUERY_TEST;
4051
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4052
      g_args.test_mode = SUBSCRIBE_TEST;
4053
    } else {
4054
      printf("ERROR: failed to read json, filetype not support\n");
4055 4056 4057
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4058
    g_args.test_mode = INSERT_TEST;
4059
  } else {
4060
    printf("ERROR: failed to read json, filetype not found\n");
4061 4062
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4063

4064
  if (INSERT_TEST == g_args.test_mode) {
4065
    ret = getMetaFromInsertJsonFile(root);
4066 4067
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4068 4069
    ret = getMetaFromQueryJsonFile(root);
  } else {
4070 4071
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4072
    goto PARSE_OVER;
4073
  }
4074 4075 4076 4077

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4078
  fclose(fp);
4079 4080
  return ret;
}
H
hzcheng 已提交
4081

4082
static void prepareSampleData() {
4083
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4084 4085 4086
    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 已提交
4087
      }
4088 4089 4090 4091
    }
  }
}

4092
static void postFreeResource() {
4093
  tmfclose(g_fpOfInsertResult);
4094
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4095
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4096 4097 4098
      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 已提交
4099
      }
4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111
      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 已提交
4112
    }
4113 4114
  }
}
S
Shuaiqiang Chang 已提交
4115

4116 4117
static int getRowDataFromSample(char*  dataBuf, int maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int* sampleUsePos) {
4118
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4119
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4120
    if (0 != ret) {
4121
      tmfree(superTblInfo->sampleDataBuf);
4122
      superTblInfo->sampleDataBuf = NULL;
4123 4124
      return -1;
    }
4125
*/
4126 4127
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4128

4129
  int    dataLen = 0;
4130

4131 4132 4133 4134
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "(%" PRId64 ", ", timestamp);
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4135
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4136

4137
  (*sampleUsePos)++;
4138
 
4139 4140
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4141

4142
static int generateRowData(char*  dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) {
4143 4144
  int    dataLen = 0;
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp);
4145
  for (int i = 0; i < stbInfo->columnCount; i++) {
4146 4147
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) {
4148
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4149
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4150
                (uint32_t)TSDB_MAX_BINARY_LEN);
4151 4152
        return (-1);
      }
4153

4154 4155
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4156
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4157 4158 4159 4160 4161
        return (-1);
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "\'%s\', ", buf);
      tmfree(buf);
4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "int", 3)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
              "%d, ", rand_int());
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "bigint", 6)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
              "%"PRId64", ", rand_bigint());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "float", 5)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
              "%f, ", rand_float());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "double", 6)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
              "%f, ", rand_double());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
                "smallint", 8)) {
4180 4181 4182 4183 4184 4185 4186 4187
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_smallint());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType, "tinyint", 7)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_tinyint());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType, "bool", 4)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%d, ", rand_bool());
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType, "timestamp", 9)) {
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "%"PRId64", ", rand_bigint());
    }  else {
4188
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4189 4190
      return (-1);
    }
S
Shuaiqiang Chang 已提交
4191
  }
4192

4193 4194
  dataLen -= 2;
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
4195

4196 4197
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4198

4199
static int32_t generateData(char *res, char **data_type,
4200
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231
  memset(res, 0, MAX_DATA_SIZE);
  char *pstr = res;
  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);
  }

  for (int i = 0; i < num_of_cols; i++) {
    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) {
      pstr += sprintf(pstr, ", %d", rand_int()); 
    } 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) {
4232
      bool b = taosRandom() & 1;
4233 4234
      pstr += sprintf(pstr, ", %s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "binary") == 0) {
4235 4236
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4237 4238 4239
      pstr += sprintf(pstr, ", \"%s\"", s);
      free(s);
    }else if (strcasecmp(data_type[i % c], "nchar") == 0) {
4240 4241
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256
      pstr += sprintf(pstr, ", \"%s\"", s);
      free(s);
    }

    if (pstr - res > MAX_DATA_SIZE) {
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

  return (int32_t)(pstr - res);
}

4257
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4258 4259
  char* sampleDataBuf = NULL;

4260
  sampleDataBuf = calloc(
4261
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4262
  if (sampleDataBuf == NULL) {
4263 4264
      errorPrint("%s() LN%d, Failed to calloc %d Bytes, reason:%s\n", 
              __func__, __LINE__,
4265 4266
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 
              strerror(errno));
4267
      return -1;
4268
  }
4269

4270 4271 4272 4273
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4274
      errorPrint("%s() LN%d, read sample from csv file failed.\n", __func__, __LINE__);
4275
      tmfree(sampleDataBuf);
4276
      superTblInfo->sampleDataBuf = NULL;
4277
      return -1;
H
Hui Li 已提交
4278
  }
4279

4280 4281 4282
  return 0;
}

4283
static int execInsert(threadInfo *pThreadInfo, char *buffer, int k)
4284 4285
{
  int affectedRows;
4286
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4287

4288 4289
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, buffer);
4290
  if (superTblInfo) {
4291
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4292
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4293
    } else {
4294
      if (0 != postProceSql(g_Dbs.host, g_Dbs.port, buffer)) {
4295
        affectedRows = -1;
4296
        printf("========restful return fail, threadID[%d]\n", pThreadInfo->threadID);
4297 4298 4299
      } else {
        affectedRows = k;
      }
4300
    }
4301
  } else {
4302
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4303 4304 4305 4306 4307
  }

  return affectedRows;
}

4308
static void getTableName(char *pTblName, threadInfo* pThreadInfo, int tableSeq)
4309 4310
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4311 4312 4313 4314 4315 4316
  if (superTblInfo) {
    if ((superTblInfo->childTblOffset >= 0)
            && (superTblInfo->childTblLimit > 0)) {
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
    } else {
4317

4318 4319 4320
        verbosePrint("[%d] %s() LN%d: from=%d count=%d seq=%d\n",
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
4321 4322 4323 4324 4325 4326
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
    }
  } else {
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%d",
4327
        g_args.tb_prefix, tableSeq);
4328 4329 4330 4331
  }
}

static int generateDataTail(char *tableName, int32_t tableSeq,
4332
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
4333 4334 4335
        int batch, char* buffer, int64_t insertRows,
        int64_t startFrom, uint64_t startTime, int *pSamplePos, int *dataLen) {
  int len = 0;
4336 4337
  int ncols_per_record = 1; // count first col ts

4338
  if (superTblInfo == NULL) {
4339 4340 4341 4342 4343
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
4344 4345
  }

4346
  verbosePrint("%s() LN%d batch=%d\n", __func__, __LINE__, batch);
4347

4348 4349
  int k = 0;
  for (k = 0; k < batch;) {
4350
    if (superTblInfo) {
4351
        int retLen = 0;
4352

4353 4354 4355
        if (0 == strncasecmp(superTblInfo->dataSource,
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
4356 4357
                    buffer + len,
                    superTblInfo->maxSqlLen - len,
4358
                    startTime + superTblInfo->timeStampStep * k,
4359
                    superTblInfo,
4360
                    pSamplePos);
4361 4362 4363
       } else if (0 == strncasecmp(superTblInfo->dataSource,
                   "rand", strlen("rand"))) {
          int rand_num = rand_tinyint() % 100;
4364
          if (0 != superTblInfo->disorderRatio
4365
                    && rand_num < superTblInfo->disorderRatio) {
4366 4367 4368
            int64_t d = startTime
                + superTblInfo->timeStampStep * k
                - taosRandom() % superTblInfo->disorderRange;
4369
            retLen = generateRowData(
4370
                      buffer + len,
4371
                      superTblInfo->maxSqlLen - len,
4372
                      d,
4373
                      superTblInfo);
4374 4375
          } else {
            retLen = generateRowData(
4376 4377
                      buffer + len,
                      superTblInfo->maxSqlLen - len,
4378
                      startTime + superTblInfo->timeStampStep * k,
4379
                      superTblInfo);
4380 4381
          }
       }
4382

4383 4384 4385
       if (retLen < 0) {
         return -1;
       }
4386

4387
       len += retLen;
4388

4389 4390 4391 4392
       if (len >= (superTblInfo->maxSqlLen - 256)) {    // reserve for overwrite
         k++;
         break;
       }
4393
    } else {
4394
      int rand_num = taosRandom() % 100;
4395 4396 4397 4398
          char data[MAX_DATA_SIZE];
          char **data_type = g_args.datatype;
          int lenOfBinary = g_args.len_of_binary;

4399
      if ((g_args.disorderRatio != 0)
4400
                && (rand_num < g_args.disorderRange)) {
4401

4402 4403
        int64_t d = startTime + DEFAULT_TIMESTAMP_STEP * k 
            - taosRandom() % 1000000 + rand_num;
4404
        len = generateData(data, data_type,
4405
                  ncols_per_record, d, lenOfBinary);
4406
      } else {
4407
            len = generateData(data, data_type,
4408
                  ncols_per_record,
4409
                  startTime + DEFAULT_TIMESTAMP_STEP * k,
4410 4411
                  lenOfBinary);
      }
4412

4413 4414
      buffer += sprintf(buffer, " %s", data);
      if (strlen(buffer) >= (g_args.max_sql_len - 256)) { // too long
4415 4416
          k++;
          break;
4417 4418 4419
      }
    }

4420 4421
    verbosePrint("%s() LN%d len=%d k=%d \nbuffer=%s\n",
            __func__, __LINE__, len, k, buffer);
4422 4423 4424

    k++;
    startFrom ++;
4425

4426
    if (startFrom >= insertRows) {
4427
      break;
4428
    }
4429
  }
4430

4431 4432 4433
  *dataLen = len;
  return k;
}
4434

4435 4436
static int generateSQLHead(char *tableName, int32_t tableSeq,
        threadInfo* pThreadInfo, SSuperTable* superTblInfo, char *buffer)
4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449
{
  int len;
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
            tagsValBuf = generateTagVaulesForStb(superTblInfo);
      } else {
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
      }
      if (NULL == tagsValBuf) {
4450
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n", __func__, __LINE__);
4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467
        return -1;
      }

      len = snprintf(buffer,
                  superTblInfo->maxSqlLen,
                  "insert into %s.%s using %s.%s tags %s values",
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
      len = snprintf(buffer,
                  superTblInfo->maxSqlLen,
                  "insert into %s.%s values",
                  pThreadInfo->db_name,
4468
                  tableName);
4469 4470
    } else {
      len = snprintf(buffer,
4471
                  superTblInfo->maxSqlLen,
4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486
                  "insert into %s.%s values",
                  pThreadInfo->db_name,
                  tableName);
    }
  } else {
      len = snprintf(buffer,
                  g_args.max_sql_len,
                  "insert into %s.%s values",
                  pThreadInfo->db_name,
                  tableName);
  }

  return len;
}

4487
static int generateProgressiveDataBuffer(char *pTblName,
4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510
        int32_t tableSeq,
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
        int64_t startFrom, int64_t startTime, int *pSamplePos)
{
  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);

  memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len);

  char *pstr = buffer;

4511 4512
  int headLen = generateSQLHead(pTblName, tableSeq, pThreadInfo, superTblInfo,
          buffer);
4513 4514 4515 4516 4517
  pstr += headLen;

  int k;
  int dataLen;
  k = generateDataTail(pTblName, tableSeq, pThreadInfo, superTblInfo,
4518 4519
          g_args.num_of_RPR, pstr, insertRows, startFrom,
          startTime,
4520
          pSamplePos, &dataLen);
4521 4522
  return k;
}
4523

4524
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
4525 4526
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
4527 4528

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540
  int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows;

  int insertMode;

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

  // TODO: prompt tbl count multple interlace rows and batch
  //
4541 4542 4543

  char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1);
  if (NULL == buffer) {
4544
    errorPrint( "Failed to alloc %d Bytes, reason:%s\n",
4545 4546 4547 4548 4549 4550
              superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len,
              strerror(errno));
    return NULL;
  }


4551
  char tableName[TSDB_TABLE_NAME_LEN];
4552 4553 4554 4555 4556

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

  int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
4557 4558
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4559 4560 4561 4562 4563 4564 4565 4566 4567
  uint64_t st = 0;
  uint64_t et = 0xffffffff;

  int64_t lastPrintTime = taosGetTimestampMs();
  int64_t startTs = taosGetTimestampUs();
  int64_t endTs;

  int tableSeq = pThreadInfo->start_table_from;

4568 4569
  debugPrint("[%d] %s() LN%d: start_table_from=%d ntables=%d insertRows=%"PRId64"\n",
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
4570 4571 4572 4573 4574
          pThreadInfo->ntables, insertRows);

  int64_t startTime = pThreadInfo->start_time;

  int batchPerTblTimes;
4575
  int batchPerTbl;
4576

4577 4578
  assert(pThreadInfo->ntables > 0);

4579 4580
  if (interlaceRows > g_args.num_of_RPR)
        interlaceRows = g_args.num_of_RPR;
4581

4582 4583
  batchPerTbl = interlaceRows;
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
4584
    batchPerTblTimes =
4585
        (g_args.num_of_RPR / (interlaceRows * pThreadInfo->ntables)) + 1;
4586 4587 4588 4589
  } else {
    batchPerTblTimes = 1;
  }

4590
  int generatedRecPerTbl = 0;
4591 4592
  bool flagSleep = true;
  int sleepTimeTotal = 0;
4593
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
4594
    if ((flagSleep) && (insert_interval)) {
4595
        st = taosGetTimestampUs();
4596
        flagSleep = false;
4597 4598 4599
    }
    // generate data
    memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len);
4600

4601
    char *pstr = buffer;
4602
    int recOfBatch = 0;
4603

4604 4605
    for (int i = 0; i < batchPerTblTimes; i ++) {
      getTableName(tableName, pThreadInfo, tableSeq);
4606

4607 4608
      int headLen;
      if (i == 0) {
4609 4610
        headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
                superTblInfo, pstr);
4611
      } else {
4612
        headLen = snprintf(pstr, TSDB_TABLE_NAME_LEN, "%s.%s values",
4613 4614
                  pThreadInfo->db_name,
                  tableName);
4615
      }
4616

4617
      // generate data buffer
4618 4619
      verbosePrint("[%d] %s() LN%d i=%d buffer:\n%s\n",
                pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4620

4621 4622
      pstr += headLen;
      int dataLen = 0;
4623

4624
      verbosePrint("[%d] %s() LN%d i=%d batchPerTblTimes=%d batchPerTbl = %d\n",
4625 4626
                pThreadInfo->threadID, __func__, __LINE__,
                i, batchPerTblTimes, batchPerTbl);
4627 4628 4629 4630 4631 4632 4633

      if (superTblInfo) {
        if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
          startTime = taosGetTimestamp(pThreadInfo->time_precision);
        }
      } else {
          startTime = 1500000000000;
4634
      }
4635 4636 4637
      generateDataTail(
        tableName, tableSeq, pThreadInfo, superTblInfo,
        batchPerTbl, pstr, insertRows, 0,
4638
        startTime,
4639
        &(pThreadInfo->samplePos), &dataLen);
4640

4641
      pstr += dataLen;
4642
      recOfBatch += batchPerTbl;
4643
      startTime += batchPerTbl * superTblInfo->timeStampStep;
4644
      pThreadInfo->totalInsertRows += batchPerTbl;
4645
      verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
4646 4647
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
4648

4649 4650 4651 4652
      tableSeq ++;
      if (insertMode == INTERLACE_INSERT_MODE) {
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
4653
            startTime += batchPerTbl * superTblInfo->timeStampStep;
4654
            tableSeq = pThreadInfo->start_table_from;
4655 4656 4657 4658 4659 4660 4661
            generatedRecPerTbl += batchPerTbl;
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
4662
          }
4663 4664
      }

4665
      int remainRows = insertRows - generatedRecPerTbl;
4666
      if ((remainRows > 0) && (batchPerTbl > remainRows))
4667 4668
        batchPerTbl = remainRows;

4669
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%d insertRows=%"PRId64"\n",
4670 4671 4672 4673
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
4674 4675 4676
        break;
    }

4677
    verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRId64"\n",
4678 4679 4680 4681 4682
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
           pThreadInfo->threadID, __func__, __LINE__, buffer);

4683 4684
    startTs = taosGetTimestampUs();

4685
    int affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696

    endTs = taosGetTimestampUs();
    int64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %10.6fms\n",
            __func__, __LINE__, delay/1000.0);

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

4697 4698
    verbosePrint("[%d] %s() LN%d affectedRows=%d\n", pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
4699 4700
    if ((affectedRows < 0) || (recOfBatch != affectedRows)) {
        errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %d\n%s\n",
4701
                pThreadInfo->threadID, __func__, __LINE__,
4702
                recOfBatch, affectedRows, buffer);
4703
        goto free_and_statistics_interlace;
4704
    }
4705

4706
    pThreadInfo->totalAffectedRows += affectedRows;
4707

4708 4709 4710
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
      printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
4711 4712 4713
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
4714 4715
      lastPrintTime = currentPrintTime;
    }
4716

4717 4718
    if ((insert_interval) && flagSleep) {
      et = taosGetTimestampUs();
4719

4720 4721
      if (insert_interval > ((et - st)/1000) ) {
        int sleepTime = insert_interval - (et -st)/1000;
4722 4723
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleepTime);
4724 4725 4726
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
4727
    }
4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739
  }

free_and_statistics_interlace:
  tmfree(buffer);

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

4740 4741 4742 4743 4744 4745 4746 4747
// 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
*/
4748
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
4749
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
4750

4751
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4752

4753 4754
  char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1);
  if (NULL == buffer) {
4755
    errorPrint( "Failed to alloc %d Bytes, reason:%s\n",
4756 4757 4758 4759
              superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len,
              strerror(errno));
    return NULL;
  }
4760

4761 4762 4763 4764
  int64_t lastPrintTime = taosGetTimestampMs();
  int64_t startTs = taosGetTimestampUs();
  int64_t endTs;

4765 4766
  int timeStampStep =
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
4767
/*  int insert_interval =
4768
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4769 4770
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
4771
  */
4772

4773 4774
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
4775

4776
  pThreadInfo->samplePos = 0;
4777

4778 4779
  for (uint32_t tableSeq =
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
4780
        tableSeq ++) {
4781
    int64_t start_time = pThreadInfo->start_time;
4782 4783 4784 4785 4786

    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;) {
4787
        /*
4788 4789
      if (insert_interval) {
            st = taosGetTimestampUs();
4790
      }
4791
      */
4792

4793 4794 4795 4796 4797 4798
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
      verbosePrint("%s() LN%d: tid=%d seq=%d tableName=%s\n",
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);

4799
      int generated = generateProgressiveDataBuffer(
4800
              tableName, tableSeq, pThreadInfo, buffer, insertRows,
4801
            i, start_time,
4802
            &(pThreadInfo->samplePos));
4803 4804 4805 4806 4807
      if (generated > 0)
        i += generated;
      else
        goto free_and_statistics_2;

4808
      start_time +=  generated * timeStampStep;
4809
      pThreadInfo->totalInsertRows += generated;
4810 4811 4812 4813

      startTs = taosGetTimestampUs();

      int affectedRows = execInsert(pThreadInfo, buffer, generated);
4814 4815 4816

      endTs = taosGetTimestampUs();
      int64_t delay = endTs - startTs;
4817 4818 4819
      performancePrint("%s() LN%d, insert execution time is %10.6fms\n",
              __func__, __LINE__, delay/1000.0);

4820 4821 4822 4823
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
4824

4825 4826 4827 4828 4829
      if (affectedRows < 0)
        goto free_and_statistics_2;

      pThreadInfo->totalAffectedRows += affectedRows;

4830 4831
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
4832
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
4833 4834 4835
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
4836 4837 4838
        lastPrintTime = currentPrintTime;
      }

4839
      if (i >= insertRows)
4840
        break;
4841
/*
4842 4843 4844 4845 4846
      if (insert_interval) {
        et = taosGetTimestampUs();

        if (insert_interval > ((et - st)/1000) ) {
            int sleep_time = insert_interval - (et -st)/1000;
4847 4848
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
4849 4850
            taosMsleep(sleep_time); // ms
        }
4851
      }
4852
      */
4853 4854
    }   // num_of_DPT

4855
    if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
4856 4857
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
4858 4859
          printf("%s() LN%d samplePos=%d\n",
                  __func__, __LINE__, pThreadInfo->samplePos);
4860
    }
4861
  } // tableSeq
4862

4863
free_and_statistics_2:
4864 4865
  tmfree(buffer);

4866
  printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", 
4867 4868 4869
          pThreadInfo->threadID, 
          pThreadInfo->totalInsertRows, 
          pThreadInfo->totalAffectedRows);
4870
  return NULL;
H
Hui Li 已提交
4871 4872
}

4873 4874 4875 4876 4877
static void* syncWrite(void *sarg) {

  threadInfo *winfo = (threadInfo *)sarg; 
  SSuperTable* superTblInfo = winfo->superTblInfo;

4878
  int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows;
4879

4880
  if (interlaceRows > 0) {
4881 4882 4883 4884 4885 4886 4887 4888
    // interlace mode
    return syncWriteInterlace(winfo);
  } else {
    // progressive mode
    return syncWriteProgressive(winfo);
  }
}

4889
static void callBack(void *param, TAOS_RES *res, int code) {
4890
  threadInfo* winfo = (threadInfo*)param; 
4891
  SSuperTable* superTblInfo = winfo->superTblInfo;
4892

4893 4894
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4895 4896 4897 4898
  if (insert_interval) {
    winfo->et = taosGetTimestampUs();
    if (((winfo->et - winfo->st)/1000) < insert_interval) {
      taosMsleep(insert_interval - (winfo->et - winfo->st)/1000); // ms
4899
    }
H
Hui Li 已提交
4900
  }
4901

4902 4903 4904
  char *buffer = calloc(1, winfo->superTblInfo->maxSqlLen);
  char *data   = calloc(1, MAX_DATA_SIZE);
  char *pstr = buffer;
4905 4906
  pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix,
          winfo->start_table_from);
4907
//  if (winfo->counter >= winfo->superTblInfo->insertRows) {
4908
  if (winfo->counter >= g_args.num_of_RPR) {
4909
    winfo->start_table_from++;
4910 4911
    winfo->counter = 0;
  }
4912
  if (winfo->start_table_from > winfo->end_table_to) {
4913 4914 4915 4916 4917 4918
    tsem_post(&winfo->lock_sem);
    free(buffer);
    free(data);
    taos_free_result(res);
    return;
  }
4919

4920
  for (int i = 0; i < g_args.num_of_RPR; i++) {
4921
    int rand_num = taosRandom() % 100;
4922 4923
    if (0 != winfo->superTblInfo->disorderRatio
            && rand_num < winfo->superTblInfo->disorderRatio) {
4924
      int64_t d = winfo->lastTs - taosRandom() % 1000000 + rand_num;
4925
      //generateData(data, datatype, ncols_per_record, d, len_of_binary);
4926
      generateRowData(data, MAX_DATA_SIZE, d, winfo->superTblInfo);
4927
    } else {
4928
      //generateData(data, datatype, ncols_per_record, start_time += 1000, len_of_binary);
4929
      generateRowData(data, MAX_DATA_SIZE, winfo->lastTs += 1000, winfo->superTblInfo);
H
Hui Li 已提交
4930
    }
4931 4932
    pstr += sprintf(pstr, "%s", data);
    winfo->counter++;
H
Hui Li 已提交
4933

4934 4935
    if (winfo->counter >= winfo->superTblInfo->insertRows) {
      break;
H
Hui Li 已提交
4936 4937
    }
  }
4938

4939 4940
  if (insert_interval) {
    winfo->st = taosGetTimestampUs();
4941 4942 4943 4944
  }
  taos_query_a(winfo->taos, buffer, callBack, winfo);
  free(buffer);
  free(data);
H
Hui Li 已提交
4945

4946
  taos_free_result(res);
H
Hui Li 已提交
4947 4948
}

4949
static void *asyncWrite(void *sarg) {
4950
  threadInfo *winfo = (threadInfo *)sarg;
4951
  SSuperTable* superTblInfo = winfo->superTblInfo;
4952 4953 4954 4955

  winfo->st = 0;
  winfo->et = 0;
  winfo->lastTs = winfo->start_time;
4956

4957
  int insert_interval =
4958
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4959 4960
  if (insert_interval) {
    winfo->st = taosGetTimestampUs();
H
Hui Li 已提交
4961
  }
4962 4963 4964
  taos_query_a(winfo->taos, "show databases", callBack, winfo);

  tsem_wait(&(winfo->lock_sem));
H
Hui Li 已提交
4965 4966 4967 4968

  return NULL;
}

4969 4970
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
4971 4972

    pthread_t *pids = malloc(threads * sizeof(pthread_t));
4973 4974
    assert(pids != NULL);

4975
    threadInfo *infos = malloc(threads * sizeof(threadInfo));
4976 4977
    assert(infos != NULL);

4978 4979
    memset(pids, 0, threads * sizeof(pthread_t));
    memset(infos, 0, threads * sizeof(threadInfo));
H
Hui Li 已提交
4980

4981
    int ntables = 0;
4982 4983
    if (superTblInfo) {

4984
        if ((superTblInfo->childTblOffset >= 0)
4985 4986
            && (superTblInfo->childTblLimit > 0)) {

4987
            ntables = superTblInfo->childTblLimit;
4988
        } else {
4989
            ntables = superTblInfo->childTblCount;
4990 4991
        }
    } else {
4992
        ntables = g_args.num_of_tables;
4993
    }
H
Hui Li 已提交
4994

4995 4996 4997 4998 4999 5000 5001 5002 5003 5004
    int a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
    }

    int b = 0;
    if (threads != 0) {
        b = ntables % threads;
    }
5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021

  //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 {
5022
      errorPrint("Not support precision: %s\n", precision);
5023 5024 5025 5026
      exit(-1);
    }
  }

5027
  int64_t start_time;
5028 5029 5030
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
5031
    } else {
5032 5033 5034 5035 5036
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
5037
          ERROR_EXIT("failed to parse time!\n");
5038
      }
5039
    }
5040 5041
  } else {
     start_time = 1500000000000;
5042 5043 5044
  }

  double start = getCurrentTime();
5045

5046
  int startFrom;
5047

5048
  if ((superTblInfo) && (superTblInfo->childTblOffset >= 0))
5049
      startFrom = superTblInfo->childTblOffset;
5050
  else
5051
      startFrom = 0;
5052

5053
  // read sample data from file first
5054
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5055
              "sample", strlen("sample")))) {
5056
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5057 5058
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5059 5060 5061 5062
      exit(-1);
    }
  }

5063
  // read sample data from file first
5064
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5065 5066
              "sample", strlen("sample")))) {
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5067 5068
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5069 5070 5071 5072 5073 5074 5075 5076
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
  if (NULL == taos) {
5077 5078
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
                __func__, __LINE__, taos_errstr(NULL));
5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096
    exit(-1);
  }

  if (superTblInfo) {

    int limit, offset;
    if (superTblInfo && (superTblInfo->childTblOffset >= 0)
            && (superTblInfo->childTblLimit > 0)) {
        limit = superTblInfo->childTblLimit;
        offset = superTblInfo->childTblOffset;
    } else {
        limit = superTblInfo->childTblCount;
        offset = 0;
    }

    superTblInfo->childTblName = (char*)calloc(1,
        limit * TSDB_TABLE_NAME_LEN);
    if (superTblInfo->childTblName == NULL) {
5097
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111
      taos_close(taos);
      exit(-1);
    }

    int childTblCount;
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
  }
  taos_close(taos);

H
Hui Li 已提交
5112
  for (int i = 0; i < threads; i++) {
5113
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5114 5115
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5116
    t_info->time_precision = timePrec;
5117 5118 5119
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5120
    t_info->minDelay = INT16_MAX;
5121

5122 5123
    if ((NULL == superTblInfo) ||
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5124
      //t_info->taos = taos;
5125
      t_info->taos = taos_connect(
5126
              g_Dbs.host, g_Dbs.user,
5127
              g_Dbs.password, db_name, g_Dbs.port);
5128
      if (NULL == t_info->taos) {
5129 5130
        errorPrint(
                "connect to server fail from insert sub thread, reason: %s\n",
5131
                taos_errstr(NULL));
5132 5133 5134 5135 5136 5137
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5138 5139
    if ((NULL == superTblInfo)
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5140 5141 5142 5143
      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;
5144
    } else {
5145 5146
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5147 5148 5149 5150 5151
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }

    tsem_init(&(t_info->lock_sem), 0, 0);
    if (SYNC == g_Dbs.queryMode) {
5152
      pthread_create(pids + i, NULL, syncWrite, t_info);
5153
    } else {
5154 5155
      pthread_create(pids + i, NULL, asyncWrite, t_info);
    }
H
Hui Li 已提交
5156
  }
5157

H
Hui Li 已提交
5158 5159 5160 5161
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5162 5163 5164
  int64_t totalDelay = 0;
  int64_t maxDelay = 0;
  int64_t minDelay = INT16_MAX;
5165
  int64_t cntDelay = 1;
5166 5167
  double  avgDelay = 0;

H
Hui Li 已提交
5168
  for (int i = 0; i < threads; i++) {
5169 5170
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5171
    tsem_destroy(&(t_info->lock_sem));
5172 5173
    taos_close(t_info->taos);

5174 5175 5176 5177
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRId64" totalAffected=%"PRId64"\n",
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5178 5179
    if (superTblInfo) {
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
5180
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5181 5182 5183
    } else {
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5184
    }
5185 5186 5187 5188

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5189
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5190
  }
5191
  cntDelay -= 1;
H
Hui Li 已提交
5192

5193
  if (cntDelay == 0)    cntDelay = 1;
5194 5195
  avgDelay = (double)totalDelay / cntDelay;

5196
  double end = getCurrentTime();
5197
  double t = end - start;
5198 5199

  if (superTblInfo) {
5200
    printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
5201
          t, superTblInfo->totalInsertRows,
5202 5203
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5204
          superTblInfo->totalInsertRows / t);
5205
    fprintf(g_fpOfInsertResult,
5206
          "Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
5207
          t, superTblInfo->totalInsertRows,
5208 5209
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5210
          superTblInfo->totalInsertRows/ t);
5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222
  } else {
    printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n",
          t, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          g_args.totalInsertRows / t);
    fprintf(g_fpOfInsertResult,
          "Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s %2.f records/second\n\n",
          t, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          g_args.totalInsertRows / t);
5223
  }
5224 5225 5226 5227 5228

  printf("insert delay, avg: %10.6fms, max: %10.6fms, min: %10.6fms\n\n",
          avgDelay/1000.0, (double)maxDelay/1000.0, (double)minDelay/1000.0);
  fprintf(g_fpOfInsertResult, "insert delay, avg:%10.6fms, max: %10.6fms, min: %10.6fms\n\n",
          avgDelay/1000.0, (double)maxDelay/1000.0, (double)minDelay/1000.0);
5229

5230 5231
  //taos_close(taos);

H
Hui Li 已提交
5232
  free(pids);
5233
  free(infos);
H
Hui Li 已提交
5234 5235
}

5236
static void *readTable(void *sarg) {
5237
#if 1
5238
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5239 5240
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5241
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5242 5243
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5244
  if (NULL == fp) {
5245
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5246 5247
    return NULL;
  }
5248

5249
    int num_of_DPT;
5250
/*  if (rinfo->superTblInfo) {
5251 5252
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5253
  */
5254
      num_of_DPT = g_args.num_of_DPT;
5255
//  }
5256

5257
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5258
  int totalData = num_of_DPT * num_of_tables;
5259
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271

  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++) {
5272 5273
      sprintf(command, "select %s from %s%d where ts>= %" PRId64,
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5274 5275

      double t = getCurrentTime();
S
Shuaiqiang Chang 已提交
5276 5277
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5278

S
Shuaiqiang Chang 已提交
5279
      if (code != 0) {
5280
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5281
        taos_free_result(pSql);
H
hzcheng 已提交
5282
        taos_close(taos);
5283
        fclose(fp);
5284
        return NULL;
H
hzcheng 已提交
5285 5286
      }

S
Shuaiqiang Chang 已提交
5287
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5288 5289 5290 5291 5292 5293
        count++;
      }

      t = getCurrentTime() - t;
      totalT += t;

S
Shuaiqiang Chang 已提交
5294
      taos_free_result(pSql);
H
hzcheng 已提交
5295 5296 5297
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5298
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5299 5300 5301 5302 5303
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT);
  }
  fprintf(fp, "\n");
  fclose(fp);
5304
#endif
H
hzcheng 已提交
5305 5306 5307
  return NULL;
}

5308
static void *readMetric(void *sarg) {
5309 5310
#if 1  
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5311 5312 5313
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5314 5315 5316 5317
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5318 5319

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5320
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5321
  int totalData = num_of_DPT * num_of_tables;
5322
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5323 5324 5325 5326 5327 5328 5329 5330 5331

  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 已提交
5332
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5333
    char tempS[64] = "\0";
H
hzcheng 已提交
5334 5335 5336 5337 5338

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5339
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5340
      } else {
5341
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5342 5343 5344
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5345
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5346 5347 5348 5349 5350 5351

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

      double t = getCurrentTime();

S
Shuaiqiang Chang 已提交
5352 5353 5354 5355
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
5356
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5357
        taos_free_result(pSql);
H
hzcheng 已提交
5358
        taos_close(taos);
5359
        fclose(fp);
5360
        return NULL;
H
hzcheng 已提交
5361 5362
      }
      int count = 0;
S
Shuaiqiang Chang 已提交
5363
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5364 5365 5366 5367
        count++;
      }
      t = getCurrentTime() - t;

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

S
Shuaiqiang Chang 已提交
5372
      taos_free_result(pSql);
H
hzcheng 已提交
5373 5374 5375 5376
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5377
#endif
H
hzcheng 已提交
5378 5379 5380
  return NULL;
}

H
Hui Li 已提交
5381

5382
static int insertTestProcess() {
5383

5384 5385 5386
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5387

5388 5389 5390
  if (ret == -1)
    exit(EXIT_FAILURE);

5391
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5392 5393
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
5394
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
5395 5396
    return -1;
  }
5397

5398 5399
  printfInsertMetaToFile(g_fpOfInsertResult);

5400 5401 5402 5403
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5404

5405 5406 5407
  init_rand_data();

  // create database and super tables
5408
  if(createDatabases() != 0) {
5409 5410 5411
    fclose(g_fpOfInsertResult);
    return -1;
  }
5412 5413

  // pretreatement
5414
  prepareSampleData();
5415

5416 5417 5418 5419 5420 5421 5422
  double start;
  double end;

  // create child tables
  start = getCurrentTime();
  createChildTables();
  end = getCurrentTime();
5423

5424
  if (g_totalChildTables > 0) {
5425
    printf("Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5426
            end - start, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5427 5428
    fprintf(g_fpOfInsertResult,
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5429
            end - start, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5430
  }
5431

5432
  taosMsleep(1000);
5433 5434
  // create sub threads for inserting data
  //start = getCurrentTime();
5435 5436 5437 5438 5439 5440
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    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 (0 == g_Dbs.db[i].superTbls[j].insertRows) {
          continue;
5441
        }
5442
        startMultiThreadInsertData(
5443 5444 5445
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
5446 5447 5448 5449
          superTblInfo);
        }
    } else {
        startMultiThreadInsertData(
5450 5451 5452
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
5453
          NULL);
H
Hui Li 已提交
5454
    }
5455
  }
5456
  //end = getCurrentTime();
5457

5458
  //int64_t    totalInsertRows = 0;
5459 5460 5461
  //int64_t    totalAffectedRows = 0;
  //for (int i = 0; i < g_Dbs.dbCount; i++) {    
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
5462
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
5463 5464
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
5465
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
5466
  postFreeResource();
5467

5468 5469 5470
  return 0;
}

5471
static void *superQueryProcess(void *sarg) {
5472
  threadInfo *winfo = (threadInfo *)sarg;
5473

5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489
  if (winfo->taos == NULL) {
    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",
            winfo->threadID, taos_errstr(NULL));
      return NULL;
    } else {
      winfo->taos = taos;
    }
  }

5490 5491 5492
  //char sqlStr[MAX_TB_NAME_SIZE*2];
  //sprintf(sqlStr, "use %s", g_queryInfo.dbName);
  //queryDB(winfo->taos, sqlStr);
5493

5494 5495
  int64_t st = 0;
  int64_t et = 0;
5496 5497 5498 5499

  int queryTimes = g_args.query_times;

  while(queryTimes --) {
5500 5501
    if (g_queryInfo.superQueryInfo.rate && (et - st) <
            (int64_t)g_queryInfo.superQueryInfo.rate*1000) {
5502
      taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms
5503
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5504 5505
    }

5506
    st = taosGetTimestampUs();
5507
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
5508
      if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) {
5509 5510 5511
        int64_t t1 = taosGetTimestampUs();
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
5512 5513
          sprintf(tmpFile, "%s-%d",
                  g_queryInfo.superQueryInfo.result[i], winfo->threadID);
5514
        }
5515 5516 5517
        selectAndGetResult(winfo->taos, g_queryInfo.superQueryInfo.sql[i], tmpFile);
        int64_t t2 = taosGetTimestampUs();
        printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %f s\n",
5518
                taosGetSelfPthreadId(), (t2 - t1)/1000000.0);
5519 5520
      } else {
        int64_t t1 = taosGetTimestampUs();
5521
        int retCode = postProceSql(g_queryInfo.host,
5522
                g_queryInfo.port, g_queryInfo.superQueryInfo.sql[i]);
5523 5524
        int64_t t2 = taosGetTimestampUs();
        printf("=[restful] thread[%"PRId64"] complete one sql, Spent %f s\n",
5525
                taosGetSelfPthreadId(), (t2 - t1)/1000000.0);
5526

5527
        if (0 != retCode) {
5528
          printf("====restful return fail, threadID[%d]\n", winfo->threadID);
5529 5530
          return NULL;
        }
5531
      }
5532
    }
5533
    et = taosGetTimestampUs();
5534
    printf("==thread[%"PRId64"] complete all sqls to specify tables once queries duration:%.6fs\n\n",
5535
            taosGetSelfPthreadId(), (double)(et - st)/1000.0);
H
Hui Li 已提交
5536
  }
5537 5538
  return NULL;
}
H
Hui Li 已提交
5539

5540
static void replaceSubTblName(char* inSql, char* outSql, int tblIndex) {
5541 5542
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
5543 5544
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
5545
          g_queryInfo.subQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
5546 5547

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

5549 5550
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
5551
    return;
H
Hui Li 已提交
5552
  }
5553

5554
  tstrncpy(outSql, inSql, pos - inSql + 1);
5555
  //printf("1: %s\n", outSql);
5556 5557 5558 5559
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
5560 5561
}

5562
static void *subQueryProcess(void *sarg) {
5563
  char sqlstr[1024];
5564
  threadInfo *winfo = (threadInfo *)sarg;
5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581

  if (winfo->taos == NULL) {
    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",
            winfo->threadID, taos_errstr(NULL));
      return NULL;
    } else {
      winfo->taos = taos;
    }
  }

5582
  int64_t st = 0;
5583
  int64_t et = (int64_t)g_queryInfo.subQueryInfo.rate*1000;
5584 5585
  int queryTimes = g_args.query_times;

5586
  while(queryTimes --) {
5587 5588
    if (g_queryInfo.subQueryInfo.rate
            && (et - st) < (int64_t)g_queryInfo.subQueryInfo.rate*1000) {
5589
      taosMsleep(g_queryInfo.subQueryInfo.rate*1000 - (et - st)); // ms
5590
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5591
    }
H
Hui Li 已提交
5592

5593
    st = taosGetTimestampUs();
5594
    for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) {
5595
      for (int j = 0; j < g_queryInfo.subQueryInfo.sqlCount; j++) {
5596
        memset(sqlstr,0,sizeof(sqlstr));
5597
        replaceSubTblName(g_queryInfo.subQueryInfo.sql[j], sqlstr, i);
5598
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5599
        if (g_queryInfo.subQueryInfo.result[j][0] != 0) {
5600
          sprintf(tmpFile, "%s-%d",
5601
                  g_queryInfo.subQueryInfo.result[j],
5602
                  winfo->threadID);
5603
        }
5604
        selectAndGetResult(winfo->taos, sqlstr, tmpFile);
5605
      }
H
Hui Li 已提交
5606
    }
5607
    et = taosGetTimestampUs();
5608
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%d - %d] once queries duration:%.4fs\n\n",
5609 5610 5611
            taosGetSelfPthreadId(),
            winfo->start_table_from,
            winfo->end_table_to,
5612
            (double)(et - st)/1000000.0);
5613
  }
5614

5615 5616 5617
  return NULL;
}

5618
static int queryTestProcess() {
5619 5620 5621 5622

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
5623 5624 5625 5626 5627 5628

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
5629
          g_queryInfo.port);
5630
  if (taos == NULL) {
5631 5632
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
5633 5634 5635 5636
    exit(-1);
  }

  if (0 != g_queryInfo.subQueryInfo.sqlCount) {
5637 5638 5639 5640
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
            g_queryInfo.subQueryInfo.sTblName,
            &g_queryInfo.subQueryInfo.childTblName,
5641
            &g_queryInfo.subQueryInfo.childTblCount);
5642
  }
5643

5644 5645 5646 5647
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5648

5649
  printfQuerySystemInfo(taos);
5650

5651 5652 5653
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
5654 5655
  if (g_queryInfo.superQueryInfo.sqlCount > 0
          && g_queryInfo.superQueryInfo.concurrent > 0) {
5656

5657
    pids  = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t));
5658 5659 5660 5661
    if (NULL == pids) {
        taos_close(taos);
        ERROR_EXIT("memory allocation failed\n");
    }
5662
    infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo));
5663
    if (NULL == infos) {
5664
      taos_close(taos);
5665 5666
      free(pids);
      ERROR_EXIT("memory allocation failed for create threads\n");
5667
    }
5668 5669

    for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) {
5670
      threadInfo *t_info = infos + i;
5671
      t_info->threadID = i;
5672

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

5675 5676
        char sqlStr[MAX_TB_NAME_SIZE*2];
        sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5677
        verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5678 5679
        if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
            taos_close(taos);
5680 5681
            free(infos);
            free(pids);
5682 5683 5684 5685
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
        }
5686
      }
5687

5688 5689
      t_info->taos = NULL;// TODO: workaround to use separate taos connection;

5690 5691
      pthread_create(pids + i, NULL, superQueryProcess, t_info);
    }
5692
  } else {
5693 5694
    g_queryInfo.superQueryInfo.concurrent = 0;
  }
5695

5696 5697
  taos_close(taos);

5698 5699 5700
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
5701 5702
  if ((g_queryInfo.subQueryInfo.sqlCount > 0)
          && (g_queryInfo.subQueryInfo.threadCnt > 0)) {
5703
    pidsOfSub  = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(pthread_t));
5704 5705 5706 5707 5708 5709 5710
    if (NULL == pidsOfSub) {
      free(infos);
      free(pids);

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

5711
    infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * sizeof(threadInfo));
5712 5713 5714 5715 5716
    if (NULL == infosOfSub) {
      free(pidsOfSub);
      free(infos);
      free(pids);
      ERROR_EXIT("memory allocation failed for create threads\n");
5717
    }
5718

5719 5720
    int ntables = g_queryInfo.subQueryInfo.childTblCount;
    int threads = g_queryInfo.subQueryInfo.threadCnt;
5721

5722 5723 5724 5725 5726
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
5727

5728 5729 5730 5731
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
5732

5733
    int startFrom = 0;
5734
    for (int i = 0; i < threads; i++) {
5735 5736
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
5737

5738 5739 5740 5741
      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;
5742
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
5743 5744 5745 5746
      pthread_create(pidsOfSub + i, NULL, subQueryProcess, t_info);
    }

    g_queryInfo.subQueryInfo.threadCnt = threads;
5747
  } else {
5748
    g_queryInfo.subQueryInfo.threadCnt = 0;
5749
  }
5750

5751 5752
  for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) {
    pthread_join(pids[i], NULL);
5753
  }
S
Shuaiqiang Chang 已提交
5754

5755
  tmfree((char*)pids);
5756
  tmfree((char*)infos);
5757

5758 5759
  for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) {
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
5760
  }
H
Hui Li 已提交
5761

5762
  tmfree((char*)pidsOfSub);
5763
  tmfree((char*)infosOfSub);
5764

5765
//  taos_close(taos);// TODO: workaround to use separate taos connection;
5766 5767 5768
  return 0;
}

5769
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
5770
  if (res == NULL || taos_errno(res) != 0) {
5771 5772
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
5773 5774
    return;
  }
5775

5776 5777
  getResult(res, (char*)param);
  taos_free_result(res);
H
hzcheng 已提交
5778 5779
}

5780
static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) {
5781
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
5782

5783
  if (g_queryInfo.superQueryInfo.subscribeMode) {
5784 5785 5786
    tsub = taos_subscribe(taos,
            g_queryInfo.superQueryInfo.subscribeRestart,
            topic, sql, subscribe_callback, (void*)resultFileName,
5787
            g_queryInfo.superQueryInfo.subscribeInterval);
5788
  } else {
5789 5790
    tsub = taos_subscribe(taos,
            g_queryInfo.superQueryInfo.subscribeRestart,
5791
            topic, sql, NULL, NULL, 0);
5792
  }
5793

5794 5795 5796
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
5797
  }
5798

5799 5800
  return tsub;
}
H
hzcheng 已提交
5801

5802
static void *subSubscribeProcess(void *sarg) {
5803
  threadInfo *winfo = (threadInfo *)sarg;
5804
  char subSqlstr[1024];
H
hzcheng 已提交
5805

5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821
  if (winfo->taos == NULL) {
    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",
            winfo->threadID, taos_errstr(NULL));
      return NULL;
    } else {
      winfo->taos = taos;
    }
  }

5822 5823
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5824
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5825 5826
  if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(winfo->taos);
5827 5828
    return NULL;
  }
5829

5830 5831 5832 5833 5834
  //int64_t st = 0;
  //int64_t et = 0;
  do {
    //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) {
    //  taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms
5835
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5836 5837 5838 5839 5840 5841 5842 5843 5844 5845
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
    for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) {
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
      replaceSubTblName(g_queryInfo.subQueryInfo.sql[i], subSqlstr, i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
      if (g_queryInfo.subQueryInfo.result[i][0] != 0) {
5846 5847
        sprintf(tmpFile, "%s-%d",
                g_queryInfo.subQueryInfo.result[i], winfo->threadID);
5848
      }
5849 5850
      g_queryInfo.subQueryInfo.tsub[i] = subscribeImpl(
              winfo->taos, subSqlstr, topic, tmpFile); 
5851
      if (NULL == g_queryInfo.subQueryInfo.tsub[i]) {
5852
        taos_close(winfo->taos);
5853 5854 5855 5856
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
5857
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
5858 5859 5860 5861 5862 5863 5864 5865 5866
  } while (0);

  // start loop to consume result
  TAOS_RES* res = NULL;
  while (1) {
    for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) {
      if (1 == g_queryInfo.subQueryInfo.subscribeMode) {
        continue;
      }
5867

5868 5869 5870 5871
      res = taos_consume(g_queryInfo.subQueryInfo.tsub[i]);
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
        if (g_queryInfo.subQueryInfo.result[i][0] != 0) {
5872 5873
          sprintf(tmpFile, "%s-%d",
                  g_queryInfo.subQueryInfo.result[i],
5874
                  winfo->threadID);
5875 5876
        }
        getResult(res, tmpFile);
H
hzcheng 已提交
5877 5878 5879
      }
    }
  }
5880
  taos_free_result(res);
5881

5882
  for (int i = 0; i < g_queryInfo.subQueryInfo.sqlCount; i++) {
5883
    taos_unsubscribe(g_queryInfo.subQueryInfo.tsub[i],
5884
            g_queryInfo.subQueryInfo.subscribeKeepProgress);
5885
  }
5886 5887

  taos_close(winfo->taos);
H
hzcheng 已提交
5888 5889 5890
  return NULL;
}

5891
static void *superSubscribeProcess(void *sarg) {
5892
  threadInfo *winfo = (threadInfo *)sarg;
H
hzcheng 已提交
5893

5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909
  if (winfo->taos == NULL) {
    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",
            winfo->threadID, taos_errstr(NULL));
      return NULL;
    } else {
      winfo->taos = taos;
    }
  }

5910 5911
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5912
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5913
  if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
5914
    taos_close(winfo->taos);
5915 5916
    return NULL;
  }
5917

5918 5919 5920 5921 5922
  //int64_t st = 0;
  //int64_t et = 0;
  do {
    //if (g_queryInfo.superQueryInfo.rate && (et - st) < g_queryInfo.superQueryInfo.rate*1000) {
    //  taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms
5923
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5924 5925 5926 5927 5928 5929 5930 5931
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
      if (g_queryInfo.subQueryInfo.result[i][0] != 0) {
5932
        sprintf(tmpFile, "%s-%d",
5933
                g_queryInfo.superQueryInfo.result[i], winfo->threadID);
5934
      }
5935 5936 5937 5938
      g_queryInfo.superQueryInfo.tsub[i] =
          subscribeImpl(winfo->taos,
                  g_queryInfo.superQueryInfo.sql[i],
                  topic, tmpFile);
5939
      if (NULL == g_queryInfo.superQueryInfo.tsub[i]) {
5940
        taos_close(winfo->taos);
5941 5942 5943 5944
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
5945
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
5946 5947 5948 5949 5950 5951 5952 5953 5954
  } while (0);

  // start loop to consume result
  TAOS_RES* res = NULL;
  while (1) {
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
      if (1 == g_queryInfo.superQueryInfo.subscribeMode) {
        continue;
      }
5955

5956 5957 5958 5959
      res = taos_consume(g_queryInfo.superQueryInfo.tsub[i]);
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
5960
          sprintf(tmpFile, "%s-%d",
5961
                  g_queryInfo.superQueryInfo.result[i], winfo->threadID);
5962 5963 5964 5965 5966 5967
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
5968

5969
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
5970
    taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i],
5971
            g_queryInfo.superQueryInfo.subscribeKeepProgress);
5972
  }
5973 5974

  taos_close(winfo->taos);
H
hzcheng 已提交
5975 5976 5977
  return NULL;
}

5978
static int subscribeTestProcess() {
5979
  setupForAnsiEscape();
5980
  printfQueryMeta();
5981
  resetAfterAnsiEscape();
5982

5983 5984
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
5985
    (void) getchar();
Y
yihaoDeng 已提交
5986
  }
5987

5988 5989 5990 5991 5992
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
5993
          g_queryInfo.port);
5994
  if (taos == NULL) {
5995 5996
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
5997 5998 5999 6000
    exit(-1);
  }

  if (0 != g_queryInfo.subQueryInfo.sqlCount) {
6001 6002 6003 6004
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
            g_queryInfo.subQueryInfo.sTblName,
            &g_queryInfo.subQueryInfo.childTblName,
6005
            &g_queryInfo.subQueryInfo.childTblCount);
6006 6007
  }

6008 6009
  taos_close(taos); // TODO: workaround to use separate taos connection;

6010 6011 6012
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023
  if ((g_queryInfo.superQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.superQueryInfo.concurrent <= 0)) {
    errorPrint("%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n",
              __func__, __LINE__, g_queryInfo.superQueryInfo.sqlCount,
              g_queryInfo.superQueryInfo.concurrent);
    exit(-1);
  }

  pids  = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.superQueryInfo.concurrent * sizeof(threadInfo));
  if ((NULL == pids) || (NULL == infos)) {
6024
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6025
      exit(-1);
6026
  }
6027

6028
  for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) {
6029 6030
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6031
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6032
      pthread_create(pids + i, NULL, superSubscribeProcess, t_info);
H
hzcheng 已提交
6033
  }
6034

6035
  //==== create sub threads for query from sub table
6036 6037
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6038
  if ((g_queryInfo.subQueryInfo.sqlCount > 0)
6039
          && (g_queryInfo.subQueryInfo.threadCnt > 0)) {
6040
    pidsOfSub  = malloc(g_queryInfo.subQueryInfo.threadCnt *
6041 6042 6043
            sizeof(pthread_t));
    infosOfSub = malloc(g_queryInfo.subQueryInfo.threadCnt * 
            sizeof(threadInfo));
6044
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6045 6046 6047
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6048
      exit(-1);
S
Shuaiqiang Chang 已提交
6049
    }
6050

6051 6052
    int ntables = g_queryInfo.subQueryInfo.childTblCount;
    int threads = g_queryInfo.subQueryInfo.threadCnt;
6053

6054 6055 6056 6057 6058
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6059

6060 6061 6062 6063
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
6064

6065
    int startFrom = 0;
6066
    for (int i = 0; i < threads; i++) {
6067 6068
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6069

6070 6071 6072 6073
      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;
6074
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6075
      pthread_create(pidsOfSub + i, NULL, subSubscribeProcess, t_info);
H
hzcheng 已提交
6076
    }
6077

6078
    g_queryInfo.subQueryInfo.threadCnt = threads;
6079 6080 6081 6082

    for (int i = 0; i < g_queryInfo.subQueryInfo.threadCnt; i++) {
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6083
  }
6084

6085 6086
  for (int i = 0; i < g_queryInfo.superQueryInfo.concurrent; i++) {
    pthread_join(pids[i], NULL);
6087
  }
H
hzcheng 已提交
6088

6089
  tmfree((char*)pids);
6090
  tmfree((char*)infos);
H
hzcheng 已提交
6091

6092
  tmfree((char*)pidsOfSub);
6093
  tmfree((char*)infosOfSub);
6094
//   taos_close(taos);
6095
  return 0;
H
hzcheng 已提交
6096 6097
}

6098
static void initOfInsertMeta() {
6099
  memset(&g_Dbs, 0, sizeof(SDbs));
6100

6101
  // set default values
6102
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6103
  g_Dbs.port = 6030;
6104 6105
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6106
  g_Dbs.threadCount = 2;
6107 6108

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6109 6110
}

6111
static void initOfQueryMeta() {
6112
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6113

6114
  // set default values
6115
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6116
  g_queryInfo.port = 6030;
6117 6118
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6119 6120
}

6121
static void setParaFromArg(){
6122
  if (g_args.host) {
6123
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6124
  } else {
6125
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6126
  }
L
Liu Tao 已提交
6127

6128
  if (g_args.user) {
6129
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6130
  }
6131 6132

  if (g_args.password) {
6133
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6134 6135
  }

6136 6137
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6138
  }
L
Liu Tao 已提交
6139

6140 6141 6142
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6143 6144
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6145

6146
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6147
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6148
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6149

6150
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6151 6152 6153 6154 6155

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

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

6157 6158
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6159

6160
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6161

6162 6163
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6164
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6165
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6166
  }
H
hzcheng 已提交
6167

6168 6169 6170 6171 6172
  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;
6173
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6174
    g_Dbs.queryMode = g_args.mode;
6175

6176 6177 6178 6179
    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;
6180
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6181 6182 6183
            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);
6184
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6185
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6186
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6187

6188
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6189
    g_Dbs.db[0].superTbls[0].maxSqlLen = TSDB_PAYLOAD_SIZE;
6190

6191 6192 6193 6194 6195
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6196

6197
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6198
              data_type[i], MAX_TB_NAME_SIZE);
6199
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6200 6201
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6202

6203 6204 6205 6206 6207
    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);
6208
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6209 6210 6211
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6212

6213
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6214
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6215

6216
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6217 6218
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6219
  } else {
6220 6221
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6222
  }
6223 6224 6225 6226 6227 6228
}

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

6230 6231 6232
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6233 6234 6235
    exit(-1);
  }

6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259
  /* 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);
}

6260
static void querySqlFile(TAOS* taos, char* sqlFile)
6261 6262 6263 6264 6265 6266
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6267

6268 6269 6270 6271 6272 6273 6274
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

  double t = getCurrentTime();
6275

6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288
  while ((read_len = tgetline(&line, &line_len, fp)) != -1) {
    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;
6289
    }
6290 6291

    memcpy(cmd + cmd_len, line, read_len);
6292
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
6293 6294 6295
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
6296 6297 6298 6299 6300
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
6301 6302
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
6303 6304
  }

6305 6306
  t = getCurrentTime() - t;
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6307

6308 6309 6310 6311
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6312 6313
}

6314
static void testMetaFile() {
6315
    if (INSERT_TEST == g_args.test_mode) {
6316 6317
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6318

6319
      insertTestProcess();
6320

6321
    } else if (QUERY_TEST == g_args.test_mode) {
6322 6323
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6324

6325
      queryTestProcess();
6326

6327
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
6328 6329
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6330

6331
      subscribeTestProcess();
6332

6333 6334 6335
    }  else {
      ;
    }
6336
}
6337

6338
static void queryResult() {
6339 6340 6341
    // select
    if (false == g_Dbs.insert_only) {
      // query data
6342

6343 6344 6345
      pthread_t read_id;
      threadInfo *rInfo = malloc(sizeof(threadInfo));
      rInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
6346
      rInfo->start_table_from = 0;
6347

6348
      //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
6349
      if (g_args.use_metric) {
6350 6351
        rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
        rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
6352
        rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
6353 6354
        tstrncpy(rInfo->tb_prefix,
              g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
6355
      } else {
6356 6357
        rInfo->ntables = g_args.num_of_tables;
        rInfo->end_table_to = g_args.num_of_tables -1;
6358
        tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
6359 6360
      }

6361
      rInfo->taos = taos_connect(
6362 6363 6364 6365
              g_Dbs.host,
              g_Dbs.user,
              g_Dbs.password,
              g_Dbs.db[0].dbName,
6366
              g_Dbs.port);
6367
      if (rInfo->taos == NULL) {
6368 6369
        errorPrint( "Failed to connect to TDengine, reason:%s\n",
                taos_errstr(NULL));
6370 6371 6372 6373
        free(rInfo);
        exit(-1);
      }

6374
      tstrncpy(rInfo->fp, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
6375 6376 6377 6378 6379 6380 6381 6382 6383

      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);
H
hzcheng 已提交
6384
    }
6385 6386
}

6387 6388
static void testCmdLine() {

6389 6390
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
6391

6392 6393 6394 6395
  if (g_Dbs.insert_only)
    return;
  else
    queryResult();
6396 6397
}

6398 6399 6400
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

6401
  debugPrint("meta file: %s\n", g_args.metaFile);
6402 6403 6404

  if (g_args.metaFile) {
    initOfInsertMeta();
6405
    initOfQueryMeta();
6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418

    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(
6419 6420 6421 6422
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
6423
          g_Dbs.port);
6424
      querySqlFile(qtaos, g_args.sqlFile);
6425 6426 6427 6428 6429
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
6430
  }
6431 6432

  return 0;
H
hzcheng 已提交
6433
}
6434