taosdemo.c 216.1 KB
Newer Older
S
TD-1057  
Shengliang Guan 已提交
1
/*
H
hzcheng 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15
 * Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
 *
 * This program is free software: you can use, redistribute, and/or modify
 * it under the terms of the GNU Affero General Public License, version 3
 * or later ("AGPL"), as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

16 17 18 19 20

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

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

351
typedef struct SpecifiedQueryInfo_S {
352 353 354 355 356
  int          rate;  // 0: unlimit  > 0   loop/s
  int          concurrent;
  int          sqlCount;
  int          subscribeMode; // 0: sync, 1: async
  int          subscribeInterval; // ms
357
  int          queryTimes;
358 359
  int          subscribeRestart;
  int          subscribeKeepProgress;
360
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
361
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
362
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
363
} SpecifiedQueryInfo;
364

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

381
  char*        childTblName;
382
} SuperQueryInfo;
383 384

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

393 394
  SpecifiedQueryInfo  specifiedQueryInfo;
  SuperQueryInfo    superQueryInfo;
395 396 397 398 399
} SQueryMetaInfo;

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

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

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

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

433 434
} threadInfo;

435
#ifdef WINDOWS
436 437
#define _CRT_RAND_S

438
#include <windows.h>
439 440 441 442 443
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

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

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

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

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

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

484
static int taosRandom()
485 486 487 488 489 490
{
    int number;
    rand_s(&number);

    return number;
}
491
#else
492
static void setupForAnsiEscape(void) {}
493

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

499 500
#include <time.h>

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

507 508
#endif

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

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

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

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

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

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

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


598
///////////////////////////////////////////////////
H
hzcheng 已提交
599

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

602 603 604 605 606 607 608 609
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

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

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

692
static void parse_args(int argc, char *argv[], SArguments *arguments) {
693
  char **sptr;
694 695 696 697 698 699 700 701
  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) {
702
          errorPrint( "Invalid path %s\n", configPath);
703 704 705 706
          return;
      }
      taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
      wordfree(&full_path);
707

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

843 844
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
          || arguments->verbose_print) {
845
    printf("###################################################################\n");
846
    printf("# meta file:                         %s\n", arguments->metaFile);
847
    printf("# Server IP:                         %s:%hu\n",
848 849 850 851 852
            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");
853 854 855 856 857 858 859 860 861
    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");
    }
862
    printf("# Insertion interval:                %d\n", arguments->insert_interval);
863
    printf("# Number of records per req:         %d\n", arguments->num_of_RPR);
864
    printf("# Max SQL length:                    %d\n", arguments->max_sql_len);
865
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
866 867 868 869 870 871 872 873
    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);
874

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

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

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

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

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

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

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

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

938
  taos_free_result(res);
939 940
  return 0;
}
H
hzcheng 已提交
941

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

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

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

969 970 971 972 973 974
  // 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 已提交
975
    }
976 977 978 979 980 981
    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 已提交
982 983
  }

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

989 990 991 992 993 994
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 已提交
995
  }
996

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

1001
static double getCurrentTime() {
1002 1003 1004 1005
  struct timeval tv;
  if (gettimeofday(&tv, NULL) != 0) {
    perror("Failed to get current time in ms");
    return 0.0;
H
hzcheng 已提交
1006
  }
S
Shuduo Sang 已提交
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 1048 1049
  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;
1050
  return randfloat[cursor];
1051 1052 1053
}

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

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

1104
static int printfInsertMeta() {
1105 1106
    SHOW_PARSE_RESULT_START();

1107 1108 1109 1110 1111 1112
  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);
1113 1114
  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);
1115
  printf("max sql length:             \033[33m%d\033[0m\n", g_args.max_sql_len);
1116 1117

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

1119 1120
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1121
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1122
    if (0 == g_Dbs.db[i].drop) {
1123 1124 1125
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
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 1163 1164
    }

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

    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);
1178 1179

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

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

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

      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);
      }
1204
      if (g_Dbs.db[i].superTbls[j].childTblOffset >= 0) {
1205 1206 1207
        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);
1208 1209

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

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

  SHOW_PARSE_RESULT_END();
1270 1271

  return 0;
1272 1273 1274
}

static void printfInsertMetaToFile(FILE* fp) {
1275 1276

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1277

1278 1279 1280 1281 1282
  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);
1283 1284
  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);
1285
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1286

1287 1288
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1289
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1290
    if (0 == g_Dbs.db[i].drop) {
1291
      fprintf(fp, "  drop:                  no\n");
1292
    }else {
1293
      fprintf(fp, "  drop:                  yes\n");
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 1331 1332
    }

    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) {
1333 1334
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1335 1336 1337 1338 1339 1340 1341 1342 1343
        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);
1344 1345

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

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

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

      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);
1368 1369 1370 1371
      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);
      }
1372 1373

      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1374
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1375
      }else {
1376
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1377
      }
1378 1379
      fprintf(fp, "      interlaceRows:     %d\n",  g_Dbs.db[i].superTbls[j].interlaceRows);
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1380
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1381 1382 1383 1384
      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);
1385
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1386 1387 1388
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

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

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

1425
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1426 1427 1428
}

static void printfQueryMeta() {
1429

1430
  SHOW_PARSE_RESULT_START();
1431

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

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

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

1461
  if (SUBSCRIBE_TEST == g_args.test_mode) {
1462 1463 1464 1465
    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);
1466
  }
1467

1468 1469 1470
  printf("sqlCount:       \033[33m%d\033[0m\n", g_queryInfo.superQueryInfo.sqlCount);
  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]);
1471
  }
1472
  printf("\n");
1473

1474
  SHOW_PARSE_RESULT_END();
1475 1476
}

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

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

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 1545 1546
  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:
1547
      formatTimestamp(buf, *(int64_t*)val, precision);
1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562
      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) {
1563
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577
    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);
1578

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

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

  res = taos_query(taos, "show databases;");
1605
  int32_t code = taos_errno(res);
1606

1607
  if (code != 0) {
1608
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
    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) {
1620
      errorPrint( "failed to allocate memory for some dbInfo[%d]\n", count);
1621 1622 1623
      return -1;
    }

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

1635
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1636
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1637 1638 1639 1640 1641 1642 1643 1644 1645
    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]));

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

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

  return count;
}

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

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

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

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

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

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

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

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

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

    char *url = "/rest/sql";

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

1767 1768 1769 1770
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

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

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

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

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

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

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

1828 1829 1830
    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) {
1831
        free(request_buf);
1832
        ERROR_EXIT("ERROR connecting");
1833
    }
1834

1835 1836 1837
    memset(base64_buf, 0, INPUT_BUF_LEN);

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

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

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

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

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

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

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

    return 0;
}

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

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

1931 1932 1933
  return dataBuf;
}

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

1953 1954 1955 1956 1957 1958 1959
      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);
1960 1961
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
              "\'%s\', ", buf);
1962
      tmfree(buf);
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 1993 1994
    } 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());
1995 1996 1997 1998 1999 2000
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2001

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

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

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

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

2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071
    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;
2072

2073 2074 2075 2076
  return 0;
}


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

2081
  char command[BUFFER_SIZE] = "\0";
2082 2083
  char limitBuf[100] = "\0";

2084
  TAOS_RES * res;
2085 2086 2087
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2088 2089 2090 2091 2092

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

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

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

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

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

2145 2146 2147 2148 2149 2150 2151
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

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

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

2161 2162
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2163

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

2169
  //get schema use cmd: describe superTblName;
2170
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2171
  res = taos_query(taos, command);
2172 2173 2174
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2175
    taos_free_result(res);
2176 2177 2178 2179 2180 2181 2182 2183 2184 2185
    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;
2186
    }
2187 2188

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

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

  calcRowLen(superTbls);

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

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

2245 2246 2247 2248 2249 2250 2251
  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;
2252
 
2253
    if (strcasecmp(dataType, "BINARY") == 0) {
2254 2255 2256
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbls->columns[colIndex].dataLen);
2257 2258
      lenOfOneRow += superTbls->columns[colIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2259 2260 2261
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbls->columns[colIndex].dataLen);
2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280
      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;
2281
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2282 2283
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2284
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297
      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
2298 2299
  superTbls->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbls->colsOfCreateChildTable) {
2300 2301 2302 2303
    printf("Failed when calloc, size:%d", len+1);
    taos_close(taos);
    exit(-1);
  }
2304
  snprintf(superTbls->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2305
  verbosePrint("%s() LN%d: %s\n", __func__, __LINE__, superTbls->colsOfCreateChildTable);
2306 2307 2308 2309 2310 2311 2312 2313 2314 2315

  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;
2316

2317
      if (strcasecmp(dataType, "BINARY") == 0) {
2318 2319
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
                "BINARY", superTbls->tags[tagIndex].dataLen);
2320 2321
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
      } else if (strcasecmp(dataType, "NCHAR") == 0) {
2322 2323
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
                "NCHAR", superTbls->tags[tagIndex].dataLen);
2324 2325
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 3;
      } else if (strcasecmp(dataType, "INT") == 0)  {
2326 2327
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "INT");
2328 2329
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 11;
      } else if (strcasecmp(dataType, "BIGINT") == 0)  {
2330 2331
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "BIGINT");
2332 2333
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 21;
      } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
2334 2335
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "SMALLINT");
2336 2337
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
      } else if (strcasecmp(dataType, "TINYINT") == 0)  {
2338 2339
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "TINYINT");
2340 2341
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 4;
      } else if (strcasecmp(dataType, "BOOL") == 0)  {
2342 2343
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "BOOL");
2344 2345
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 6;
      } else if (strcasecmp(dataType, "FLOAT") == 0) {
2346 2347
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "FLOAT");
2348 2349
        lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 22;
      } else if (strcasecmp(dataType, "DOUBLE") == 0) { 
2350 2351
        len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
                "DOUBLE");
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362
        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;
2363 2364 2365 2366

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

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

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

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

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

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

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

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

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

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

  taos_close(taos);
  return 0;
}

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

  int64_t  lastPrintTime = taosGetTimestampMs();

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

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

  int len = 0;
  int batchNum = 0;
2530

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

  for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) {
2536
    if (0 == g_Dbs.use_metric) {
2537
      snprintf(buffer, buff_len,
2538 2539
              "create table if not exists %s.%s%d %s;",
              winfo->db_name,
2540 2541
              g_args.tb_prefix, i,
              winfo->cols);
2542
    } else {
2543 2544 2545
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
                  __func__, __LINE__);
2546
        free(buffer);
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 2581 2582
        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;
        }
2583 2584 2585 2586
      }
    }

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

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

2609 2610 2611 2612
  free(buffer);
  return NULL;
}

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

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

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

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

  return 0;
2680 2681
}

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

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

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

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

2727
        len = snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
2728

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

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

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

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

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

2772
  while ((readLen = tgetline(&line, &n, fp)) != -1) {
2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784
    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) {
2785 2786
      char *tmp = realloc(tagDataBuf,
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
2787 2788 2789
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
2790 2791
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
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 2817 2818
      } 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
*/
2819 2820
static int readSampleFromCsvFileToMem(
        SSuperTable* superTblInfo) {
2821 2822 2823 2824
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
2825

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

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

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

    if (readLen == 0) {
      continue;
    }

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

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

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

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

2874
  fclose(fp);
2875 2876 2877 2878
  tmfree(line);
  return 0;
}

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

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

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

2905
  //superTbls->columnCount = columnSize;
2906 2907 2908 2909 2910 2911 2912
  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) {
2913
      count = countObj->valueint;
2914
    } else if (countObj && countObj->type != cJSON_Number) {
2915
      errorPrint("%s() LN%d, failed to read json, column count not found\n", __func__, __LINE__);
2916 2917 2918 2919 2920 2921 2922 2923 2924
      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) {
2925
      errorPrint("%s() LN%d: failed to read json, column type not found\n", __func__, __LINE__);
2926 2927
      goto PARSE_OVER;
    }
2928 2929
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
2930

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

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

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

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

2970 2971 2972
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
2973
      count = countObj->valueint;
2974
    } else if (countObj && countObj->type != cJSON_Number) {
2975
      printf("ERROR: failed to read json, column count not found\n");
2976 2977 2978 2979 2980 2981 2982 2983 2984
      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) {
2985
      printf("ERROR: failed to read json, tag type not found\n");
2986 2987
      goto PARSE_OVER;
    }
2988
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
2989

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

3000
    for (int n = 0; n < count; ++n) {
3001
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType, MAX_TB_NAME_SIZE);
3002
      superTbls->tags[index].dataLen = columnCase.dataLen;
3003 3004
      index++;
    }
3005
  }
3006 3007 3008 3009 3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021
  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) {
3022
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3023 3024 3025 3026
  }

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

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

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

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

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

3084 3085 3086 3087 3088 3089 3090 3091 3092
  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;
  }
3093

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

    // 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;
    }
3108
  } else if (!interlaceRows) {
3109
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3110
  } else {
3111
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n", __func__, __LINE__);
3112
    goto PARSE_OVER;
3113
  }
3114

3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
  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;
  }

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

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

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3161
    errorPrint(
3162 3163
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174
    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) {
3175
      printf("ERROR: failed to read json, dbinfo not found\n");
3176 3177
      goto PARSE_OVER;
    }
3178

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3418 3419 3420
      if (childTblExists
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3421 3422 3423 3424 3425 3426 3427 3428 3429 3430
        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 {
3431 3432
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
                __func__, __LINE__);
3433 3434
        goto PARSE_OVER;
      }
3435

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

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

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

3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489
      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;
      }

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

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

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

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

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

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

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

3598 3599 3600
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3601 3602 3603 3604 3605 3606 3607 3608 3609 3610
        // 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;
        }
3611 3612
      } 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
3613
      } else {
3614 3615 3616
        errorPrint(
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3617
        goto PARSE_OVER;
3618
      }
3619 3620 3621 3622 3623 3624 3625

      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 {
3626
        printf("ERROR: failed to read json, disorderRatio not found\n");
3627
        goto PARSE_OVER;
3628
      }
3629 3630 3631 3632 3633 3634 3635

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

3640 3641 3642 3643 3644 3645
      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 {
3646 3647
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658
        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 {
3659 3660
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
3661 3662 3663
        goto PARSE_OVER;
      }

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

  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) {
3686
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3687 3688 3689 3690
  }

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

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

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

3737 3738 3739 3740 3741 3742 3743 3744 3745 3746
  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;
  }

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

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

3765
  // super_table_query 
3766 3767 3768 3769 3770
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
3771
    printf("ERROR: failed to read json, super_table_query not found\n");
3772
    goto PARSE_OVER;
3773
  } else {
3774
    cJSON* rate = cJSON_GetObjectItem(specifiedQuery, "query_interval");
3775
    if (rate && rate->type == cJSON_Number) {
3776
      g_queryInfo.specifiedQueryInfo.rate = rate->valueint;
3777
    } else if (!rate) {
3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788
      g_queryInfo.specifiedQueryInfo.rate = 0;
    }

    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery, "query_times");
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n", __func__, __LINE__);
      goto PARSE_OVER;
3789
    }
3790

3791
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
3792
    if (concurrent && concurrent->type == cJSON_Number) {
3793
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
3794
    } else if (!concurrent) {
3795
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
3796
    }
3797

3798
    cJSON* mode = cJSON_GetObjectItem(specifiedQuery, "mode");
3799
    if (mode && mode->type == cJSON_String && mode->valuestring != NULL) {
3800
      if (0 == strcmp("sync", mode->valuestring)) {
3801
        g_queryInfo.specifiedQueryInfo.subscribeMode = 0;
3802
      } else if (0 == strcmp("async", mode->valuestring)) {
3803
        g_queryInfo.specifiedQueryInfo.subscribeMode = 1;
3804
      } else {
3805
        printf("ERROR: failed to read json, subscribe mod error\n");
3806 3807 3808
        goto PARSE_OVER;
      }
    } else {
3809
      g_queryInfo.specifiedQueryInfo.subscribeMode = 0;
3810
    }
3811

3812
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
3813
    if (interval && interval->type == cJSON_Number) {
3814
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
3815
    } else if (!interval) {
3816 3817
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
3818
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
3819
    }
3820

3821
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
3822
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
3823
      if (0 == strcmp("yes", restart->valuestring)) {
3824
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
3825
      } else if (0 == strcmp("no", restart->valuestring)) {
3826
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
3827
      } else {
3828
        printf("ERROR: failed to read json, subscribe restart error\n");
3829 3830 3831
        goto PARSE_OVER;
      }
    } else {
3832
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
3833
    }
3834

3835
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
3836 3837 3838
    if (keepProgress
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
3839
      if (0 == strcmp("yes", keepProgress->valuestring)) {
3840
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
3841
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
3842
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
3843
      } else {
3844
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
3845 3846 3847
        goto PARSE_OVER;
      }
    } else {
3848
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
3849 3850
    }

3851
    // sqls
3852
    cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
3853
    if (!superSqls) {
3854
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
3855
    } else if (superSqls->type != cJSON_Array) {
3856
      printf("ERROR: failed to read json, super sqls not found\n");
3857
      goto PARSE_OVER;
3858
    } else {
3859 3860
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
3861
        printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT);
3862 3863
        goto PARSE_OVER;
      }
3864

3865
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
3866 3867 3868
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
3869

3870 3871
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
3872
          printf("ERROR: failed to read json, sql not found\n");
3873 3874
          goto PARSE_OVER;
        }
3875
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
3876

3877 3878
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
3879
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
3880
        } else if (NULL == result) {
3881
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
3882
        } else {
3883
          printf("ERROR: failed to read json, super query result file not found\n");
3884
          goto PARSE_OVER;
3885
        }
3886 3887 3888
      }
    }
  }
3889

3890
  // sub_table_query 
3891 3892 3893 3894 3895
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
    g_queryInfo.superQueryInfo.threadCnt = 0;
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
3896
    printf("ERROR: failed to read json, sub_table_query not found\n");
3897 3898
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
3899
  } else {
3900
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
3901
    if (subrate && subrate->type == cJSON_Number) {
3902
      g_queryInfo.superQueryInfo.rate = subrate->valueint;
3903
    } else if (!subrate) {
3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914
      g_queryInfo.superQueryInfo.rate = 0;
    }

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

3917
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
3918
    if (threads && threads->type == cJSON_Number) {
3919
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
3920
    } else if (!threads) {
3921
      g_queryInfo.superQueryInfo.threadCnt = 1;
3922
    }
3923

3924
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
3925
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
3926
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
3927
    //} else if (!subTblCnt) {
3928
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
3929
    //}
3930

3931
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
3932
    if (stblname && stblname->type == cJSON_String && stblname->valuestring != NULL) {
3933
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring, MAX_TB_NAME_SIZE);
3934
    } else {
3935
      printf("ERROR: failed to read json, super table name not found\n");
3936 3937
      goto PARSE_OVER;
    }
3938

3939
    cJSON* submode = cJSON_GetObjectItem(superQuery, "mode");
3940
    if (submode && submode->type == cJSON_String && submode->valuestring != NULL) {
3941
      if (0 == strcmp("sync", submode->valuestring)) {
3942
        g_queryInfo.superQueryInfo.subscribeMode = 0;
3943
      } else if (0 == strcmp("async", submode->valuestring)) {
3944
        g_queryInfo.superQueryInfo.subscribeMode = 1;
3945
      } else {
3946
        printf("ERROR: failed to read json, subscribe mod error\n");
3947 3948 3949
        goto PARSE_OVER;
      }
    } else {
3950
      g_queryInfo.superQueryInfo.subscribeMode = 0;
3951
    }
3952

3953
    cJSON* subinterval = cJSON_GetObjectItem(superQuery, "interval");
3954
    if (subinterval && subinterval->type == cJSON_Number) {
3955
      g_queryInfo.superQueryInfo.subscribeInterval = subinterval->valueint;
3956 3957 3958
    } else if (!subinterval) {    
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
3959
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
3960
    }
3961

3962
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
3963
    if (subrestart && subrestart->type == cJSON_String && subrestart->valuestring != NULL) {
3964
      if (0 == strcmp("yes", subrestart->valuestring)) {
3965
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
3966
      } else if (0 == strcmp("no", subrestart->valuestring)) {
3967
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
3968
      } else {
3969
        printf("ERROR: failed to read json, subscribe restart error\n");
3970 3971 3972
        goto PARSE_OVER;
      }
    } else {
3973
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
3974
    }
3975

3976
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
3977 3978 3979
    if (subkeepProgress &&
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
3980
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
3981
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
3982
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
3983
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
3984
      } else {
3985
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
3986 3987 3988
        goto PARSE_OVER;
      }
    } else {
3989
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
3990
    }
3991

3992
    // sqls
3993
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
3994
    if (!subsqls) {
3995
      g_queryInfo.superQueryInfo.sqlCount = 0;
3996
    } else if (subsqls->type != cJSON_Array) {
3997
      printf("ERROR: failed to read json, super sqls not found\n");
3998
      goto PARSE_OVER;
3999
    } else {
4000 4001
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4002
        printf("ERROR: failed to read json, query sql size overflow, max is %d\n", MAX_QUERY_SQL_COUNT);
4003 4004
        goto PARSE_OVER;
      }
4005

4006
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4007
      for (int j = 0; j < superSqlSize; ++j) {
4008 4009
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4010

4011 4012
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4013
          printf("ERROR: failed to read json, sql not found\n");
4014 4015
          goto PARSE_OVER;
        }
4016
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
4017 4018 4019

        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (result != NULL && result->type == cJSON_String && result->valuestring != NULL){
4020
          tstrncpy(g_queryInfo.superQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4021
        } else if (NULL == result) {
4022
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4023
        }  else {
4024
          printf("ERROR: failed to read json, sub query result file not found\n");
4025
          goto PARSE_OVER;
4026
        }
4027 4028
      }
    }
H
hzcheng 已提交
4029 4030
  }

4031
  ret = true;
H
hzcheng 已提交
4032

4033 4034 4035 4036 4037 4038
PARSE_OVER:
  //free(content);
  //cJSON_Delete(root);
  //fclose(fp);
  return ret;
}
H
hzcheng 已提交
4039

4040
static bool getInfoFromJsonFile(char* file) {
4041
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4042

4043 4044 4045 4046 4047
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4048

4049 4050 4051 4052 4053 4054 4055 4056 4057
  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 已提交
4058
  }
H
Hui Li 已提交
4059

4060 4061 4062
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4063
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4064 4065
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4066

4067 4068 4069
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4070
      g_args.test_mode = INSERT_TEST;
4071
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4072
      g_args.test_mode = QUERY_TEST;
4073
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4074
      g_args.test_mode = SUBSCRIBE_TEST;
4075
    } else {
4076
      printf("ERROR: failed to read json, filetype not support\n");
4077 4078 4079
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4080
    g_args.test_mode = INSERT_TEST;
4081
  } else {
4082
    printf("ERROR: failed to read json, filetype not found\n");
4083 4084
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4085

4086
  if (INSERT_TEST == g_args.test_mode) {
4087
    ret = getMetaFromInsertJsonFile(root);
4088 4089
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4090 4091
    ret = getMetaFromQueryJsonFile(root);
  } else {
4092 4093
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4094
    goto PARSE_OVER;
4095
  }
4096 4097 4098 4099

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4100
  fclose(fp);
4101 4102
  return ret;
}
H
hzcheng 已提交
4103

4104
static void prepareSampleData() {
4105
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4106 4107 4108
    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 已提交
4109
      }
4110 4111 4112 4113
    }
  }
}

4114
static void postFreeResource() {
4115
  tmfclose(g_fpOfInsertResult);
4116
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4117
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4118 4119 4120
      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 已提交
4121
      }
4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133
      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 已提交
4134
    }
4135 4136
  }
}
S
Shuaiqiang Chang 已提交
4137

4138 4139
static int getRowDataFromSample(char*  dataBuf, int maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int* sampleUsePos) {
4140
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4141
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4142
    if (0 != ret) {
4143
      tmfree(superTblInfo->sampleDataBuf);
4144
      superTblInfo->sampleDataBuf = NULL;
4145 4146
      return -1;
    }
4147
*/
4148 4149
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4150

4151
  int    dataLen = 0;
4152

4153 4154 4155 4156
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "(%" PRId64 ", ", timestamp);
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4157
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4158

4159
  (*sampleUsePos)++;
4160
 
4161 4162
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4163

4164
static int generateRowData(char*  dataBuf, int maxLen, int64_t timestamp, SSuperTable* stbInfo) {
4165 4166
  int    dataLen = 0;
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "(%" PRId64 ", ", timestamp);
4167
  for (int i = 0; i < stbInfo->columnCount; i++) {
4168 4169
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "binary", 6))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "nchar", 5))) {
4170
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4171
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4172
                (uint32_t)TSDB_MAX_BINARY_LEN);
4173 4174
        return (-1);
      }
4175

4176 4177
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4178
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4179 4180 4181 4182 4183
        return (-1);
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
      dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, "\'%s\', ", buf);
      tmfree(buf);
4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201
    } 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)) {
4202 4203 4204 4205 4206 4207 4208 4209
      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 {
4210
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4211 4212
      return (-1);
    }
S
Shuaiqiang Chang 已提交
4213
  }
4214

4215 4216
  dataLen -= 2;
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
4217

4218 4219
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4220

4221
static int32_t generateData(char *res, char **data_type,
4222
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253
  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) {
4254
      bool b = taosRandom() & 1;
4255 4256
      pstr += sprintf(pstr, ", %s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "binary") == 0) {
4257 4258
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4259 4260 4261
      pstr += sprintf(pstr, ", \"%s\"", s);
      free(s);
    }else if (strcasecmp(data_type[i % c], "nchar") == 0) {
4262 4263
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278
      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);
}

4279
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4280 4281
  char* sampleDataBuf = NULL;

4282
  sampleDataBuf = calloc(
4283
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4284
  if (sampleDataBuf == NULL) {
4285 4286
      errorPrint("%s() LN%d, Failed to calloc %d Bytes, reason:%s\n", 
              __func__, __LINE__,
4287 4288
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 
              strerror(errno));
4289
      return -1;
4290
  }
4291

4292 4293 4294 4295
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4296
      errorPrint("%s() LN%d, read sample from csv file failed.\n", __func__, __LINE__);
4297
      tmfree(sampleDataBuf);
4298
      superTblInfo->sampleDataBuf = NULL;
4299
      return -1;
H
Hui Li 已提交
4300
  }
4301

4302 4303 4304
  return 0;
}

4305
static int execInsert(threadInfo *pThreadInfo, char *buffer, int k)
4306 4307
{
  int affectedRows;
4308
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4309

4310 4311
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, buffer);
4312
  if (superTblInfo) {
4313
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4314
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4315
    } else {
4316
      if (0 != postProceSql(g_Dbs.host, g_Dbs.port, buffer)) {
4317
        affectedRows = -1;
4318
        printf("========restful return fail, threadID[%d]\n", pThreadInfo->threadID);
4319 4320 4321
      } else {
        affectedRows = k;
      }
4322
    }
4323
  } else {
4324
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4325 4326 4327 4328 4329
  }

  return affectedRows;
}

4330
static void getTableName(char *pTblName, threadInfo* pThreadInfo, int tableSeq)
4331 4332
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4333 4334 4335 4336 4337 4338
  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 {
4339

4340 4341 4342
        verbosePrint("[%d] %s() LN%d: from=%d count=%d seq=%d\n",
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
4343 4344 4345 4346 4347 4348
                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",
4349
        g_args.tb_prefix, tableSeq);
4350 4351 4352 4353
  }
}

static int generateDataTail(char *tableName, int32_t tableSeq,
4354
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
4355 4356 4357
        int batch, char* buffer, int64_t insertRows,
        int64_t startFrom, uint64_t startTime, int *pSamplePos, int *dataLen) {
  int len = 0;
4358 4359
  int ncols_per_record = 1; // count first col ts

4360
  if (superTblInfo == NULL) {
4361 4362 4363 4364 4365
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
4366 4367
  }

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

4370 4371
  int k = 0;
  for (k = 0; k < batch;) {
4372
    if (superTblInfo) {
4373
        int retLen = 0;
4374

4375 4376 4377
        if (0 == strncasecmp(superTblInfo->dataSource,
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
4378 4379
                    buffer + len,
                    superTblInfo->maxSqlLen - len,
4380
                    startTime + superTblInfo->timeStampStep * k,
4381
                    superTblInfo,
4382
                    pSamplePos);
4383 4384 4385
       } else if (0 == strncasecmp(superTblInfo->dataSource,
                   "rand", strlen("rand"))) {
          int rand_num = rand_tinyint() % 100;
4386
          if (0 != superTblInfo->disorderRatio
4387
                    && rand_num < superTblInfo->disorderRatio) {
4388 4389 4390
            int64_t d = startTime
                + superTblInfo->timeStampStep * k
                - taosRandom() % superTblInfo->disorderRange;
4391
            retLen = generateRowData(
4392
                      buffer + len,
4393
                      superTblInfo->maxSqlLen - len,
4394
                      d,
4395
                      superTblInfo);
4396 4397
          } else {
            retLen = generateRowData(
4398 4399
                      buffer + len,
                      superTblInfo->maxSqlLen - len,
4400
                      startTime + superTblInfo->timeStampStep * k,
4401
                      superTblInfo);
4402 4403
          }
       }
4404

4405 4406 4407
       if (retLen < 0) {
         return -1;
       }
4408

4409
       len += retLen;
4410

4411 4412 4413 4414
       if (len >= (superTblInfo->maxSqlLen - 256)) {    // reserve for overwrite
         k++;
         break;
       }
4415
    } else {
4416
      int rand_num = taosRandom() % 100;
4417 4418 4419 4420
          char data[MAX_DATA_SIZE];
          char **data_type = g_args.datatype;
          int lenOfBinary = g_args.len_of_binary;

4421
      if ((g_args.disorderRatio != 0)
4422
                && (rand_num < g_args.disorderRange)) {
4423

4424 4425
        int64_t d = startTime + DEFAULT_TIMESTAMP_STEP * k 
            - taosRandom() % 1000000 + rand_num;
4426
        len = generateData(data, data_type,
4427
                  ncols_per_record, d, lenOfBinary);
4428
      } else {
4429
            len = generateData(data, data_type,
4430
                  ncols_per_record,
4431
                  startTime + DEFAULT_TIMESTAMP_STEP * k,
4432 4433
                  lenOfBinary);
      }
4434

4435 4436
      buffer += sprintf(buffer, " %s", data);
      if (strlen(buffer) >= (g_args.max_sql_len - 256)) { // too long
4437 4438
          k++;
          break;
4439 4440 4441
      }
    }

4442 4443
    verbosePrint("%s() LN%d len=%d k=%d \nbuffer=%s\n",
            __func__, __LINE__, len, k, buffer);
4444 4445 4446

    k++;
    startFrom ++;
4447

4448
    if (startFrom >= insertRows) {
4449
      break;
4450
    }
4451
  }
4452

4453 4454 4455
  *dataLen = len;
  return k;
}
4456

4457 4458
static int generateSQLHead(char *tableName, int32_t tableSeq,
        threadInfo* pThreadInfo, SSuperTable* superTblInfo, char *buffer)
4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471
{
  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) {
4472
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n", __func__, __LINE__);
4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489
        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,
4490
                  tableName);
4491 4492
    } else {
      len = snprintf(buffer,
4493
                  superTblInfo->maxSqlLen,
4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508
                  "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;
}

4509
static int generateProgressiveDataBuffer(char *pTblName,
4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532
        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;

4533 4534
  int headLen = generateSQLHead(pTblName, tableSeq, pThreadInfo, superTblInfo,
          buffer);
4535 4536 4537 4538 4539
  pstr += headLen;

  int k;
  int dataLen;
  k = generateDataTail(pTblName, tableSeq, pThreadInfo, superTblInfo,
4540 4541
          g_args.num_of_RPR, pstr, insertRows, startFrom,
          startTime,
4542
          pSamplePos, &dataLen);
4543 4544
  return k;
}
4545

4546
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
4547 4548
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
4549 4550

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562
  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
  //
4563 4564 4565

  char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1);
  if (NULL == buffer) {
4566
    errorPrint( "Failed to alloc %d Bytes, reason:%s\n",
4567 4568 4569 4570 4571 4572
              superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len,
              strerror(errno));
    return NULL;
  }


4573
  char tableName[TSDB_TABLE_NAME_LEN];
4574 4575 4576 4577 4578

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

  int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
4579 4580
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4581 4582 4583 4584 4585 4586 4587 4588 4589
  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;

4590 4591
  debugPrint("[%d] %s() LN%d: start_table_from=%d ntables=%d insertRows=%"PRId64"\n",
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
4592 4593 4594 4595 4596
          pThreadInfo->ntables, insertRows);

  int64_t startTime = pThreadInfo->start_time;

  int batchPerTblTimes;
4597
  int batchPerTbl;
4598

4599 4600
  assert(pThreadInfo->ntables > 0);

4601 4602
  if (interlaceRows > g_args.num_of_RPR)
        interlaceRows = g_args.num_of_RPR;
4603

4604 4605
  batchPerTbl = interlaceRows;
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
4606
    batchPerTblTimes =
4607
        (g_args.num_of_RPR / (interlaceRows * pThreadInfo->ntables)) + 1;
4608 4609 4610 4611
  } else {
    batchPerTblTimes = 1;
  }

4612
  int generatedRecPerTbl = 0;
4613 4614
  bool flagSleep = true;
  int sleepTimeTotal = 0;
4615
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
4616
    if ((flagSleep) && (insert_interval)) {
4617
        st = taosGetTimestampUs();
4618
        flagSleep = false;
4619 4620 4621
    }
    // generate data
    memset(buffer, 0, superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len);
4622

4623
    char *pstr = buffer;
4624
    int recOfBatch = 0;
4625

4626 4627
    for (int i = 0; i < batchPerTblTimes; i ++) {
      getTableName(tableName, pThreadInfo, tableSeq);
4628

4629 4630
      int headLen;
      if (i == 0) {
4631 4632
        headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
                superTblInfo, pstr);
4633
      } else {
4634
        headLen = snprintf(pstr, TSDB_TABLE_NAME_LEN, "%s.%s values",
4635 4636
                  pThreadInfo->db_name,
                  tableName);
4637
      }
4638

4639
      // generate data buffer
4640 4641
      verbosePrint("[%d] %s() LN%d i=%d buffer:\n%s\n",
                pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4642

4643 4644
      pstr += headLen;
      int dataLen = 0;
4645

4646
      verbosePrint("[%d] %s() LN%d i=%d batchPerTblTimes=%d batchPerTbl = %d\n",
4647 4648
                pThreadInfo->threadID, __func__, __LINE__,
                i, batchPerTblTimes, batchPerTbl);
4649 4650 4651 4652 4653 4654 4655

      if (superTblInfo) {
        if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
          startTime = taosGetTimestamp(pThreadInfo->time_precision);
        }
      } else {
          startTime = 1500000000000;
4656
      }
4657 4658 4659
      generateDataTail(
        tableName, tableSeq, pThreadInfo, superTblInfo,
        batchPerTbl, pstr, insertRows, 0,
4660
        startTime,
4661
        &(pThreadInfo->samplePos), &dataLen);
4662

4663
      pstr += dataLen;
4664
      recOfBatch += batchPerTbl;
4665
      startTime += batchPerTbl * superTblInfo->timeStampStep;
4666
      pThreadInfo->totalInsertRows += batchPerTbl;
4667
      verbosePrint("[%d] %s() LN%d batchPerTbl=%d recOfBatch=%d\n",
4668 4669
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
4670

4671 4672 4673 4674
      tableSeq ++;
      if (insertMode == INTERLACE_INSERT_MODE) {
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
4675
            startTime += batchPerTbl * superTblInfo->timeStampStep;
4676
            tableSeq = pThreadInfo->start_table_from;
4677 4678 4679 4680 4681 4682 4683
            generatedRecPerTbl += batchPerTbl;
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
4684
          }
4685 4686
      }

4687
      int remainRows = insertRows - generatedRecPerTbl;
4688
      if ((remainRows > 0) && (batchPerTbl > remainRows))
4689 4690
        batchPerTbl = remainRows;

4691
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%d insertRows=%"PRId64"\n",
4692 4693 4694 4695
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
4696 4697 4698
        break;
    }

4699
    verbosePrint("[%d] %s() LN%d recOfBatch=%d totalInsertRows=%"PRId64"\n",
4700 4701 4702 4703 4704
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
           pThreadInfo->threadID, __func__, __LINE__, buffer);

4705 4706
    startTs = taosGetTimestampUs();

4707
    int affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718

    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;

4719 4720
    verbosePrint("[%d] %s() LN%d affectedRows=%d\n", pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
4721 4722
    if ((affectedRows < 0) || (recOfBatch != affectedRows)) {
        errorPrint("[%d] %s() LN%d execInsert insert %d, affected rows: %d\n%s\n",
4723
                pThreadInfo->threadID, __func__, __LINE__,
4724
                recOfBatch, affectedRows, buffer);
4725
        goto free_and_statistics_interlace;
4726
    }
4727

4728
    pThreadInfo->totalAffectedRows += affectedRows;
4729

4730 4731 4732
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
      printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
4733 4734 4735
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
4736 4737
      lastPrintTime = currentPrintTime;
    }
4738

4739 4740
    if ((insert_interval) && flagSleep) {
      et = taosGetTimestampUs();
4741

4742 4743
      if (insert_interval > ((et - st)/1000) ) {
        int sleepTime = insert_interval - (et -st)/1000;
4744 4745
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleepTime);
4746 4747 4748
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
4749
    }
4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761
  }

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

4762 4763 4764 4765 4766 4767 4768 4769
// 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
*/
4770
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
4771
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
4772

4773
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4774

4775 4776
  char* buffer = calloc(superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len, 1);
  if (NULL == buffer) {
4777
    errorPrint( "Failed to alloc %d Bytes, reason:%s\n",
4778 4779 4780 4781
              superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len,
              strerror(errno));
    return NULL;
  }
4782

4783 4784 4785 4786
  int64_t lastPrintTime = taosGetTimestampMs();
  int64_t startTs = taosGetTimestampUs();
  int64_t endTs;

4787 4788
  int timeStampStep =
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
4789
/*  int insert_interval =
4790
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4791 4792
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
4793
  */
4794

4795 4796
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
4797

4798
  pThreadInfo->samplePos = 0;
4799

4800 4801
  for (uint32_t tableSeq =
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
4802
        tableSeq ++) {
4803
    int64_t start_time = pThreadInfo->start_time;
4804 4805 4806 4807 4808

    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;) {
4809
        /*
4810 4811
      if (insert_interval) {
            st = taosGetTimestampUs();
4812
      }
4813
      */
4814

4815 4816 4817 4818 4819 4820
      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);

4821
      int generated = generateProgressiveDataBuffer(
4822
              tableName, tableSeq, pThreadInfo, buffer, insertRows,
4823
            i, start_time,
4824
            &(pThreadInfo->samplePos));
4825 4826 4827 4828 4829
      if (generated > 0)
        i += generated;
      else
        goto free_and_statistics_2;

4830
      start_time +=  generated * timeStampStep;
4831
      pThreadInfo->totalInsertRows += generated;
4832 4833 4834 4835

      startTs = taosGetTimestampUs();

      int affectedRows = execInsert(pThreadInfo, buffer, generated);
4836 4837 4838

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

4842 4843 4844 4845
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
4846

4847 4848 4849 4850 4851
      if (affectedRows < 0)
        goto free_and_statistics_2;

      pThreadInfo->totalAffectedRows += affectedRows;

4852 4853
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
4854
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
4855 4856 4857
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
4858 4859 4860
        lastPrintTime = currentPrintTime;
      }

4861
      if (i >= insertRows)
4862
        break;
4863
/*
4864 4865 4866 4867 4868
      if (insert_interval) {
        et = taosGetTimestampUs();

        if (insert_interval > ((et - st)/1000) ) {
            int sleep_time = insert_interval - (et -st)/1000;
4869 4870
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
4871 4872
            taosMsleep(sleep_time); // ms
        }
4873
      }
4874
      */
4875 4876
    }   // num_of_DPT

4877
    if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
4878 4879
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
4880 4881
          printf("%s() LN%d samplePos=%d\n",
                  __func__, __LINE__, pThreadInfo->samplePos);
4882
    }
4883
  } // tableSeq
4884

4885
free_and_statistics_2:
4886 4887
  tmfree(buffer);

4888
  printf("====thread[%d] completed total inserted rows: %"PRId64 ", total affected rows: %"PRId64 "====\n", 
4889 4890 4891
          pThreadInfo->threadID, 
          pThreadInfo->totalInsertRows, 
          pThreadInfo->totalAffectedRows);
4892
  return NULL;
H
Hui Li 已提交
4893 4894
}

4895 4896 4897 4898 4899
static void* syncWrite(void *sarg) {

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

4900
  int interlaceRows = superTblInfo?superTblInfo->interlaceRows:g_args.interlace_rows;
4901

4902
  if (interlaceRows > 0) {
4903 4904 4905 4906 4907 4908 4909 4910
    // interlace mode
    return syncWriteInterlace(winfo);
  } else {
    // progressive mode
    return syncWriteProgressive(winfo);
  }
}

4911
static void callBack(void *param, TAOS_RES *res, int code) {
4912
  threadInfo* winfo = (threadInfo*)param; 
4913
  SSuperTable* superTblInfo = winfo->superTblInfo;
4914

4915 4916
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4917 4918 4919 4920
  if (insert_interval) {
    winfo->et = taosGetTimestampUs();
    if (((winfo->et - winfo->st)/1000) < insert_interval) {
      taosMsleep(insert_interval - (winfo->et - winfo->st)/1000); // ms
4921
    }
H
Hui Li 已提交
4922
  }
4923

4924 4925 4926
  char *buffer = calloc(1, winfo->superTblInfo->maxSqlLen);
  char *data   = calloc(1, MAX_DATA_SIZE);
  char *pstr = buffer;
4927 4928
  pstr += sprintf(pstr, "insert into %s.%s%d values", winfo->db_name, winfo->tb_prefix,
          winfo->start_table_from);
4929
//  if (winfo->counter >= winfo->superTblInfo->insertRows) {
4930
  if (winfo->counter >= g_args.num_of_RPR) {
4931
    winfo->start_table_from++;
4932 4933
    winfo->counter = 0;
  }
4934
  if (winfo->start_table_from > winfo->end_table_to) {
4935 4936 4937 4938 4939 4940
    tsem_post(&winfo->lock_sem);
    free(buffer);
    free(data);
    taos_free_result(res);
    return;
  }
4941

4942
  for (int i = 0; i < g_args.num_of_RPR; i++) {
4943
    int rand_num = taosRandom() % 100;
4944 4945
    if (0 != winfo->superTblInfo->disorderRatio
            && rand_num < winfo->superTblInfo->disorderRatio) {
4946
      int64_t d = winfo->lastTs - taosRandom() % 1000000 + rand_num;
4947
      //generateData(data, datatype, ncols_per_record, d, len_of_binary);
4948
      generateRowData(data, MAX_DATA_SIZE, d, winfo->superTblInfo);
4949
    } else {
4950
      //generateData(data, datatype, ncols_per_record, start_time += 1000, len_of_binary);
4951
      generateRowData(data, MAX_DATA_SIZE, winfo->lastTs += 1000, winfo->superTblInfo);
H
Hui Li 已提交
4952
    }
4953 4954
    pstr += sprintf(pstr, "%s", data);
    winfo->counter++;
H
Hui Li 已提交
4955

4956 4957
    if (winfo->counter >= winfo->superTblInfo->insertRows) {
      break;
H
Hui Li 已提交
4958 4959
    }
  }
4960

4961 4962
  if (insert_interval) {
    winfo->st = taosGetTimestampUs();
4963 4964 4965 4966
  }
  taos_query_a(winfo->taos, buffer, callBack, winfo);
  free(buffer);
  free(data);
H
Hui Li 已提交
4967

4968
  taos_free_result(res);
H
Hui Li 已提交
4969 4970
}

4971
static void *asyncWrite(void *sarg) {
4972
  threadInfo *winfo = (threadInfo *)sarg;
4973
  SSuperTable* superTblInfo = winfo->superTblInfo;
4974 4975 4976 4977

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

4979
  int insert_interval =
4980
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
4981 4982
  if (insert_interval) {
    winfo->st = taosGetTimestampUs();
H
Hui Li 已提交
4983
  }
4984 4985 4986
  taos_query_a(winfo->taos, "show databases", callBack, winfo);

  tsem_wait(&(winfo->lock_sem));
H
Hui Li 已提交
4987 4988 4989 4990

  return NULL;
}

4991 4992
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
4993 4994

    pthread_t *pids = malloc(threads * sizeof(pthread_t));
4995 4996
    assert(pids != NULL);

4997
    threadInfo *infos = malloc(threads * sizeof(threadInfo));
4998 4999
    assert(infos != NULL);

5000 5001
    memset(pids, 0, threads * sizeof(pthread_t));
    memset(infos, 0, threads * sizeof(threadInfo));
H
Hui Li 已提交
5002

5003
    int ntables = 0;
5004 5005
    if (superTblInfo) {

5006
        if ((superTblInfo->childTblOffset >= 0)
5007 5008
            && (superTblInfo->childTblLimit > 0)) {

5009
            ntables = superTblInfo->childTblLimit;
5010
        } else {
5011
            ntables = superTblInfo->childTblCount;
5012 5013
        }
    } else {
5014
        ntables = g_args.num_of_tables;
5015
    }
H
Hui Li 已提交
5016

5017 5018 5019 5020 5021 5022 5023 5024 5025 5026
    int a = ntables / threads;
    if (a < 1) {
        threads = ntables;
        a = 1;
    }

    int b = 0;
    if (threads != 0) {
        b = ntables % threads;
    }
5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043

  //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 {
5044
      errorPrint("Not support precision: %s\n", precision);
5045 5046 5047 5048
      exit(-1);
    }
  }

5049
  int64_t start_time;
5050 5051 5052
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
5053
    } else {
5054 5055 5056 5057 5058
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
5059
          ERROR_EXIT("failed to parse time!\n");
5060
      }
5061
    }
5062 5063
  } else {
     start_time = 1500000000000;
5064 5065 5066
  }

  double start = getCurrentTime();
5067

5068
  int startFrom;
5069

5070
  if ((superTblInfo) && (superTblInfo->childTblOffset >= 0))
5071
      startFrom = superTblInfo->childTblOffset;
5072
  else
5073
      startFrom = 0;
5074

5075
  // read sample data from file first
5076
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5077
              "sample", strlen("sample")))) {
5078
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5079 5080
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5081 5082 5083 5084
      exit(-1);
    }
  }

5085
  // read sample data from file first
5086
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5087 5088
              "sample", strlen("sample")))) {
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5089 5090
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5091 5092 5093 5094 5095 5096 5097 5098
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
  if (NULL == taos) {
5099 5100
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
                __func__, __LINE__, taos_errstr(NULL));
5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118
    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) {
5119
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133
      taos_close(taos);
      exit(-1);
    }

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

H
Hui Li 已提交
5134
  for (int i = 0; i < threads; i++) {
5135
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5136 5137
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5138
    t_info->time_precision = timePrec;
5139 5140 5141
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5142
    t_info->minDelay = INT16_MAX;
5143

5144 5145
    if ((NULL == superTblInfo) ||
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5146
      //t_info->taos = taos;
5147
      t_info->taos = taos_connect(
5148
              g_Dbs.host, g_Dbs.user,
5149
              g_Dbs.password, db_name, g_Dbs.port);
5150
      if (NULL == t_info->taos) {
5151 5152
        errorPrint(
                "connect to server fail from insert sub thread, reason: %s\n",
5153
                taos_errstr(NULL));
5154 5155 5156 5157 5158 5159
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5160 5161
    if ((NULL == superTblInfo)
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5162 5163 5164 5165
      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;
5166
    } else {
5167 5168
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5169 5170 5171 5172 5173
      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) {
5174
      pthread_create(pids + i, NULL, syncWrite, t_info);
5175
    } else {
5176 5177
      pthread_create(pids + i, NULL, asyncWrite, t_info);
    }
H
Hui Li 已提交
5178
  }
5179

H
Hui Li 已提交
5180 5181 5182 5183
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5184 5185 5186
  int64_t totalDelay = 0;
  int64_t maxDelay = 0;
  int64_t minDelay = INT16_MAX;
5187
  int64_t cntDelay = 1;
5188 5189
  double  avgDelay = 0;

H
Hui Li 已提交
5190
  for (int i = 0; i < threads; i++) {
5191 5192
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5193
    tsem_destroy(&(t_info->lock_sem));
5194 5195
    taos_close(t_info->taos);

5196 5197 5198 5199
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRId64" totalAffected=%"PRId64"\n",
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5200 5201
    if (superTblInfo) {
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
5202
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5203 5204 5205
    } else {
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5206
    }
5207 5208 5209 5210

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5211
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5212
  }
5213
  cntDelay -= 1;
H
Hui Li 已提交
5214

5215
  if (cntDelay == 0)    cntDelay = 1;
5216 5217
  avgDelay = (double)totalDelay / cntDelay;

5218
  double end = getCurrentTime();
5219
  double t = end - start;
5220 5221

  if (superTblInfo) {
5222
    printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
5223
          t, superTblInfo->totalInsertRows,
5224 5225
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5226
          superTblInfo->totalInsertRows / t);
5227
    fprintf(g_fpOfInsertResult,
5228
          "Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s) into %s.%s. %2.f records/second\n\n",
5229
          t, superTblInfo->totalInsertRows,
5230 5231
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5232
          superTblInfo->totalInsertRows/ t);
5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244
  } 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);
5245
  }
5246 5247 5248 5249 5250

  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);
5251

5252 5253
  //taos_close(taos);

H
Hui Li 已提交
5254
  free(pids);
5255
  free(infos);
H
Hui Li 已提交
5256 5257
}

5258
static void *readTable(void *sarg) {
5259
#if 1
5260
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5261 5262
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5263
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5264 5265
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5266
  if (NULL == fp) {
5267
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5268 5269
    return NULL;
  }
5270

5271
    int num_of_DPT;
5272
/*  if (rinfo->superTblInfo) {
5273 5274
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5275
  */
5276
      num_of_DPT = g_args.num_of_DPT;
5277
//  }
5278

5279
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5280
  int totalData = num_of_DPT * num_of_tables;
5281
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293

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

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

S
Shuaiqiang Chang 已提交
5301
      if (code != 0) {
5302
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5303
        taos_free_result(pSql);
H
hzcheng 已提交
5304
        taos_close(taos);
5305
        fclose(fp);
5306
        return NULL;
H
hzcheng 已提交
5307 5308
      }

S
Shuaiqiang Chang 已提交
5309
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5310 5311 5312 5313 5314 5315
        count++;
      }

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

S
Shuaiqiang Chang 已提交
5316
      taos_free_result(pSql);
H
hzcheng 已提交
5317 5318 5319
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5320
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5321 5322 5323 5324 5325
            (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);
5326
#endif
H
hzcheng 已提交
5327 5328 5329
  return NULL;
}

5330
static void *readMetric(void *sarg) {
5331 5332
#if 1  
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5333 5334 5335
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5336 5337 5338 5339
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5340 5341

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5342
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5343
  int totalData = num_of_DPT * num_of_tables;
5344
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5345 5346 5347 5348 5349 5350 5351 5352 5353

  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 已提交
5354
    char condition[BUFFER_SIZE - 30] = "\0";
B
Bomin Zhang 已提交
5355
    char tempS[64] = "\0";
H
hzcheng 已提交
5356 5357 5358 5359 5360

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
5361
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
5362
      } else {
5363
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
5364 5365 5366
      }
      strcat(condition, tempS);

L
liu0x54 已提交
5367
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
5368 5369 5370 5371 5372 5373

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

      double t = getCurrentTime();

S
Shuaiqiang Chang 已提交
5374 5375 5376 5377
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
5378
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5379
        taos_free_result(pSql);
H
hzcheng 已提交
5380
        taos_close(taos);
5381
        fclose(fp);
5382
        return NULL;
H
hzcheng 已提交
5383 5384
      }
      int count = 0;
S
Shuaiqiang Chang 已提交
5385
      while (taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5386 5387 5388 5389
        count++;
      }
      t = getCurrentTime() - t;

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

S
Shuaiqiang Chang 已提交
5394
      taos_free_result(pSql);
H
hzcheng 已提交
5395 5396 5397 5398
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
5399
#endif
H
hzcheng 已提交
5400 5401 5402
  return NULL;
}

H
Hui Li 已提交
5403

5404
static int insertTestProcess() {
5405

5406 5407 5408
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
5409

5410 5411 5412
  if (ret == -1)
    exit(EXIT_FAILURE);

5413
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
5414 5415
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
5416
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
5417 5418
    return -1;
  }
5419

5420 5421
  printfInsertMetaToFile(g_fpOfInsertResult);

5422 5423 5424 5425
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5426

5427 5428 5429
  init_rand_data();

  // create database and super tables
5430
  if(createDatabases() != 0) {
5431 5432 5433
    fclose(g_fpOfInsertResult);
    return -1;
  }
5434 5435

  // pretreatement
5436
  prepareSampleData();
5437

5438 5439 5440 5441 5442 5443 5444
  double start;
  double end;

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

5446
  if (g_totalChildTables > 0) {
5447
    printf("Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5448
            end - start, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5449 5450
    fprintf(g_fpOfInsertResult,
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
5451
            end - start, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
5452
  }
5453

5454
  taosMsleep(1000);
5455 5456
  // create sub threads for inserting data
  //start = getCurrentTime();
5457 5458 5459 5460 5461 5462
  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;
5463
        }
5464
        startMultiThreadInsertData(
5465 5466 5467
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
5468 5469 5470 5471
          superTblInfo);
        }
    } else {
        startMultiThreadInsertData(
5472 5473 5474
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
5475
          NULL);
H
Hui Li 已提交
5476
    }
5477
  }
5478
  //end = getCurrentTime();
5479

5480
  //int64_t    totalInsertRows = 0;
5481 5482 5483
  //int64_t    totalAffectedRows = 0;
  //for (int i = 0; i < g_Dbs.dbCount; i++) {    
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
5484
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
5485 5486
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
5487
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
5488
  postFreeResource();
5489

5490 5491 5492
  return 0;
}

5493
static void *superQueryProcess(void *sarg) {
5494
  threadInfo *winfo = (threadInfo *)sarg;
5495

5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511
  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;
    }
  }

5512 5513 5514
  //char sqlStr[MAX_TB_NAME_SIZE*2];
  //sprintf(sqlStr, "use %s", g_queryInfo.dbName);
  //queryDB(winfo->taos, sqlStr);
5515

5516 5517
  int64_t st = 0;
  int64_t et = 0;
5518

5519
  int queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
5520 5521

  while(queryTimes --) {
5522 5523 5524
    if (g_queryInfo.specifiedQueryInfo.rate && (et - st) <
            (int64_t)g_queryInfo.specifiedQueryInfo.rate*1000) {
      taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms
5525
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5526 5527
    }

5528
    st = taosGetTimestampUs();
5529
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
5530
      if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", 5)) {
5531 5532
        int64_t t1 = taosGetTimestampUs();
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5533
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
5534
          sprintf(tmpFile, "%s-%d",
5535
                  g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID);
5536
        }
5537
        selectAndGetResult(winfo->taos, g_queryInfo.specifiedQueryInfo.sql[i], tmpFile);
5538 5539
        int64_t t2 = taosGetTimestampUs();
        printf("=[taosc] thread[%"PRId64"] complete one sql, Spent %f s\n",
5540
                taosGetSelfPthreadId(), (t2 - t1)/1000000.0);
5541 5542
      } else {
        int64_t t1 = taosGetTimestampUs();
5543
        int retCode = postProceSql(g_queryInfo.host,
5544
                g_queryInfo.port, g_queryInfo.specifiedQueryInfo.sql[i]);
5545 5546
        int64_t t2 = taosGetTimestampUs();
        printf("=[restful] thread[%"PRId64"] complete one sql, Spent %f s\n",
5547
                taosGetSelfPthreadId(), (t2 - t1)/1000000.0);
5548

5549
        if (0 != retCode) {
5550
          printf("====restful return fail, threadID[%d]\n", winfo->threadID);
5551 5552
          return NULL;
        }
5553
      }
5554
    }
5555
    et = taosGetTimestampUs();
5556
    printf("==thread[%"PRId64"] complete all sqls to specify tables once queries duration:%.6fs\n\n",
5557
            taosGetSelfPthreadId(), (double)(et - st)/1000.0);
H
Hui Li 已提交
5558
  }
5559 5560
  return NULL;
}
H
Hui Li 已提交
5561

5562
static void replaceSubTblName(char* inSql, char* outSql, int tblIndex) {
5563 5564
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
5565 5566
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
5567
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
5568 5569

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

5571 5572
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
5573
    return;
H
Hui Li 已提交
5574
  }
5575

5576
  tstrncpy(outSql, inSql, pos - inSql + 1);
5577
  //printf("1: %s\n", outSql);
5578 5579 5580 5581
  strcat(outSql, subTblName);
  //printf("2: %s\n", outSql);
  strcat(outSql, pos+strlen(sourceString));
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
5582 5583
}

5584
static void *subQueryProcess(void *sarg) {
5585
  char sqlstr[1024];
5586
  threadInfo *winfo = (threadInfo *)sarg;
5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603

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

5604
  int64_t st = 0;
5605 5606 5607
  int64_t et = (int64_t)g_queryInfo.superQueryInfo.rate*1000;

  int queryTimes = g_queryInfo.superQueryInfo.queryTimes;
5608

5609
  while(queryTimes --) {
5610 5611 5612
    if (g_queryInfo.superQueryInfo.rate
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.rate*1000) {
      taosMsleep(g_queryInfo.superQueryInfo.rate*1000 - (et - st)); // ms
5613
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5614
    }
H
Hui Li 已提交
5615

5616
    st = taosGetTimestampUs();
5617
    for (int i = winfo->start_table_from; i <= winfo->end_table_to; i++) {
5618
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
5619
        memset(sqlstr,0,sizeof(sqlstr));
5620
        replaceSubTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
5621
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5622
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
5623
          sprintf(tmpFile, "%s-%d",
5624
                  g_queryInfo.superQueryInfo.result[j],
5625
                  winfo->threadID);
5626
        }
5627
        selectAndGetResult(winfo->taos, sqlstr, tmpFile);
5628
      }
H
Hui Li 已提交
5629
    }
5630
    et = taosGetTimestampUs();
5631
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%d - %d] once queries duration:%.4fs\n\n",
5632 5633 5634
            taosGetSelfPthreadId(),
            winfo->start_table_from,
            winfo->end_table_to,
5635
            (double)(et - st)/1000000.0);
5636
  }
5637

5638 5639 5640
  return NULL;
}

5641
static int queryTestProcess() {
5642 5643 5644 5645

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
5646 5647 5648 5649 5650 5651

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
5652
          g_queryInfo.port);
5653
  if (taos == NULL) {
5654 5655
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
5656 5657 5658
    exit(-1);
  }

5659
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
5660 5661
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
5662 5663 5664
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
5665
  }
5666

5667 5668 5669 5670
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
5671

5672
  printfQuerySystemInfo(taos);
5673

5674 5675 5676
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
5677 5678
  if (g_queryInfo.specifiedQueryInfo.sqlCount > 0
          && g_queryInfo.specifiedQueryInfo.concurrent > 0) {
5679

5680
    pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
5681 5682 5683 5684
    if (NULL == pids) {
        taos_close(taos);
        ERROR_EXIT("memory allocation failed\n");
    }
5685
    infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
5686
    if (NULL == infos) {
5687
      taos_close(taos);
5688 5689
      free(pids);
      ERROR_EXIT("memory allocation failed for create threads\n");
5690
    }
5691

5692
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
5693
      threadInfo *t_info = infos + i;
5694
      t_info->threadID = i;
5695

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

5698 5699
        char sqlStr[MAX_TB_NAME_SIZE*2];
        sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5700
        verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5701 5702
        if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
            taos_close(taos);
5703 5704
            free(infos);
            free(pids);
5705 5706 5707 5708
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
        }
5709
      }
5710

5711 5712
      t_info->taos = NULL;// TODO: workaround to use separate taos connection;

5713 5714
      pthread_create(pids + i, NULL, superQueryProcess, t_info);
    }
5715
  } else {
5716
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
5717
  }
5718

5719 5720
  taos_close(taos);

5721 5722 5723
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
5724 5725 5726
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t));
5727 5728 5729 5730 5731 5732 5733
    if (NULL == pidsOfSub) {
      free(infos);
      free(pids);

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

5734
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo));
5735 5736 5737 5738 5739
    if (NULL == infosOfSub) {
      free(pidsOfSub);
      free(infos);
      free(pids);
      ERROR_EXIT("memory allocation failed for create threads\n");
5740
    }
5741

5742 5743
    int ntables = g_queryInfo.superQueryInfo.childTblCount;
    int threads = g_queryInfo.superQueryInfo.threadCnt;
5744

5745 5746 5747 5748 5749
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
5750

5751 5752 5753 5754
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
5755

5756
    int startFrom = 0;
5757
    for (int i = 0; i < threads; i++) {
5758 5759
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
5760

5761 5762 5763 5764
      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;
5765
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
5766 5767 5768
      pthread_create(pidsOfSub + i, NULL, subQueryProcess, t_info);
    }

5769
    g_queryInfo.superQueryInfo.threadCnt = threads;
5770
  } else {
5771
    g_queryInfo.superQueryInfo.threadCnt = 0;
5772
  }
5773

5774
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
5775
    pthread_join(pids[i], NULL);
5776
  }
S
Shuaiqiang Chang 已提交
5777

5778
  tmfree((char*)pids);
5779
  tmfree((char*)infos);
5780

5781
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
5782
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
5783
  }
H
Hui Li 已提交
5784

5785
  tmfree((char*)pidsOfSub);
5786
  tmfree((char*)infosOfSub);
5787

5788
//  taos_close(taos);// TODO: workaround to use separate taos connection;
5789 5790 5791
  return 0;
}

5792
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
5793
  if (res == NULL || taos_errno(res) != 0) {
5794 5795
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
5796 5797
    return;
  }
5798

5799 5800
  getResult(res, (char*)param);
  taos_free_result(res);
H
hzcheng 已提交
5801 5802
}

5803
static TAOS_SUB* subscribeImpl(TAOS *taos, char *sql, char* topic, char* resultFileName) {
5804
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
5805

5806
  if (g_queryInfo.specifiedQueryInfo.subscribeMode) {
5807
    tsub = taos_subscribe(taos,
5808
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
5809
            topic, sql, subscribe_callback, (void*)resultFileName,
5810
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
5811
  } else {
5812
    tsub = taos_subscribe(taos,
5813
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
5814
            topic, sql, NULL, NULL, 0);
5815
  }
5816

5817 5818 5819
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
5820
  }
5821

5822 5823
  return tsub;
}
H
hzcheng 已提交
5824

5825
static void *subSubscribeProcess(void *sarg) {
5826
  threadInfo *winfo = (threadInfo *)sarg;
5827
  char subSqlstr[1024];
H
hzcheng 已提交
5828

5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844
  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;
    }
  }

5845 5846
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5847
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5848 5849
  if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(winfo->taos);
5850 5851
    return NULL;
  }
5852

5853 5854 5855
  //int64_t st = 0;
  //int64_t et = 0;
  do {
5856 5857
    //if (g_queryInfo.specifiedQueryInfo.rate && (et - st) < g_queryInfo.specifiedQueryInfo.rate*1000) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms
5858
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5859 5860 5861 5862
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
5863
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
5864 5865
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
5866
      replaceSubTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i);
5867
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5868
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
5869
        sprintf(tmpFile, "%s-%d",
5870
                g_queryInfo.superQueryInfo.result[i], winfo->threadID);
5871
      }
5872
      g_queryInfo.superQueryInfo.tsub[i] = subscribeImpl(
5873
              winfo->taos, subSqlstr, topic, tmpFile); 
5874
      if (NULL == g_queryInfo.superQueryInfo.tsub[i]) {
5875
        taos_close(winfo->taos);
5876 5877 5878 5879
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
5880
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
5881 5882 5883 5884 5885
  } while (0);

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

5891
      res = taos_consume(g_queryInfo.superQueryInfo.tsub[i]);
5892 5893
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5894
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
5895
          sprintf(tmpFile, "%s-%d",
5896
                  g_queryInfo.superQueryInfo.result[i],
5897
                  winfo->threadID);
5898 5899
        }
        getResult(res, tmpFile);
H
hzcheng 已提交
5900 5901 5902
      }
    }
  }
5903
  taos_free_result(res);
5904

5905 5906 5907
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
    taos_unsubscribe(g_queryInfo.superQueryInfo.tsub[i],
            g_queryInfo.superQueryInfo.subscribeKeepProgress);
5908
  }
5909 5910

  taos_close(winfo->taos);
H
hzcheng 已提交
5911 5912 5913
  return NULL;
}

5914
static void *superSubscribeProcess(void *sarg) {
5915
  threadInfo *winfo = (threadInfo *)sarg;
H
hzcheng 已提交
5916

5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932
  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;
    }
  }

5933 5934
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
5935
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
5936
  if (0 != queryDbExec(winfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
5937
    taos_close(winfo->taos);
5938 5939
    return NULL;
  }
5940

5941 5942 5943
  //int64_t st = 0;
  //int64_t et = 0;
  do {
5944 5945
    //if (g_queryInfo.specifiedQueryInfo.rate && (et - st) < g_queryInfo.specifiedQueryInfo.rate*1000) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.rate*1000 - (et - st)); // ms
5946
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, winfo->start_table_from, winfo->end_table_to);
5947 5948 5949 5950
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
5951
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
5952 5953
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5954
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
5955
        sprintf(tmpFile, "%s-%d",
5956
                g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID);
5957
      }
5958
      g_queryInfo.specifiedQueryInfo.tsub[i] =
5959
          subscribeImpl(winfo->taos,
5960
                  g_queryInfo.specifiedQueryInfo.sql[i],
5961
                  topic, tmpFile);
5962
      if (NULL == g_queryInfo.specifiedQueryInfo.tsub[i]) {
5963
        taos_close(winfo->taos);
5964 5965 5966 5967
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
5968
    //printf("========thread[%"PRId64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
5969 5970 5971 5972 5973
  } while (0);

  // start loop to consume result
  TAOS_RES* res = NULL;
  while (1) {
5974 5975
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
      if (1 == g_queryInfo.specifiedQueryInfo.subscribeMode) {
5976 5977
        continue;
      }
5978

5979
      res = taos_consume(g_queryInfo.specifiedQueryInfo.tsub[i]);
5980 5981
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
5982
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
5983
          sprintf(tmpFile, "%s-%d",
5984
                  g_queryInfo.specifiedQueryInfo.result[i], winfo->threadID);
5985 5986 5987 5988 5989 5990
        }
        getResult(res, tmpFile);
      }
    }
  }
  taos_free_result(res);
5991

5992 5993 5994
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
    taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[i],
            g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
5995
  }
5996 5997

  taos_close(winfo->taos);
H
hzcheng 已提交
5998 5999 6000
  return NULL;
}

6001
static int subscribeTestProcess() {
6002
  setupForAnsiEscape();
6003
  printfQueryMeta();
6004
  resetAfterAnsiEscape();
6005

6006 6007
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6008
    (void) getchar();
Y
yihaoDeng 已提交
6009
  }
6010

6011 6012 6013 6014 6015
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6016
          g_queryInfo.port);
6017
  if (taos == NULL) {
6018 6019
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6020 6021 6022
    exit(-1);
  }

6023
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6024 6025
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6026 6027 6028
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6029 6030
  }

6031 6032
  taos_close(taos); // TODO: workaround to use separate taos connection;

6033 6034 6035
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6036 6037
  if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) {
6038
    errorPrint("%s() LN%d, query sqlCount %d or concurrent %d is not correct.\n",
6039 6040
              __func__, __LINE__, g_queryInfo.specifiedQueryInfo.sqlCount,
              g_queryInfo.specifiedQueryInfo.concurrent);
6041 6042 6043
    exit(-1);
  }

6044 6045
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6046
  if ((NULL == pids) || (NULL == infos)) {
6047
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6048
      exit(-1);
6049
  }
6050

6051
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6052 6053
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6054
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6055
      pthread_create(pids + i, NULL, superSubscribeProcess, t_info);
H
hzcheng 已提交
6056
  }
6057

6058
  //==== create sub threads for query from sub table
6059 6060
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6061 6062 6063
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6064
            sizeof(pthread_t));
6065
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * 
6066
            sizeof(threadInfo));
6067
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6068 6069 6070
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6071
      exit(-1);
S
Shuaiqiang Chang 已提交
6072
    }
6073

6074 6075
    int ntables = g_queryInfo.superQueryInfo.childTblCount;
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6076

6077 6078 6079 6080 6081
    int a = ntables / threads;
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6082

6083 6084 6085 6086
    int b = 0;
    if (threads != 0) {
      b = ntables % threads;
    }
6087

6088
    int startFrom = 0;
6089
    for (int i = 0; i < threads; i++) {
6090 6091
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6092

6093 6094 6095 6096
      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;
6097
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6098
      pthread_create(pidsOfSub + i, NULL, subSubscribeProcess, t_info);
H
hzcheng 已提交
6099
    }
6100

6101
    g_queryInfo.superQueryInfo.threadCnt = threads;
6102

6103
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6104 6105
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6106
  }
6107

6108
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6109
    pthread_join(pids[i], NULL);
6110
  }
H
hzcheng 已提交
6111

6112
  tmfree((char*)pids);
6113
  tmfree((char*)infos);
H
hzcheng 已提交
6114

6115
  tmfree((char*)pidsOfSub);
6116
  tmfree((char*)infosOfSub);
6117
//   taos_close(taos);
6118
  return 0;
H
hzcheng 已提交
6119 6120
}

6121
static void initOfInsertMeta() {
6122
  memset(&g_Dbs, 0, sizeof(SDbs));
6123

6124
  // set default values
6125
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6126
  g_Dbs.port = 6030;
6127 6128
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6129
  g_Dbs.threadCount = 2;
6130 6131

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6132 6133
}

6134
static void initOfQueryMeta() {
6135
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6136

6137
  // set default values
6138
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6139
  g_queryInfo.port = 6030;
6140 6141
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6142 6143
}

6144
static void setParaFromArg(){
6145
  if (g_args.host) {
6146
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6147
  } else {
6148
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6149
  }
L
Liu Tao 已提交
6150

6151
  if (g_args.user) {
6152
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6153
  }
6154 6155

  if (g_args.password) {
6156
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6157 6158
  }

6159 6160
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6161
  }
L
Liu Tao 已提交
6162

6163 6164 6165
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6166 6167
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6168

6169
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6170
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6171
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6172

6173
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6174 6175 6176 6177 6178

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

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

6180 6181
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6182

6183
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6184

6185 6186
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6187
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6188
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6189
  }
H
hzcheng 已提交
6190

6191 6192 6193 6194 6195
  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;
6196
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6197
    g_Dbs.queryMode = g_args.mode;
6198

6199 6200 6201 6202
    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;
6203
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6204 6205 6206
            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);
6207
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6208
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6209
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6210

6211
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6212
    g_Dbs.db[0].superTbls[0].maxSqlLen = TSDB_PAYLOAD_SIZE;
6213

6214 6215 6216 6217 6218
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6219

6220
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6221
              data_type[i], MAX_TB_NAME_SIZE);
6222
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6223 6224
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6225

6226 6227 6228 6229 6230
    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);
6231
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6232 6233 6234
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6235

6236
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6237
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6238

6239
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6240 6241
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6242
  } else {
6243 6244
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6245
  }
6246 6247 6248 6249 6250 6251
}

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

6253 6254 6255
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6256 6257 6258
    exit(-1);
  }

6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282
  /* 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);
}

6283
static void querySqlFile(TAOS* taos, char* sqlFile)
6284 6285 6286 6287 6288 6289
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6290

6291 6292 6293 6294 6295 6296 6297
  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();
6298

6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311
  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;
6312
    }
6313 6314

    memcpy(cmd + cmd_len, line, read_len);
6315
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
6316 6317 6318
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
6319 6320 6321 6322 6323
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
6324 6325
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
6326 6327
  }

6328 6329
  t = getCurrentTime() - t;
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
6330

6331 6332 6333 6334
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
6335 6336
}

6337
static void testMetaFile() {
6338
    if (INSERT_TEST == g_args.test_mode) {
6339 6340
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
6341

6342
      insertTestProcess();
6343

6344
    } else if (QUERY_TEST == g_args.test_mode) {
6345 6346
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6347

6348
      queryTestProcess();
6349

6350
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
6351 6352
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
6353

6354
      subscribeTestProcess();
6355

6356 6357 6358
    }  else {
      ;
    }
6359
}
6360

6361
static void queryResult() {
6362 6363 6364
    // select
    if (false == g_Dbs.insert_only) {
      // query data
6365

6366 6367 6368
      pthread_t read_id;
      threadInfo *rInfo = malloc(sizeof(threadInfo));
      rInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
6369
      rInfo->start_table_from = 0;
6370

6371
      //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
6372
      if (g_args.use_metric) {
6373 6374
        rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
        rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
6375
        rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
6376 6377
        tstrncpy(rInfo->tb_prefix,
              g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
6378
      } else {
6379 6380
        rInfo->ntables = g_args.num_of_tables;
        rInfo->end_table_to = g_args.num_of_tables -1;
6381
        tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
6382 6383
      }

6384
      rInfo->taos = taos_connect(
6385 6386 6387 6388
              g_Dbs.host,
              g_Dbs.user,
              g_Dbs.password,
              g_Dbs.db[0].dbName,
6389
              g_Dbs.port);
6390
      if (rInfo->taos == NULL) {
6391 6392
        errorPrint( "Failed to connect to TDengine, reason:%s\n",
                taos_errstr(NULL));
6393 6394 6395 6396
        free(rInfo);
        exit(-1);
      }

6397
      tstrncpy(rInfo->fp, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
6398 6399 6400 6401 6402 6403 6404 6405 6406

      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 已提交
6407
    }
6408 6409
}

6410 6411
static void testCmdLine() {

6412 6413
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
6414

6415 6416 6417 6418
  if (g_Dbs.insert_only)
    return;
  else
    queryResult();
6419 6420
}

6421 6422 6423
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

6424
  debugPrint("meta file: %s\n", g_args.metaFile);
6425 6426 6427

  if (g_args.metaFile) {
    initOfInsertMeta();
6428
    initOfQueryMeta();
6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441

    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(
6442 6443 6444 6445
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
6446
          g_Dbs.port);
6447
      querySqlFile(qtaos, g_args.sqlFile);
6448 6449 6450 6451 6452
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
6453
  }
6454 6455

  return 0;
H
hzcheng 已提交
6456
}
6457