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

16 17 18 19 20

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

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

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

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

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

55 56 57
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

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

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

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

71 72
#define MAX_RECORDS_PER_REQ     32766

73 74
#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
75
#define COND_BUF_LEN        BUFFER_SIZE - 30
76 77
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
78
#define MAX_DB_NAME_SIZE   64
79
#define MAX_HOSTNAME_SIZE  64
80
#define MAX_TB_NAME_SIZE   64
81
#define MAX_DATA_SIZE      (16*1024)+20     // max record len: 16*1024, timestamp string and ,('') need extra space
82 83 84 85 86 87 88 89 90 91
#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
92
#define   MAX_SUPER_TABLE_COUNT  200
93 94 95
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

96
#define   MAX_QUERY_SQL_COUNT    100
97
#define   MAX_QUERY_SQL_LENGTH   1024
98 99

#define   MAX_DATABASE_COUNT     256
100
#define INPUT_BUF_LEN   256
101

102
#define DEFAULT_TIMESTAMP_STEP  1
103

104

105 106 107 108 109
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
110

111 112
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
113
  TBL_ALREADY_EXISTS,
114 115 116
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

117
enum enumSYNC_MODE {
118 119
  SYNC_MODE,
  ASYNC_MODE,
120 121
  MODE_BUT
};
122

123 124 125 126 127 128
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

129 130 131 132 133 134
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

135
typedef enum enumQUERY_TYPE {
136
  NO_INSERT_TYPE,
137
  INSERT_TYPE,
138
  QUERY_TYPE_BUT
139
} QUERY_TYPE;
140 141 142 143 144 145 146

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

176 177 178 179 180 181 182 183 184 185 186 187 188 189
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 已提交
190 191

/* Used by main to communicate with parse_opt. */
192 193
static char *g_dupstr = NULL;

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

typedef struct SColumn_S {
235 236 237
  char      field[TSDB_COL_NAME_LEN + 1];
  char      dataType[MAX_TB_NAME_SIZE];
  uint32_t  dataLen;
238
  char      note[128];
239 240 241
} StrColumn;

typedef struct SSuperTable_S {
242
  char         sTblName[MAX_TB_NAME_SIZE+1];
243
  int64_t      childTblCount;
244
  bool         childTblExists;          // 0: no, 1: yes
245 246
  uint64_t     batchCreateTableNum;     // 0: no batch,  > 0: batch table number in one sql
  uint8_t      autoCreateTable;         // 0: create sub table, 1: auto create sub table
247
  char         childTblPrefix[MAX_TB_NAME_SIZE];
248
  char         dataSource[MAX_TB_NAME_SIZE+1];  // rand_gen or sample
249
  char         insertMode[MAX_TB_NAME_SIZE];    // taosc, rest
250
  int64_t      childTblLimit;
251
  uint64_t     childTblOffset;
252

253
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
254
  uint64_t     interlaceRows;           //
255 256
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
257
  uint64_t     maxSqlLen;               //
258

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

267
  uint32_t     columnCount;
268
  StrColumn    columns[MAX_COLUMN_COUNT];
269
  uint32_t     tagCount;
270 271 272
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
273
  char*        colsOfCreateChildTable;
274 275
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
276 277 278 279 280

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

281
  uint32_t     tagSource;    // 0: rand, 1: tag sample
282
  char*        tagDataBuf;
283 284
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
285

286
  // statistics
287 288
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
289 290 291 292 293
} SSuperTable;

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

313
typedef struct SDbCfg_S {
314
//  int       maxtablesPerVnode;
315 316
  uint32_t  minRows;        // 0 means default
  uint32_t  maxRows;        // 0 means default
317 318
  int       comp;
  int       walLevel;
319
  int       cacheLast;
320
  int       fsync;
321 322 323 324 325 326 327
  int       replica;
  int       update;
  int       keep;
  int       days;
  int       cache;
  int       blocks;
  int       quorum;
328
  char      precision[MAX_TB_NAME_SIZE];
329 330 331 332
} SDbCfg;

typedef struct SDataBase_S {
  char         dbName[MAX_DB_NAME_SIZE];
333
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
334
  SDbCfg       dbCfg;
335
  uint64_t     superTblCount;
336 337 338 339
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
340
  char         cfgDir[MAX_FILE_NAME_LEN+1];
341
  char         host[MAX_HOSTNAME_SIZE];
342 343
  struct sockaddr_in serv_addr;

344
  uint16_t     port;
345 346
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
347
  char         resultFile[MAX_FILE_NAME_LEN+1];
348 349 350
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
351
  bool         asyncMode;
352

353 354 355
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
356 357 358
  SDataBase    db[MAX_DB_COUNT];

  // statistics
359 360
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
361

362 363
} SDbs;

364
typedef struct SpecifiedQueryInfo_S {
365
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
366
  uint32_t     concurrent;
367
  uint64_t     sqlCount;
368
  uint32_t     asyncMode; // 0: sync, 1: async
369 370
  uint64_t     subscribeInterval; // ms
  uint64_t     queryTimes;
371
  bool         subscribeRestart;
372
  int          subscribeKeepProgress;
373
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
374
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
375
  int          resubAfterConsume[MAX_QUERY_SQL_COUNT];
376
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
377 378 379
  char         topic[MAX_QUERY_SQL_COUNT][32];
  int          consumed[MAX_QUERY_SQL_COUNT];
  TAOS_RES*    res[MAX_QUERY_SQL_COUNT];
380
  uint64_t     totalQueried;
381
} SpecifiedQueryInfo;
382

383
typedef struct SuperQueryInfo_S {
384
  char         sTblName[MAX_TB_NAME_SIZE+1];
385 386
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
  uint32_t     threadCnt;
387
  uint32_t     asyncMode; // 0: sync, 1: async
388
  uint64_t     subscribeInterval; // ms
389
  bool         subscribeRestart;
390
  int          subscribeKeepProgress;
391
  uint64_t     queryTimes;
392
  int64_t      childTblCount;
393
  char         childTblPrefix[MAX_TB_NAME_SIZE];
394
  uint64_t     sqlCount;
395
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
396
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
397
  int          resubAfterConsume;
398
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
399

400
  char*        childTblName;
401
  uint64_t     totalQueried;
402
} SuperQueryInfo;
403 404

typedef struct SQueryMetaInfo_S {
405
  char         cfgDir[MAX_FILE_NAME_LEN+1];
406
  char         host[MAX_HOSTNAME_SIZE];
407
  uint16_t     port;
408
  struct       sockaddr_in serv_addr;
409 410
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
411
  char         dbName[MAX_DB_NAME_SIZE+1];
412
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
413

414
  SpecifiedQueryInfo  specifiedQueryInfo;
415
  SuperQueryInfo      superQueryInfo;
416
  uint64_t     totalQueried;
417 418 419
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
420 421 422 423
  TAOS *    taos;
  int       threadID;
  char      db_name[MAX_DB_NAME_SIZE+1];
  uint32_t  time_precision;
424 425
  char      filePath[4096];
  FILE      *fp;
426 427 428
  char      tb_prefix[MAX_TB_NAME_SIZE];
  uint64_t  start_table_from;
  uint64_t  end_table_to;
429
  int64_t   ntables;
430 431 432 433
  uint64_t  data_of_rate;
  int64_t   start_time;
  char*     cols;
  bool      use_metric;
434 435 436
  SSuperTable* superTblInfo;

  // for async insert
437 438
  tsem_t    lock_sem;
  int64_t   counter;
439 440
  uint64_t  st;
  uint64_t  et;
441
  uint64_t  lastTs;
442

443
  // sample data
444
  int64_t   samplePos;
445
  // statistics
446 447
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
448 449

  // insert delay statistics
450 451 452 453 454
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
455

456
  // seq of query or subscribe
457
  uint64_t  querySeq;   // sequence number of sql command
458
  TAOS_SUB*  tsub;
459

460 461
} threadInfo;

462
#ifdef WINDOWS
463 464
#define _CRT_RAND_S

465
#include <windows.h>
466 467 468 469 470
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
471 472
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
473 474
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
475 476 477 478

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

479
static void setupForAnsiEscape(void) {
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
  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());
498
  }
499 500
}

501
static void resetAfterAnsiEscape(void) {
502
  // Reset colors
503
  printf("\x1b[0m");
504 505 506 507 508 509

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

511
static int taosRandom()
512 513 514 515 516 517
{
    int number;
    rand_s(&number);

    return number;
}
518
#else   // Not windows
519
static void setupForAnsiEscape(void) {}
520

521
static void resetAfterAnsiEscape(void) {
522 523 524
  // Reset colors
  printf("\x1b[0m");
}
525

526 527
#include <time.h>

528
static int taosRandom()
529
{
530
  return rand();
531 532
}

533
#endif // ifdef Windows
534

535
static void prompt();
536
static int createDatabasesAndStables();
537
static void createChildTables();
538
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
539
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
540
        uint16_t port, char* sqlstr, threadInfo *pThreadInfo);
541 542
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
                  int disorderRatio, int disorderRange);
543 544 545 546 547 548 549

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

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

553
SArguments g_args = {
554 555
                     NULL,            // metaFile
                     0,               // test_mode
556 557 558
                     "127.0.0.1",     // host
                     6030,            // port
                     "root",          // user
559
                     #ifdef _TD_POWER_
560 561 562 563 564 565 566 567
                     "powerdb",      // password
                     #else
                     "taosdata",      // password
                     #endif
                     "test",          // database
                     1,               // replica
                     "t",             // tb_prefix
                     NULL,            // sqlFile
568
                     true,            // use_metric
569
                     true,            // drop_database
570
                     true,            // insert_only
571
                     false,           // debug_print
572
                     false,           // verbose_print
573
                     false,           // performance statistic print
574 575 576 577
                     false,           // answer_yes;
                     "./output.txt",  // output_file
                     0,               // mode : sync or async
                     {
578 579 580 581
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
582 583
                     },
                     16,              // len_of_binary
584
                     4,               // num_of_CPR
585 586
                     10,              // num_of_connections/thread
                     0,               // insert_interval
587
                     1,               // query_times
588
                     0,               // interlace_rows;
589
                     30000,           // num_of_RPR
590
                     (1024*1024),         // max_sql_len
591 592 593 594 595 596 597 598 599 600 601 602
                     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;
603
static int64_t         g_totalChildTables = 0;
604 605 606 607
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

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

611
#define verbosePrint(fmt, ...) \
612 613
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
614

615 616 617 618
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

619 620 621 622
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


623
///////////////////////////////////////////////////
H
hzcheng 已提交
624

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

627 628 629 630 631 632 633 634
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

635
#ifndef TAOSDEMO_STATUS
636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
#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);
    }
}

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

720 721 722 723 724 725 726 727 728 729 730 731 732 733 734
static bool isStringNumber(char *input)
{
  int len = strlen(input);
  if (0 == len) {
    return false;
  }

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

  return true;
}

735
static void parse_args(int argc, char *argv[], SArguments *arguments) {
736 737 738 739 740

  for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-f") == 0) {
      arguments->metaFile = argv[++i];
    } else if (strcmp(argv[i], "-c") == 0) {
741 742 743 744 745
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
746
      tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
747
    } else if (strcmp(argv[i], "-h") == 0) {
748 749 750 751 752
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-h need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
753 754
      arguments->host = argv[++i];
    } else if (strcmp(argv[i], "-p") == 0) {
755 756 757 758 759 760
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-p need a number following!\n");
        exit(EXIT_FAILURE);
      }
761 762
      arguments->port = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-u") == 0) {
763 764 765 766 767
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-u need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
768 769
      arguments->user = argv[++i];
    } else if (strcmp(argv[i], "-P") == 0) {
770 771 772 773 774
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-P need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
775 776
      arguments->password = argv[++i];
    } else if (strcmp(argv[i], "-o") == 0) {
777 778 779 780 781
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-o need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
782 783
      arguments->output_file = argv[++i];
    } else if (strcmp(argv[i], "-s") == 0) {
784 785 786 787 788
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-s need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
789 790
      arguments->sqlFile = argv[++i];
    } else if (strcmp(argv[i], "-q") == 0) {
791 792
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
793
        printHelp();
794
        errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, 1: ASYNC. Default is SYNC.\n");
795 796
        exit(EXIT_FAILURE);
      }
797
      arguments->async_mode = atoi(argv[++i]);
798
    } else if (strcmp(argv[i], "-T") == 0) {
799 800
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
801 802 803 804
        printHelp();
        errorPrint("%s", "\n\t-T need a number following!\n");
        exit(EXIT_FAILURE);
      }
805 806
      arguments->num_of_threads = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-i") == 0) {
807 808
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
809 810 811 812
        printHelp();
        errorPrint("%s", "\n\t-i need a number following!\n");
        exit(EXIT_FAILURE);
      }
813
      arguments->insert_interval = atoi(argv[++i]);
814
    } else if (strcmp(argv[i], "-qt") == 0) {
815 816
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
817
        printHelp();
818
        errorPrint("%s", "\n\t-qt need a number following!\n");
819 820
        exit(EXIT_FAILURE);
      }
821
      arguments->query_times = atoi(argv[++i]);
822
    } else if (strcmp(argv[i], "-B") == 0) {
823 824
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
825 826 827 828
        printHelp();
        errorPrint("%s", "\n\t-B need a number following!\n");
        exit(EXIT_FAILURE);
      }
829
      arguments->interlace_rows = atoi(argv[++i]);
830
    } else if (strcmp(argv[i], "-r") == 0) {
831 832
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
833 834 835 836
        printHelp();
        errorPrint("%s", "\n\t-r need a number following!\n");
        exit(EXIT_FAILURE);
      }
837 838
      arguments->num_of_RPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-t") == 0) {
839 840 841 842 843 844
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-t need a number following!\n");
        exit(EXIT_FAILURE);
      }
845 846
      arguments->num_of_tables = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-n") == 0) {
847 848 849 850 851 852
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-n need a number following!\n");
        exit(EXIT_FAILURE);
      }
853 854
      arguments->num_of_DPT = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-d") == 0) {
855 856 857 858 859
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-d need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
860 861
      arguments->database = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0) {
862 863 864 865 866 867
      if (argc == i+1) {
        if (!isStringNumber(argv[i+1])) {
            printHelp();
            errorPrint("%s", "\n\t-l need a number following!\n");
            exit(EXIT_FAILURE);
        }
868
      }
869
      arguments->num_of_CPR = atoi(argv[++i]);
870 871 872 873 874 875 876 877 878 879 880

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

      for (int col = arguments->num_of_CPR; col < MAX_NUM_DATATYPE; col++) {
          arguments->datatype[col] = NULL;
      }

881
    } else if (strcmp(argv[i], "-b") == 0) {
882 883 884 885 886
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-b need valid string following!\n");
        exit(EXIT_FAILURE);
      }
887 888
      ++i;
      if (strstr(argv[i], ",") == NULL) {
889
        // only one col
890 891 892 893 894 895 896
        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")
897
                && strcasecmp(argv[i], "BINARY")
898 899
                && strcasecmp(argv[i], "NCHAR")) {
          printHelp();
900
          errorPrint("%s", "-b: Invalid data_type!\n");
901
          exit(EXIT_FAILURE);
902
        }
903
        arguments->datatype[0] = argv[i];
904
      } else {
905
        // more than one col
906
        int index = 0;
907 908
        g_dupstr = strdup(argv[i]);
        char *running = g_dupstr;
909
        char *token = strsep(&running, ",");
910
        while(token != NULL) {
911 912 913 914 915 916 917 918 919 920
          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();
921
            free(g_dupstr);
922
            errorPrint("%s", "-b: Invalid data_type!\n");
923
            exit(EXIT_FAILURE);
H
hzcheng 已提交
924
          }
925
          arguments->datatype[index++] = token;
926 927
          token = strsep(&running, ",");
          if (index >= MAX_NUM_DATATYPE) break;
S
TD-1057  
Shengliang Guan 已提交
928
        }
929
        arguments->datatype[index] = NULL;
930
      }
931
    } else if (strcmp(argv[i], "-w") == 0) {
932 933 934 935 936 937
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-w need a number following!\n");
        exit(EXIT_FAILURE);
      }
938 939
      arguments->len_of_binary = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-m") == 0) {
940 941 942 943 944 945
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-m need a number following!\n");
        exit(EXIT_FAILURE);
      }
946
      arguments->tb_prefix = argv[++i];
947 948
    } else if (strcmp(argv[i], "-N") == 0) {
      arguments->use_metric = false;
949
    } else if (strcmp(argv[i], "-x") == 0) {
950
      arguments->insert_only = false;
951
    } else if (strcmp(argv[i], "-y") == 0) {
952
      arguments->answer_yes = true;
953 954
    } else if (strcmp(argv[i], "-g") == 0) {
      arguments->debug_print = true;
955 956
    } else if (strcmp(argv[i], "-gg") == 0) {
      arguments->verbose_print = true;
957 958
    } else if (strcmp(argv[i], "-pp") == 0) {
      arguments->performance_print = true;
959
    } else if (strcmp(argv[i], "-O") == 0) {
960 961 962 963 964 965
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-O need a number following!\n");
        exit(EXIT_FAILURE);
      }
966

967
      arguments->disorderRatio = atoi(argv[++i]);
968

969
      if (arguments->disorderRatio > 50) {
970
        arguments->disorderRatio = 50;
971
      }
972

973
      if (arguments->disorderRatio < 0) {
974
        arguments->disorderRatio = 0;
975
      }
976

977
    } else if (strcmp(argv[i], "-R") == 0) {
978 979 980 981 982 983
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
984

985
      arguments->disorderRange = atoi(argv[++i]);
986 987 988
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

989
    } else if (strcmp(argv[i], "-a") == 0) {
990 991 992 993 994 995
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-a need a number following!\n");
        exit(EXIT_FAILURE);
      }
996 997 998
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
999
      }
1000 1001
    } else if (strcmp(argv[i], "-D") == 0) {
      arguments->method_of_delete = atoi(argv[++i]);
1002 1003 1004
      if (arguments->method_of_delete > 3) {
        errorPrint("%s", "\n\t-D need a valud (0~3) number following!\n");
        exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
1005
      }
1006 1007 1008 1009
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
1010 1011 1012 1013 1014
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
1015
      errorPrint("%s", "ERROR: wrong options\n");
1016
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
1017 1018
    }
  }
1019

1020 1021
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
          || arguments->verbose_print) {
1022
    printf("###################################################################\n");
1023
    printf("# meta file:                         %s\n", arguments->metaFile);
1024
    printf("# Server IP:                         %s:%hu\n",
1025 1026 1027 1028 1029
            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");
1030 1031 1032 1033 1034 1035 1036 1037 1038
    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");
    }
1039
    printf("# Insertion interval:                %"PRIu64"\n",
1040
            arguments->insert_interval);
1041
    printf("# Number of records per req:         %"PRIu64"\n",
1042
            arguments->num_of_RPR);
1043
    printf("# Max SQL length:                    %"PRIu64"\n",
1044
            arguments->max_sql_len);
1045
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1046
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1047
    printf("# Number of Tables:                  %"PRId64"\n",
1048
            arguments->num_of_tables);
1049
    printf("# Number of Data per Table:          %"PRId64"\n",
1050
            arguments->num_of_DPT);
1051 1052 1053 1054 1055
    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);
1056

1057 1058 1059 1060
    }
    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);
1061
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1062
    printf("###################################################################\n");
1063 1064

    prompt();
1065
  }
1066
}
H
hzcheng 已提交
1067

1068 1069 1070 1071
static bool getInfoFromJsonFile(char* file);
//static int generateOneRowDataForStb(SSuperTable* stbInfo);
//static int getDataIntoMemForStb(SSuperTable* stbInfo);
static void init_rand_data();
1072
static void tmfclose(FILE *fp) {
1073 1074 1075 1076
  if (NULL != fp) {
    fclose(fp);
  }
}
1077

1078
static void tmfree(char *buf) {
1079 1080
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1081
  }
1082
}
H
Hui Li 已提交
1083

1084
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1085 1086 1087
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1088

1089 1090 1091 1092
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1093
    }
1094

1095 1096 1097 1098
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1099
    }
H
hzcheng 已提交
1100 1101
  }

1102
  verbosePrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
1103
  if (code != 0) {
1104
    if (!quiet) {
1105
      errorPrint("Failed to execute %s, reason: %s\n", command, taos_errstr(res));
1106
    }
1107 1108 1109
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1110
  }
H
hzcheng 已提交
1111

1112 1113 1114 1115
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1116
  }
1117

1118
  taos_free_result(res);
1119 1120
  return 0;
}
H
hzcheng 已提交
1121

1122
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
1123
{
1124 1125
  pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
  if (pThreadInfo->fp == NULL) {
1126 1127
      errorPrint(
              "%s() LN%d, failed to open result file: %s, result will not save to file\n",
1128
              __func__, __LINE__, pThreadInfo->filePath);
1129 1130
      return;
  }
1131

1132 1133 1134
  fprintf(pThreadInfo->fp, "%s", resultBuf);
  tmfclose(pThreadInfo->fp);
  pThreadInfo->fp = NULL;
1135
}
1136

1137
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
1138 1139 1140 1141 1142
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

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

1150 1151
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1152

1153
  // fetch the records row by row
1154
  while((row = taos_fetch_row(res))) {
1155
    if ((strlen(pThreadInfo->filePath) > 0)
1156
            && (totalLen >= 100*1024*1024 - 32000)) {
1157
        appendResultBufToFile(databuf, pThreadInfo);
1158 1159
        totalLen = 0;
        memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1160
    }
1161 1162 1163 1164 1165 1166
    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 已提交
1167 1168
  }

1169
  verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
1170 1171 1172
          __func__, __LINE__, databuf, pThreadInfo->filePath);
  if (strlen(pThreadInfo->filePath) > 0) {
    appendResultBufToFile(databuf, pThreadInfo);
1173
  }
1174 1175
  free(databuf);
}
H
hzcheng 已提交
1176

1177
static void selectAndGetResult(
1178
        threadInfo *pThreadInfo, char *command)
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
{
  if (0 == strncasecmp(g_queryInfo.queryMode, "taosc", strlen("taosc"))) {
    TAOS_RES *res = taos_query(pThreadInfo->taos, command);
    if (res == NULL || taos_errno(res) != 0) {
        errorPrint("%s() LN%d, failed to execute sql:%s, reason:%s\n",
            __func__, __LINE__, command, taos_errstr(res));
        taos_free_result(res);
        return;
    }

1189
    fetchResult(res, pThreadInfo);
1190
    taos_free_result(res);
1191

1192 1193 1194 1195
  } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
      int retCode = postProceSql(
              g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
              command,
1196
              pThreadInfo);
1197 1198 1199 1200 1201 1202 1203 1204
      if (0 != retCode) {
        printf("====restful return fail, threadID[%d]\n", pThreadInfo->threadID);
      }

  } else {
      errorPrint("%s() LN%d, unknown query mode: %s\n",
        __func__, __LINE__, g_queryInfo.queryMode);
  }
1205
}
H
hzcheng 已提交
1206

1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245
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;
1246
  return randfloat[cursor];
1247 1248
}

1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265
#if 0
static const char charNum[] = "0123456789";

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

1266
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1267

1268
static void rand_string(char *str, int size) {
1269 1270 1271 1272
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1273
    for (n = 0; n < size; n++) {
1274
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290
      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++){
1291 1292 1293 1294
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1295 1296 1297
  }
}

1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317
#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)

1318
static int printfInsertMeta() {
1319 1320
    SHOW_PARSE_RESULT_START();

1321 1322
  printf("host:                       \033[33m%s:%u\033[0m\n",
          g_Dbs.host, g_Dbs.port);
1323 1324
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
1325
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1326 1327
  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);
1328 1329
  printf("thread num of create table: \033[33m%d\033[0m\n",
          g_Dbs.threadCountByCreateTbl);
1330
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1331
          g_args.insert_interval);
1332
  printf("number of records per req:  \033[33m%"PRIu64"\033[0m\n",
1333
          g_args.num_of_RPR);
1334
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1335
          g_args.max_sql_len);
1336 1337

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

1339 1340
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1341 1342
    printf("  database[%d] name:      \033[33m%s\033[0m\n",
            i, g_Dbs.db[i].dbName);
1343
    if (0 == g_Dbs.db[i].drop) {
1344 1345 1346
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1347 1348 1349
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
1350 1351
      printf("  blocks:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.blocks);
1352 1353
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
1354 1355
      printf("  cache:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.cache);
1356 1357
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
1358 1359
      printf("  days:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.days);
1360 1361
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
1362 1363
      printf("  keep:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.keep);
1364 1365
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
1366 1367
      printf("  replica:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.replica);
1368 1369
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
1370 1371
      printf("  update:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.update);
1372 1373
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
1374 1375
      printf("  minRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.minRows);
1376 1377
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
1378 1379
      printf("  maxRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.maxRows);
1380 1381 1382 1383 1384
    }
    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) {
1385 1386
      printf("  walLevel:              \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.walLevel);
1387 1388
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
1389 1390
      printf("  fsync:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.fsync);
1391 1392
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
1393 1394
      printf("  quorum:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.quorum);
1395 1396
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1397 1398
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1399 1400
        printf("  precision:             \033[33m%s\033[0m\n",
            g_Dbs.db[i].dbCfg.precision);
1401
      } else {
1402 1403 1404
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                g_Dbs.db[i].dbCfg.precision);
        return -1;
1405 1406 1407
      }
    }

1408
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1409
        g_Dbs.db[i].superTblCount);
1410 1411
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1412

1413 1414
      printf("      stbName:           \033[33m%s\033[0m\n",
          g_Dbs.db[i].superTbls[j].sTblName);
1415 1416 1417 1418 1419 1420 1421 1422

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

1424 1425 1426 1427 1428 1429 1430
      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");
      }
1431

1432
      printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
1433 1434 1435 1436 1437 1438 1439
              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);
1440
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1441
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1442
                g_Dbs.db[i].superTbls[j].childTblLimit);
1443
      }
1444
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1445
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1446
                g_Dbs.db[i].superTbls[j].childTblOffset);
1447
      }
1448
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
1449
              g_Dbs.db[i].superTbls[j].insertRows);
1450
/*
1451
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1452
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1453
      }else {
1454
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1455
      }
1456
      */
1457
      printf("      interlaceRows:     \033[33m%"PRIu64"\033[0m\n",
1458
              g_Dbs.db[i].superTbls[j].interlaceRows);
1459 1460

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

1465 1466 1467 1468
      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);
1469
      printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
1470
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1471
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1472 1473 1474 1475 1476 1477 1478 1479 1480
              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);
1481
      printf("      columnCount:       \033[33m%d\033[0m\n",
1482
              g_Dbs.db[i].superTbls[j].columnCount);
1483 1484
      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);
1485 1486 1487 1488
        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))) {
1489
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1490 1491
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1492
        } else {
1493 1494
          printf("column[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1495 1496 1497
        }
      }
      printf("\n");
1498 1499 1500

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1501 1502
      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);
1503 1504 1505 1506
        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")))) {
1507
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1508 1509
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1510
        } else {
1511 1512
          printf("tag[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1513
        }
1514 1515 1516 1517 1518
      }
      printf("\n");
    }
    printf("\n");
  }
1519 1520

  SHOW_PARSE_RESULT_END();
1521 1522

  return 0;
1523 1524 1525
}

static void printfInsertMetaToFile(FILE* fp) {
1526 1527

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1528

1529 1530
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1531
  fprintf(fp, "configDir:                  %s\n", configDir);
1532 1533 1534
  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);
1535 1536
  fprintf(fp, "number of records per req:  %"PRIu64"\n", g_args.num_of_RPR);
  fprintf(fp, "max sql length:             %"PRIu64"\n", g_args.max_sql_len);
1537
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1538

1539 1540
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1541
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1542
    if (0 == g_Dbs.db[i].drop) {
1543
      fprintf(fp, "  drop:                  no\n");
1544
    }else {
1545
      fprintf(fp, "  drop:                  yes\n");
1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
    }

    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) {
1585 1586
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1587 1588
        fprintf(fp, "  precision:             %s\n",
                g_Dbs.db[i].dbCfg.precision);
1589
      } else {
1590 1591
        fprintf(fp, "  precision error:       %s\n",
                g_Dbs.db[i].dbCfg.precision);
1592 1593 1594
      }
    }

1595 1596
    fprintf(fp, "  super table count:     %"PRIu64"\n",
            g_Dbs.db[i].superTblCount);
1597 1598
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1599

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

      if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
        fprintf(fp, "      autoCreateTable:   %s\n",  "no");
1605 1606
      } else if (AUTO_CREATE_SUBTBL
              == g_Dbs.db[i].superTbls[j].autoCreateTable) {
1607 1608 1609 1610
        fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
      } else {
        fprintf(fp, "      autoCreateTable:   %s\n",  "error");
      }
1611

1612 1613
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
1614 1615
      } else if (TBL_ALREADY_EXISTS
              == g_Dbs.db[i].superTbls[j].childTblExists) {
1616 1617 1618 1619
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1620

1621
      fprintf(fp, "      childTblCount:     %"PRId64"\n",
1622 1623 1624 1625 1626 1627 1628
              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);
1629
      fprintf(fp, "      insertRows:        %"PRId64"\n",
1630
              g_Dbs.db[i].superTbls[j].insertRows);
1631
      fprintf(fp, "      interlace rows:    %"PRIu64"\n",
1632
              g_Dbs.db[i].superTbls[j].interlaceRows);
1633
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1634
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1635
                g_Dbs.db[i].superTbls[j].insertInterval);
1636
      }
1637
/*
1638
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1639
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1640
      }else {
1641
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1642
      }
1643
      */
1644
      fprintf(fp, "      interlaceRows:     %"PRIu64"\n",
1645
              g_Dbs.db[i].superTbls[j].interlaceRows);
1646 1647 1648 1649
      fprintf(fp, "      disorderRange:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRange);
      fprintf(fp, "      disorderRatio:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRatio);
1650
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1651
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1652

1653 1654 1655 1656
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1657 1658 1659 1660 1661 1662
      fprintf(fp, "      sampleFormat:      %s\n",
              g_Dbs.db[i].superTbls[j].sampleFormat);
      fprintf(fp, "      sampleFile:        %s\n",
              g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",
              g_Dbs.db[i].superTbls[j].tagsFile);
1663

1664 1665
      fprintf(fp, "      columnCount:       %d\n        ",
              g_Dbs.db[i].superTbls[j].columnCount);
1666 1667
      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);
1668 1669 1670
        if ((0 == strncasecmp(
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "binary", strlen("binary")))
1671 1672
                || (0 == strncasecmp(
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
1673 1674 1675 1676
                        "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);
1677
        } else {
1678 1679
          fprintf(fp, "column[%d]:%s ",
                  k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
1680 1681 1682
        }
      }
      fprintf(fp, "\n");
1683 1684 1685

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1686 1687
      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);
1688 1689 1690 1691
        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")))) {
1692 1693
          fprintf(fp, "tag[%d]:%s(%d) ",
                  k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
1694
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1695 1696
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1697
        }
1698 1699 1700 1701 1702
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1703

1704
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1705 1706 1707
}

static void printfQueryMeta() {
1708

1709
  SHOW_PARSE_RESULT_START();
1710

1711 1712
  printf("host:                    \033[33m%s:%u\033[0m\n",
          g_queryInfo.host, g_queryInfo.port);
1713 1714 1715 1716
  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");
1717 1718 1719 1720

  if ((SUBSCRIBE_TEST == g_args.test_mode) || (QUERY_TEST == g_args.test_mode)) {
    printf("specified table query info:                   \n");
    printf("sqlCount:       \033[33m%"PRIu64"\033[0m\n",
1721
      g_queryInfo.specifiedQueryInfo.sqlCount);
1722 1723 1724
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1725
      g_queryInfo.specifiedQueryInfo.queryTimes);
1726 1727 1728
      printf("query interval: \033[33m%"PRIu64" ms\033[0m\n",
        g_queryInfo.specifiedQueryInfo.queryInterval);
      printf("top query times:\033[33m%"PRIu64"\033[0m\n", g_args.query_times);
1729
      printf("concurrent:     \033[33m%d\033[0m\n",
1730 1731
      g_queryInfo.specifiedQueryInfo.concurrent);
      printf("mod:            \033[33m%s\033[0m\n",
1732
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1733
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1734
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1735
      printf("restart:        \033[33m%d\033[0m\n",
1736
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1737
      printf("keepProgress:   \033[33m%d\033[0m\n",
1738
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1739

1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755
      for (uint64_t i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        printf("  sql[%"PRIu64"]: \033[33m%s\033[0m\n",
            i, g_queryInfo.specifiedQueryInfo.sql[i]);
      }
      printf("\n");
    }

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

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

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

1772 1773 1774 1775 1776 1777
      for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
        printf("  sql[%d]: \033[33m%s\033[0m\n",
            i, g_queryInfo.superQueryInfo.sql[i]);
      }
      printf("\n");
    }
1778
  }
1779

1780
  SHOW_PARSE_RESULT_END();
1781 1782
}

1783
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814
  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;
}

1815 1816 1817
static void xDumpFieldToFile(FILE* fp, const char* val,
        TAOS_FIELD* field, int32_t length, int precision) {

1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852
  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:
1853
      formatTimestamp(buf, *(int64_t*)val, precision);
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868
      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) {
1869
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883
    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);
1884

1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904
  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;
}

1905 1906
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1907 1908
  TAOS_ROW row = NULL;
  int count = 0;
1909 1910

  res = taos_query(taos, "show databases;");
1911
  int32_t code = taos_errno(res);
1912

1913
  if (code != 0) {
1914
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1915 1916 1917 1918 1919
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1920
  while((row = taos_fetch_row(res)) != NULL) {
1921
    // sys database name : 'log'
1922 1923 1924 1925
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
      continue;
    }
1926 1927 1928

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

1933 1934
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1935
    formatTimestamp(dbInfos[count]->create_time,
1936 1937
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1938
    dbInfos[count]->ntables = *((int64_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1939
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1940 1941
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1942
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1943

1944
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1945
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1946 1947 1948 1949 1950 1951 1952
    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]));
1953 1954
    dbInfos[count]->cachelast =
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1955

1956
    tstrncpy(dbInfos[count]->precision,
1957
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
1958
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1959
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1960
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1961
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1962

1963 1964
    count++;
    if (count > MAX_DATABASE_COUNT) {
1965 1966
      errorPrint("%s() LN%d, The database count overflow than %d\n",
         __func__, __LINE__, MAX_DATABASE_COUNT);
1967 1968 1969 1970 1971 1972 1973
      break;
    }
  }

  return count;
}

1974 1975
static void printfDbInfoForQueryToFile(
        char* filename, SDbInfo* dbInfos, int index) {
1976

1977
  if (filename[0] == 0)
1978
      return;
1979 1980 1981

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1982
    errorPrint( "failed to open file: %s\n", filename);
1983
    return;
1984 1985 1986 1987 1988
  }

  fprintf(fp, "================ database[%d] ================\n", index);
  fprintf(fp, "name: %s\n", dbInfos->name);
  fprintf(fp, "created_time: %s\n", dbInfos->create_time);
1989
  fprintf(fp, "ntables: %"PRId64"\n", dbInfos->ntables);
1990
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1991 1992
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1993 1994
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1995 1996 1997 1998 1999 2000 2001
  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);
2002 2003
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
2004
  fprintf(fp, "update: %d\n", dbInfos->update);
2005
  fprintf(fp, "status: %s\n", dbInfos->status);
2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019
  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);
2020 2021 2022 2023
  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);

2024 2025
  // show variables
  res = taos_query(taos, "show variables;");
2026
  //fetchResult(res, filename);
2027 2028 2029 2030 2031
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
2032
  //fetchResult(res, filename);
2033

2034 2035 2036 2037
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
2038
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
2039 2040 2041
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
2042 2043 2044 2045
  if (dbCount <= 0) {
      free(dbInfos);
      return;
  }
2046 2047

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

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

2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066
    // 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);
}

2067
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
2068
        char* sqlstr, threadInfo *pThreadInfo)
2069
{
2070
    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";
2071 2072 2073

    char *url = "/rest/sql";

2074
    int bytes, sent, received, req_str_len, resp_len;
2075 2076 2077
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
2078

2079 2080 2081
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

    request_buf = malloc(req_buf_len);
2082 2083 2084 2085
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2086

2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097
    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', '+', '/'};
2098

2099 2100 2101 2102 2103 2104
    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];
2105
#ifdef WINDOWS
2106
    WSADATA wsaData;
2107
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2108 2109 2110 2111
    SOCKET sockfd;
#else
    int sockfd;
#endif
2112
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
2113
    if (sockfd < 0) {
2114
#ifdef WINDOWS
2115
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2116
#endif
2117
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
2118
        free(request_buf);
2119
        ERROR_EXIT("ERROR opening socket");
2120
    }
2121

2122
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2123 2124
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
2125
        free(request_buf);
2126
        ERROR_EXIT("ERROR connecting");
2127
    }
2128

2129 2130 2131
    memset(base64_buf, 0, INPUT_BUF_LEN);

    for (int n = 0, m = 0; n < userpass_buf_len;) {
2132
      uint32_t oct_a = n < userpass_buf_len ?
2133
        (unsigned char) userpass_buf[n++]:0;
2134
      uint32_t oct_b = n < userpass_buf_len ?
2135
        (unsigned char) userpass_buf[n++]:0;
2136
      uint32_t oct_c = n < userpass_buf_len ?
2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148
        (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] = '=';

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

2153 2154 2155
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
2156 2157 2158 2159 2160
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
2161
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
2162

2163
    req_str_len = strlen(request_buf);
2164 2165
    sent = 0;
    do {
2166 2167 2168
#ifdef WINDOWS
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
#else
2169
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2170
#endif
2171
        if (bytes < 0)
2172
            ERROR_EXIT("ERROR writing message to socket");
2173 2174 2175
        if (bytes == 0)
            break;
        sent+=bytes;
2176
    } while(sent < req_str_len);
2177

2178 2179
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
2180 2181
    received = 0;
    do {
2182 2183 2184
#ifdef WINDOWS
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
#else
2185
        bytes = read(sockfd, response_buf + received, resp_len - received);
2186
#endif
2187 2188
        if (bytes < 0) {
            free(request_buf);
2189
            ERROR_EXIT("ERROR reading response from socket");
2190
        }
2191 2192
        if (bytes == 0)
            break;
2193
        received += bytes;
2194
    } while(received < resp_len);
2195

2196 2197
    if (received == resp_len) {
        free(request_buf);
2198
        ERROR_EXIT("ERROR storing complete response from socket");
2199
    }
2200

2201
    response_buf[RESP_BUF_LEN - 1] = '\0';
2202 2203
    printf("Response:\n%s\n", response_buf);

2204 2205
    if (strlen(pThreadInfo->filePath) > 0) {
       appendResultBufToFile(response_buf, pThreadInfo);
2206 2207
    }

2208
    free(request_buf);
2209 2210 2211 2212
#ifdef WINDOWS
    closesocket(sockfd);
    WSACleanup();
#else
2213
    close(sockfd);
2214
#endif
2215 2216 2217 2218

    return 0;
}

2219
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2220 2221
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2222 2223
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2224 2225
    return NULL;
  }
2226

2227
  int    dataLen = 0;
2228 2229 2230
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);

2231 2232 2233
  return dataBuf;
}

2234
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2235 2236 2237 2238 2239 2240 2241 2242 2243
  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++) {
2244 2245
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2246
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2247 2248
        printf("binary or nchar length overflow, max size:%u\n",
                (uint32_t)TSDB_MAX_BINARY_LEN);
2249 2250 2251
        tmfree(dataBuf);
        return NULL;
      }
2252

2253 2254
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2255 2256 2257 2258 2259
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2260 2261 2262 2263 2264 2265 2266

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2267 2268
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
              "\'%s\', ", buf);
2269
      tmfree(buf);
2270 2271 2272
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
                "int", strlen("int"))) {
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2273
              "%d, ", tableSeq);
2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
    } 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());
2302 2303 2304 2305 2306 2307
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2308

2309
  dataLen -= 2;
2310
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2311 2312 2313
  return dataBuf;
}

2314
static int calcRowLen(SSuperTable*  superTbls) {
2315 2316
  int colIndex;
  int  lenOfOneRow = 0;
2317

2318 2319
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2320

2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336
    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;
2337
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2338
      lenOfOneRow += 42;
2339
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352
      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;
2353

2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369
    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;
2370
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2371 2372 2373 2374 2375 2376 2377 2378
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2379

2380 2381 2382 2383
  return 0;
}


2384 2385
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2386
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2387

2388
  char command[BUFFER_SIZE] = "\0";
2389 2390
  char limitBuf[100] = "\0";

2391
  TAOS_RES * res;
2392 2393 2394
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2395 2396

  if (offset >= 0) {
2397
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2398
            limit, offset);
2399 2400
  }

2401
  //get all child table name use cmd: select tbname from superTblName;
2402 2403
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
          dbName, sTblName, limitBuf);
2404

2405
  res = taos_query(taos, command);
2406 2407 2408 2409
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2410 2411
    errorPrint("%s() LN%d, failed to run command %s\n",
           __func__, __LINE__, command);
2412 2413 2414
    exit(-1);
  }

2415 2416
  int64_t childTblCount = (limit < 0)?10000:limit;
  int64_t count = 0;
2417 2418 2419 2420 2421 2422 2423 2424 2425 2426
  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);
    }
  }

2427
  char* pTblName = childTblName;
2428
  while((row = taos_fetch_row(res)) != NULL) {
2429
    int32_t* len = taos_fetch_lengths(res);
2430
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2431 2432 2433
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2434 2435
      char *tmp = realloc(childTblName,
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2436 2437 2438
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2439 2440
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2441 2442
      } else {
        // exit, if allocate more memory failed
2443 2444
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
               __func__, __LINE__, dbName, sTblName);
2445 2446 2447 2448 2449 2450
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2451
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2452
  }
2453

2454 2455 2456 2457 2458 2459 2460
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2461 2462
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
        char* sTblName, char** childTblNameOfSuperTbl,
2463
        int64_t* childTblCountOfSuperTbl) {
2464 2465 2466

    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2467
            -1, 0);
2468 2469
}

2470 2471
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2472

2473
  char command[BUFFER_SIZE] = "\0";
2474
  TAOS_RES * res;
2475 2476
  TAOS_ROW row = NULL;
  int count = 0;
2477

2478
  //get schema use cmd: describe superTblName;
2479
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2480
  res = taos_query(taos, command);
2481 2482 2483
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2484
    taos_free_result(res);
2485 2486 2487 2488 2489 2490
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2491
  while((row = taos_fetch_row(res)) != NULL) {
2492 2493 2494
    if (0 == count) {
      count++;
      continue;
2495
    }
2496 2497

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508
      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);
2509
      tagIndex++;
2510
    } else {
2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521
      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);
2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2533
/*
2534
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2535
    //get all child table name use cmd: select tbname from superTblName;
2536 2537 2538
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2539
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2540 2541
      return -1;
    }
2542
    getAllChildNameOfSuperTable(taos, dbName,
2543 2544 2545
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2546
  }
2547
  */
2548 2549 2550
  return 0;
}

2551 2552
static int createSuperTable(
        TAOS * taos, char* dbName,
2553
        SSuperTable*  superTbl) {
2554

2555
  char command[BUFFER_SIZE] = "\0";
2556

2557 2558 2559 2560 2561
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2562 2563 2564 2565 2566 2567 2568 2569 2570

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

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

2572
    if (strcasecmp(dataType, "BINARY") == 0) {
2573 2574
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "BINARY",
2575 2576
          superTbl->columns[colIndex].dataLen);
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2577
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2578 2579
      len += snprintf(cols + len, STRING_LEN - len,
          ", col%d %s(%d)", colIndex, "NCHAR",
2580 2581
          superTbl->columns[colIndex].dataLen);
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599
    } 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;
2600
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2601 2602
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2603
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2604 2605 2606 2607
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2608 2609
      errorPrint("%s() LN%d, config error data type : %s\n",
         __func__, __LINE__, dataType);
2610 2611 2612 2613
      exit(-1);
    }
  }

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

  // save for creating child table
2618 2619 2620 2621
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
           __func__, __LINE__, len+1);
2622 2623 2624 2625
    taos_close(taos);
    exit(-1);
  }

2626
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2627 2628
  verbosePrint("%s() LN%d: %s\n",
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2629

2630 2631 2632 2633 2634
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
            __func__, __LINE__, superTbl->tagCount);
    return -1;
  }
2635

2636 2637 2638
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2639

2640 2641 2642 2643
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2644

2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
              "BINARY", superTbl->tags[tagIndex].dataLen);
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
              "NCHAR", superTbl->tags[tagIndex].dataLen);
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "INT");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "BIGINT");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "SMALLINT");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "TINYINT");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "BOOL");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "FLOAT");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
              "DOUBLE");
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
    } else {
      taos_close(taos);
2683 2684
      errorPrint("%s() LN%d, config error tag type : %s\n",
         __func__, __LINE__, dataType);
2685
      exit(-1);
2686 2687
    }
  }
2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

  snprintf(command, BUFFER_SIZE,
          "create table if not exists %s.%s (ts timestamp%s) tags %s",
          dbName, superTbl->sTblName, cols, tags);
  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2703 2704 2705
  return 0;
}

2706
static int createDatabasesAndStables() {
2707 2708 2709 2710
  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) {
2711
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2712
    return -1;
2713 2714 2715
  }
  char command[BUFFER_SIZE] = "\0";

2716
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2717 2718
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2719
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2720 2721 2722 2723
        taos_close(taos);
        return -1;
      }

2724
      int dataLen = 0;
2725
      dataLen += snprintf(command + dataLen,
2726
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2727

2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
      }
      //if (g_Dbs.db[i].dbCfg.maxtablesPerVnode > 0) {
      //  dataLen += snprintf(command + dataLen,
      //  BUFFER_SIZE - dataLen, "tables %d ", g_Dbs.db[i].dbCfg.maxtablesPerVnode);
      //}
      if (g_Dbs.db[i].dbCfg.minRows > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
      }

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

2799
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2800
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2801 2802 2803

    int validStbCount = 0;

2804
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2805 2806 2807 2808 2809
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      ret = queryDbExec(taos, command, NO_INSERT_TYPE, true);

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

2813
        if (0 != ret) {
2814 2815
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2816 2817 2818
        }
      }

2819
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2820
                &g_Dbs.db[i].superTbls[j]);
2821 2822 2823
      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);
2824
        continue;
2825
      }
2826 2827

      validStbCount ++;
2828
    }
2829 2830

    g_Dbs.db[i].superTblCount = validStbCount;
2831 2832 2833 2834 2835 2836
  }

  taos_close(taos);
  return 0;
}

2837 2838
static void* createTable(void *sarg)
{
2839 2840
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2841 2842 2843

  int64_t  lastPrintTime = taosGetTimestampMs();

2844
  int buff_len;
2845
  buff_len = BUFFER_SIZE / 8;
2846

2847
  char *buffer = calloc(buff_len, 1);
2848
  if (buffer == NULL) {
2849
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2850 2851
    exit(-1);
  }
2852 2853 2854

  int len = 0;
  int batchNum = 0;
2855

2856
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2857
          __func__, __LINE__,
2858
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2859

2860
  for (uint64_t i = pThreadInfo->start_table_from;
2861
          i <= pThreadInfo->end_table_to; i++) {
2862
    if (0 == g_Dbs.use_metric) {
2863
      snprintf(buffer, buff_len,
2864
              "create table if not exists %s.%s%"PRIu64" %s;",
2865
              pThreadInfo->db_name,
2866
              g_args.tb_prefix, i,
2867
              pThreadInfo->cols);
2868
    } else {
2869 2870 2871
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
                  __func__, __LINE__);
2872
        free(buffer);
2873 2874 2875 2876 2877 2878 2879 2880 2881 2882
        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) {
2883
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2884 2885 2886 2887 2888 2889 2890 2891 2892 2893
        } else {
          tagsValBuf = getTagValueFromTagSample(
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
        len += snprintf(buffer + len,
2894
                buff_len - len,
2895
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
2896 2897
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
2898 2899 2900 2901
                superTblInfo->sTblName, tagsValBuf);
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2902
                && ((buff_len - len)
2903 2904 2905
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
          continue;
        }
2906 2907 2908 2909
      }
    }

    len = 0;
2910
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2911
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2912
      free(buffer);
2913 2914 2915 2916 2917
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2918
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2919
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2920 2921 2922
      lastPrintTime = currentPrintTime;
    }
  }
2923

2924
  if (0 != len) {
2925
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2926
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2927
    }
2928
  }
2929

2930 2931 2932 2933
  free(buffer);
  return NULL;
}

2934
static int startMultiThreadCreateChildTable(
2935
        char* cols, int threads, uint64_t startFrom, int64_t ntables,
2936
        char* db_name, SSuperTable* superTblInfo) {
2937

2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949
  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;
  }

2950
  int64_t a = ntables / threads;
2951 2952 2953 2954 2955
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2956
  int64_t b = 0;
2957
  b = ntables % threads;
2958

2959
  for (int64_t i = 0; i < threads; i++) {
2960 2961 2962 2963
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
    tstrncpy(pThreadInfo->db_name, db_name, MAX_DB_NAME_SIZE);
    pThreadInfo->superTblInfo = superTblInfo;
2964
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
2965
    pThreadInfo->taos = taos_connect(
2966 2967 2968 2969 2970
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
2971
    if (pThreadInfo->taos == NULL) {
2972 2973
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
         __func__, __LINE__, taos_errstr(NULL));
2974
      free(pids);
2975
      free(infos);
2976 2977
      return -1;
    }
2978

2979 2980 2981 2982 2983 2984 2985 2986
    pThreadInfo->start_table_from = startFrom;
    pThreadInfo->ntables = i<b?a+1:a;
    pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
    startFrom = pThreadInfo->end_table_to + 1;
    pThreadInfo->use_metric = true;
    pThreadInfo->cols = cols;
    pThreadInfo->minDelay = UINT64_MAX;
    pthread_create(pids + i, NULL, createTable, pThreadInfo);
2987
  }
2988

2989 2990 2991 2992 2993
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

  for (int i = 0; i < threads; i++) {
2994 2995
    threadInfo *pThreadInfo = infos + i;
    taos_close(pThreadInfo->taos);
2996 2997 2998
  }

  free(pids);
2999
  free(infos);
3000 3001

  return 0;
3002 3003
}

3004 3005 3006 3007
static void createChildTables() {
    char tblColsBuf[MAX_SQL_SIZE];
    int len;

3008
  for (int i = 0; i < g_Dbs.dbCount; i++) {
3009 3010 3011 3012 3013 3014 3015 3016
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
          // with super table
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
            continue;
          }
3017

3018 3019
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
3020
          uint64_t startFrom = 0;
3021 3022
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

3023
          verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
3024 3025 3026 3027 3028 3029 3030 3031
                  __func__, __LINE__, g_totalChildTables, startFrom);
          startMultiThreadCreateChildTable(
                g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
                g_Dbs.threadCountByCreateTbl,
                startFrom,
                g_Dbs.db[i].superTbls[j].childTblCount,
                g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
        }
3032 3033
      }
    } else {
3034 3035
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
3036
      for (int j = 0; j < g_args.num_of_CPR; j++) {
3037 3038 3039 3040
          if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0)
                  || (strncasecmp(g_args.datatype[j],
                      "NCHAR", strlen("NCHAR")) == 0)) {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
3041
                      ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary);
3042 3043 3044 3045 3046 3047
          } else {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                      ", COL%d %s", j, g_args.datatype[j]);
          }
          len = strlen(tblColsBuf);
      }
3048

3049
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
3050

3051
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
3052 3053 3054 3055 3056 3057 3058 3059 3060
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
      startMultiThreadCreateChildTable(
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
3061
    }
3062 3063 3064 3065 3066 3067
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3068
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3069 3070 3071
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3072

3073 3074
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3075 3076
    printf("Failed to open tags file: %s, reason:%s\n",
            superTblInfo->tagsFile, strerror(errno));
3077 3078 3079 3080 3081 3082 3083
    return -1;
  }

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

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

3094
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106
    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) {
3107 3108
      char *tmp = realloc(tagDataBuf,
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3109 3110 3111
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3112 3113
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140
      } 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
*/
3141 3142
static int readSampleFromCsvFileToMem(
        SSuperTable* superTblInfo) {
3143 3144 3145 3146
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3147

3148 3149
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3150
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
3151 3152 3153
              superTblInfo->sampleFile, strerror(errno));
      return -1;
  }
3154

3155
  assert(superTblInfo->sampleDataBuf);
3156 3157
  memset(superTblInfo->sampleDataBuf, 0,
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3158
  while(1) {
3159
    readLen = tgetline(&line, &n, fp);
3160 3161
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3162
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3163
                superTblInfo->sampleFile, strerror(errno));
3164
        fclose(fp);
3165 3166 3167 3168
        return -1;
      }
      continue;
    }
3169

3170 3171 3172 3173 3174 3175 3176 3177 3178
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3179
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3180
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3181 3182 3183
      continue;
    }

3184 3185
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
          line, readLen);
3186 3187 3188 3189 3190 3191 3192
    getRows++;

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

3193
  fclose(fp);
3194 3195 3196 3197
  tmfree(line);
  return 0;
}

3198 3199
static bool getColumnAndTagTypeFromInsertJsonFile(
        cJSON* stbInfo, SSuperTable* superTbls) {
3200
  bool  ret = false;
3201

3202
  // columns
3203 3204
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3205
    printf("ERROR: failed to read json, columns not found\n");
3206 3207 3208 3209 3210 3211
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3212

3213
  int columnSize = cJSON_GetArraySize(columns);
3214
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3215 3216
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
            __func__, __LINE__, MAX_COLUMN_COUNT);
3217 3218 3219 3220 3221 3222
    goto PARSE_OVER;
  }

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

3224
  //superTbls->columnCount = columnSize;
3225 3226 3227 3228 3229 3230 3231
  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) {
3232
      count = countObj->valueint;
3233
    } else if (countObj && countObj->type != cJSON_Number) {
3234 3235
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
          __func__, __LINE__);
3236 3237 3238 3239 3240
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3241
    // column info
3242 3243
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3244 3245 3246 3247
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
          __func__, __LINE__);
3248 3249
      goto PARSE_OVER;
    }
3250 3251
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3252

3253 3254
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3255
      columnCase.dataLen = dataLen->valueint;
3256
    } else if (dataLen && dataLen->type != cJSON_Number) {
3257 3258
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
          __func__, __LINE__);
3259 3260 3261 3262
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3263

3264
    for (int n = 0; n < count; ++n) {
3265 3266 3267
      tstrncpy(superTbls->columns[index].dataType,
              columnCase.dataType, MAX_TB_NAME_SIZE);
      superTbls->columns[index].dataLen = columnCase.dataLen;
3268 3269
      index++;
    }
3270
  }
3271

3272 3273
  if ((index + 1 /* ts */) > MAX_COLUMN_COUNT) {
    errorPrint("%s() LN%d, failed to read json, column size overflow, allowed max column size is %d\n",
3274 3275 3276 3277
            __func__, __LINE__, MAX_COLUMN_COUNT);
    goto PARSE_OVER;
  }

3278
  superTbls->columnCount = index;
3279

3280 3281
  count = 1;
  index = 0;
3282
  // tags
3283 3284
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3285 3286
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
        __func__, __LINE__);
3287 3288
    goto PARSE_OVER;
  }
3289

3290 3291
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3292 3293
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
        __func__, __LINE__, MAX_TAG_COUNT);
3294 3295
    goto PARSE_OVER;
  }
3296 3297

  //superTbls->tagCount = tagSize;
3298 3299 3300
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3301

3302 3303 3304
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3305
      count = countObj->valueint;
3306
    } else if (countObj && countObj->type != cJSON_Number) {
3307
      printf("ERROR: failed to read json, column count not found\n");
3308 3309 3310 3311 3312
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3313
    // column info
3314 3315
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3316 3317 3318 3319
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
          __func__, __LINE__);
3320 3321
      goto PARSE_OVER;
    }
3322
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3323

3324 3325
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3326
      columnCase.dataLen = dataLen->valueint;
3327
    } else if (dataLen && dataLen->type != cJSON_Number) {
3328 3329
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
          __func__, __LINE__);
3330 3331 3332
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3333 3334
    }

3335
    for (int n = 0; n < count; ++n) {
3336 3337
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
          MAX_TB_NAME_SIZE);
3338
      superTbls->tags[index].dataLen = columnCase.dataLen;
3339 3340
      index++;
    }
3341
  }
3342 3343

  if (index > MAX_TAG_COUNT) {
3344
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3345 3346 3347 3348
        __func__, __LINE__, MAX_TAG_COUNT);
    goto PARSE_OVER;
  }

3349 3350
  superTbls->tagCount = index;

3351 3352 3353
  if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > MAX_COLUMN_COUNT) {
    errorPrint("%s() LN%d, columns + tags is more than allowed max columns count: %d\n",
        __func__, __LINE__, MAX_COLUMN_COUNT);
3354 3355
    goto PARSE_OVER;
  }
3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366
  ret = true;

PARSE_OVER:
  return ret;
}

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

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
3367
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3368 3369 3370 3371
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3372
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3373
  } else if (!host) {
3374
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3375
  } else {
3376
    printf("ERROR: failed to read json, host not found\n");
3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388
    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) {
3389
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3390
  } else if (!user) {
3391
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3392 3393 3394 3395
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3396
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3397
  } else if (!password) {
3398
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3399 3400 3401 3402
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3403
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3404
  } else if (!resultfile) {
3405
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3406 3407 3408 3409 3410 3411 3412 3413
  }

  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 {
3414
    printf("ERROR: failed to read json, threads not found\n");
3415
    goto PARSE_OVER;
3416 3417
  }

3418 3419 3420 3421
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
3422
    g_Dbs.threadCountByCreateTbl = 1;
3423
  } else {
3424 3425
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
            __func__, __LINE__);
3426
    goto PARSE_OVER;
3427
  }
3428

3429 3430
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3431 3432 3433 3434 3435
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3436 3437 3438 3439
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3440 3441
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
        __func__, __LINE__);
3442 3443
    goto PARSE_OVER;
  }
3444

3445 3446
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3447 3448 3449 3450 3451 3452
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3453 3454
    g_args.interlace_rows = interlaceRows->valueint;
  } else if (!interlaceRows) {
3455
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3456
  } else {
3457 3458
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
3459
    goto PARSE_OVER;
3460
  }
3461

3462 3463
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3464 3465 3466 3467 3468
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3469 3470
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
3471
    g_args.max_sql_len = (1024*1024);
3472
  } else {
3473 3474
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
3475 3476 3477 3478 3479
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3480
    if (numRecPerReq->valueint <= 0) {
3481 3482 3483
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
3484
    } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
3485 3486 3487 3488 3489
      printf("NOTICE: number of records per request value %"PRIu64" > %d\n\n",
              numRecPerReq->valueint, MAX_RECORDS_PER_REQ);
      printf("        number of records per request value will be set to %d\n\n",
              MAX_RECORDS_PER_REQ);
      prompt();
3490
      numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
3491
    }
3492 3493
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3494
    g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
3495
  } else {
3496 3497
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
        __func__, __LINE__);
3498 3499 3500
    goto PARSE_OVER;
  }

3501
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3502
  if (answerPrompt
3503 3504
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3505 3506 3507 3508 3509 3510 3511 3512
    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) {
3513
    g_args.answer_yes = true;   // default is no, mean answer_yes.
3514
  } else {
3515
    errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
3516
    goto PARSE_OVER;
3517
  }
3518

3519 3520 3521 3522 3523 3524 3525 3526 3527 3528
  // rows per table need be less than insert batch
  if (g_args.interlace_rows > g_args.num_of_RPR) {
      printf("NOTICE: interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
              g_args.interlace_rows, g_args.num_of_RPR);
      printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
              g_args.num_of_RPR);
      prompt();
      g_args.interlace_rows = g_args.num_of_RPR;
  }

3529 3530
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3531
    printf("ERROR: failed to read json, databases not found\n");
3532 3533 3534 3535 3536
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3537
    errorPrint(
3538 3539
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3540 3541 3542 3543 3544 3545 3546 3547
    goto PARSE_OVER;
  }

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

3548
    // dbinfo
3549 3550
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3551
      printf("ERROR: failed to read json, dbinfo not found\n");
3552 3553
      goto PARSE_OVER;
    }
3554

3555 3556
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3557
      printf("ERROR: failed to read json, db name not found\n");
3558 3559
      goto PARSE_OVER;
    }
3560
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3561 3562 3563

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3564 3565
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3566
      } else {
3567
        g_Dbs.db[i].drop = false;
3568
      }
3569
    } else if (!drop) {
3570
      g_Dbs.db[i].drop = g_args.drop_database;
3571
    } else {
3572 3573
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
              __func__, __LINE__);
3574 3575 3576 3577
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3578 3579 3580 3581
    if (precision && precision->type == cJSON_String
            && precision->valuestring != NULL) {
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
              MAX_DB_NAME_SIZE);
3582
    } else if (!precision) {
3583
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3584 3585
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3586
      printf("ERROR: failed to read json, precision not found\n");
3587 3588 3589 3590 3591 3592 3593 3594 3595
      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 {
3596
      printf("ERROR: failed to read json, update not found\n");
3597 3598 3599 3600 3601 3602 3603 3604 3605
      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 {
3606
      printf("ERROR: failed to read json, replica not found\n");
3607 3608 3609 3610 3611 3612 3613 3614 3615
      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 {
3616
     printf("ERROR: failed to read json, keep not found\n");
3617 3618
     goto PARSE_OVER;
    }
3619

3620 3621 3622 3623 3624 3625
    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 {
3626
     printf("ERROR: failed to read json, days not found\n");
3627 3628
     goto PARSE_OVER;
    }
3629

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

3640 3641 3642 3643 3644 3645
    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 {
3646
     printf("ERROR: failed to read json, block not found\n");
3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663
     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) {
3664
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3665
    } else {
3666
     printf("ERROR: failed to read json, minRows not found\n");
3667 3668 3669 3670 3671 3672 3673
     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) {
3674
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3675
    } else {
3676
     printf("ERROR: failed to read json, maxRows not found\n");
3677 3678 3679 3680 3681 3682 3683 3684 3685
     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 {
3686
     printf("ERROR: failed to read json, comp not found\n");
3687 3688 3689 3690 3691 3692 3693 3694 3695
     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 {
3696
     printf("ERROR: failed to read json, walLevel not found\n");
3697 3698 3699
     goto PARSE_OVER;
    }

3700 3701 3702 3703 3704 3705
    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 {
3706
     printf("ERROR: failed to read json, cacheLast not found\n");
3707 3708 3709
     goto PARSE_OVER;
    }

3710 3711 3712 3713
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3714
      g_Dbs.db[i].dbCfg.quorum = 1;
3715
    } else {
3716
     printf("failed to read json, quorum input mistake");
3717 3718 3719 3720 3721 3722 3723 3724 3725
     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 {
3726 3727 3728
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
              __func__, __LINE__);
      goto PARSE_OVER;
3729
    }
3730

3731
    // super_talbes
3732 3733
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3734 3735
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
              __func__, __LINE__);
3736
      goto PARSE_OVER;
3737 3738
    }

3739 3740
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3741
      errorPrint(
3742 3743
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3744 3745 3746 3747 3748 3749 3750
      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;
3751 3752

      // dbinfo
3753 3754
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3755 3756
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
                __func__, __LINE__);
3757 3758
        goto PARSE_OVER;
      }
3759
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3760

3761 3762
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3763
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3764 3765
        goto PARSE_OVER;
      }
3766
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3767 3768

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3769 3770 3771
      if (autoCreateTbl
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3772 3773 3774 3775 3776 3777 3778 3779 3780 3781
        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 {
3782
        printf("ERROR: failed to read json, auto_create_table not found\n");
3783 3784
        goto PARSE_OVER;
      }
3785

3786 3787 3788 3789
      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) {
3790
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3791
      } else {
3792
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3793
        goto PARSE_OVER;
3794
      }
3795 3796

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3797 3798 3799
      if (childTblExists
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3800 3801
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3802
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3803 3804
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
              || (g_Dbs.db[i].drop == true))) {
3805 3806 3807 3808 3809 3810 3811
          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 {
3812 3813
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
                __func__, __LINE__);
3814 3815
        goto PARSE_OVER;
      }
3816

3817 3818
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3819
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3820
                __func__, __LINE__);
3821 3822 3823 3824 3825
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3826 3827 3828 3829
      if (dataSource && dataSource->type == cJSON_String
              && dataSource->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3830
      } else if (!dataSource) {
3831
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3832
      } else {
3833 3834
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
            __func__, __LINE__);
3835 3836 3837
        goto PARSE_OVER;
      }

3838
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3839 3840 3841 3842
      if (insertMode && insertMode->type == cJSON_String
              && insertMode->valuestring != NULL) {
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3843
      } else if (!insertMode) {
3844
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3845
      } else {
3846
        printf("ERROR: failed to read json, insert_mode not found\n");
3847 3848 3849
        goto PARSE_OVER;
      }

3850
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3851 3852
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3853 3854 3855 3856 3857 3858
        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 {
3859
        g_Dbs.db[i].superTbls[j].childTblLimit = -1;    // select ... limit -1 means all query result, drop = yes mean all table need recreate, limit value is invalid.
3860 3861 3862
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3863 3864
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3865 3866 3867 3868 3869 3870 3871 3872 3873
        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;
      }

3874 3875
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3876 3877
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                ts->valuestring, MAX_DB_NAME_SIZE);
3878
      } else if (!ts) {
3879 3880
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
                "now", MAX_DB_NAME_SIZE);
3881
      } else {
3882
        printf("ERROR: failed to read json, start_timestamp not found\n");
3883 3884
        goto PARSE_OVER;
      }
3885

3886 3887 3888 3889
      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) {
3890
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3891
      } else {
3892
        printf("ERROR: failed to read json, timestamp_step not found\n");
3893 3894 3895 3896
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3897 3898
      if (sampleFormat && sampleFormat->type
              == cJSON_String && sampleFormat->valuestring != NULL) {
3899 3900
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3901
      } else if (!sampleFormat) {
3902
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3903
      } else {
3904
        printf("ERROR: failed to read json, sample_format not found\n");
3905
        goto PARSE_OVER;
3906
      }
3907

3908
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
3909 3910
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
3911 3912
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3913 3914 3915
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3916
        printf("ERROR: failed to read json, sample_file not found\n");
3917
        goto PARSE_OVER;
3918
      }
3919

3920 3921
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3922 3923
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3924 3925 3926 3927 3928 3929 3930 3931 3932
        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 {
3933
        printf("ERROR: failed to read json, tags_file not found\n");
3934 3935
        goto PARSE_OVER;
      }
3936

3937 3938 3939 3940 3941
      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;
3942 3943
        } else if (len < 5) {
          len = 5;
3944
        }
3945 3946
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
3947
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
3948
      } else {
3949 3950
        errorPrint("%s() LN%d, failed to read json, maxSqlLen input mistake\n",
            __func__, __LINE__);
3951
        goto PARSE_OVER;
3952
      }
3953
/*
3954 3955 3956 3957 3958
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
3959 3960 3961 3962
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
3963
        }
3964 3965 3966
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
3967
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
3968 3969
        goto PARSE_OVER;
      }
3970
*/
3971 3972
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
3973 3974 3975 3976 3977
        if (interlaceRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
3978
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3979 3980
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
3981
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3982
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
3983
          printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3984
                  g_args.num_of_RPR);
3985
          prompt();
3986 3987
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
3988 3989
      } 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
3990
      } else {
3991 3992 3993
        errorPrint(
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3994
        goto PARSE_OVER;
3995
      }
3996 3997 3998

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3999 4000 4001 4002 4003 4004
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

4005 4006 4007 4008
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
4009
        printf("ERROR: failed to read json, disorderRatio not found\n");
4010
        goto PARSE_OVER;
4011
      }
4012 4013 4014 4015 4016 4017 4018

      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 {
4019
        printf("ERROR: failed to read json, disorderRange not found\n");
4020 4021
        goto PARSE_OVER;
      }
4022

4023 4024
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
4025 4026 4027 4028 4029
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4030 4031 4032 4033
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
4034 4035
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
4036 4037 4038 4039 4040 4041
        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;
4042 4043 4044 4045 4046
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4047
      } else if (!insertInterval) {
4048
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
4049 4050 4051
                __func__, __LINE__, g_args.insert_interval);
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
4052 4053
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
4054 4055 4056
        goto PARSE_OVER;
      }

4057 4058
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4059 4060
      if (false == retVal) {
        goto PARSE_OVER;
4061 4062
      }
    }
4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075
  }

  ret = true;

PARSE_OVER:
  return ret;
}

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

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
4076
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4077 4078 4079 4080
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4081
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4082
  } else if (!host) {
4083
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4084
  } else {
4085
    printf("ERROR: failed to read json, host not found\n");
4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097
    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) {
4098
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4099
  } else if (!user) {
4100
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4101 4102 4103 4104
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4105
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4106
  } else if (!password) {
4107
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4108
  }
H
hzcheng 已提交
4109

4110
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4111 4112
  if (answerPrompt && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
4113 4114 4115 4116
    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 已提交
4117
    } else {
4118
      g_args.answer_yes = false;
H
hzcheng 已提交
4119
    }
4120 4121 4122
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4123
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4124
    goto PARSE_OVER;
4125
  }
4126

4127 4128
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4129
    if (gQueryTimes->valueint <= 0) {
4130 4131
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4132 4133
      goto PARSE_OVER;
    }
4134 4135 4136 4137
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4138 4139
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4140 4141 4142
    goto PARSE_OVER;
  }

4143 4144
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4145
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
4146
  } else if (!dbs) {
4147
    printf("ERROR: failed to read json, databases not found\n");
4148
    goto PARSE_OVER;
H
hzcheng 已提交
4149
  }
4150 4151 4152

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4153
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4154
  } else if (!queryMode) {
4155
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4156
  } else {
4157
    printf("ERROR: failed to read json, query_mode not found\n");
4158
    goto PARSE_OVER;
H
hzcheng 已提交
4159
  }
4160

4161
  // specified_table_query
4162 4163
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4164
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4165 4166
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4167
    printf("ERROR: failed to read json, super_table_query not found\n");
4168
    goto PARSE_OVER;
4169
  } else {
4170 4171 4172 4173 4174
    cJSON* queryInterval = cJSON_GetObjectItem(specifiedQuery, "query_interval");
    if (queryInterval && queryInterval->type == cJSON_Number) {
      g_queryInfo.specifiedQueryInfo.queryInterval = queryInterval->valueint;
    } else if (!queryInterval) {
      g_queryInfo.specifiedQueryInfo.queryInterval = 0;
4175 4176
    }

4177 4178
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
        "query_times");
4179
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4180
      if (specifiedQueryTimes->valueint <= 0) {
4181 4182
        errorPrint(
                "%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4183
          __func__, __LINE__, specifiedQueryTimes->valueint);
4184 4185 4186
        goto PARSE_OVER;

      }
4187 4188 4189 4190
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4191 4192
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4193
      goto PARSE_OVER;
4194
    }
4195

4196
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4197
    if (concurrent && concurrent->type == cJSON_Number) {
4198
      if (concurrent->valueint <= 0) {
4199
        errorPrint(
4200
                "%s() LN%d, query sqlCount %"PRIu64" or concurrent %d is not correct.\n",
4201 4202
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4203 4204 4205
              g_queryInfo.specifiedQueryInfo.concurrent);
        goto PARSE_OVER;
      }
4206
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4207
    } else if (!concurrent) {
4208
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4209
    }
4210

4211 4212 4213 4214 4215 4216 4217
    cJSON* specifiedAsyncMode = cJSON_GetObjectItem(specifiedQuery, "mode");
    if (specifiedAsyncMode && specifiedAsyncMode->type == cJSON_String
        && specifiedAsyncMode->valuestring != NULL) {
      if (0 == strcmp("sync", specifiedAsyncMode->valuestring)) {
        g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
      } else if (0 == strcmp("async", specifiedAsyncMode->valuestring)) {
        g_queryInfo.specifiedQueryInfo.asyncMode = ASYNC_MODE;
4218
      } else {
4219
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4220
            __func__, __LINE__);
4221 4222 4223
        goto PARSE_OVER;
      }
    } else {
4224
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4225
    }
4226

4227
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4228
    if (interval && interval->type == cJSON_Number) {
4229
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4230
    } else if (!interval) {
4231 4232
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4233
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4234
    }
4235

4236
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4237
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4238
      if (0 == strcmp("yes", restart->valuestring)) {
4239
        g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4240
      } else if (0 == strcmp("no", restart->valuestring)) {
4241
        g_queryInfo.specifiedQueryInfo.subscribeRestart = false;
4242
      } else {
4243
        printf("ERROR: failed to read json, subscribe restart error\n");
4244 4245 4246
        goto PARSE_OVER;
      }
    } else {
4247
      g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4248
    }
4249

4250
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4251 4252 4253
    if (keepProgress
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4254
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4255
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4256
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4257
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4258
      } else {
4259
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4260 4261 4262
        goto PARSE_OVER;
      }
    } else {
4263
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4264 4265
    }

4266
    // sqls
4267 4268
    cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
    if (!specifiedSqls) {
4269
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4270
    } else if (specifiedSqls->type != cJSON_Array) {
4271 4272
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
          __func__, __LINE__);
4273
      goto PARSE_OVER;
4274
    } else {
4275 4276 4277 4278 4279 4280 4281 4282
      int superSqlSize = cJSON_GetArraySize(specifiedSqls);
      if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent
              > MAX_QUERY_SQL_COUNT) {
        errorPrint("%s() LN%d, failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n",
           __func__, __LINE__,
           superSqlSize,
           g_queryInfo.specifiedQueryInfo.concurrent,
           MAX_QUERY_SQL_COUNT);
4283 4284
        goto PARSE_OVER;
      }
4285

4286
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4287
      for (int j = 0; j < superSqlSize; ++j) {
4288
        cJSON* sql = cJSON_GetArrayItem(specifiedSqls, j);
4289
        if (sql == NULL) continue;
4290

4291 4292
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4293
          printf("ERROR: failed to read json, sql not found\n");
4294 4295
          goto PARSE_OVER;
        }
4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
                sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);

        cJSON* resubAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
        if (resubAfterConsume
                && resubAfterConsume->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
                = resubAfterConsume->valueint;
        } else if (!resubAfterConsume) {
            //printf("failed to read json, subscribe interval no found\n");
            //goto PARSE_OVER;
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = 1;
        }
H
hzcheng 已提交
4310

4311
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4312 4313 4314 4315
        if ((NULL != result) && (result->type == cJSON_String)
                && (result->valuestring != NULL)) {
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                  result->valuestring, MAX_FILE_NAME_LEN);
4316
        } else if (NULL == result) {
4317 4318
          memset(g_queryInfo.specifiedQueryInfo.result[j],
                  0, MAX_FILE_NAME_LEN);
4319
        } else {
4320
          printf("ERROR: failed to read json, super query result file not found\n");
4321
          goto PARSE_OVER;
4322
        }
4323 4324 4325
      }
    }
  }
4326

4327
  // super_table_query
4328 4329
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4330
    g_queryInfo.superQueryInfo.threadCnt = 1;
4331 4332
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4333
    printf("ERROR: failed to read json, sub_table_query not found\n");
4334 4335
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4336
  } else {
4337
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4338
    if (subrate && subrate->type == cJSON_Number) {
4339
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4340
    } else if (!subrate) {
4341
      g_queryInfo.superQueryInfo.queryInterval = 0;
4342 4343 4344 4345
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4346 4347 4348
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
          __func__, __LINE__, superQueryTimes->valueint);
4349 4350
        goto PARSE_OVER;
      }
4351 4352 4353 4354
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4355 4356
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4357
      goto PARSE_OVER;
4358
    }
4359

4360
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4361
    if (threads && threads->type == cJSON_Number) {
4362 4363 4364 4365 4366 4367
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4368
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4369
    } else if (!threads) {
4370
      g_queryInfo.superQueryInfo.threadCnt = 1;
4371
    }
4372

4373
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4374
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4375
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4376
    //} else if (!subTblCnt) {
4377
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4378
    //}
4379

4380
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4381 4382 4383 4384
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
          MAX_TB_NAME_SIZE);
4385
    } else {
4386 4387
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
          __func__, __LINE__);
4388 4389
      goto PARSE_OVER;
    }
4390

4391 4392 4393 4394 4395 4396 4397
    cJSON* superAsyncMode = cJSON_GetObjectItem(superQuery, "mode");
    if (superAsyncMode && superAsyncMode->type == cJSON_String
        && superAsyncMode->valuestring != NULL) {
      if (0 == strcmp("sync", superAsyncMode->valuestring)) {
        g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
      } else if (0 == strcmp("async", superAsyncMode->valuestring)) {
        g_queryInfo.superQueryInfo.asyncMode = ASYNC_MODE;
4398
      } else {
4399
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4400
            __func__, __LINE__);
4401 4402 4403
        goto PARSE_OVER;
      }
    } else {
4404
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4405
    }
4406

4407 4408 4409 4410 4411 4412 4413 4414 4415
    cJSON* superInterval = cJSON_GetObjectItem(superQuery, "interval");
    if (superInterval && superInterval->type == cJSON_Number) {
      if (superInterval->valueint < 0) {
        errorPrint("%s() LN%d, failed to read json, interval input mistake\n",
            __func__, __LINE__);
        goto PARSE_OVER;
      }
      g_queryInfo.superQueryInfo.subscribeInterval = superInterval->valueint;
    } else if (!superInterval) {
4416 4417
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4418
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4419
    }
4420

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

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

4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463
    cJSON* superResubAfterConsume =
            cJSON_GetObjectItem(superQuery, "resubAfterConsume");
    if (superResubAfterConsume
            && superResubAfterConsume->type == cJSON_Number) {
        g_queryInfo.superQueryInfo.resubAfterConsume =
            superResubAfterConsume->valueint;
    } else if (!superResubAfterConsume) {
        //printf("failed to read json, subscribe interval no found\n");
        ////goto PARSE_OVER;
        g_queryInfo.superQueryInfo.resubAfterConsume = 1;
    }

4464 4465 4466
    // supert table sqls
    cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
    if (!superSqls) {
4467
      g_queryInfo.superQueryInfo.sqlCount = 0;
4468
    } else if (superSqls->type != cJSON_Array) {
4469 4470
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
          __func__, __LINE__);
4471
      goto PARSE_OVER;
4472
    } else {
4473
      int superSqlSize = cJSON_GetArraySize(superSqls);
4474
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4475 4476
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4477 4478
        goto PARSE_OVER;
      }
4479

4480
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4481
      for (int j = 0; j < superSqlSize; ++j) {
4482
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
4483
        if (sql == NULL) continue;
4484

4485
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4486 4487 4488 4489
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
              __func__, __LINE__);
4490 4491
          goto PARSE_OVER;
        }
4492 4493
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
            MAX_QUERY_SQL_LENGTH);
4494 4495

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4496 4497 4498 4499
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
              result->valuestring, MAX_FILE_NAME_LEN);
4500
        } else if (NULL == result) {
4501
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4502
        }  else {
4503 4504
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
              __func__, __LINE__);
4505
          goto PARSE_OVER;
4506
        }
4507 4508
      }
    }
H
hzcheng 已提交
4509 4510
  }

4511
  ret = true;
H
hzcheng 已提交
4512

4513 4514 4515
PARSE_OVER:
  return ret;
}
H
hzcheng 已提交
4516

4517
static bool getInfoFromJsonFile(char* file) {
4518
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4519

4520 4521 4522 4523 4524
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4525

4526
  bool  ret = false;
4527
  int   maxLen = 6400000;
4528 4529 4530 4531 4532 4533 4534
  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 已提交
4535
  }
H
Hui Li 已提交
4536

4537 4538 4539
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4540
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4541 4542
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4543

4544 4545 4546
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4547
      g_args.test_mode = INSERT_TEST;
4548
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4549
      g_args.test_mode = QUERY_TEST;
4550
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4551
      g_args.test_mode = SUBSCRIBE_TEST;
4552
    } else {
4553
      printf("ERROR: failed to read json, filetype not support\n");
4554 4555 4556
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4557
    g_args.test_mode = INSERT_TEST;
4558
  } else {
4559
    printf("ERROR: failed to read json, filetype not found\n");
4560 4561
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4562

4563
  if (INSERT_TEST == g_args.test_mode) {
4564
    ret = getMetaFromInsertJsonFile(root);
4565 4566
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4567 4568
    ret = getMetaFromQueryJsonFile(root);
  } else {
4569 4570
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4571
    goto PARSE_OVER;
4572
  }
4573 4574 4575 4576

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4577
  fclose(fp);
4578 4579
  return ret;
}
H
hzcheng 已提交
4580

4581
static void prepareSampleData() {
4582
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4583 4584 4585
    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 已提交
4586
      }
4587 4588 4589 4590
    }
  }
}

4591
static void postFreeResource() {
4592
  tmfclose(g_fpOfInsertResult);
4593
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4594
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4595 4596 4597
      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 已提交
4598
      }
4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610
      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 已提交
4611
    }
4612 4613
  }
}
S
Shuaiqiang Chang 已提交
4614

4615 4616 4617
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4618
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4619
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4620
    if (0 != ret) {
4621
      tmfree(superTblInfo->sampleDataBuf);
4622
      superTblInfo->sampleDataBuf = NULL;
4623 4624
      return -1;
    }
4625
*/
4626 4627
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4628

4629
  int    dataLen = 0;
4630

4631 4632 4633 4634
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "(%" PRId64 ", ", timestamp);
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4635
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4636

4637
  (*sampleUsePos)++;
4638

4639 4640
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4641

4642 4643
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4644
  char  *pstr = recBuf;
4645
  int64_t maxLen = MAX_DATA_SIZE;
4646

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

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

4658 4659
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4660
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4661
        return -1;
4662 4663
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4664
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4665
      tmfree(buf);
4666
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4667
                "INT", 3)) {
4668
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4669
              "%d,", rand_int());
4670
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4671
                "BIGINT", 6)) {
4672
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4673
              "%"PRId64",", rand_bigint());
4674
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4675
                "FLOAT", 5)) {
4676
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4677
              "%f,", rand_float());
4678
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4679
                "DOUBLE", 6)) {
4680
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4681
              "%f,", rand_double());
4682
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4683
                "SMALLINT", 8)) {
4684
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4685
          "%d,", rand_smallint());
4686
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4687
          "TINYINT", strlen("TINYINT"))) {
4688
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4689
          "%d,", rand_tinyint());
4690
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4691
          "BOOL", strlen("BOOL"))) {
4692
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4693
          "%d,", rand_bool());
4694
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4695
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4696
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4697
          "%"PRId64",", rand_bigint());
4698
    }  else {
4699
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4700
      return -1;
4701
    }
S
Shuaiqiang Chang 已提交
4702
  }
4703

4704
  dataLen -= 1;
4705
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4706

4707 4708 4709
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4710
}
S
Shuaiqiang Chang 已提交
4711

4712
static int64_t generateData(char *recBuf, char **data_type,
4713
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4714 4715
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729
  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);
  }

4730
  for (int i = 0; i < c; i++) {
4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741
    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) {
4742
      double t = rand_double();
4743 4744
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4745
      bool b = rand_bool() & 1;
4746 4747
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4748 4749
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4750
      pstr += sprintf(pstr, ",\"%s\"", s);
4751
      free(s);
4752
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4753 4754
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4755
      pstr += sprintf(pstr, ",\"%s\"", s);
4756 4757 4758
      free(s);
    }

4759
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4760 4761 4762 4763 4764 4765 4766
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4769
  return (int32_t)strlen(recBuf);
4770 4771
}

4772
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4773 4774
  char* sampleDataBuf = NULL;

4775
  sampleDataBuf = calloc(
4776
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4777
  if (sampleDataBuf == NULL) {
4778
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4779
              __func__, __LINE__,
4780
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
4781
              strerror(errno));
4782
      return -1;
4783
  }
4784

4785 4786 4787 4788
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4789 4790
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
4791
      tmfree(sampleDataBuf);
4792
      superTblInfo->sampleDataBuf = NULL;
4793
      return -1;
H
Hui Li 已提交
4794
  }
4795

4796 4797 4798
  return 0;
}

4799
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4800 4801
{
  int affectedRows;
4802
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4803

4804 4805
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, buffer);
4806
  if (superTblInfo) {
4807
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4808
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4809
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
4810 4811
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
                  buffer, NULL /* not set result file */)) {
4812
        affectedRows = -1;
4813 4814
        printf("========restful return fail, threadID[%d]\n",
            pThreadInfo->threadID);
4815 4816 4817
      } else {
        affectedRows = k;
      }
4818 4819 4820 4821
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4822
    }
4823
  } else {
4824
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4825 4826 4827 4828 4829
  }

  return affectedRows;
}

4830 4831
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
4832 4833
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4834 4835
  if ((superTblInfo)
          && (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable)) {
4836
    if (superTblInfo->childTblLimit > 0) {
4837
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
4838 4839
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4840
    } else {
4841

4842
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
4843 4844
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
4845 4846 4847 4848 4849
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
    }
  } else {
4850
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4851
        g_args.tb_prefix, tableSeq);
4852 4853 4854
  }
}

4855
static int64_t generateDataTail(
4856
        SSuperTable* superTblInfo,
4857
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4858
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4859 4860
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4861

4862 4863
  char *pstr = buffer;

4864
  if (superTblInfo == NULL) {
4865
    uint32_t datatypeSeq = 0;
4866 4867 4868 4869
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
4870 4871
  }

4872
  verbosePrint("%s() LN%d batch=%"PRIu64"\n", __func__, __LINE__, batch);
4873

4874 4875 4876 4877 4878 4879 4880 4881
  bool tsRand;
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
                  "rand", strlen("rand")))) {
        tsRand = true;
    } else {
        tsRand = false;
  }

4882
  uint64_t k = 0;
4883
  for (k = 0; k < batch;) {
4884
    char data[MAX_DATA_SIZE];
4885 4886
    memset(data, 0, MAX_DATA_SIZE);

4887
    int64_t retLen = 0;
4888

4889
    if (superTblInfo) {
4890 4891 4892 4893 4894 4895 4896 4897 4898
        if (tsRand) {
            retLen = generateRowData(
                    data,
                    startTime + getTSRandTail(
                        superTblInfo->timeStampStep, k,
                        superTblInfo->disorderRatio,
                        superTblInfo->disorderRange),
                    superTblInfo);
        } else {
4899
          retLen = getRowDataFromSample(
4900 4901
                    data,
                    remainderBufLen,
4902
                    startTime + superTblInfo->timeStampStep * k,
4903
                    superTblInfo,
4904
                    pSamplePos);
4905
        }
4906 4907
        if (retLen > remainderBufLen) {
            break;
4908
        }
4909

4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925
        pstr += snprintf(pstr , retLen + 1, "%s", data);
        k++;
        len += retLen;
        remainderBufLen -= retLen;
    } else {
        char **data_type = g_args.datatype;
        int lenOfBinary = g_args.len_of_binary;
        retLen = generateData(data, data_type,
                ncols_per_record,
                startTime + getTSRandTail(
                    DEFAULT_TIMESTAMP_STEP, k,
                    g_args.disorderRatio,
                    g_args.disorderRange),
                lenOfBinary);
        if (len > remainderBufLen)
            break;
4926

4927 4928 4929 4930
        pstr += sprintf(pstr, "%s", data);
        k++;
        len += retLen;
        remainderBufLen -= retLen;
4931 4932
    }

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

    startFrom ++;
4937

4938
    if (startFrom >= insertRows) {
4939
      break;
4940
    }
4941
  }
4942

4943 4944 4945
  *dataLen = len;
  return k;
}
4946

4947
static int generateSQLHead(char *tableName, int32_t tableSeq,
4948 4949
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4950 4951
{
  int len;
4952 4953 4954 4955

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

4956 4957 4958 4959
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4960
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4961 4962 4963 4964 4965 4966
      } else {
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
      }
      if (NULL == tagsValBuf) {
4967 4968
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
            __func__, __LINE__);
4969 4970 4971
        return -1;
      }

4972 4973 4974
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4975
                  "%s.%s using %s.%s tags %s values",
4976 4977 4978 4979 4980 4981 4982
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
4983 4984 4985
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4986
                  "%s.%s values",
4987
                  pThreadInfo->db_name,
4988
                  tableName);
4989
    } else {
4990 4991 4992
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
4993
                  "%s.%s values",
4994 4995 4996 4997
                  pThreadInfo->db_name,
                  tableName);
    }
  } else {
4998 4999 5000
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
5001
                  "%s.%s values",
5002 5003 5004 5005
                  pThreadInfo->db_name,
                  tableName);
  }

5006 5007 5008 5009 5010
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

5011 5012 5013
  return len;
}

5014
static int64_t generateInterlaceDataBuffer(
5015 5016
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
5017
        threadInfo *pThreadInfo, char *buffer,
5018
        int64_t insertRows,
5019
        int64_t startTime,
5020
        uint64_t *pRemainderBufLen)
5021
{
5022
  assert(buffer);
5023 5024 5025 5026 5027 5028 5029 5030 5031 5032
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

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

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
5033
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
5034 5035 5036 5037 5038
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5039
  int64_t dataLen = 0;
5040

5041
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
5042 5043 5044 5045 5046 5047 5048 5049 5050 5051
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);

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

5053
  int64_t k = generateDataTail(
5054
    superTblInfo,
5055 5056 5057 5058
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);

5059
  if (k == batchPerTbl) {
5060 5061 5062
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5063
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
5064
            __func__, __LINE__, k, batchPerTbl);
5065 5066
    pstr -= headLen;
    pstr[0] = '\0';
5067
    k = 0;
5068 5069 5070 5071 5072
  }

  return k;
}

5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088
static int64_t getTSRandTail(int64_t timeStampStep, int32_t seq,
          int disorderRatio, int disorderRange)
{
    int64_t randTail = timeStampStep * seq;
    if (disorderRatio > 0) {
        int rand_num = taosRandom() % 100;
        if(rand_num < disorderRatio) {
            randTail = (randTail +
                    (taosRandom() % disorderRange + 1)) * (-1);
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
    }

    return randTail;
}

5089
static int64_t generateProgressiveDataBuffer(
5090
        char *tableName,
5091
        int64_t tableSeq,
5092 5093
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
5094
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos,
5095
        int64_t *pRemainderBufLen)
5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109
{
  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);
5110
  char *pstr = buffer;
5111

5112
  int64_t k = 0;
5113

5114
  memset(buffer, 0, *pRemainderBufLen);
5115

5116
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
5117
          buffer, *pRemainderBufLen);
5118 5119 5120 5121

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

5125
  int64_t dataLen;
5126
  k = generateDataTail(superTblInfo,
5127
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
5128
          startTime,
5129
          pSamplePos, &dataLen);
5130

5131 5132
  return k;
}
5133

5134 5135 5136 5137 5138 5139 5140 5141 5142
static void printStatPerThread(threadInfo *pThreadInfo)
{
  fprintf(stderr, "====thread[%d] completed total inserted rows: %"PRIu64 ", total affected rows: %"PRIu64". %.2f records/second====\n",
          pThreadInfo->threadID,
          pThreadInfo->totalInsertRows,
          pThreadInfo->totalAffectedRows,
          (double)(pThreadInfo->totalAffectedRows / (pThreadInfo->totalDelay/1000.0)));
}

5143
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5144 5145
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
5146

5147
  int64_t insertRows;
5148
  uint64_t interlaceRows;
5149

5150
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5151

5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

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

5166
  if (interlaceRows > insertRows)
5167
    interlaceRows = insertRows;
5168

5169 5170
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5171

5172 5173 5174 5175 5176 5177 5178 5179 5180 5181
  int insertMode;

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

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

5183
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5184
  char* buffer = calloc(maxSqlLen, 1);
5185
  if (NULL == buffer) {
5186
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5187
              __func__, __LINE__, maxSqlLen, strerror(errno));
5188 5189 5190
    return NULL;
  }

5191
  char tableName[TSDB_TABLE_NAME_LEN];
5192 5193 5194 5195

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

5196
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5197

5198
  uint64_t insert_interval =
5199
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5200 5201
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5202

5203 5204 5205
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5206

5207
  uint64_t tableSeq = pThreadInfo->start_table_from;
5208

5209
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n",
5210
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
5211 5212 5213 5214
          pThreadInfo->ntables, insertRows);

  int64_t startTime = pThreadInfo->start_time;

5215 5216
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5217

5218
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5219
    batchPerTblTimes =
5220
        g_args.num_of_RPR / interlaceRows;
5221 5222 5223 5224
  } else {
    batchPerTblTimes = 1;
  }

5225
  uint64_t generatedRecPerTbl = 0;
5226
  bool flagSleep = true;
5227
  uint64_t sleepTimeTotal = 0;
5228

5229 5230 5231
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5232
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5233
    if ((flagSleep) && (insert_interval)) {
5234
        st = taosGetTimestampMs();
5235
        flagSleep = false;
5236 5237
    }
    // generate data
5238
    memset(buffer, 0, maxSqlLen);
5239
    uint64_t remainderBufLen = maxSqlLen;
5240

5241
    char *pstr = buffer;
5242 5243 5244 5245 5246

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

5247
    uint64_t recOfBatch = 0;
5248

5249
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5250
      getTableName(tableName, pThreadInfo, tableSeq);
5251 5252 5253
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
5254
        free(buffer);
5255 5256
        return NULL;
      }
5257

5258
      uint64_t oldRemainderLen = remainderBufLen;
5259
      int64_t generated = generateInterlaceDataBuffer(
5260 5261 5262 5263
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
5264
        startTime,
5265
        &remainderBufLen);
5266

5267 5268
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5269
      if (generated < 0) {
5270
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5271
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5272
        goto free_of_interlace;
5273 5274
      } else if (generated == 0) {
        break;
5275 5276
      }

5277
      tableSeq ++;
5278
      recOfBatch += batchPerTbl;
5279
      pstr += (oldRemainderLen - remainderBufLen);
5280
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5281
      pThreadInfo->totalInsertRows += batchPerTbl;
5282
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5283 5284
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5285

5286 5287 5288 5289
      if (insertMode == INTERLACE_INSERT_MODE) {
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
5290
            generatedRecPerTbl += batchPerTbl;
5291 5292

            startTime = pThreadInfo->start_time
5293
              + generatedRecPerTbl * nTimeStampStep;
5294

5295 5296 5297 5298
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

5299 5300 5301 5302
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;

5303 5304
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
5305
          }
5306 5307
      }

5308
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5309 5310 5311 5312
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5313 5314 5315
        break;
    }

5316
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5317 5318 5319 5320 5321
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
           pThreadInfo->threadID, __func__, __LINE__, buffer);

5322
    startTs = taosGetTimestampMs();
5323

5324 5325 5326 5327 5328 5329 5330
    if (recOfBatch == 0) {
      errorPrint("[%d] %s() LN%d try inserting records of batch is %"PRIu64"\n",
              pThreadInfo->threadID, __func__, __LINE__,
              recOfBatch);
      errorPrint("%s\n", "\tPlease check if the batch or the buffer length is proper value!\n");
      goto free_of_interlace;
    }
5331
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5332

5333
    endTs = taosGetTimestampMs();
5334 5335
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5336
            __func__, __LINE__, delay);
5337 5338 5339
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5340 5341 5342 5343 5344 5345

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

5346 5347
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5348
                pThreadInfo->threadID, __func__, __LINE__,
5349
                recOfBatch, affectedRows, buffer);
5350
        goto free_of_interlace;
5351
    }
5352

5353
    pThreadInfo->totalAffectedRows += affectedRows;
5354

5355 5356
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5357
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5358 5359 5360
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5361 5362
      lastPrintTime = currentPrintTime;
    }
5363

5364
    if ((insert_interval) && flagSleep) {
5365
      et = taosGetTimestampMs();
5366

5367 5368
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5369 5370
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleepTime);
5371 5372 5373
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5374
    }
5375 5376
  }

5377
free_of_interlace:
5378
  tmfree(buffer);
5379
  printStatPerThread(pThreadInfo);
5380 5381 5382
  return NULL;
}

5383 5384 5385 5386 5387 5388 5389 5390
// 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
*/
5391
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5392
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5393

5394
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5395
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5396

5397
  char* buffer = calloc(maxSqlLen, 1);
5398
  if (NULL == buffer) {
5399
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5400
              maxSqlLen,
5401 5402 5403
              strerror(errno));
    return NULL;
  }
5404

5405 5406 5407
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5408

5409
  int64_t timeStampStep =
5410
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5411
/*  int insert_interval =
5412
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5413 5414
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5415
  */
5416

5417 5418
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5419

5420
  pThreadInfo->samplePos = 0;
5421

5422
  for (uint64_t tableSeq =
5423
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
5424
        tableSeq ++) {
5425
    int64_t start_time = pThreadInfo->start_time;
5426

5427
    int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
5428

5429 5430
    verbosePrint("%s() LN%d insertRows=%"PRId64"\n", __func__, __LINE__, insertRows);

5431
    for (uint64_t i = 0; i < insertRows;) {
5432
        /*
5433
      if (insert_interval) {
5434
            st = taosGetTimestampMs();
5435
      }
5436
      */
5437

5438 5439
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5440
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5441 5442 5443
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);

5444
      int64_t remainderBufLen = maxSqlLen;
5445 5446 5447 5448 5449 5450 5451 5452
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5453
      int64_t generated = generateProgressiveDataBuffer(
5454
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
5455
            i, start_time,
5456 5457
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5458 5459 5460
      if (generated > 0)
        i += generated;
      else
5461
        goto free_of_progressive;
5462

5463
      start_time +=  generated * timeStampStep;
5464
      pThreadInfo->totalInsertRows += generated;
5465

5466
      startTs = taosGetTimestampMs();
5467

5468
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5469

5470
      endTs = taosGetTimestampMs();
5471
      uint64_t delay = endTs - startTs;
5472 5473
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
              __func__, __LINE__, delay);
5474 5475 5476
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5477

5478 5479 5480 5481
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5482

5483 5484 5485 5486 5487
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5488 5489 5490

      pThreadInfo->totalAffectedRows += affectedRows;

5491 5492
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5493
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5494 5495 5496
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5497 5498 5499
        lastPrintTime = currentPrintTime;
      }

5500
      if (i >= insertRows)
5501
        break;
5502
/*
5503
      if (insert_interval) {
5504
        et = taosGetTimestampMs();
5505

5506 5507
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5508 5509
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5510 5511
            taosMsleep(sleep_time); // ms
        }
5512
      }
5513
      */
5514 5515
    }   // num_of_DPT

5516 5517
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5518 5519
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5520
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5521
                  __func__, __LINE__, pThreadInfo->samplePos);
5522
      }
5523
    }
5524
  } // tableSeq
5525

5526
free_of_progressive:
5527
  tmfree(buffer);
5528
  printStatPerThread(pThreadInfo);
5529
  return NULL;
H
Hui Li 已提交
5530 5531
}

5532 5533
static void* syncWrite(void *sarg) {

5534 5535
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5536

5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548
  int interlaceRows;

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

5550
  if (interlaceRows > 0) {
5551
    // interlace mode
5552
    return syncWriteInterlace(pThreadInfo);
5553 5554
  } else {
    // progressive mode
5555
    return syncWriteProgressive(pThreadInfo);
5556
  }
5557

5558 5559
}

5560
static void callBack(void *param, TAOS_RES *res, int code) {
5561 5562
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5563

5564 5565
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5566
  if (insert_interval) {
5567 5568 5569
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5570
    }
H
Hui Li 已提交
5571
  }
5572

5573
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5574
  char data[MAX_DATA_SIZE];
5575
  char *pstr = buffer;
5576 5577
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5578 5579 5580 5581 5582 5583 5584 5585
          pThreadInfo->start_table_from);
//  if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
  if (pThreadInfo->counter >= g_args.num_of_RPR) {
    pThreadInfo->start_table_from++;
    pThreadInfo->counter = 0;
  }
  if (pThreadInfo->start_table_from > pThreadInfo->end_table_to) {
    tsem_post(&pThreadInfo->lock_sem);
5586 5587 5588 5589
    free(buffer);
    taos_free_result(res);
    return;
  }
5590

5591
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5592
    int rand_num = taosRandom() % 100;
5593 5594
    if (0 != pThreadInfo->superTblInfo->disorderRatio
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5595 5596
      int64_t d = pThreadInfo->lastTs
          - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
5597
      generateRowData(data, d, pThreadInfo->superTblInfo);
5598
    } else {
5599
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5600
    }
5601
    pstr += sprintf(pstr, "%s", data);
5602
    pThreadInfo->counter++;
H
Hui Li 已提交
5603

5604
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5605
      break;
H
Hui Li 已提交
5606 5607
    }
  }
5608

5609
  if (insert_interval) {
5610
    pThreadInfo->st = taosGetTimestampMs();
5611
  }
5612
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5613
  free(buffer);
H
Hui Li 已提交
5614

5615
  taos_free_result(res);
H
Hui Li 已提交
5616 5617
}

5618
static void *asyncWrite(void *sarg) {
5619 5620
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5621

5622 5623 5624
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5625

5626
  int insert_interval =
5627
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5628
  if (insert_interval) {
5629
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5630
  }
5631
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5632

5633
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5634 5635 5636 5637

  return NULL;
}

5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663
static int convertHostToServAddr(char *host, uint16_t port, struct sockaddr_in *serv_addr)
{
  uint16_t rest_port = port + TSDB_PORT_HTTP;
  struct hostent *server = gethostbyname(host);
  if ((server == NULL) || (server->h_addr == NULL)) {
    errorPrint("%s", "ERROR, no such host");
    return -1;
  }

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

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

5664 5665
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
5666

5667 5668
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5669

5670 5671
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5672

5673 5674
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5675 5676 5677 5678 5679 5680 5681 5682 5683 5684 5685 5686 5687 5688 5689 5690 5691

  //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 {
5692
      errorPrint("Not support precision: %s\n", precision);
5693 5694 5695 5696
      exit(-1);
    }
  }

5697
  int64_t start_time;
5698 5699 5700
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
5701
    } else {
5702 5703 5704 5705 5706
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
5707
          ERROR_EXIT("failed to parse time!\n");
5708
      }
5709
    }
5710 5711
  } else {
     start_time = 1500000000000;
5712 5713
  }

5714
  int64_t start = taosGetTimestampMs();
5715

5716
  // read sample data from file first
5717
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5718
              "sample", strlen("sample")))) {
5719
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5720 5721
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5722 5723 5724 5725
      exit(-1);
    }
  }

5726
  // read sample data from file first
5727
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5728 5729
              "sample", strlen("sample")))) {
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5730 5731
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5732 5733 5734 5735 5736 5737 5738 5739
      exit(-1);
    }
  }

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

5745
  int64_t ntables = 0;
5746
  uint64_t startFrom;
5747

5748
  if (superTblInfo) {
5749 5750
    int64_t limit;
    uint64_t offset;
5751

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

5757
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5758 5759
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5760
            > (superTblInfo->childTblCount))) {
5761 5762 5763 5764 5765 5766
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5767
    } else {
5768 5769
      limit = superTblInfo->childTblCount;
      offset = 0;
5770 5771
    }

5772 5773 5774
    ntables = limit;
    startFrom = offset;

5775 5776 5777 5778
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
5779
      prompt();
5780 5781 5782 5783 5784
    }

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

5788 5789 5790
    superTblInfo->childTblName = (char*)calloc(1,
        limit * TSDB_TABLE_NAME_LEN);
    if (superTblInfo->childTblName == NULL) {
5791
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5792 5793 5794 5795
      taos_close(taos);
      exit(-1);
    }

5796
    int64_t childTblCount;
5797 5798 5799 5800 5801 5802
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5803 5804 5805
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5806
  }
5807

5808 5809
  taos_close(taos);

5810
  int64_t a = ntables / threads;
5811 5812 5813 5814 5815
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5816
  int64_t b = 0;
5817 5818 5819 5820
  if (threads != 0) {
    b = ntables % threads;
  }

5821 5822 5823 5824 5825 5826
  if ((superTblInfo)
      && (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest")))) {
    if (convertHostToServAddr(g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0)
      exit(-1);
  }

H
Hui Li 已提交
5827
  for (int i = 0; i < threads; i++) {
5828 5829 5830 5831 5832
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
    tstrncpy(pThreadInfo->db_name, db_name, MAX_DB_NAME_SIZE);
    pThreadInfo->time_precision = timePrec;
    pThreadInfo->superTblInfo = superTblInfo;
5833

5834 5835
    pThreadInfo->start_time = start_time;
    pThreadInfo->minDelay = UINT64_MAX;
5836

5837 5838
    if ((NULL == superTblInfo) ||
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5839 5840
      //pThreadInfo->taos = taos;
      pThreadInfo->taos = taos_connect(
5841
              g_Dbs.host, g_Dbs.user,
5842
              g_Dbs.password, db_name, g_Dbs.port);
5843
      if (NULL == pThreadInfo->taos) {
5844 5845
        errorPrint(
                "connect to server fail from insert sub thread, reason: %s\n",
5846
                taos_errstr(NULL));
5847 5848 5849
        exit(-1);
      }
    } else {
5850
      pThreadInfo->taos = NULL;
5851 5852
    }

5853
/*    if ((NULL == superTblInfo)
5854
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5855
            */
5856 5857 5858 5859
      pThreadInfo->start_table_from = startFrom;
      pThreadInfo->ntables = i<b?a+1:a;
      pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = pThreadInfo->end_table_to + 1;
5860
/*    } else {
5861 5862 5863
      pThreadInfo->start_table_from = 0;
      pThreadInfo->ntables = superTblInfo->childTblCount;
      pThreadInfo->start_time = pThreadInfo->start_time + rand_int() % 10000 - rand_tinyint();
5864
    }
5865
*/
5866
    tsem_init(&(pThreadInfo->lock_sem), 0, 0);
5867
    if (ASYNC_MODE == g_Dbs.asyncMode) {
5868
      pthread_create(pids + i, NULL, asyncWrite, pThreadInfo);
5869
    } else {
5870
      pthread_create(pids + i, NULL, syncWrite, pThreadInfo);
5871
    }
H
Hui Li 已提交
5872
  }
5873

H
Hui Li 已提交
5874 5875 5876 5877
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5878 5879 5880 5881
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5882 5883
  double  avgDelay = 0;

H
Hui Li 已提交
5884
  for (int i = 0; i < threads; i++) {
5885
    threadInfo *pThreadInfo = infos + i;
5886

5887 5888
    tsem_destroy(&(pThreadInfo->lock_sem));
    taos_close(pThreadInfo->taos);
5889

5890
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5891
            __func__, __LINE__,
5892 5893
            pThreadInfo->threadID, pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows);
5894
    if (superTblInfo) {
5895 5896
        superTblInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
        superTblInfo->totalInsertRows += pThreadInfo->totalInsertRows;
5897
    } else {
5898 5899
        g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
        g_args.totalInsertRows += pThreadInfo->totalInsertRows;
5900
    }
5901

5902 5903 5904 5905
    totalDelay  += pThreadInfo->totalDelay;
    cntDelay   += pThreadInfo->cntDelay;
    if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
    if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
H
Hui Li 已提交
5906
  }
5907
  cntDelay -= 1;
H
Hui Li 已提交
5908

5909
  if (cntDelay == 0)    cntDelay = 1;
5910 5911
  avgDelay = (double)totalDelay / cntDelay;

5912 5913
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5914 5915

  if (superTblInfo) {
5916
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5917
          t / 1000.0, superTblInfo->totalInsertRows,
5918 5919
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5920
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5921 5922 5923 5924

    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
          "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5925
          t / 1000.0, superTblInfo->totalInsertRows,
5926 5927
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5928
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5929
    }
5930
  } else {
5931
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5932
          t / 1000.0, g_args.totalInsertRows,
5933 5934
          g_args.totalAffectedRows,
          threads, db_name,
5935
          (double)g_args.totalInsertRows / (t / 1000.0));
5936 5937 5938
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
          "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5939
          t * 1000.0, g_args.totalInsertRows,
5940 5941
          g_args.totalAffectedRows,
          threads, db_name,
5942
          (double)g_args.totalInsertRows / (t / 1000.0));
5943
    }
5944
  }
5945

5946
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5947
          avgDelay, maxDelay, minDelay);
5948 5949
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5950
          avgDelay, maxDelay, minDelay);
5951
  }
5952

5953 5954
  //taos_close(taos);

H
Hui Li 已提交
5955
  free(pids);
5956
  free(infos);
H
Hui Li 已提交
5957 5958
}

5959
static void *readTable(void *sarg) {
5960
#if 1
5961 5962
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
5963
  char command[BUFFER_SIZE] = "\0";
5964 5965 5966
  uint64_t sTime = pThreadInfo->start_time;
  char *tb_prefix = pThreadInfo->tb_prefix;
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
5967
  if (NULL == fp) {
5968
    errorPrint( "fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
5969 5970
    return NULL;
  }
5971

5972
  int64_t num_of_DPT;
5973 5974
/*  if (pThreadInfo->superTblInfo) {
    num_of_DPT = pThreadInfo->superTblInfo->insertRows; //  nrecords_per_table;
5975
  } else {
5976
  */
5977
      num_of_DPT = g_args.num_of_DPT;
5978
//  }
5979

5980
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
5981
  int64_t totalData = num_of_DPT * num_of_tables;
5982
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5983 5984 5985 5986 5987

  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");
  }
5988
  printf("%"PRId64" records:\n", totalData);
H
hzcheng 已提交
5989 5990
  fprintf(fp, "| QFunctions |    QRecords    |   QSpeed(R/s)   |  QLatency(ms) |\n");

5991
  for (int j = 0; j < n; j++) {
H
hzcheng 已提交
5992
    double totalT = 0;
5993
    uint64_t count = 0;
5994 5995
    for (int64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
5996
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5997

5998
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5999 6000
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
6001

S
Shuaiqiang Chang 已提交
6002
      if (code != 0) {
6003
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6004
        taos_free_result(pSql);
H
hzcheng 已提交
6005
        taos_close(taos);
6006
        fclose(fp);
6007
        return NULL;
H
hzcheng 已提交
6008 6009
      }

6010
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6011 6012 6013
        count++;
      }

6014
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6015 6016
      totalT += t;

S
Shuaiqiang Chang 已提交
6017
      taos_free_result(pSql);
H
hzcheng 已提交
6018 6019
    }

6020
    fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
6021
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
6022
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
6023
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
6024 6025 6026
  }
  fprintf(fp, "\n");
  fclose(fp);
6027
#endif
H
hzcheng 已提交
6028 6029 6030
  return NULL;
}

6031
static void *readMetric(void *sarg) {
6032
#if 1
6033 6034
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6035
  char command[BUFFER_SIZE] = "\0";
6036
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6037
  if (NULL == fp) {
6038
    printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6039 6040
    return NULL;
  }
6041

6042 6043
  int64_t num_of_DPT = pThreadInfo->superTblInfo->insertRows;
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
6044
  int64_t totalData = num_of_DPT * num_of_tables;
6045
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6046 6047 6048 6049 6050

  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");
  }
6051 6052
  printf("%"PRId64" records:\n", totalData);
  fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
6053 6054

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

6058
    int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
6059

6060
    for (int64_t i = 1; i <= m; i++) {
H
hzcheng 已提交
6061
      if (i == 1) {
6062
        sprintf(tempS, "t1 = %"PRId64"", i);
H
hzcheng 已提交
6063
      } else {
6064
        sprintf(tempS, " or t1 = %"PRId64" ", i);
H
hzcheng 已提交
6065
      }
6066
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6067

L
liu0x54 已提交
6068
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6069 6070 6071 6072

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

6073
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6074

S
Shuaiqiang Chang 已提交
6075 6076 6077 6078
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6079
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6080
        taos_free_result(pSql);
H
hzcheng 已提交
6081
        taos_close(taos);
6082
        fclose(fp);
6083
        return NULL;
H
hzcheng 已提交
6084 6085
      }
      int count = 0;
6086
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6087 6088
        count++;
      }
6089
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6090

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

S
Shuaiqiang Chang 已提交
6095
      taos_free_result(pSql);
H
hzcheng 已提交
6096 6097 6098 6099
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6100
#endif
H
hzcheng 已提交
6101 6102 6103
  return NULL;
}

6104 6105 6106
static void prompt()
{
  if (!g_args.answer_yes) {
6107
    printf("         Press enter key to continue or Ctrl-C to stop\n\n");
6108 6109 6110 6111
    (void)getchar();
  }
}

6112
static int insertTestProcess() {
6113

6114 6115 6116
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6117

6118 6119 6120
  if (ret == -1)
    exit(EXIT_FAILURE);

6121
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6122 6123
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6124
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6125 6126
    return -1;
  }
6127

6128 6129
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6130

6131
  prompt();
6132

6133 6134 6135
  init_rand_data();

  // create database and super tables
6136
  if(createDatabasesAndStables() != 0) {
6137 6138
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6139 6140
    return -1;
  }
6141 6142

  // pretreatement
6143
  prepareSampleData();
6144

6145 6146 6147 6148
  double start;
  double end;

  // create child tables
6149
  start = taosGetTimestampMs();
6150
  createChildTables();
6151
  end = taosGetTimestampMs();
6152

6153
  if (g_totalChildTables > 0) {
6154
    fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6155
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6156 6157
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6158
            "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6159
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6160
    }
6161
  }
6162

6163
  taosMsleep(1000);
6164
  // create sub threads for inserting data
6165
  //start = taosGetTimestampMs();
6166
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {

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

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
          }
6180
        }
6181
      }
6182 6183
    } else {
        startMultiThreadInsertData(
6184 6185 6186
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6187
          NULL);
H
Hui Li 已提交
6188
    }
6189
  }
6190
  //end = taosGetTimestampMs();
6191

6192
  //int64_t    totalInsertRows = 0;
6193
  //int64_t    totalAffectedRows = 0;
6194
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6195
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6196
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6197 6198
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6199
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6200
  postFreeResource();
6201

6202 6203 6204
  return 0;
}

6205 6206
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6207

6208
  if (pThreadInfo->taos == NULL) {
6209 6210 6211 6212 6213 6214 6215 6216
    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",
6217
            pThreadInfo->threadID, taos_errstr(NULL));
6218 6219
      return NULL;
    } else {
6220
      pThreadInfo->taos = taos;
6221 6222 6223
    }
  }

6224 6225
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6226 6227
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6228 6229 6230 6231
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6232

6233 6234
  uint64_t st = 0;
  uint64_t et = 0;
6235

6236
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6237

6238 6239 6240
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6241

6242 6243
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) {
    sprintf(pThreadInfo->filePath, "%s-%d",
6244 6245 6246 6247
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }

6248
  while(queryTimes --) {
6249 6250 6251
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6252 6253
    }

6254 6255 6256
    st = taosGetTimestampMs();

    selectAndGetResult(pThreadInfo,
6257
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
6258

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

6263 6264
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6265

6266 6267
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6268
    if (currentPrintTime - lastPrintTime > 30*1000) {
6269
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6270
          __func__, __LINE__, endTs, startTs);
6271
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6272 6273
                    pThreadInfo->threadID,
                    totalQueried,
6274
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6275
      lastPrintTime = currentPrintTime;
6276
    }
H
Hui Li 已提交
6277
  }
6278 6279
  return NULL;
}
H
Hui Li 已提交
6280

6281
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6282 6283
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6284 6285
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6286
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6287 6288

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

6290 6291
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6292
    return;
H
Hui Li 已提交
6293
  }
6294

6295
  tstrncpy(outSql, inSql, pos - inSql + 1);
6296
  //printf("1: %s\n", outSql);
6297
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6298
  //printf("2: %s\n", outSql);
6299
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6300
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6301 6302
}

6303
static void *superTableQuery(void *sarg) {
6304
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6305
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6306

6307
  if (pThreadInfo->taos == NULL) {
6308 6309 6310 6311 6312 6313 6314 6315
    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",
6316
            pThreadInfo->threadID, taos_errstr(NULL));
6317 6318
      return NULL;
    } else {
6319
      pThreadInfo->taos = taos;
6320 6321 6322
    }
  }

6323 6324
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6325

6326 6327 6328
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6329

6330
  uint64_t  lastPrintTime = taosGetTimestampMs();
6331
  while(queryTimes --) {
6332 6333 6334
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6335
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6336
    }
H
Hui Li 已提交
6337

6338
    st = taosGetTimestampMs();
6339
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6340
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6341
        memset(sqlstr,0,sizeof(sqlstr));
6342
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6343 6344
        if (g_queryInfo.superQueryInfo.result[j] != NULL) {
          sprintf(pThreadInfo->filePath, "%s-%d",
6345
                  g_queryInfo.superQueryInfo.result[j],
6346
                  pThreadInfo->threadID);
6347
        }
6348
        selectAndGetResult(pThreadInfo, sqlstr);
6349 6350 6351 6352 6353 6354 6355

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6356
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6357 6358
                    pThreadInfo->threadID,
                    totalQueried,
6359
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6360
          lastPrintTime = currentPrintTime;
6361
        }
6362
      }
H
Hui Li 已提交
6363
    }
6364
    et = taosGetTimestampMs();
6365
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6366
            taosGetSelfPthreadId(),
6367 6368
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6369
            (double)(et - st)/1000.0);
6370
  }
6371

6372 6373 6374
  return NULL;
}

6375
static int queryTestProcess() {
6376 6377 6378 6379

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6380 6381 6382 6383 6384 6385

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6386
          g_queryInfo.port);
6387
  if (taos == NULL) {
6388 6389
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6390 6391 6392
    exit(-1);
  }

6393
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6394 6395
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6396 6397 6398
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6399
  }
6400

6401
  prompt();
6402

6403 6404 6405
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
6406

6407 6408 6409 6410 6411 6412
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6413 6414 6415
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6416
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
6417
  uint64_t nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6418

6419
  uint64_t startTs = taosGetTimestampMs();
6420

6421 6422 6423 6424 6425 6426
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6427
      taos_close(taos);
6428
      ERROR_EXIT("memory allocation failed for create threads\n");
6429
    }
6430

6431 6432 6433
    for (uint64_t i = 0; i < nSqlCount; i++) {
        for (int j = 0; j < nConcurrent; j++) {
            uint64_t seq = i * nConcurrent + j;
6434 6435 6436
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450

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

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

6452
            pThreadInfo->taos = NULL;// TODO: workaround to use separate taos connection;
6453

6454
            pthread_create(pids + seq, NULL, specifiedTableQuery,
6455
                pThreadInfo);
6456
        }
6457
    }
6458
  } else {
6459
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6460
  }
6461

6462 6463
  taos_close(taos);

6464 6465 6466
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6467 6468 6469 6470
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(pthread_t));
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt * sizeof(threadInfo));
6471 6472

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6473 6474
      free(infos);
      free(pids);
6475

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

6479
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6480
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6481

6482
    int64_t a = ntables / threads;
6483 6484 6485 6486
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6487

6488
    int64_t b = 0;
6489 6490 6491
    if (threads != 0) {
      b = ntables % threads;
    }
6492

6493
    uint64_t startFrom = 0;
6494
    for (int i = 0; i < threads; i++) {
6495 6496
      threadInfo *pThreadInfo = infosOfSub + i;
      pThreadInfo->threadID = i;
6497

6498 6499 6500 6501 6502 6503
      pThreadInfo->start_table_from = startFrom;
      pThreadInfo->ntables = i<b?a+1:a;
      pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = pThreadInfo->end_table_to + 1;
      pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
      pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
6504 6505
    }

6506
    g_queryInfo.superQueryInfo.threadCnt = threads;
6507
  } else {
6508
    g_queryInfo.superQueryInfo.threadCnt = 0;
6509
  }
6510

6511 6512 6513 6514 6515 6516
  if ((nSqlCount > 0) && (nConcurrent > 0)) {
    for (int i = 0; i < nConcurrent; i++) {
      for (int j = 0; j < nSqlCount; j++) {
        pthread_join(pids[i * nSqlCount + j], NULL);
      }
    }
6517
  }
S
Shuaiqiang Chang 已提交
6518

6519
  tmfree((char*)pids);
6520
  tmfree((char*)infos);
6521

6522
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6523
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6524
  }
H
Hui Li 已提交
6525

6526
  tmfree((char*)pidsOfSub);
6527
  tmfree((char*)infosOfSub);
6528

6529
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6530
  uint64_t endTs = taosGetTimestampMs();
6531

6532
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6533 6534
    g_queryInfo.superQueryInfo.totalQueried;

6535
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6536
          totalQueried,
6537
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6538 6539 6540
  return 0;
}

6541 6542 6543 6544 6545 6546 6547 6548 6549
static void stable_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
  if (res == NULL || taos_errno(res) != 0) {
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
    return;
  }

  if (param)
6550
    fetchResult(res, (threadInfo *)param);
6551 6552 6553 6554 6555
  // tao_unscribe() will free result.
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6556
  if (res == NULL || taos_errno(res) != 0) {
6557 6558
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6559 6560
    return;
  }
6561

6562
  if (param)
6563
    fetchResult(res, (threadInfo *)param);
6564
  // tao_unscribe() will free result.
H
hzcheng 已提交
6565 6566
}

6567
static TAOS_SUB* subscribeImpl(
6568
        QUERY_CLASS class,
6569
        threadInfo *pThreadInfo,
6570
        char *sql, char* topic, bool restart, uint64_t interval)
6571
{
6572
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6573

6574 6575
  if ((SPECIFIED_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode)) {
6576 6577
    tsub = taos_subscribe(
            pThreadInfo->taos,
6578
            restart,
6579
            topic, sql, specified_sub_callback, (void*)pThreadInfo,
6580
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6581 6582
  } else if ((STABLE_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode)) {
6583 6584 6585 6586 6587
    tsub = taos_subscribe(
            pThreadInfo->taos,
            restart,
            topic, sql, stable_sub_callback, (void*)pThreadInfo,
            g_queryInfo.superQueryInfo.subscribeInterval);
6588
  } else {
6589 6590
    tsub = taos_subscribe(
            pThreadInfo->taos,
6591
            restart,
6592
            topic, sql, NULL, NULL, interval);
6593
  }
6594

6595 6596 6597
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6598
  }
6599

6600 6601
  return tsub;
}
H
hzcheng 已提交
6602

6603 6604
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6605
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
6606
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
6607
  uint64_t tsubSeq;
H
hzcheng 已提交
6608

6609 6610
  if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
      errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
6611 6612 6613 6614 6615
              pThreadInfo->ntables,
              MAX_QUERY_SQL_COUNT);
      exit(-1);
  }

6616
  if (pThreadInfo->taos == NULL) {
6617
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
6618 6619 6620 6621
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
6622
    if (pThreadInfo->taos == NULL) {
6623
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6624
            pThreadInfo->threadID, taos_errstr(NULL));
6625 6626 6627 6628
      return NULL;
    }
  }

6629 6630
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6631 6632
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6633 6634
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6635 6636
    return NULL;
  }
6637

6638 6639 6640
  char topic[32] = {0};
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
6641 6642

      tsubSeq = i - pThreadInfo->start_table_from;
6643 6644 6645 6646 6647
      verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n",
              __func__, __LINE__,
              pThreadInfo->threadID,
              pThreadInfo->start_table_from,
              pThreadInfo->end_table_to, i);
6648 6649
      sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"",
              i, pThreadInfo->querySeq);
6650
      memset(subSqlstr, 0, sizeof(subSqlstr));
6651 6652 6653 6654
      replaceChildTblName(
              g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
              subSqlstr, i);
      if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6655
        sprintf(pThreadInfo->filePath, "%s-%d",
6656 6657 6658 6659 6660 6661
                g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
      }

      debugPrint("%s() LN%d, [%d] subSqlstr: %s\n",
              __func__, __LINE__, pThreadInfo->threadID, subSqlstr);
6662
      tsub[tsubSeq] = subscribeImpl(
6663
              STABLE_CLASS,
6664
              pThreadInfo, subSqlstr, topic,
6665 6666
              g_queryInfo.superQueryInfo.subscribeRestart,
              g_queryInfo.superQueryInfo.subscribeInterval);
6667
      if (NULL == tsub[tsubSeq]) {
6668
        taos_close(pThreadInfo->taos);
6669 6670
        return NULL;
      }
6671
  }
6672 6673

  // start loop to consume result
6674 6675 6676 6677
  int consumed[MAX_QUERY_SQL_COUNT];
  for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
    consumed[i] = 0;
  }
6678
  TAOS_RES* res = NULL;
6679

6680 6681
  uint64_t st = 0, et = 0;

6682
  while(1) {
6683 6684
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
6685 6686 6687 6688
      tsubSeq = i - pThreadInfo->start_table_from;
      if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
          continue;
      }
6689

6690 6691
      st = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
6692
      res = taos_consume(tsub[tsubSeq]);
6693 6694 6695
      et = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));

6696 6697
      if (res) {
          if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6698
              sprintf(pThreadInfo->filePath, "%s-%d",
6699 6700
                      g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6701
              fetchResult(res, pThreadInfo);
6702 6703
          }
          if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6704
              sprintf(pThreadInfo->filePath, "%s-%d",
6705 6706
                      g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6707
              fetchResult(res, pThreadInfo);
6708 6709 6710 6711 6712
          }
          consumed[tsubSeq] ++;

          if ((g_queryInfo.superQueryInfo.subscribeKeepProgress)
                  && (consumed[tsubSeq] >=
6713
                      g_queryInfo.superQueryInfo.resubAfterConsume)) {
6714 6715 6716 6717
              printf("keepProgress:%d, resub super table query: %"PRIu64"\n",
                      g_queryInfo.superQueryInfo.subscribeKeepProgress,
                      pThreadInfo->querySeq);
              taos_unsubscribe(tsub[tsubSeq],
6718
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);
6719 6720 6721 6722 6723 6724 6725 6726 6727 6728 6729 6730 6731
              consumed[tsubSeq]= 0;
              tsub[tsubSeq] = subscribeImpl(
                      STABLE_CLASS,
                      pThreadInfo, subSqlstr, topic,
                      g_queryInfo.superQueryInfo.subscribeRestart,
                      g_queryInfo.superQueryInfo.subscribeInterval
                      );
              if (NULL == tsub[tsubSeq]) {
                  taos_close(pThreadInfo->taos);
                  return NULL;
              }
          }
      }
H
hzcheng 已提交
6732 6733
    }
  }
6734
  taos_free_result(res);
6735

6736 6737
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
6738 6739
    tsubSeq = i - pThreadInfo->start_table_from;
    taos_unsubscribe(tsub[tsubSeq], 0);
6740
  }
6741

6742
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6743 6744 6745
  return NULL;
}

6746 6747
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6748
//  TAOS_SUB*  tsub = NULL;
6749

6750
  if (pThreadInfo->taos == NULL) {
6751
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
6752 6753 6754 6755
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
6756
    if (pThreadInfo->taos == NULL) {
6757
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6758
            pThreadInfo->threadID, taos_errstr(NULL));
6759 6760 6761 6762
      return NULL;
    }
  }

6763 6764
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6765 6766
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6767 6768
    return NULL;
  }
6769

6770 6771 6772 6773 6774 6775
  sprintf(g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
          "taosdemo-subscribe-%"PRIu64"-%d",
          pThreadInfo->querySeq,
          pThreadInfo->threadID);
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) {
      sprintf(pThreadInfo->filePath, "%s-%d",
6776
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
6777
                pThreadInfo->threadID);
6778
  }
6779 6780
  g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
          SPECIFIED_CLASS, pThreadInfo,
6781
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
6782
          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
6783 6784
          g_queryInfo.specifiedQueryInfo.subscribeRestart,
          g_queryInfo.specifiedQueryInfo.subscribeInterval);
6785
  if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
6786 6787
      taos_close(pThreadInfo->taos);
      return NULL;
6788
  }
6789

6790
  // start loop to consume result
6791

6792
  g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
6793
  while(1) {
6794
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6795 6796
        continue;
      }
6797

6798 6799 6800
      g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]);
      if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) {
6801
          if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6802
              sprintf(pThreadInfo->filePath, "%s-%d",
6803 6804
                      g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6805
              fetchResult(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID], pThreadInfo);
6806 6807
          }

6808
          g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++;
6809
          if ((g_queryInfo.specifiedQueryInfo.subscribeKeepProgress)
6810
                && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >=
6811 6812 6813 6814
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) {
              printf("keepProgress:%d, resub specified query: %"PRIu64"\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress,
                    pThreadInfo->querySeq);
6815 6816
              g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
              taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID],
6817
                      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6818
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
6819 6820 6821
                      SPECIFIED_CLASS,
                      pThreadInfo,
                      g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
6822
                      g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
6823 6824
                      g_queryInfo.specifiedQueryInfo.subscribeRestart,
                      g_queryInfo.specifiedQueryInfo.subscribeInterval);
6825
              if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
6826 6827
                taos_close(pThreadInfo->taos);
                return NULL;
6828 6829
              }
          }
6830 6831
      }
  }
6832 6833
  taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
  taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->querySeq], 0);
6834
  taos_close(pThreadInfo->taos);
6835

H
hzcheng 已提交
6836 6837 6838
  return NULL;
}

6839
static int subscribeTestProcess() {
6840
  setupForAnsiEscape();
6841
  printfQueryMeta();
6842
  resetAfterAnsiEscape();
6843

6844
  prompt();
6845

6846 6847 6848 6849 6850
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6851
          g_queryInfo.port);
6852
  if (taos == NULL) {
6853 6854
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6855 6856 6857
    exit(-1);
  }

6858
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6859 6860
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6861 6862 6863
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6864 6865
  }

6866 6867
  taos_close(taos); // TODO: workaround to use separate taos connection;

6868 6869
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
6870 6871 6872 6873 6874

  pthread_t  *pidsOfStable  = NULL;
  threadInfo *infosOfStable = NULL;

  //==== create threads for query for specified table
6875
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
6876
    debugPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
6877
              __func__, __LINE__,
6878 6879 6880 6881 6882 6883 6884 6885
              g_queryInfo.specifiedQueryInfo.sqlCount);
  } else {
    if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
        errorPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount);
        exit(-1);
    }
6886

6887
    pids  = malloc(
6888 6889 6890
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(pthread_t));
6891
    infos = malloc(
6892 6893 6894
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(threadInfo));
6895 6896 6897 6898
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
6899

6900 6901 6902
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
            uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
6903 6904 6905 6906 6907
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
            pThreadInfo->taos = NULL;  // TODO: workaround to use separate taos connection;
            pthread_create(pids + seq, NULL, specifiedSubscribe, pThreadInfo);
6908
        }
6909
    }
H
hzcheng 已提交
6910
  }
6911

6912
  //==== create threads for super table query
6913
  if (g_queryInfo.superQueryInfo.sqlCount <= 0) {
6914
    debugPrint("%s() LN%d, super table query sqlCount %"PRIu64".\n",
6915
              __func__, __LINE__,
6916
              g_queryInfo.superQueryInfo.sqlCount);
6917 6918
  } else {
    if ((g_queryInfo.superQueryInfo.sqlCount > 0)
6919
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
6920 6921 6922
        pidsOfStable  = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
6923
            sizeof(pthread_t));
6924 6925 6926
        infosOfStable = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
6927
            sizeof(threadInfo));
6928 6929
        if ((NULL == pidsOfStable) || (NULL == infosOfStable)) {
            errorPrint("%s() LN%d, malloc failed for create threads\n",
6930
              __func__, __LINE__);
6931 6932 6933
            // taos_close(taos);
            exit(-1);
        }
6934

6935 6936
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
6937

6938 6939 6940 6941 6942
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
6943

6944 6945 6946 6947
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
6948

6949
        for (uint64_t i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6950
            uint64_t startFrom = 0;
6951 6952
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
6953 6954 6955 6956 6957 6958 6959 6960 6961
                threadInfo *pThreadInfo = infosOfStable + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;

                pThreadInfo->start_table_from = startFrom;
                pThreadInfo->ntables = j<b?a+1:a;
                pThreadInfo->end_table_to = j<b?startFrom+a:startFrom+a-1;
                startFrom = pThreadInfo->end_table_to + 1;
                pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
6962
                pthread_create(pidsOfStable + seq,
6963
                        NULL, superSubscribe, pThreadInfo);
6964 6965
            }
        }
6966

6967
        g_queryInfo.superQueryInfo.threadCnt = threads;
6968

6969 6970 6971 6972 6973 6974
        for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
                pthread_join(pidsOfStable[seq], NULL);
            }
        }
6975
    }
H
hzcheng 已提交
6976
  }
6977

6978 6979 6980 6981 6982
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
    for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
        uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
        pthread_join(pids[seq], NULL);
    }
6983
  }
H
hzcheng 已提交
6984

6985
  tmfree((char*)pids);
6986
  tmfree((char*)infos);
H
hzcheng 已提交
6987

6988 6989
  tmfree((char*)pidsOfStable);
  tmfree((char*)infosOfStable);
6990
//   taos_close(taos);
6991
  return 0;
H
hzcheng 已提交
6992 6993
}

6994
static void initOfInsertMeta() {
6995
  memset(&g_Dbs, 0, sizeof(SDbs));
6996

6997
  // set default values
6998
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6999
  g_Dbs.port = 6030;
7000 7001
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
7002
  g_Dbs.threadCount = 2;
7003 7004

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
7005 7006
}

7007
static void initOfQueryMeta() {
7008
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
7009

7010
  // set default values
7011
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7012
  g_queryInfo.port = 6030;
7013 7014
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
7015 7016
}

7017
static void setParaFromArg(){
7018
  if (g_args.host) {
7019
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
7020
  } else {
7021
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7022
  }
L
Liu Tao 已提交
7023

7024
  if (g_args.user) {
7025
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
7026
  }
7027 7028

  if (g_args.password) {
7029
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
7030 7031
  }

7032 7033
  if (g_args.port) {
    g_Dbs.port = g_args.port;
7034
  }
L
Liu Tao 已提交
7035

7036 7037 7038
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

7039 7040
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
7041

7042
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
7043
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
7044
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
7045

7046
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
7047 7048 7049 7050 7051

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

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

7053 7054
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
7055

7056
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
7057

7058 7059
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
7060
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
7061
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
7062
  }
H
hzcheng 已提交
7063

7064 7065 7066 7067 7068
  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;
7069
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
7070
    g_Dbs.asyncMode = g_args.async_mode;
7071

7072 7073 7074 7075
    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;
7076
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
7077 7078 7079
            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);
7080
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
7081
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
7082
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
7083

7084
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
7085
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
7086

7087 7088 7089 7090 7091
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
7092

7093
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7094
              data_type[i], MAX_TB_NAME_SIZE);
7095
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
7096 7097
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
7098

7099 7100 7101
    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 {
7102 7103 7104 7105
      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);
7106
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
7107 7108 7109
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
7110

7111 7112
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
            "INT", MAX_TB_NAME_SIZE);
7113
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
7114

7115 7116
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
            "BINARY", MAX_TB_NAME_SIZE);
7117 7118
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
7119
  } else {
7120 7121
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
7122
  }
7123 7124 7125 7126 7127 7128
}

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

7130 7131 7132
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
7133 7134 7135
    exit(-1);
  }

7136 7137 7138 7139 7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152 7153 7154 7155 7156 7157 7158 7159
  /* 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);
}

7160
static void querySqlFile(TAOS* taos, char* sqlFile)
7161 7162 7163 7164 7165 7166
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
7167

7168 7169 7170 7171 7172 7173
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

7174
  double t = taosGetTimestampMs();
7175

7176
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188
    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;
7189
    }
7190 7191

    memcpy(cmd + cmd_len, line, read_len);
7192 7193 7194
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7195 7196 7197 7198 7199
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7200 7201
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7202 7203
  }

7204
  t = taosGetTimestampMs() - t;
7205
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7206

7207 7208 7209 7210
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7211 7212
}

7213
static void testMetaFile() {
7214
    if (INSERT_TEST == g_args.test_mode) {
7215 7216
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7217

7218
      insertTestProcess();
7219

7220
    } else if (QUERY_TEST == g_args.test_mode) {
7221 7222
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7223

7224
      queryTestProcess();
7225

7226
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7227 7228
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7229

7230
      subscribeTestProcess();
7231

7232 7233 7234
    }  else {
      ;
    }
7235
}
7236

7237
static void queryResult() {
7238
  // query data
7239

7240
  pthread_t read_id;
7241 7242 7243 7244
  threadInfo *pThreadInfo = malloc(sizeof(threadInfo));
  assert(pThreadInfo);
  pThreadInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  pThreadInfo->start_table_from = 0;
7245

7246
  //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
7247
  if (g_args.use_metric) {
7248 7249 7250 7251
    pThreadInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    pThreadInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    pThreadInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(pThreadInfo->tb_prefix,
7252 7253
          g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
  } else {
7254 7255 7256
    pThreadInfo->ntables = g_args.num_of_tables;
    pThreadInfo->end_table_to = g_args.num_of_tables -1;
    tstrncpy(pThreadInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
7257 7258
  }

7259
  pThreadInfo->taos = taos_connect(
7260 7261 7262 7263 7264
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
          g_Dbs.port);
7265
  if (pThreadInfo->taos == NULL) {
7266 7267
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7268
    free(pThreadInfo);
7269 7270 7271
    exit(-1);
  }

7272
  tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
7273 7274

  if (!g_Dbs.use_metric) {
7275
    pthread_create(&read_id, NULL, readTable, pThreadInfo);
7276
  } else {
7277
    pthread_create(&read_id, NULL, readMetric, pThreadInfo);
7278 7279
  }
  pthread_join(read_id, NULL);
7280 7281
  taos_close(pThreadInfo->taos);
  free(pThreadInfo);
7282 7283
}

7284 7285
static void testCmdLine() {

7286 7287 7288 7289 7290 7291 7292 7293 7294 7295
  if (strlen(configDir)) {
    wordexp_t full_path;
    if (wordexp(configDir, &full_path, 0) != 0) {
      errorPrint( "Invalid path %s\n", configDir);
      return;
    }
    taos_options(TSDB_OPTION_CONFIGDIR, full_path.we_wordv[0]);
    wordfree(&full_path);
  }

7296 7297
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7298

7299
  if (false == g_Dbs.insert_only)
7300
    queryResult();
7301 7302
}

7303 7304 7305
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7306
  debugPrint("meta file: %s\n", g_args.metaFile);
7307 7308 7309

  if (g_args.metaFile) {
    initOfInsertMeta();
7310
    initOfQueryMeta();
7311 7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323

    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(
7324 7325 7326 7327
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7328
          g_Dbs.port);
7329
      querySqlFile(qtaos, g_args.sqlFile);
7330 7331 7332 7333 7334
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
7335 7336 7337

    if (g_dupstr)
        free(g_dupstr);
H
hzcheng 已提交
7338
  }
7339 7340

  return 0;
H
hzcheng 已提交
7341
}
7342