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

16 17 18 19 20

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

21
#include <stdint.h>
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 117
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

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

123 124 125 126 127 128 129
enum INTERFACE {
    TAOSC_INTERFACE,
    REST_INTERFACE,
    STMT_INTERFACE,
    INTERFACE_BUT
};

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

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

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

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

/* Used by main to communicate with parse_opt. */
193 194
typedef struct SArguments_S {
  char *   metaFile;
195
  uint32_t test_mode;
196 197
  char *   host;
  uint16_t port;
198
  uint16_t interface;
199 200 201 202 203 204 205
  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 223 224
  uint64_t interlace_rows;
  uint64_t num_of_RPR;                  // num_of_records_per_req
  uint64_t max_sql_len;
  uint64_t num_of_tables;
  uint64_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 260
  uint64_t     insertInterval;          // insert interval, will override global insert interval
  uint64_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 294
} SSuperTable;

typedef struct {
  char     name[TSDB_DB_NAME_LEN + 1];
  char     create_time[32];
  int32_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 366 367
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
  uint64_t     concurrent;
  uint64_t     sqlCount;
368
  uint32_t     asyncMode; // 0: sync, 1: async
369 370
  uint64_t     subscribeInterval; // ms
  uint64_t     queryTimes;
371 372
  int          subscribeRestart;
  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
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
376
  uint64_t     totalQueried;
377
} SpecifiedQueryInfo;
378

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

395
  char*        childTblName;
396
  uint64_t     totalQueried;
397
} SuperQueryInfo;
398 399

typedef struct SQueryMetaInfo_S {
400
  char         cfgDir[MAX_FILE_NAME_LEN+1];
401
  char         host[MAX_HOSTNAME_SIZE];
402
  uint16_t     port;
403
  struct       sockaddr_in serv_addr;
404 405
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
406
  char         dbName[MAX_DB_NAME_SIZE+1];
407
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
408

409 410
  SpecifiedQueryInfo  specifiedQueryInfo;
  SuperQueryInfo    superQueryInfo;
411
  uint64_t     totalQueried;
412 413 414
} SQueryMetaInfo;

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

  // for async insert
431 432
  tsem_t    lock_sem;
  int64_t   counter;
433 434
  uint64_t  st;
  uint64_t  et;
435
  uint64_t  lastTs;
436

437
  // sample data
438
  int64_t   samplePos;
439
  // statistics
440 441
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
442 443

  // insert delay statistics
444 445 446 447 448
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
449

450
  // query
451
  uint64_t  querySeq;   // sequence number of sql command
452 453
} threadInfo;

454
#ifdef WINDOWS
455 456
#define _CRT_RAND_S

457
#include <windows.h>
458 459 460 461 462
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
463 464
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
465 466
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
467 468 469 470

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

471
static void setupForAnsiEscape(void) {
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
  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());
490
  }
491 492
}

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

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

503
static int taosRandom()
504 505 506 507 508 509
{
    int number;
    rand_s(&number);

    return number;
}
510
#else   // Not windows
511
static void setupForAnsiEscape(void) {}
512

513
static void resetAfterAnsiEscape(void) {
514 515 516
  // Reset colors
  printf("\x1b[0m");
}
517

518 519
#include <time.h>

520
static int taosRandom()
521
{
522
  return rand();
523 524
}

525
#endif // ifdef Windows
526

527
static int createDatabasesAndStables();
528
static void createChildTables();
529
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
530 531
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
        char* sqlstr, char *resultFile);
532 533 534 535 536 537 538

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

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

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



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

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

601
#define verbosePrint(fmt, ...) \
602 603
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
604

605 606 607 608
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

609 610 611 612
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


613
///////////////////////////////////////////////////
H
hzcheng 已提交
614

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

617 618 619 620 621 622 623 624
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

625
#ifndef TAOSDEMO_STATUS
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
#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);
    }
}

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

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
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;
}

726
static void parse_args(int argc, char *argv[], SArguments *arguments) {
727
  char **sptr;
728 729 730 731 732

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

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

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

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

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

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

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

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

1056 1057 1058 1059
    }
    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);
1060
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1061 1062 1063 1064 1065 1066
    printf("###################################################################\n");
    if (!arguments->answer_yes) {
        printf("Press enter key to continue\n\n");
        (void) getchar();
    }
  }
1067
}
H
hzcheng 已提交
1068

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

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

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

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

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

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

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

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

1123 1124
static void appendResultBufToFile(char *resultBuf, char *resultFile)
{
1125
  FILE *fp = NULL;
1126 1127
  if (resultFile[0] != 0) {
    fp = fopen(resultFile, "at");
1128
    if (fp == NULL) {
1129 1130 1131 1132
      errorPrint(
              "%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFile);
      return;
1133 1134
    }
  }
1135

S
Shengliang Guan 已提交
1136

1137 1138 1139 1140 1141 1142 1143 1144 1145 1146
  fprintf(fp, "%s", resultBuf);
  tmfclose(fp);
}

static void appendResultToFile(TAOS_RES *res, char* resultFile) {
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

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

1154 1155
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1156

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

S
Shengliang Guan 已提交
1172
  verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n", __func__, __LINE__, databuf, resultFile);
1173
  appendResultBufToFile(databuf, resultFile);
1174 1175
  free(databuf);
}
H
hzcheng 已提交
1176

1177
static void selectAndGetResult(
S
Shuduo Sang 已提交
1178
        threadInfo *pThreadInfo, char *command, char* resultFile) {
1179 1180 1181 1182 1183 1184 1185 1186 1187
  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;
    }

1188 1189 1190
    if ((resultFile) && (strlen(resultFile))) {
      appendResultToFile(res, resultFile);
    }
1191
    taos_free_result(res);
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,
1196 1197
              command,
              resultFile);
1198 1199 1200 1201 1202 1203 1204 1205
      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);
  }
1206
}
H
hzcheng 已提交
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 1246
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;
1247
  return randfloat[cursor];
1248 1249
}

1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266
#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

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

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

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

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

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

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

1338 1339
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1340
    printf("  database[%d] name:      \033[33m%s\033[0m\n", i, g_Dbs.db[i].dbName);
1341
    if (0 == g_Dbs.db[i].drop) {
1342 1343 1344
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
      printf("  blocks:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.blocks);
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
      printf("  cache:                 \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.cache);
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
      printf("  days:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.days);
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
      printf("  keep:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.keep);
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
      printf("  replica:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.replica);
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
      printf("  update:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.update);
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
      printf("  minRows:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.minRows);
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
      printf("  maxRows:               \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.maxRows);
    }
    if (g_Dbs.db[i].dbCfg.comp > 0) {
      printf("  comp:                  \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.comp);
    }
    if (g_Dbs.db[i].dbCfg.walLevel > 0) {
      printf("  walLevel:              \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.walLevel);
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
      printf("  fsync:                 \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.fsync);
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
      printf("  quorum:                \033[33m%d\033[0m\n", g_Dbs.db[i].dbCfg.quorum);
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1384
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1385
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1386
        printf("  precision:             \033[33m%s\033[0m\n",
1387
            g_Dbs.db[i].dbCfg.precision);
1388
      } else {
1389
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
1390
                g_Dbs.db[i].dbCfg.precision);
1391
        return -1;
1392 1393 1394
      }
    }

1395
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1396
        g_Dbs.db[i].superTblCount);
1397 1398
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1399

1400
      printf("      stbName:           \033[33m%s\033[0m\n",
1401
          g_Dbs.db[i].superTbls[j].sTblName);
1402 1403 1404 1405 1406 1407 1408 1409

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

1411 1412 1413 1414 1415 1416 1417
      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");
      }
1418

1419
      printf("      childTblCount:     \033[33m%"PRIu64"\033[0m\n",
1420
              g_Dbs.db[i].superTbls[j].childTblCount);
1421
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",
1422
              g_Dbs.db[i].superTbls[j].childTblPrefix);
1423
      printf("      dataSource:        \033[33m%s\033[0m\n",
1424
              g_Dbs.db[i].superTbls[j].dataSource);
1425
      printf("      insertMode:        \033[33m%s\033[0m\n",
1426
              g_Dbs.db[i].superTbls[j].insertMode);
1427
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1428
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1429
                g_Dbs.db[i].superTbls[j].childTblLimit);
1430
      }
1431
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1432
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1433
                g_Dbs.db[i].superTbls[j].childTblOffset);
1434
      }
1435
      printf("      insertRows:        \033[33m%"PRIu64"\033[0m\n",
1436
              g_Dbs.db[i].superTbls[j].insertRows);
1437
/*
1438
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1439
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1440
      }else {
1441
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1442
      }
1443
      */
1444
      printf("      interlaceRows:     \033[33m%"PRIu64"\033[0m\n",
1445
              g_Dbs.db[i].superTbls[j].interlaceRows);
1446 1447

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

1452
      printf("      disorderRange:     \033[33m%d\033[0m\n",
1453
              g_Dbs.db[i].superTbls[j].disorderRange);
1454
      printf("      disorderRatio:     \033[33m%d\033[0m\n",
1455
              g_Dbs.db[i].superTbls[j].disorderRatio);
1456
      printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
1457
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1458
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1459
              g_Dbs.db[i].superTbls[j].timeStampStep);
1460
      printf("      startTimestamp:    \033[33m%s\033[0m\n",
1461
              g_Dbs.db[i].superTbls[j].startTimestamp);
1462
      printf("      sampleFormat:      \033[33m%s\033[0m\n",
1463
              g_Dbs.db[i].superTbls[j].sampleFormat);
1464
      printf("      sampleFile:        \033[33m%s\033[0m\n",
1465
              g_Dbs.db[i].superTbls[j].sampleFile);
1466
      printf("      tagsFile:          \033[33m%s\033[0m\n",
1467
              g_Dbs.db[i].superTbls[j].tagsFile);
1468
      printf("      columnCount:       \033[33m%d\033[0m\n",
1469
              g_Dbs.db[i].superTbls[j].columnCount);
1470 1471
      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);
1472
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
1473 1474 1475
                       "binary", 6))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                       "nchar", 5))) {
1476
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1477 1478
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1479
        } else {
1480
          printf("column[%d]:\033[33m%s\033[0m ", k,
1481
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1482 1483 1484
        }
      }
      printf("\n");
1485 1486

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
1487
              g_Dbs.db[i].superTbls[j].tagCount);
1488 1489
      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);
1490
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1491 1492 1493
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1494
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1495 1496
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1497
        } else {
1498
          printf("tag[%d]:\033[33m%s\033[0m ", k,
1499
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1500
        }
1501 1502 1503 1504 1505
      }
      printf("\n");
    }
    printf("\n");
  }
1506 1507

  SHOW_PARSE_RESULT_END();
1508 1509

  return 0;
1510 1511 1512
}

static void printfInsertMetaToFile(FILE* fp) {
1513 1514

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1515

1516 1517
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1518
  fprintf(fp, "configDir:                  %s\n", configDir);
1519 1520 1521
  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);
1522 1523
  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);
1524
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1525

1526 1527
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1528
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1529
    if (0 == g_Dbs.db[i].drop) {
1530
      fprintf(fp, "  drop:                  no\n");
1531
    }else {
1532
      fprintf(fp, "  drop:                  yes\n");
1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 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
    }

    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) {
1572
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1573
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1574 1575 1576 1577 1578 1579
        fprintf(fp, "  precision:             %s\n", g_Dbs.db[i].dbCfg.precision);
      } else {
        fprintf(fp, "  precision error:       %s\n", g_Dbs.db[i].dbCfg.precision);
      }
    }

1580
    fprintf(fp, "  super table count:     %"PRIu64"\n", g_Dbs.db[i].superTblCount);
1581 1582
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1583 1584

      fprintf(fp, "      stbName:           %s\n",  g_Dbs.db[i].superTbls[j].sTblName);
1585 1586 1587 1588 1589 1590 1591 1592

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

1594 1595 1596 1597 1598 1599 1600
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
      } else if (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1601

1602
      fprintf(fp, "      childTblCount:     %"PRIu64"\n",
1603 1604 1605 1606 1607 1608 1609
              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);
1610
      fprintf(fp, "      insertRows:        %"PRIu64"\n",
1611
              g_Dbs.db[i].superTbls[j].insertRows);
1612
      fprintf(fp, "      interlace rows:    %"PRIu64"\n",
1613
              g_Dbs.db[i].superTbls[j].interlaceRows);
1614
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1615
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1616
                g_Dbs.db[i].superTbls[j].insertInterval);
1617
      }
1618
/*
1619
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1620
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1621
      }else {
1622
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1623
      }
1624
      */
1625
      fprintf(fp, "      interlaceRows:     %"PRIu64"\n",
1626
              g_Dbs.db[i].superTbls[j].interlaceRows);
1627
      fprintf(fp, "      disorderRange:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRange);
1628
      fprintf(fp, "      disorderRatio:     %d\n",  g_Dbs.db[i].superTbls[j].disorderRatio);
1629
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1630
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1631

1632 1633 1634 1635
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1636
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1637 1638 1639
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

1640 1641 1642
      fprintf(fp, "      columnCount:       %d\n        ",  g_Dbs.db[i].superTbls[j].columnCount);
      for (int k = 0; k < g_Dbs.db[i].superTbls[j].columnCount; k++) {
        //printf("dataType:%s, dataLen:%d\t", g_Dbs.db[i].superTbls[j].columns[k].dataType, g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1643
        if ((0 == strncasecmp(
1644 1645 1646 1647
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "nchar", strlen("nchar")))) {
1648 1649 1650
          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);
1651 1652 1653 1654 1655
        } else {
          fprintf(fp, "column[%d]:%s ", k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
        }
      }
      fprintf(fp, "\n");
1656 1657 1658

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1659 1660
      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);
1661
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1662 1663 1664
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1665 1666
          fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1667 1668
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1669
        }
1670 1671 1672 1673 1674
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1675

1676
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1677 1678 1679
}

static void printfQueryMeta() {
1680

1681
  SHOW_PARSE_RESULT_START();
1682

1683
  printf("host:                    \033[33m%s:%u\033[0m\n",
1684
          g_queryInfo.host, g_queryInfo.port);
1685 1686 1687 1688
  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");
1689 1690 1691 1692

  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",
1693
      g_queryInfo.specifiedQueryInfo.sqlCount);
1694 1695 1696
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1697
      g_queryInfo.specifiedQueryInfo.queryTimes);
1698 1699 1700 1701 1702 1703
      printf("query interval: \033[33m%"PRIu64" ms\033[0m\n",
        g_queryInfo.specifiedQueryInfo.queryInterval);
      printf("top query times:\033[33m%"PRIu64"\033[0m\n", g_args.query_times);
      printf("concurrent:     \033[33m%"PRIu64"\033[0m\n",
      g_queryInfo.specifiedQueryInfo.concurrent);
      printf("mod:            \033[33m%s\033[0m\n",
1704
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1705
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1706
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1707
      printf("restart:        \033[33m%d\033[0m\n",
1708
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1709
      printf("keepProgress:   \033[33m%d\033[0m\n",
1710
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1711

1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735
      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);
      printf("childTblCount:  \033[33m%"PRIu64"\033[0m\n",
        g_queryInfo.superQueryInfo.childTblCount);
      printf("stable name:    \033[33m%s\033[0m\n",
        g_queryInfo.superQueryInfo.sTblName);
      printf("stb query times:\033[33m%"PRIu64"\033[0m\n",
        g_queryInfo.superQueryInfo.queryTimes);

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

1744 1745 1746 1747 1748 1749
      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");
    }
1750
  }
1751

1752
  SHOW_PARSE_RESULT_END();
1753 1754
}

1755
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
  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;
}

1787
static void xDumpFieldToFile(FILE* fp, const char* val,
1788
        TAOS_FIELD* field, int32_t length, int precision) {
1789

1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824
  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:
1825
      formatTimestamp(buf, *(int64_t*)val, precision);
1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840
      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) {
1841
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
    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);
1856

1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876
  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;
}

1877 1878
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1879 1880
  TAOS_ROW row = NULL;
  int count = 0;
1881 1882

  res = taos_query(taos, "show databases;");
1883
  int32_t code = taos_errno(res);
1884

1885
  if (code != 0) {
1886
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1887 1888 1889 1890 1891
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1892
  while((row = taos_fetch_row(res)) != NULL) {
1893
    // sys database name : 'log'
1894
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1895
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1896 1897
      continue;
    }
1898 1899 1900

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

1905
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
1906
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1907
    formatTimestamp(dbInfos[count]->create_time,
1908 1909
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1910
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1911
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1912 1913
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1914
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1915

1916
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1917
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1918 1919 1920 1921 1922 1923 1924
    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]));
1925
    dbInfos[count]->cachelast =
1926
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1927

1928
    tstrncpy(dbInfos[count]->precision,
1929 1930
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1931
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1932
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1933
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1934

1935 1936
    count++;
    if (count > MAX_DATABASE_COUNT) {
1937
      errorPrint("%s() LN%d, The database count overflow than %d\n",
1938
         __func__, __LINE__, MAX_DATABASE_COUNT);
1939 1940 1941 1942 1943 1944 1945
      break;
    }
  }

  return count;
}

1946
static void printfDbInfoForQueryToFile(
1947
        char* filename, SDbInfo* dbInfos, int index) {
1948

1949
  if (filename[0] == 0)
1950
      return;
1951 1952 1953

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1954
    errorPrint( "failed to open file: %s\n", filename);
1955
    return;
1956 1957 1958 1959 1960 1961
  }

  fprintf(fp, "================ database[%d] ================\n", index);
  fprintf(fp, "name: %s\n", dbInfos->name);
  fprintf(fp, "created_time: %s\n", dbInfos->create_time);
  fprintf(fp, "ntables: %d\n", dbInfos->ntables);
1962
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
1963 1964
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
1965 1966
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
1967 1968 1969 1970 1971 1972 1973
  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);
1974 1975
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
1976
  fprintf(fp, "update: %d\n", dbInfos->update);
1977
  fprintf(fp, "status: %s\n", dbInfos->status);
1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991
  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);
1992
  snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
1993 1994
          lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
          lt->tm_sec);
1995

1996 1997
  // show variables
  res = taos_query(taos, "show variables;");
1998
  //appendResultToFile(res, filename);
1999 2000 2001 2002 2003
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
2004
  //appendResultToFile(res, filename);
2005

2006 2007 2008 2009
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
2010
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
2011 2012 2013
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
2014
  if (dbCount <= 0) {
2015 2016
      free(dbInfos);
      return;
2017
  }
2018 2019

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

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

2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038
    // 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);
}

2039 2040
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
        char* sqlstr, char *resultFile)
2041
{
2042
    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";
2043

2044
    char *url = "/rest/sql";
2045

2046 2047 2048 2049
    int bytes, sent, received, req_str_len, resp_len;
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
2050

2051
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
2052

2053 2054 2055 2056 2057
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2058

2059 2060
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
2061

2062 2063 2064 2065 2066 2067 2068 2069
    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', '+', '/'};
2070

2071 2072 2073 2074
    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);
2075

2076
    char base64_buf[INPUT_BUF_LEN];
2077
#ifdef WINDOWS
2078
    WSADATA wsaData;
2079
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2080 2081
    SOCKET sockfd;
#else
2082
    int sockfd;
2083
#endif
2084 2085
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
2086
#ifdef WINDOWS
2087
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2088
#endif
2089 2090 2091 2092
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
        ERROR_EXIT("ERROR opening socket");
    }
2093

2094
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2095 2096 2097 2098 2099
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2100

2101
    memset(base64_buf, 0, INPUT_BUF_LEN);
2102

2103 2104 2105 2106 2107 2108 2109 2110
    for (int n = 0, m = 0; n < userpass_buf_len;) {
      uint32_t oct_a = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t oct_b = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t oct_c = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t triple = (oct_a << 0x10) + (oct_b << 0x08) + oct_c;
2111

2112 2113 2114 2115 2116
      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];
    }
2117

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

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

2125 2126 2127 2128 2129 2130 2131 2132 2133
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
2134

2135 2136 2137
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2138
#ifdef WINDOWS
2139
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2140
#else
2141
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2142
#endif
2143 2144 2145 2146 2147 2148
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2149

2150 2151 2152 2153
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2154
#ifdef WINDOWS
2155
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2156
#else
2157
        bytes = read(sockfd, response_buf + received, resp_len - received);
2158
#endif
2159 2160 2161 2162 2163 2164 2165 2166
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2167

2168 2169 2170 2171
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2172

2173 2174
    response_buf[RESP_BUF_LEN - 1] = '\0';
    printf("Response:\n%s\n", response_buf);
H
Haojun Liao 已提交
2175

2176 2177 2178 2179
    if (resultFile) {
       appendResultBufToFile(response_buf, resultFile);
    }

2180
    free(request_buf);
2181
#ifdef WINDOWS
2182
    closesocket(sockfd);
2183 2184
    WSACleanup();
#else
2185
    close(sockfd);
2186
#endif
2187

2188
    return 0;
2189 2190
}

2191
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2192 2193
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2194
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2195
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2196 2197
    return NULL;
  }
2198

2199
  int    dataLen = 0;
2200
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2201
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2202

2203 2204 2205
  return dataBuf;
}

2206
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2207 2208 2209 2210 2211 2212 2213 2214 2215
  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++) {
2216
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
2217
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2218
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2219
        printf("binary or nchar length overflow, max size:%u\n",
2220
                (uint32_t)TSDB_MAX_BINARY_LEN);
2221 2222 2223
        tmfree(dataBuf);
        return NULL;
      }
2224

2225 2226
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2227 2228 2229 2230 2231
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2232 2233 2234 2235 2236 2237 2238

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2239
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2240
              "\'%s\', ", buf);
2241
      tmfree(buf);
2242
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2243
                "int", strlen("int"))) {
2244
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2245
              "%d, ", tableSeq);
2246
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2247
                "bigint", strlen("bigint"))) {
2248
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2249
              "%"PRId64", ", rand_bigint());
2250
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2251
                "float", strlen("float"))) {
2252
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2253
              "%f, ", rand_float());
2254
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2255
                "double", strlen("double"))) {
2256
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2257
              "%f, ", rand_double());
2258
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2259
                "smallint", strlen("smallint"))) {
2260
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2261
              "%d, ", rand_smallint());
2262
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2263
                "tinyint", strlen("tinyint"))) {
2264
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2265
              "%d, ", rand_tinyint());
2266
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2267
                "bool", strlen("bool"))) {
2268
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2269
              "%d, ", rand_bool());
2270
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2271
                "timestamp", strlen("timestamp"))) {
2272
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2273
              "%"PRId64", ", rand_bigint());
2274 2275 2276 2277 2278 2279
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2280

2281
  dataLen -= 2;
2282
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2283 2284 2285
  return dataBuf;
}

2286
static int calcRowLen(SSuperTable*  superTbls) {
2287 2288
  int colIndex;
  int  lenOfOneRow = 0;
2289

2290 2291
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2292

2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308
    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;
2309
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2310
      lenOfOneRow += 42;
2311
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324
      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;
2325

2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341
    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;
2342
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2343 2344 2345 2346 2347 2348 2349 2350
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2351

2352 2353 2354 2355
  return 0;
}


2356
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2357
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2358
        uint64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2359

2360
  char command[BUFFER_SIZE] = "\0";
2361 2362
  char limitBuf[100] = "\0";

2363
  TAOS_RES * res;
2364 2365 2366
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2367 2368

  if (offset >= 0) {
2369
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2370
            limit, offset);
2371 2372
  }

2373
  //get all child table name use cmd: select tbname from superTblName;
2374
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2375
          dbName, sTblName, limitBuf);
2376

2377
  res = taos_query(taos, command);
2378 2379 2380 2381
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2382
    errorPrint("%s() LN%d, failed to run command %s\n",
2383
           __func__, __LINE__, command);
2384 2385 2386
    exit(-1);
  }

2387
  int childTblCount = (limit < 0)?10000:limit;
2388
  int count = 0;
2389 2390 2391
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2392 2393 2394 2395
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2396 2397 2398
    }
  }

2399
  char* pTblName = childTblName;
2400
  while((row = taos_fetch_row(res)) != NULL) {
2401
    int32_t* len = taos_fetch_lengths(res);
2402
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2403 2404 2405
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2406
      char *tmp = realloc(childTblName,
2407
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2408 2409 2410
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2411
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
2412
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2413 2414
      } else {
        // exit, if allocate more memory failed
2415
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
2416
               __func__, __LINE__, dbName, sTblName);
2417 2418 2419 2420 2421 2422
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2423
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2424
  }
2425

2426 2427 2428 2429 2430 2431 2432
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2433
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2434
        char* sTblName, char** childTblNameOfSuperTbl,
2435
        uint64_t* childTblCountOfSuperTbl) {
2436

2437 2438
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2439
            -1, 0);
2440 2441
}

2442
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2443
        SSuperTable*  superTbls) {
2444

2445
  char command[BUFFER_SIZE] = "\0";
2446
  TAOS_RES * res;
2447 2448
  TAOS_ROW row = NULL;
  int count = 0;
2449

2450
  //get schema use cmd: describe superTblName;
2451
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2452
  res = taos_query(taos, command);
2453 2454 2455
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2456
    taos_free_result(res);
2457 2458 2459 2460 2461 2462
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2463
  while((row = taos_fetch_row(res)) != NULL) {
2464 2465 2466
    if (0 == count) {
      count++;
      continue;
2467
    }
2468 2469

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2470
      tstrncpy(superTbls->tags[tagIndex].field,
2471 2472
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2473
      tstrncpy(superTbls->tags[tagIndex].dataType,
2474 2475
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2476 2477 2478
      superTbls->tags[tagIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->tags[tagIndex].note,
2479 2480
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2481
      tagIndex++;
2482
    } else {
2483
      tstrncpy(superTbls->columns[columnIndex].field,
2484 2485
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2486
      tstrncpy(superTbls->columns[columnIndex].dataType,
2487 2488
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2489 2490 2491
      superTbls->columns[columnIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->columns[columnIndex].note,
2492 2493
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2505
/*
2506
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2507
    //get all child table name use cmd: select tbname from superTblName;
2508 2509 2510
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2511
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2512 2513
      return -1;
    }
2514
    getAllChildNameOfSuperTable(taos, dbName,
2515 2516 2517
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2518
  }
2519
  */
2520 2521 2522
  return 0;
}

H
Haojun Liao 已提交
2523
static int createSuperTable(
2524 2525
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2526

2527
  char command[BUFFER_SIZE] = "\0";
2528

2529 2530 2531 2532 2533
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2534 2535 2536

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

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

2544
    if (strcasecmp(dataType, "BINARY") == 0) {
2545
      len += snprintf(cols + len, STRING_LEN - len,
2546 2547
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbl->columns[colIndex].dataLen);
2548
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2549
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2550
      len += snprintf(cols + len, STRING_LEN - len,
2551 2552
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbl->columns[colIndex].dataLen);
2553
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571
    } 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;
2572
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2573 2574
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2575
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2576 2577 2578 2579
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2580
      errorPrint("%s() LN%d, config error data type : %s\n",
2581
         __func__, __LINE__, dataType);
2582 2583 2584 2585
      exit(-1);
    }
  }

2586 2587
  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);
2588 2589

  // save for creating child table
2590 2591 2592
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2593
           __func__, __LINE__, len+1);
2594 2595 2596 2597
    taos_close(taos);
    exit(-1);
  }

2598
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2599
  verbosePrint("%s() LN%d: %s\n",
2600
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2601

2602 2603
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
2604
            __func__, __LINE__, superTbl->tagCount);
2605 2606
    return -1;
  }
2607

2608 2609 2610
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2611

2612 2613 2614 2615
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2616

2617 2618
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2619
              "BINARY", superTbl->tags[tagIndex].dataLen);
2620 2621 2622
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2623
              "NCHAR", superTbl->tags[tagIndex].dataLen);
2624 2625 2626
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2627
              "INT");
2628 2629 2630
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2631
              "BIGINT");
2632 2633 2634
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2635
              "SMALLINT");
2636 2637 2638
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2639
              "TINYINT");
2640 2641 2642
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2643
              "BOOL");
2644 2645 2646
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2647
              "FLOAT");
2648 2649 2650
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2651
              "DOUBLE");
2652 2653 2654
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
    } else {
      taos_close(taos);
2655
      errorPrint("%s() LN%d, config error tag type : %s\n",
2656
         __func__, __LINE__, dataType);
2657
      exit(-1);
2658 2659
    }
  }
2660 2661 2662 2663 2664 2665 2666

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2672 2673 2674
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2675 2676
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2677 2678 2679
  return 0;
}

2680
static int createDatabasesAndStables() {
2681 2682 2683 2684
  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) {
2685
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2686
    return -1;
2687 2688 2689
  }
  char command[BUFFER_SIZE] = "\0";

2690
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2691 2692
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2693
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2694
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2695 2696 2697 2698
        taos_close(taos);
        return -1;
      }

2699
      int dataLen = 0;
2700
      dataLen += snprintf(command + dataLen,
2701
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2702

2703 2704
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
2705
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
2706 2707 2708
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
2709
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
2710 2711 2712
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
2713
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
2714 2715 2716
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
2717
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
2718 2719 2720
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
2721
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
2722 2723 2724
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
2725
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
2726 2727 2728
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
2729
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
2730 2731 2732 2733 2734 2735 2736
      }
      //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,
2737
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
2738 2739 2740
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
2741
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
2742 2743 2744
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
2745
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
2746 2747 2748
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
2749
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
2750 2751 2752
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
2753
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
2754 2755 2756
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2757
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
2758 2759
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
2760 2761
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
2762
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2763
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
2764 2765 2766 2767 2768 2769 2770 2771 2772
      }

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

2775
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2776
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2777 2778 2779

    int validStbCount = 0;

2780
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2781 2782 2783 2784 2785 2786 2787
      sprintf(command, "describe %s.%s;", g_Dbs.db[i].dbName,
              g_Dbs.db[i].superTbls[j].sTblName);
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);

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

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

2791
        if (0 != ret) {
2792 2793
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2794 2795 2796
        }
      }

2797
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2798
                &g_Dbs.db[i].superTbls[j]);
2799 2800
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2801
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2802
        continue;
2803
      }
2804 2805

      validStbCount ++;
2806
    }
2807 2808

    g_Dbs.db[i].superTblCount = validStbCount;
2809 2810 2811 2812 2813 2814
  }

  taos_close(taos);
  return 0;
}

2815 2816
static void* createTable(void *sarg)
{
2817 2818
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2819 2820 2821

  int64_t  lastPrintTime = taosGetTimestampMs();

2822
  int buff_len;
2823
  buff_len = BUFFER_SIZE / 8;
2824

2825
  char *buffer = calloc(buff_len, 1);
2826
  if (buffer == NULL) {
2827
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2828 2829
    exit(-1);
  }
2830 2831 2832

  int len = 0;
  int batchNum = 0;
2833

2834
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2835 2836
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2837

2838
  for (uint64_t i = pThreadInfo->start_table_from;
2839
          i <= pThreadInfo->end_table_to; i++) {
2840
    if (0 == g_Dbs.use_metric) {
2841
      snprintf(buffer, buff_len,
2842
              "create table if not exists %s.%s%"PRIu64" %s;",
2843 2844 2845
              pThreadInfo->db_name,
              g_args.tb_prefix, i,
              pThreadInfo->cols);
2846
    } else {
2847 2848
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
2849
                  __func__, __LINE__);
2850
        free(buffer);
2851 2852 2853 2854 2855 2856
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
          memset(buffer, 0, buff_len);
          len += snprintf(buffer + len,
2857
                  buff_len - len, "create table ");
2858 2859 2860
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
2861
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2862 2863
        } else {
          tagsValBuf = getTagValueFromTagSample(
2864 2865
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
2866 2867 2868 2869 2870 2871
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
        len += snprintf(buffer + len,
2872
                buff_len - len,
2873
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
2874 2875 2876
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
                superTblInfo->sTblName, tagsValBuf);
2877 2878 2879
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2880 2881
                && ((buff_len - len)
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
2882 2883
          continue;
        }
2884 2885 2886 2887
      }
    }

    len = 0;
2888
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2889
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2890
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2891
      free(buffer);
2892 2893 2894 2895 2896
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2897
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2898
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2899 2900 2901
      lastPrintTime = currentPrintTime;
    }
  }
2902

2903
  if (0 != len) {
2904
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2905
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2906
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2907
    }
2908
  }
2909

2910 2911 2912 2913
  free(buffer);
  return NULL;
}

2914
static int startMultiThreadCreateChildTable(
2915
        char* cols, int threads, uint64_t startFrom, uint64_t ntables,
2916
        char* db_name, SSuperTable* superTblInfo) {
2917

2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929
  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;
  }

2930
  uint64_t a = ntables / threads;
2931 2932 2933 2934 2935
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2936
  uint64_t b = 0;
2937
  b = ntables % threads;
2938

2939
  for (int64_t i = 0; i < threads; i++) {
2940 2941
    threadInfo *t_info = infos + i;
    t_info->threadID = i;
H
Hui Li 已提交
2942
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
2943
    t_info->superTblInfo = superTblInfo;
2944
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
2945
    t_info->taos = taos_connect(
2946 2947 2948 2949 2950
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
2951
    if (t_info->taos == NULL) {
2952
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
2953
         __func__, __LINE__, taos_errstr(NULL));
2954
      free(pids);
2955
      free(infos);
2956 2957
      return -1;
    }
2958 2959 2960 2961 2962

    t_info->start_table_from = startFrom;
    t_info->ntables = i<b?a+1:a;
    t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
    startFrom = t_info->end_table_to + 1;
2963
    t_info->use_metric = true;
2964
    t_info->cols = cols;
2965
    t_info->minDelay = UINT64_MAX;
2966 2967
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2968

2969 2970 2971 2972 2973 2974 2975 2976 2977 2978
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

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

  free(pids);
2979
  free(infos);
2980 2981

  return 0;
2982 2983
}

2984
static void createChildTables() {
2985 2986
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
2987

2988
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2989 2990
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
2991
          // with super table
2992 2993
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
2994
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
2995 2996
            continue;
          }
2997

2998
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
2999
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
3000 3001 3002 3003
          int startFrom = 0;
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

          verbosePrint("%s() LN%d: create %d child tables from %d\n",
3004
                  __func__, __LINE__, g_totalChildTables, startFrom);
3005
          startMultiThreadCreateChildTable(
3006 3007 3008 3009 3010
                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]));
3011
        }
3012 3013
      }
    } else {
3014 3015
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
H
Haojun Liao 已提交
3016
      for (int j = 0; j < g_args.num_of_CPR; j++) {
3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
          if ((strncasecmp(g_args.datatype[j], "BINARY", strlen("BINARY")) == 0)
                  || (strncasecmp(g_args.datatype[j],
                      "NCHAR", strlen("NCHAR")) == 0)) {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                      ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary);
          } else {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                      ", COL%d %s", j, g_args.datatype[j]);
          }
          len = strlen(tblColsBuf);
3027
      }
3028

3029
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
3030

3031
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRIu64" schema: %s\n",
3032 3033
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
3034
      startMultiThreadCreateChildTable(
3035 3036 3037 3038 3039 3040
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
3041
    }
3042 3043 3044 3045 3046 3047
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3048
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3049 3050 3051
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3052

3053 3054
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3055
    printf("Failed to open tags file: %s, reason:%s\n",
3056
            superTblInfo->tagsFile, strerror(errno));
3057 3058 3059 3060 3061 3062 3063
    return -1;
  }

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

3065 3066 3067 3068 3069 3070 3071 3072 3073
  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;
  }

3074
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
    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) {
3087
      char *tmp = realloc(tagDataBuf,
3088
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3089 3090 3091
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3092
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3093
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
      } 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
*/
3121
static int readSampleFromCsvFileToMem(
3122
        SSuperTable* superTblInfo) {
3123 3124 3125 3126
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3127

3128 3129
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3130 3131 3132
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3133
  }
3134

3135
  assert(superTblInfo->sampleDataBuf);
3136
  memset(superTblInfo->sampleDataBuf, 0,
3137
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3138
  while(1) {
3139
    readLen = tgetline(&line, &n, fp);
3140 3141
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3142
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3143
                superTblInfo->sampleFile, strerror(errno));
3144
        fclose(fp);
3145 3146 3147 3148
        return -1;
      }
      continue;
    }
3149

3150 3151 3152 3153 3154 3155 3156 3157 3158
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3159
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3160
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3161 3162 3163
      continue;
    }

3164
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3165
          line, readLen);
3166 3167 3168 3169 3170 3171 3172
    getRows++;

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

3173
  fclose(fp);
3174 3175 3176 3177
  tmfree(line);
  return 0;
}

3178
static bool getColumnAndTagTypeFromInsertJsonFile(
3179
        cJSON* stbInfo, SSuperTable* superTbls) {
3180
  bool  ret = false;
3181

3182
  // columns
3183 3184
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3185
    printf("ERROR: failed to read json, columns not found\n");
3186 3187 3188 3189 3190 3191
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3192

3193
  int columnSize = cJSON_GetArraySize(columns);
3194
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3195
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3196
            __func__, __LINE__, MAX_COLUMN_COUNT);
3197 3198 3199 3200 3201 3202
    goto PARSE_OVER;
  }

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

3204
  //superTbls->columnCount = columnSize;
3205 3206 3207 3208 3209 3210 3211
  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) {
3212
      count = countObj->valueint;
3213
    } else if (countObj && countObj->type != cJSON_Number) {
3214
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
3215
          __func__, __LINE__);
3216 3217 3218 3219 3220
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3221
    // column info
3222 3223
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(column, "type");
3224 3225 3226
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
3227
          __func__, __LINE__);
3228 3229
      goto PARSE_OVER;
    }
3230 3231
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3232

3233 3234
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3235
      columnCase.dataLen = dataLen->valueint;
3236
    } else if (dataLen && dataLen->type != cJSON_Number) {
3237
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
3238
          __func__, __LINE__);
3239 3240 3241 3242
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3243

3244
    for (int n = 0; n < count; ++n) {
3245
      tstrncpy(superTbls->columns[index].dataType,
3246
              columnCase.dataType, MAX_TB_NAME_SIZE);
3247
      superTbls->columns[index].dataLen = columnCase.dataLen;
3248 3249
      index++;
    }
3250
  }
3251

3252 3253
  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",
3254
            __func__, __LINE__, MAX_COLUMN_COUNT);
3255 3256 3257
    goto PARSE_OVER;
  }

3258
  superTbls->columnCount = index;
3259

3260 3261
  count = 1;
  index = 0;
3262
  // tags
3263 3264
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3265
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3266
        __func__, __LINE__);
3267 3268
    goto PARSE_OVER;
  }
3269

3270 3271
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3272
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3273
        __func__, __LINE__, MAX_TAG_COUNT);
3274 3275
    goto PARSE_OVER;
  }
3276 3277

  //superTbls->tagCount = tagSize;
3278 3279 3280
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3281

3282 3283 3284
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3285
      count = countObj->valueint;
3286
    } else if (countObj && countObj->type != cJSON_Number) {
3287
      printf("ERROR: failed to read json, column count not found\n");
3288 3289 3290 3291 3292
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3293
    // column info
3294 3295
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3296 3297 3298
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
3299
          __func__, __LINE__);
3300 3301
      goto PARSE_OVER;
    }
3302
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3303

3304 3305
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3306
      columnCase.dataLen = dataLen->valueint;
3307
    } else if (dataLen && dataLen->type != cJSON_Number) {
3308
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
3309
          __func__, __LINE__);
3310 3311 3312
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3313 3314
    }

3315
    for (int n = 0; n < count; ++n) {
3316
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3317
          MAX_TB_NAME_SIZE);
3318
      superTbls->tags[index].dataLen = columnCase.dataLen;
3319 3320
      index++;
    }
3321
  }
3322 3323

  if (index > MAX_TAG_COUNT) {
3324
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3325
        __func__, __LINE__, MAX_TAG_COUNT);
3326 3327 3328
    goto PARSE_OVER;
  }

3329 3330
  superTbls->tagCount = index;

3331 3332
  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",
3333
        __func__, __LINE__, MAX_COLUMN_COUNT);
3334 3335
    goto PARSE_OVER;
  }
3336 3337
  ret = true;

3338
PARSE_OVER:
3339 3340 3341 3342 3343 3344 3345 3346
  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) {
3347
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3348 3349 3350 3351
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3352
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3353
  } else if (!host) {
3354
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3355
  } else {
3356
    printf("ERROR: failed to read json, host not found\n");
3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368
    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) {
3369
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3370
  } else if (!user) {
3371
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3372 3373 3374 3375
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3376
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3377
  } else if (!password) {
3378
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3379 3380 3381 3382
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3383
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3384
  } else if (!resultfile) {
3385
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3386 3387 3388 3389 3390 3391 3392 3393
  }

  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 {
3394
    printf("ERROR: failed to read json, threads not found\n");
3395
    goto PARSE_OVER;
3396 3397
  }

3398 3399 3400 3401
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
sangshuduo's avatar
sangshuduo 已提交
3402
    g_Dbs.threadCountByCreateTbl = 1;
3403
  } else {
3404
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3405
            __func__, __LINE__);
3406
    goto PARSE_OVER;
3407
  }
3408

3409 3410
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3411 3412 3413 3414 3415
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3416 3417 3418 3419
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3420
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3421
        __func__, __LINE__);
3422 3423
    goto PARSE_OVER;
  }
3424

3425 3426
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3427 3428 3429 3430 3431 3432
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3433
    g_args.interlace_rows = interlaceRows->valueint;
3434 3435 3436

    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
3437
      printf("NOTICE: interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3438
              g_args.interlace_rows, g_args.num_of_RPR);
3439
      printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3440
              g_args.num_of_RPR);
3441 3442 3443 3444
      if (!g_args.answer_yes) {
        printf("        press Enter key to continue or Ctrl-C to stop.");
        (void)getchar();
      }
3445 3446
      g_args.interlace_rows = g_args.num_of_RPR;
    }
3447
  } else if (!interlaceRows) {
3448
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3449
  } else {
3450
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
3451
        __func__, __LINE__);
3452
    goto PARSE_OVER;
3453
  }
3454

3455 3456
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3457 3458 3459 3460 3461
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3462 3463
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
sangshuduo's avatar
sangshuduo 已提交
3464
    g_args.max_sql_len = (1024*1024);
3465
  } else {
3466
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
3467
        __func__, __LINE__);
3468 3469 3470 3471 3472
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3473
    if (numRecPerReq->valueint <= 0) {
3474 3475 3476
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
3477 3478
    } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
      numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
3479
    }
3480 3481
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3482
    g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
3483
  } else {
3484
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
3485
        __func__, __LINE__);
3486 3487 3488
    goto PARSE_OVER;
  }

3489
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3490
  if (answerPrompt
3491 3492
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3493 3494 3495 3496 3497 3498 3499 3500 3501 3502
    if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
      g_args.answer_yes = false;
    } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
      g_args.answer_yes = true;
    } else {
      g_args.answer_yes = false;
    }
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
3503
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3504
    goto PARSE_OVER;
3505
  }
3506 3507 3508

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3509
    printf("ERROR: failed to read json, databases not found\n");
3510 3511 3512 3513 3514
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3515
    errorPrint(
3516 3517
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3518 3519 3520 3521 3522 3523 3524 3525
    goto PARSE_OVER;
  }

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

3526
    // dbinfo
3527 3528
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3529
      printf("ERROR: failed to read json, dbinfo not found\n");
3530 3531
      goto PARSE_OVER;
    }
3532

3533 3534
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3535
      printf("ERROR: failed to read json, db name not found\n");
3536 3537
      goto PARSE_OVER;
    }
3538
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3539 3540 3541

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3542 3543
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3544
      } else {
3545
        g_Dbs.db[i].drop = false;
3546
      }
3547
    } else if (!drop) {
3548
      g_Dbs.db[i].drop = g_args.drop_database;
3549
    } else {
3550
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
3551
              __func__, __LINE__);
3552 3553 3554 3555
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3556
    if (precision && precision->type == cJSON_String
3557
            && precision->valuestring != NULL) {
3558
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
3559
              MAX_DB_NAME_SIZE);
3560
    } else if (!precision) {
3561
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3562 3563
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3564
      printf("ERROR: failed to read json, precision not found\n");
3565 3566 3567 3568 3569 3570 3571 3572 3573
      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 {
3574
      printf("ERROR: failed to read json, update not found\n");
3575 3576 3577 3578 3579 3580 3581 3582 3583
      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 {
3584
      printf("ERROR: failed to read json, replica not found\n");
3585 3586 3587 3588 3589 3590 3591 3592 3593
      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 {
3594 3595
     printf("ERROR: failed to read json, keep not found\n");
     goto PARSE_OVER;
3596
    }
3597

3598 3599 3600 3601 3602 3603
    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 {
3604 3605
     printf("ERROR: failed to read json, days not found\n");
     goto PARSE_OVER;
3606
    }
3607

3608 3609 3610 3611 3612 3613
    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 {
3614 3615
     printf("ERROR: failed to read json, cache not found\n");
     goto PARSE_OVER;
3616
    }
3617

3618 3619 3620 3621 3622 3623
    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 {
3624 3625
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641
    }

    //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) {
3642
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3643
    } else {
3644 3645
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3646 3647 3648 3649 3650 3651
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3652
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3653
    } else {
3654 3655
     printf("ERROR: failed to read json, maxRows not found\n");
     goto PARSE_OVER;
3656 3657 3658 3659 3660 3661 3662 3663
    }

    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 {
3664 3665
     printf("ERROR: failed to read json, comp not found\n");
     goto PARSE_OVER;
3666 3667 3668 3669 3670 3671 3672 3673
    }

    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 {
3674 3675
     printf("ERROR: failed to read json, walLevel not found\n");
     goto PARSE_OVER;
3676 3677
    }

3678 3679 3680 3681 3682 3683
    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 {
3684 3685
     printf("ERROR: failed to read json, cacheLast not found\n");
     goto PARSE_OVER;
3686 3687
    }

3688 3689 3690 3691
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3692
      g_Dbs.db[i].dbCfg.quorum = 1;
3693
    } else {
3694 3695
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3696 3697 3698 3699 3700 3701 3702 3703
    }

    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 {
3704
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3705
              __func__, __LINE__);
3706
      goto PARSE_OVER;
3707
    }
3708

3709
    // super_talbes
3710 3711
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3712
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3713
              __func__, __LINE__);
3714
      goto PARSE_OVER;
3715 3716
    }

3717 3718
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3719
      errorPrint(
3720 3721
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3722 3723 3724 3725 3726 3727 3728
      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;
3729 3730

      // dbinfo
3731 3732
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3733
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3734
                __func__, __LINE__);
3735 3736
        goto PARSE_OVER;
      }
3737
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3738

3739 3740
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3741
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3742 3743
        goto PARSE_OVER;
      }
3744
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3745 3746

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3747
      if (autoCreateTbl
3748 3749
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759
        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 {
3760
        printf("ERROR: failed to read json, auto_create_table not found\n");
3761 3762
        goto PARSE_OVER;
      }
3763

3764 3765 3766 3767
      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) {
3768
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3769
      } else {
3770
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3771
        goto PARSE_OVER;
3772
      }
3773 3774

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3775
      if (childTblExists
3776 3777
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3778 3779
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3780
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3781
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
3782
              || (g_Dbs.db[i].drop == true))) {
3783 3784 3785 3786 3787 3788 3789
          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 {
3790
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
3791
                __func__, __LINE__);
3792 3793
        goto PARSE_OVER;
      }
3794

3795 3796
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3797
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3798
                __func__, __LINE__);
3799 3800 3801 3802 3803
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3804
      if (dataSource && dataSource->type == cJSON_String
3805
              && dataSource->valuestring != NULL) {
3806
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
3807
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3808
      } else if (!dataSource) {
3809
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3810
      } else {
3811
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
3812
            __func__, __LINE__);
3813 3814 3815
        goto PARSE_OVER;
      }

3816
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3817
      if (insertMode && insertMode->type == cJSON_String
3818
              && insertMode->valuestring != NULL) {
3819
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
3820
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3821
      } else if (!insertMode) {
3822
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3823
      } else {
3824
        printf("ERROR: failed to read json, insert_mode not found\n");
3825 3826 3827
        goto PARSE_OVER;
      }

3828
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3829 3830
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3831
        if (childTbl_limit->type != cJSON_Number) {
3832 3833
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
3834 3835 3836
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
3837
        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.
3838 3839 3840
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3841 3842
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3843
        if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) {
3844 3845
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
3846 3847 3848 3849 3850 3851
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

3852 3853
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3854
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3855
                ts->valuestring, MAX_DB_NAME_SIZE);
3856
      } else if (!ts) {
3857
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3858
                "now", MAX_DB_NAME_SIZE);
3859
      } else {
3860
        printf("ERROR: failed to read json, start_timestamp not found\n");
3861 3862
        goto PARSE_OVER;
      }
3863

3864 3865 3866 3867
      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) {
3868
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3869
      } else {
3870
        printf("ERROR: failed to read json, timestamp_step not found\n");
3871 3872 3873 3874
        goto PARSE_OVER;
      }

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

3886
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
3887 3888
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
3889
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
3890
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3891 3892 3893
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3894
        printf("ERROR: failed to read json, sample_file not found\n");
3895
        goto PARSE_OVER;
3896
      }
3897

3898 3899
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3900
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
3901
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3902 3903 3904 3905 3906 3907 3908 3909 3910
        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 {
3911
        printf("ERROR: failed to read json, tags_file not found\n");
3912 3913
        goto PARSE_OVER;
      }
3914

3915 3916 3917 3918 3919
      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;
3920 3921
        } else if (len < 5) {
          len = 5;
3922
        }
3923 3924
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
3925
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
3926
      } else {
3927
        errorPrint("%s() LN%d, failed to read json, maxSqlLen input mistake\n",
3928
            __func__, __LINE__);
3929
        goto PARSE_OVER;
3930
      }
3931
/*
3932 3933 3934 3935 3936
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
3937 3938 3939 3940
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
3941
        }
3942 3943 3944
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
3945
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
3946 3947
        goto PARSE_OVER;
      }
3948
*/
3949 3950
      cJSON* interlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (interlaceRows && interlaceRows->type == cJSON_Number) {
3951 3952 3953 3954 3955
        if (interlaceRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
3956
        g_Dbs.db[i].superTbls[j].interlaceRows = interlaceRows->valueint;
3957 3958
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
3959
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3960
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
3961
          printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3962
                  g_args.num_of_RPR);
3963 3964 3965 3966
          if (!g_args.answer_yes) {
            printf("        press Enter key to continue or Ctrl-C to stop.");
            (void)getchar();
          }
3967 3968
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
3969 3970
      } 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
3971
      } else {
3972
        errorPrint(
3973 3974
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
3975
        goto PARSE_OVER;
3976
      }
3977 3978 3979

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3980 3981 3982 3983 3984 3985
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

3986 3987 3988 3989
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3990
        printf("ERROR: failed to read json, disorderRatio not found\n");
3991
        goto PARSE_OVER;
3992
      }
3993 3994 3995 3996 3997 3998 3999

      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 {
4000
        printf("ERROR: failed to read json, disorderRange not found\n");
4001 4002
        goto PARSE_OVER;
      }
4003

4004 4005
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
4006 4007 4008 4009 4010
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4011 4012 4013 4014
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
4015
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
4016
                __func__, __LINE__);
4017 4018 4019 4020 4021 4022
        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;
4023 4024 4025 4026 4027
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4028
      } else if (!insertInterval) {
4029
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
4030
                __func__, __LINE__, g_args.insert_interval);
4031 4032
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
4033
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
4034
                __func__, __LINE__);
4035 4036 4037
        goto PARSE_OVER;
      }

4038
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
4039
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4040 4041
      if (false == retVal) {
        goto PARSE_OVER;
4042 4043
      }
    }
4044 4045 4046 4047
  }

  ret = true;

4048
PARSE_OVER:
4049 4050 4051 4052 4053 4054 4055 4056
  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) {
4057
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4058 4059 4060 4061
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4062
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4063
  } else if (!host) {
4064
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4065
  } else {
4066
    printf("ERROR: failed to read json, host not found\n");
4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078
    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) {
4079
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4080
  } else if (!user) {
4081
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4082 4083 4084 4085
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4086
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4087
  } else if (!password) {
4088
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4089
  }
H
hzcheng 已提交
4090

4091
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4092
  if (answerPrompt && answerPrompt->type == cJSON_String
4093
          && answerPrompt->valuestring != NULL) {
4094 4095 4096 4097
    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 已提交
4098
    } else {
4099
      g_args.answer_yes = false;
H
hzcheng 已提交
4100
    }
4101 4102 4103
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4104
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4105
    goto PARSE_OVER;
4106
  }
4107

4108 4109
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4110
    if (gQueryTimes->valueint <= 0) {
4111 4112
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4113 4114
      goto PARSE_OVER;
    }
4115 4116 4117 4118
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4119
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4120
        __func__, __LINE__);
4121 4122 4123
    goto PARSE_OVER;
  }

4124 4125
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4126
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
4127
  } else if (!dbs) {
4128
    printf("ERROR: failed to read json, databases not found\n");
4129
    goto PARSE_OVER;
H
hzcheng 已提交
4130
  }
4131 4132 4133

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4134
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4135
  } else if (!queryMode) {
4136
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4137
  } else {
4138
    printf("ERROR: failed to read json, query_mode not found\n");
4139
    goto PARSE_OVER;
H
hzcheng 已提交
4140
  }
4141

4142
  // specified_table_query
4143 4144
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4145
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4146 4147
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4148
    printf("ERROR: failed to read json, super_table_query not found\n");
4149
    goto PARSE_OVER;
4150
  } else {
4151 4152 4153 4154 4155
    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;
4156 4157
    }

4158
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4159
        "query_times");
4160
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4161 4162
      if (specifiedQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4163
          __func__, __LINE__, specifiedQueryTimes->valueint);
4164 4165 4166
        goto PARSE_OVER;

      }
4167 4168 4169 4170
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4171
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4172
          __func__, __LINE__);
4173
      goto PARSE_OVER;
4174
    }
4175

4176
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4177
    if (concurrent && concurrent->type == cJSON_Number) {
4178 4179 4180 4181
      if (concurrent->valueint <= 0) {
        errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4182
              g_queryInfo.specifiedQueryInfo.concurrent);
4183 4184
        goto PARSE_OVER;
      }
4185
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4186
    } else if (!concurrent) {
4187
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4188
    }
4189

4190 4191 4192 4193 4194 4195 4196
    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;
4197
      } else {
4198
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4199
            __func__, __LINE__);
4200 4201 4202
        goto PARSE_OVER;
      }
    } else {
4203
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4204
    }
4205

4206
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4207
    if (interval && interval->type == cJSON_Number) {
4208
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4209
    } else if (!interval) {
4210 4211
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4212
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4213
    }
4214

4215
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4216
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4217
      if (0 == strcmp("yes", restart->valuestring)) {
4218
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4219
      } else if (0 == strcmp("no", restart->valuestring)) {
4220
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
4221
      } else {
4222
        printf("ERROR: failed to read json, subscribe restart error\n");
4223 4224 4225
        goto PARSE_OVER;
      }
    } else {
4226
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4227
    }
4228

4229
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4230
    if (keepProgress
4231 4232
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4233
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4234
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4235
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4236
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4237
      } else {
4238
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4239 4240 4241
        goto PARSE_OVER;
      }
    } else {
4242
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4243 4244
    }

4245
    // sqls
4246
    cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
4247
    if (!superSqls) {
4248
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4249
    } else if (superSqls->type != cJSON_Array) {
4250
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
4251
          __func__, __LINE__);
4252
      goto PARSE_OVER;
4253
    } else {
4254 4255
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4256
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4257
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4258 4259
        goto PARSE_OVER;
      }
4260

4261
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4262 4263 4264
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4265

4266 4267
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4268
          printf("ERROR: failed to read json, sql not found\n");
4269 4270
          goto PARSE_OVER;
        }
4271
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4272

4273 4274
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
4275
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4276
        } else if (NULL == result) {
4277
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4278
        } else {
4279
          printf("ERROR: failed to read json, super query result file not found\n");
4280
          goto PARSE_OVER;
4281
        }
4282 4283 4284
      }
    }
  }
4285

4286
  // super_table_query
4287 4288
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4289
    g_queryInfo.superQueryInfo.threadCnt = 1;
4290 4291
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4292
    printf("ERROR: failed to read json, sub_table_query not found\n");
4293 4294
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4295
  } else {
4296
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4297
    if (subrate && subrate->type == cJSON_Number) {
4298
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4299
    } else if (!subrate) {
4300
      g_queryInfo.superQueryInfo.queryInterval = 0;
4301 4302 4303 4304
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4305 4306
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4307
          __func__, __LINE__, superQueryTimes->valueint);
4308 4309
        goto PARSE_OVER;
      }
4310 4311 4312 4313
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4314
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4315
          __func__, __LINE__);
4316
      goto PARSE_OVER;
4317
    }
4318

4319
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4320
    if (threads && threads->type == cJSON_Number) {
4321 4322 4323 4324 4325 4326
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4327
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4328
    } else if (!threads) {
4329
      g_queryInfo.superQueryInfo.threadCnt = 1;
4330
    }
4331

4332
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4333
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4334
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4335
    //} else if (!subTblCnt) {
4336
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4337
    //}
4338

4339
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4340 4341 4342
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4343
          MAX_TB_NAME_SIZE);
4344
    } else {
4345
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4346
          __func__, __LINE__);
4347 4348
      goto PARSE_OVER;
    }
4349

4350 4351 4352 4353 4354 4355 4356
    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;
4357
      } else {
4358
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4359
            __func__, __LINE__);
4360 4361 4362
        goto PARSE_OVER;
      }
    } else {
4363
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4364
    }
4365

4366 4367 4368 4369 4370 4371 4372 4373 4374
    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) {
4375 4376
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4377
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4378
    }
4379

4380
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4381 4382
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4383
      if (0 == strcmp("yes", subrestart->valuestring)) {
4384
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
4385
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4386
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
4387
      } else {
4388
        printf("ERROR: failed to read json, subscribe restart error\n");
4389 4390 4391
        goto PARSE_OVER;
      }
    } else {
4392
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
4393
    }
4394

4395
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
4396
    if (subkeepProgress &&
4397 4398
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
4399
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
4400
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4401
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
4402
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4403
      } else {
4404
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4405 4406 4407
        goto PARSE_OVER;
      }
    } else {
4408
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4409
    }
4410

4411
    // sqls
4412
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
4413
    if (!subsqls) {
4414
      g_queryInfo.superQueryInfo.sqlCount = 0;
4415
    } else if (subsqls->type != cJSON_Array) {
4416
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
4417
          __func__, __LINE__);
4418
      goto PARSE_OVER;
4419
    } else {
4420 4421
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4422
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4423
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4424 4425
        goto PARSE_OVER;
      }
4426

4427
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4428
      for (int j = 0; j < superSqlSize; ++j) {
4429 4430
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4431

4432
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4433 4434 4435
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4436
              __func__, __LINE__);
4437 4438
          goto PARSE_OVER;
        }
4439
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4440
            MAX_QUERY_SQL_LENGTH);
4441 4442

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4443 4444 4445
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
4446
              result->valuestring, MAX_FILE_NAME_LEN);
4447
        } else if (NULL == result) {
4448
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4449
        }  else {
4450
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
4451
              __func__, __LINE__);
4452
          goto PARSE_OVER;
4453
        }
4454 4455
      }
    }
H
hzcheng 已提交
4456 4457
  }

4458
  ret = true;
H
hzcheng 已提交
4459

4460
PARSE_OVER:
4461 4462
  return ret;
}
H
hzcheng 已提交
4463

4464
static bool getInfoFromJsonFile(char* file) {
4465
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4466

4467 4468 4469 4470 4471
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4472

4473
  bool  ret = false;
4474
  int   maxLen = 6400000;
4475 4476 4477 4478 4479 4480 4481
  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 已提交
4482
  }
H
Hui Li 已提交
4483

4484 4485 4486
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4487
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4488 4489
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4490

4491 4492 4493
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4494
      g_args.test_mode = INSERT_TEST;
4495
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4496
      g_args.test_mode = QUERY_TEST;
4497
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4498
      g_args.test_mode = SUBSCRIBE_TEST;
4499
    } else {
4500
      printf("ERROR: failed to read json, filetype not support\n");
4501 4502 4503
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4504
    g_args.test_mode = INSERT_TEST;
4505
  } else {
4506
    printf("ERROR: failed to read json, filetype not found\n");
4507 4508
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4509

4510
  if (INSERT_TEST == g_args.test_mode) {
4511
    ret = getMetaFromInsertJsonFile(root);
4512
  } else if ((QUERY_TEST == g_args.test_mode)
4513
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4514 4515
    ret = getMetaFromQueryJsonFile(root);
  } else {
4516
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4517
            __func__, __LINE__);
4518
    goto PARSE_OVER;
4519
  }
4520

4521
PARSE_OVER:
4522 4523
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4524
  fclose(fp);
4525 4526
  return ret;
}
H
hzcheng 已提交
4527

4528
static void prepareSampleData() {
4529
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4530 4531 4532
    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 已提交
4533
      }
4534 4535 4536 4537
    }
  }
}

4538
static void postFreeResource() {
4539
  tmfclose(g_fpOfInsertResult);
4540
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4541
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4542 4543 4544
      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 已提交
4545
      }
4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557
      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 已提交
4558
    }
4559 4560
  }
}
S
Shuaiqiang Chang 已提交
4561

4562 4563 4564
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4565
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4566
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4567
    if (0 != ret) {
4568
      tmfree(superTblInfo->sampleDataBuf);
4569
      superTblInfo->sampleDataBuf = NULL;
4570 4571
      return -1;
    }
4572
*/
4573 4574
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4575

4576
  int    dataLen = 0;
4577

4578
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4579
          "(%" PRId64 ", ", timestamp);
4580
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4581
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4582
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4583

4584
  (*sampleUsePos)++;
4585

4586 4587
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4588

4589 4590
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4591
  char  *pstr = recBuf;
4592
  int64_t maxLen = MAX_DATA_SIZE;
4593

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

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

4605 4606
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4607
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4608
        return -1;
4609 4610
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4611
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4612
      tmfree(buf);
4613
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4614
                "INT", 3)) {
4615
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4616
              "%d,", rand_int());
4617
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4618
                "BIGINT", 6)) {
4619
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4620
              "%"PRId64",", rand_bigint());
4621
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4622
                "FLOAT", 5)) {
4623
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4624
              "%f,", rand_float());
4625
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4626
                "DOUBLE", 6)) {
4627
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4628
              "%f,", rand_double());
4629
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4630
                "SMALLINT", 8)) {
4631
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4632
          "%d,", rand_smallint());
4633
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4634
          "TINYINT", strlen("TINYINT"))) {
4635
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4636
          "%d,", rand_tinyint());
4637
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4638
          "BOOL", strlen("BOOL"))) {
4639
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4640
          "%d,", rand_bool());
4641
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4642
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4643
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4644
          "%"PRId64",", rand_bigint());
4645
    }  else {
4646
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4647
      return -1;
4648
    }
S
Shuaiqiang Chang 已提交
4649
  }
4650

4651
  dataLen -= 1;
4652
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4653

4654 4655 4656
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4657
}
S
Shuaiqiang Chang 已提交
4658

4659
static int64_t generateData(char *recBuf, char **data_type,
4660
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4661 4662
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676
  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);
  }

H
Haojun Liao 已提交
4677
  for (int i = 0; i < c; i++) {
4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688
    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) {
4689
      double t = rand_double();
4690 4691
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4692
      bool b = taosRandom() & 1;
4693 4694
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4695 4696
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4697
      pstr += sprintf(pstr, ",\"%s\"", s);
4698
      free(s);
4699
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4700 4701
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4702
      pstr += sprintf(pstr, ",\"%s\"", s);
4703 4704 4705
      free(s);
    }

4706
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4707 4708 4709 4710 4711 4712 4713
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4716
  return (int32_t)strlen(recBuf);
4717 4718
}

4719
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4720 4721
  char* sampleDataBuf = NULL;

4722
  sampleDataBuf = calloc(
4723
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4724
  if (sampleDataBuf == NULL) {
4725
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4726 4727 4728 4729
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4730
  }
4731

4732 4733 4734 4735
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4736 4737 4738 4739 4740
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4741
  }
4742

4743 4744 4745
  return 0;
}

4746
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4747 4748
{
  int affectedRows;
4749
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4750

4751
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
4752
            __func__, __LINE__, buffer);
4753
  if (superTblInfo) {
4754
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4755
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4756
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
4757 4758
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
                  buffer, NULL /* not set result file */)) {
4759
        affectedRows = -1;
4760
        printf("========restful return fail, threadID[%d]\n",
4761
            pThreadInfo->threadID);
4762 4763 4764
      } else {
        affectedRows = k;
      }
4765 4766 4767 4768
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4769
    }
4770
  } else {
4771
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4772 4773 4774 4775 4776
  }

  return affectedRows;
}

4777
static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq)
4778 4779
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4780
  if (superTblInfo) {
4781
    if (superTblInfo->childTblLimit > 0) {
4782 4783 4784
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4785
    } else {
4786

4787
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRIu64" seq=%"PRIu64"\n",
4788 4789 4790 4791 4792
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
4793 4794
    }
  } else {
4795
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4796
        g_args.tb_prefix, tableSeq);
4797 4798 4799
  }
}

4800
static int64_t generateDataTail(
4801
        SSuperTable* superTblInfo,
4802
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4803
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4804 4805
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4806

4807 4808
  char *pstr = buffer;

4809
  if (superTblInfo == NULL) {
4810
    uint32_t datatypeSeq = 0;
4811
    while(g_args.datatype[datatypeSeq]) {
4812 4813
        datatypeSeq ++;
        ncols_per_record ++;
4814
    }
4815 4816
  }

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

4819
  uint64_t k = 0;
4820
  for (k = 0; k < batch;) {
4821
    char data[MAX_DATA_SIZE];
4822 4823
    memset(data, 0, MAX_DATA_SIZE);

4824
    int64_t retLen = 0;
4825

4826 4827
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4828 4829 4830 4831 4832 4833 4834
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
                    data,
                    remainderBufLen,
                    startTime + superTblInfo->timeStampStep * k,
                    superTblInfo,
                    pSamplePos);
4835
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4836
                   "rand", strlen("rand"))) {
4837

4838
        int64_t randTail = superTblInfo->timeStampStep * k;
4839 4840 4841 4842
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4843
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4844
          }
4845 4846
        }

4847
        int64_t d = startTime
4848
                + randTail;
4849
        retLen = generateRowData(
4850 4851 4852
                      data,
                      d,
                      superTblInfo);
4853
      }
4854

4855 4856 4857
      if (retLen > remainderBufLen) {
        break;
      }
4858

4859
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4860 4861 4862
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4863
    } else {
4864 4865
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4866

4867 4868 4869 4870 4871 4872
      int64_t randTail = DEFAULT_TIMESTAMP_STEP * k;

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

4874 4875
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4876
      } else {
4877 4878 4879 4880
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4881 4882 4883
                  ncols_per_record,
                  startTime + randTail,
                  lenOfBinary);
4884

4885 4886 4887
      if (len > remainderBufLen)
        break;

H
Haojun Liao 已提交
4888
      pstr += sprintf(pstr, "%s", data);
4889 4890 4891
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4892 4893
    }

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

    startFrom ++;
4898

4899
    if (startFrom >= insertRows) {
4900
      break;
4901
    }
4902
  }
4903

4904 4905 4906
  *dataLen = len;
  return k;
}
4907

4908
static int generateSQLHead(char *tableName, int32_t tableSeq,
4909 4910
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4911 4912
{
  int len;
4913 4914 4915 4916

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

4917 4918 4919 4920
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4921
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4922
      } else {
4923 4924 4925
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
4926 4927
      }
      if (NULL == tagsValBuf) {
4928
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
4929
            __func__, __LINE__);
4930 4931 4932
        return -1;
      }

4933 4934
      len = snprintf(
          headBuf,
4935 4936 4937 4938 4939 4940 4941
                  HEAD_BUFF_LEN,
                  "%s.%s using %s.%s tags %s values",
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
4942 4943
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
4944 4945
      len = snprintf(
          headBuf,
4946 4947 4948 4949
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4950
    } else {
4951 4952
      len = snprintf(
          headBuf,
4953 4954 4955 4956
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4957 4958
    }
  } else {
4959 4960 4961 4962 4963 4964
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4965 4966
  }

4967 4968 4969 4970 4971
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

4972 4973 4974
  return len;
}

4975
static int64_t generateInterlaceDataBuffer(
4976 4977
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
4978
        threadInfo *pThreadInfo, char *buffer,
4979
        uint64_t insertRows,
4980
        int64_t startTime,
4981
        uint64_t *pRemainderBufLen)
4982
{
4983
  assert(buffer);
4984 4985 4986 4987
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
4988
            superTblInfo, pstr, *pRemainderBufLen);
4989 4990 4991 4992 4993

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
4994
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
4995
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4996 4997 4998 4999

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5000
  int64_t dataLen = 0;
5001

5002
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
5003 5004
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
5005 5006 5007 5008 5009 5010

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

5014
  int64_t k = generateDataTail(
5015 5016 5017 5018
    superTblInfo,
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);
5019

5020
  if (k == batchPerTbl) {
5021 5022 5023
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5024
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
5025
            __func__, __LINE__, k, batchPerTbl);
5026 5027
    pstr -= headLen;
    pstr[0] = '\0';
5028
    k = 0;
5029 5030 5031 5032 5033
  }

  return k;
}

5034
static int64_t generateProgressiveDataBuffer(
5035
        char *tableName,
5036
        int64_t tableSeq,
5037 5038
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
5039 5040
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
5041 5042 5043 5044 5045 5046 5047 5048
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

  if (superTblInfo == NULL) {
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
5049 5050
        datatypeSeq ++;
        ncols_per_record ++;
5051 5052 5053 5054
    }
  }

  assert(buffer != NULL);
5055
  char *pstr = buffer;
5056

5057
  int64_t k = 0;
5058

5059
  memset(buffer, 0, *pRemainderBufLen);
5060

5061
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
5062
          buffer, *pRemainderBufLen);
5063 5064 5065 5066

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

5070
  int64_t dataLen;
5071
  k = generateDataTail(superTblInfo,
5072 5073 5074
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
          startTime,
          pSamplePos, &dataLen);
5075

5076 5077
  return k;
}
5078

5079 5080 5081 5082 5083 5084 5085 5086 5087
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)));
}

5088
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5089
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5090 5091
         pThreadInfo->threadID, __func__, __LINE__);

5092 5093
  uint64_t insertRows;
  uint64_t interlaceRows;
5094 5095

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5096

5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109
  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;
  }
5110

5111
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5112
    interlaceRows = insertRows;
5113

5114 5115
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5116

5117 5118 5119 5120 5121 5122 5123 5124 5125 5126
  int insertMode;

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

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

5128
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5129
  char* buffer = calloc(maxSqlLen, 1);
5130
  if (NULL == buffer) {
5131
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5132
              __func__, __LINE__, maxSqlLen, strerror(errno));
5133 5134 5135
    return NULL;
  }

5136
  char tableName[TSDB_TABLE_NAME_LEN];
5137 5138 5139 5140

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

5141
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5142

5143
  uint64_t insert_interval =
5144
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5145 5146
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5147

5148 5149 5150
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5151

5152
  uint64_t tableSeq = pThreadInfo->start_table_from;
5153

5154
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRIu64" insertRows=%"PRIu64"\n",
5155 5156
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);
5157 5158 5159

  int64_t startTime = pThreadInfo->start_time;

5160 5161
  assert(pThreadInfo->ntables > 0);

5162 5163
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5164

5165
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5166
    batchPerTblTimes =
5167
        g_args.num_of_RPR / interlaceRows;
5168 5169 5170 5171
  } else {
    batchPerTblTimes = 1;
  }

5172
  uint64_t generatedRecPerTbl = 0;
5173
  bool flagSleep = true;
5174
  uint64_t sleepTimeTotal = 0;
5175

5176 5177 5178
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5179
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5180
    if ((flagSleep) && (insert_interval)) {
5181 5182
        st = taosGetTimestampMs();
        flagSleep = false;
5183 5184
    }
    // generate data
5185
    memset(buffer, 0, maxSqlLen);
5186
    uint64_t remainderBufLen = maxSqlLen;
5187

5188
    char *pstr = buffer;
5189 5190 5191 5192 5193

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

5194
    uint64_t recOfBatch = 0;
5195

5196
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5197
      getTableName(tableName, pThreadInfo, tableSeq);
5198 5199
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5200
            pThreadInfo->threadID, __func__, __LINE__);
5201
        free(buffer);
5202 5203
        return NULL;
      }
5204

5205
      uint64_t oldRemainderLen = remainderBufLen;
5206
      int64_t generated = generateInterlaceDataBuffer(
5207 5208 5209 5210 5211 5212
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
        startTime,
        &remainderBufLen);
5213

5214 5215
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5216
      if (generated < 0) {
5217
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5218
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5219
        goto free_of_interlace;
5220 5221
      } else if (generated == 0) {
        break;
5222 5223
      }

5224
      tableSeq ++;
5225
      recOfBatch += batchPerTbl;
5226
      pstr += (oldRemainderLen - remainderBufLen);
5227
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5228
      pThreadInfo->totalInsertRows += batchPerTbl;
5229
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5230 5231
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5232

5233
      if (insertMode == INTERLACE_INSERT_MODE) {
5234 5235 5236 5237
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5238

5239 5240
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5241

5242 5243 5244
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5245

5246 5247 5248
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5249

5250 5251 5252 5253
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
          }
      }
5254

5255
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5256 5257
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5258 5259

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5260 5261 5262
        break;
    }

5263
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5264 5265
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5266
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
5267
           pThreadInfo->threadID, __func__, __LINE__, buffer);
5268

5269
    startTs = taosGetTimestampMs();
5270

5271 5272 5273 5274 5275 5276 5277
    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;
    }
5278
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5279

5280
    endTs = taosGetTimestampMs();
5281 5282
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5283
            __func__, __LINE__, delay);
5284 5285 5286
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5287 5288 5289 5290 5291 5292

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

5293 5294
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5295 5296
                pThreadInfo->threadID, __func__, __LINE__,
                recOfBatch, affectedRows, buffer);
5297
        goto free_of_interlace;
5298
    }
5299

5300
    pThreadInfo->totalAffectedRows += affectedRows;
5301

5302 5303
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5304
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5305 5306 5307
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5308 5309
      lastPrintTime = currentPrintTime;
    }
5310

5311
    if ((insert_interval) && flagSleep) {
5312
      et = taosGetTimestampMs();
5313

5314 5315
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5316
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
5317
                    __func__, __LINE__, sleepTime);
5318 5319 5320
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5321
    }
5322 5323
  }

5324
free_of_interlace:
5325
  tmfree(buffer);
5326
  printStatPerThread(pThreadInfo);
5327 5328 5329
  return NULL;
}

5330 5331 5332 5333 5334 5335 5336 5337
// 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
*/
5338
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5339
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5340

5341
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5342
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5343

5344
  char* buffer = calloc(maxSqlLen, 1);
5345
  if (NULL == buffer) {
5346
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5347 5348
              maxSqlLen,
              strerror(errno));
5349 5350
    return NULL;
  }
5351

5352 5353 5354
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5355

5356
  int64_t timeStampStep =
5357
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5358
/*  int insert_interval =
5359
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5360 5361
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5362
  */
5363

5364 5365
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5366

5367
  pThreadInfo->samplePos = 0;
5368

5369
  for (uint64_t tableSeq =
5370 5371
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
        tableSeq ++) {
5372
    int64_t start_time = pThreadInfo->start_time;
5373

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

5377
    for (uint64_t i = 0; i < insertRows;) {
5378 5379 5380 5381 5382
        /*
      if (insert_interval) {
            st = taosGetTimestampMs();
      }
      */
5383

5384 5385
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5386
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5387 5388
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5389

5390
      int64_t remainderBufLen = maxSqlLen;
5391 5392 5393 5394 5395 5396 5397 5398
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5399
      int64_t generated = generateProgressiveDataBuffer(
5400 5401 5402 5403
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5404 5405 5406
      if (generated > 0)
        i += generated;
      else
5407
        goto free_of_progressive;
5408

5409
      start_time +=  generated * timeStampStep;
5410
      pThreadInfo->totalInsertRows += generated;
5411

5412
      startTs = taosGetTimestampMs();
5413

5414
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5415

5416
      endTs = taosGetTimestampMs();
5417
      uint64_t delay = endTs - startTs;
5418
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5419
              __func__, __LINE__, delay);
5420 5421 5422
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5423

5424 5425 5426 5427
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5428

5429 5430 5431 5432 5433
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5434 5435 5436

      pThreadInfo->totalAffectedRows += affectedRows;

5437 5438
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5439
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5440 5441 5442
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5443 5444 5445
        lastPrintTime = currentPrintTime;
      }

5446
      if (i >= insertRows)
5447
        break;
5448
/*
5449
      if (insert_interval) {
5450
        et = taosGetTimestampMs();
5451

5452 5453
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5454 5455
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5456 5457
            taosMsleep(sleep_time); // ms
        }
5458
      }
5459
      */
5460 5461
    }   // num_of_DPT

5462 5463
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5464 5465
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5466
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5467
                  __func__, __LINE__, pThreadInfo->samplePos);
5468
      }
5469
    }
5470
  } // tableSeq
5471

5472
free_of_progressive:
5473
  tmfree(buffer);
5474
  printStatPerThread(pThreadInfo);
5475
  return NULL;
H
Hui Li 已提交
5476 5477
}

5478 5479
static void* syncWrite(void *sarg) {

5480 5481
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5482

5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494
  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;
  }
5495

5496
  if (interlaceRows > 0) {
5497
    // interlace mode
5498
    return syncWriteInterlace(pThreadInfo);
5499 5500
  } else {
    // progressive mode
5501
    return syncWriteProgressive(pThreadInfo);
5502
  }
5503

5504 5505
}

5506
static void callBack(void *param, TAOS_RES *res, int code) {
5507 5508
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5509

5510 5511
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5512
  if (insert_interval) {
5513 5514 5515
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5516
    }
H
Hui Li 已提交
5517
  }
5518

5519
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5520
  char data[MAX_DATA_SIZE];
5521
  char *pstr = buffer;
5522 5523
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5524
          pThreadInfo->start_table_from);
5525 5526 5527 5528 5529 5530 5531
//  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);
5532 5533 5534 5535
    free(buffer);
    taos_free_result(res);
    return;
  }
5536

5537
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5538
    int rand_num = taosRandom() % 100;
5539
    if (0 != pThreadInfo->superTblInfo->disorderRatio
5540
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5541 5542
      int64_t d = pThreadInfo->lastTs - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateRowData(data, d, pThreadInfo->superTblInfo);
5543
    } else {
5544
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5545
    }
5546
    pstr += sprintf(pstr, "%s", data);
5547
    pThreadInfo->counter++;
H
Hui Li 已提交
5548

5549
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5550
      break;
H
Hui Li 已提交
5551 5552
    }
  }
5553

5554
  if (insert_interval) {
5555
    pThreadInfo->st = taosGetTimestampMs();
5556
  }
5557
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5558
  free(buffer);
H
Hui Li 已提交
5559

5560
  taos_free_result(res);
H
Hui Li 已提交
5561 5562
}

5563
static void *asyncWrite(void *sarg) {
5564 5565
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5566

5567 5568 5569
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5570

5571
  int insert_interval =
5572
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5573
  if (insert_interval) {
5574
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5575
  }
5576
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5577

5578
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5579 5580 5581 5582

  return NULL;
}

5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608
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;
}

5609
static void startMultiThreadInsertData(int threads, char* db_name,
5610
        char* precision,SSuperTable* superTblInfo) {
5611

5612 5613
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5614

5615 5616
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5617

5618 5619
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636

  //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 {
5637
      errorPrint("Not support precision: %s\n", precision);
5638 5639 5640 5641
      exit(-1);
    }
  }

5642
  int64_t start_time;
5643 5644
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5645
        start_time = taosGetTimestamp(timePrec);
5646
    } else {
5647
      if (TSDB_CODE_SUCCESS != taosParseTime(
5648 5649 5650 5651 5652
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5653
      }
5654
    }
5655
  } else {
5656
     start_time = 1500000000000;
5657 5658
  }

5659
  int64_t start = taosGetTimestampMs();
5660

5661
  // read sample data from file first
5662
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5663
              "sample", strlen("sample")))) {
5664
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5665
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5666
              __func__, __LINE__);
5667 5668 5669 5670
      exit(-1);
    }
  }

5671
  // read sample data from file first
5672
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5673
              "sample", strlen("sample")))) {
5674
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5675
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5676
              __func__, __LINE__);
5677 5678 5679 5680 5681
      exit(-1);
    }
  }

  TAOS* taos = taos_connect(
5682 5683
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5684
  if (NULL == taos) {
5685
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5686
                __func__, __LINE__, taos_errstr(NULL));
5687 5688 5689
    exit(-1);
  }

5690 5691
  int ntables = 0;
  int startFrom;
5692

5693
  if (superTblInfo) {
5694 5695
    int64_t limit;
    uint64_t offset;
5696

H
Haojun Liao 已提交
5697
    if ((NULL != g_args.sqlFile) && (superTblInfo->childTblExists == TBL_NO_EXISTS) &&
5698
            ((superTblInfo->childTblOffset != 0) || (superTblInfo->childTblLimit >= 0))) {
H
Haojun Liao 已提交
5699
      printf("WARNING: offset and limit will not be used since the child tables not exists!\n");
5700 5701
    }

5702
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5703 5704
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5705
            > (superTblInfo->childTblCount))) {
5706 5707 5708 5709 5710 5711
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5712
    } else {
5713 5714
      limit = superTblInfo->childTblCount;
      offset = 0;
5715 5716
    }

5717 5718 5719
    ntables = limit;
    startFrom = offset;

5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
      if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
      }
    }

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

5739
    superTblInfo->childTblName = (char*)calloc(1,
5740
        limit * TSDB_TABLE_NAME_LEN);
5741
    if (superTblInfo->childTblName == NULL) {
5742
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5743 5744 5745 5746
      taos_close(taos);
      exit(-1);
    }

5747
    uint64_t childTblCount;
5748 5749 5750 5751 5752 5753
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5754 5755 5756
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5757
  }
5758

5759 5760
  taos_close(taos);

5761
  uint64_t a = ntables / threads;
5762 5763 5764 5765 5766
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5767
  uint64_t b = 0;
5768 5769 5770 5771
  if (threads != 0) {
    b = ntables % threads;
  }

5772 5773 5774 5775 5776 5777
  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 已提交
5778
  for (int i = 0; i < threads; i++) {
5779
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5780 5781
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5782
    t_info->time_precision = timePrec;
5783 5784 5785
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5786
    t_info->minDelay = UINT64_MAX;
5787

5788
    if ((NULL == superTblInfo) ||
5789
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5790
      //t_info->taos = taos;
5791
      t_info->taos = taos_connect(
5792 5793
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5794
      if (NULL == t_info->taos) {
5795
        errorPrint(
5796 5797
                "connect to server fail from insert sub thread, reason: %s\n",
                taos_errstr(NULL));
5798 5799 5800 5801 5802 5803
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5804
/*    if ((NULL == superTblInfo)
5805
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5806
            */
5807 5808 5809 5810
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
5811
/*    } else {
5812 5813
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5814 5815
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5816
*/
5817
    tsem_init(&(t_info->lock_sem), 0, 0);
5818
    if (ASYNC_MODE == g_Dbs.asyncMode) {
5819
      pthread_create(pids + i, NULL, asyncWrite, t_info);
5820 5821
    } else {
      pthread_create(pids + i, NULL, syncWrite, t_info);
5822
    }
H
Hui Li 已提交
5823
  }
5824

H
Hui Li 已提交
5825 5826 5827 5828
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5829 5830 5831 5832
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5833 5834
  double  avgDelay = 0;

H
Hui Li 已提交
5835
  for (int i = 0; i < threads; i++) {
5836 5837
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5838
    tsem_destroy(&(t_info->lock_sem));
5839 5840
    taos_close(t_info->taos);

5841
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5842 5843 5844
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5845
    if (superTblInfo) {
5846 5847
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5848
    } else {
5849 5850
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5851
    }
5852 5853 5854 5855

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5856
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5857
  }
5858
  cntDelay -= 1;
H
Hui Li 已提交
5859

5860
  if (cntDelay == 0)    cntDelay = 1;
5861 5862
  avgDelay = (double)totalDelay / cntDelay;

5863 5864
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5865 5866

  if (superTblInfo) {
5867
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5868 5869 5870 5871
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5872 5873 5874 5875

    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",
5876 5877 5878 5879
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5880
    }
5881
  } else {
5882
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5883 5884 5885 5886
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5887 5888 5889
    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",
5890 5891 5892 5893
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5894
    }
5895
  }
5896

5897
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5898
          avgDelay, maxDelay, minDelay);
5899 5900
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5901
          avgDelay, maxDelay, minDelay);
5902
  }
5903

5904 5905
  //taos_close(taos);

H
Hui Li 已提交
5906
  free(pids);
5907
  free(infos);
H
Hui Li 已提交
5908 5909
}

5910
static void *readTable(void *sarg) {
5911
#if 1
5912
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5913 5914
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5915
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5916 5917
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5918
  if (NULL == fp) {
5919
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5920 5921
    return NULL;
  }
5922

5923
    int num_of_DPT;
5924
/*  if (rinfo->superTblInfo) {
5925 5926
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5927
  */
5928
      num_of_DPT = g_args.num_of_DPT;
5929
//  }
5930

5931
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5932
  int totalData = num_of_DPT * num_of_tables;
5933
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5934 5935 5936 5937 5938 5939 5940 5941

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

5942
  for (uint64_t j = 0; j < n; j++) {
H
hzcheng 已提交
5943
    double totalT = 0;
5944 5945 5946
    uint64_t count = 0;
    for (uint64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRIu64" where ts>= %" PRIu64,
5947
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5948

5949
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5950 5951
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5952

S
Shuaiqiang Chang 已提交
5953
      if (code != 0) {
5954
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5955
        taos_free_result(pSql);
H
hzcheng 已提交
5956
        taos_close(taos);
5957
        fclose(fp);
5958
        return NULL;
H
hzcheng 已提交
5959 5960
      }

5961
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5962 5963 5964
        count++;
      }

5965
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5966 5967
      totalT += t;

S
Shuaiqiang Chang 已提交
5968
      taos_free_result(pSql);
H
hzcheng 已提交
5969 5970 5971
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5972
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5973
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
5974
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
5975 5976 5977
  }
  fprintf(fp, "\n");
  fclose(fp);
5978
#endif
H
hzcheng 已提交
5979 5980 5981
  return NULL;
}

5982
static void *readMetric(void *sarg) {
5983
#if 1
5984
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5985 5986 5987
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5988 5989 5990 5991
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5992 5993

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5994
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5995
  int totalData = num_of_DPT * num_of_tables;
5996
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5997 5998 5999 6000 6001 6002 6003 6004 6005

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

  for (int j = 0; j < n; j++) {
6006
    char condition[COND_BUF_LEN] = "\0";
B
Bomin Zhang 已提交
6007
    char tempS[64] = "\0";
H
hzcheng 已提交
6008 6009 6010 6011 6012

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
6013
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
6014
      } else {
6015
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
6016
      }
6017
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6018

L
liu0x54 已提交
6019
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6020 6021 6022 6023

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

6024
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6025

S
Shuaiqiang Chang 已提交
6026 6027 6028 6029
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6030
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6031
        taos_free_result(pSql);
H
hzcheng 已提交
6032
        taos_close(taos);
6033
        fclose(fp);
6034
        return NULL;
H
hzcheng 已提交
6035 6036
      }
      int count = 0;
6037
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6038 6039
        count++;
      }
6040
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6041

6042
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6043 6044
              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 已提交
6045

S
Shuaiqiang Chang 已提交
6046
      taos_free_result(pSql);
H
hzcheng 已提交
6047 6048 6049 6050
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6051
#endif
H
hzcheng 已提交
6052 6053 6054
  return NULL;
}

H
Hui Li 已提交
6055

6056
static int insertTestProcess() {
6057

6058 6059 6060
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6061

6062 6063 6064
  if (ret == -1)
    exit(EXIT_FAILURE);

6065
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6066 6067
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6068
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6069 6070
    return -1;
  }
6071

6072 6073
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6074

6075 6076 6077 6078
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6079

6080 6081 6082
  init_rand_data();

  // create database and super tables
6083
  if(createDatabasesAndStables() != 0) {
6084 6085
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6086 6087
    return -1;
  }
6088 6089

  // pretreatement
6090
  prepareSampleData();
6091

6092 6093 6094 6095
  double start;
  double end;

  // create child tables
6096
  start = taosGetTimestampMs();
6097
  createChildTables();
6098
  end = taosGetTimestampMs();
6099

6100
  if (g_totalChildTables > 0) {
6101
    fprintf(stderr, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6102
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6103 6104
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6105
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6106
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6107
    }
6108
  }
6109

6110
  taosMsleep(1000);
6111
  // create sub threads for inserting data
6112
  //start = taosGetTimestampMs();
6113
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6114 6115 6116 6117 6118 6119 6120 6121
    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(
6122 6123 6124 6125
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6126
          }
6127
        }
6128
      }
6129
    } else {
6130
        startMultiThreadInsertData(
6131 6132 6133
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6134
          NULL);
H
Hui Li 已提交
6135
    }
6136
  }
6137
  //end = taosGetTimestampMs();
6138

6139
  //int64_t    totalInsertRows = 0;
6140
  //int64_t    totalAffectedRows = 0;
6141
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6142
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6143
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6144 6145
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6146
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6147
  postFreeResource();
6148

6149 6150 6151
  return 0;
}

6152 6153
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6154

6155
  if (pThreadInfo->taos == NULL) {
6156 6157
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6158 6159 6160 6161
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6162 6163
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6164
            pThreadInfo->threadID, taos_errstr(NULL));
6165 6166
      return NULL;
    } else {
6167
      pThreadInfo->taos = taos;
6168 6169 6170
    }
  }

6171 6172
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6173 6174
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6175 6176 6177 6178
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6179

6180 6181
  uint64_t st = 0;
  uint64_t et = 0;
6182

6183
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6184

6185 6186 6187
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6188

6189
  while(queryTimes --) {
6190
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6191
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6192
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6193 6194
    }

6195 6196
    char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6197
        sprintf(tmpFile, "%s-%d",
6198 6199
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6200 6201 6202 6203 6204
    }

    st = taosGetTimestampMs();

    selectAndGetResult(pThreadInfo,
6205
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq], tmpFile);
6206

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

6211 6212
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6213

6214 6215
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6216
    if (currentPrintTime - lastPrintTime > 30*1000) {
6217
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6218
          __func__, __LINE__, endTs, startTs);
6219
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6220 6221
                    pThreadInfo->threadID,
                    totalQueried,
6222
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6223
      lastPrintTime = currentPrintTime;
6224
    }
H
Hui Li 已提交
6225
  }
6226 6227
  return NULL;
}
H
Hui Li 已提交
6228

6229
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6230 6231
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6232 6233
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6234
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6235 6236

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

6238 6239
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6240
    return;
H
Hui Li 已提交
6241
  }
6242

6243
  tstrncpy(outSql, inSql, pos - inSql + 1);
6244
  //printf("1: %s\n", outSql);
6245
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6246
  //printf("2: %s\n", outSql);
6247
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6248
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6249 6250
}

6251
static void *superTableQuery(void *sarg) {
6252
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6253
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6254

6255
  if (pThreadInfo->taos == NULL) {
6256 6257 6258 6259 6260 6261 6262 6263
    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",
6264
            pThreadInfo->threadID, taos_errstr(NULL));
6265 6266
      return NULL;
    } else {
6267
      pThreadInfo->taos = taos;
6268 6269 6270
    }
  }

6271 6272
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6273

6274 6275 6276
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6277

6278
  uint64_t  lastPrintTime = taosGetTimestampMs();
6279
  while(queryTimes --) {
6280 6281 6282
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6283
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6284
    }
H
Hui Li 已提交
6285

6286
    st = taosGetTimestampMs();
6287
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6288
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6289
        memset(sqlstr,0,sizeof(sqlstr));
6290
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6291
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6292
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6293
          sprintf(tmpFile, "%s-%d",
6294
                  g_queryInfo.superQueryInfo.result[j],
6295
                  pThreadInfo->threadID);
6296
        }
6297
        selectAndGetResult(pThreadInfo, sqlstr, tmpFile);
6298 6299 6300 6301 6302 6303 6304

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6305
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6306 6307
                    pThreadInfo->threadID,
                    totalQueried,
6308
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6309
          lastPrintTime = currentPrintTime;
6310
        }
6311
      }
H
Hui Li 已提交
6312
    }
6313
    et = taosGetTimestampMs();
6314
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6315
            taosGetSelfPthreadId(),
6316 6317
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6318
            (double)(et - st)/1000.0);
6319
  }
6320

6321 6322 6323
  return NULL;
}

6324
static int queryTestProcess() {
6325 6326 6327 6328

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6329 6330 6331 6332 6333 6334

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6335
          g_queryInfo.port);
6336
  if (taos == NULL) {
6337 6338
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6339 6340 6341
    exit(-1);
  }

6342
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6343 6344
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6345 6346 6347
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6348
  }
6349

6350 6351 6352 6353
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6354

6355 6356 6357
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
6358

6359 6360 6361 6362 6363 6364
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6365 6366 6367
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6368 6369
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6370

6371
  uint64_t startTs = taosGetTimestampMs();
6372

6373 6374 6375 6376 6377 6378
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6379
      taos_close(taos);
6380
      ERROR_EXIT("memory allocation failed for create threads\n");
6381
    }
6382

6383 6384 6385 6386 6387
    for (int i = 0; i < nConcurrent; i++) {
      for (int j = 0; j < nSqlCount; j++) {
        threadInfo *t_info = infos + i * nSqlCount + j;
        t_info->threadID = i * nSqlCount + j;
        t_info->querySeq = j;
6388

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

6391 6392 6393 6394
          char sqlStr[MAX_TB_NAME_SIZE*2];
          sprintf(sqlStr, "use %s", g_queryInfo.dbName);
          verbosePrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
          if (0 != queryDbExec(taos, sqlStr, NO_INSERT_TYPE, false)) {
6395
            taos_close(taos);
6396 6397
            free(infos);
            free(pids);
6398 6399 6400
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6401
          }
6402
        }
6403

6404
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6405

6406
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6407 6408
            t_info);
      }
6409
    }
6410
  } else {
6411
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6412
  }
6413

6414 6415
  taos_close(taos);

6416 6417 6418
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6419 6420 6421 6422
  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));
6423 6424

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6425 6426
      free(infos);
      free(pids);
6427

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

6431
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6432
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6433

6434
    uint64_t a = ntables / threads;
6435 6436 6437 6438
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6439

6440
    uint64_t b = 0;
6441 6442 6443
    if (threads != 0) {
      b = ntables % threads;
    }
6444

6445
    uint64_t startFrom = 0;
6446
    for (int i = 0; i < threads; i++) {
6447 6448
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6449

6450 6451 6452 6453
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6454
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6455
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6456 6457
    }

6458
    g_queryInfo.superQueryInfo.threadCnt = threads;
6459
  } else {
6460
    g_queryInfo.superQueryInfo.threadCnt = 0;
6461
  }
6462

6463 6464 6465 6466 6467 6468
  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);
      }
    }
6469
  }
S
Shuaiqiang Chang 已提交
6470

6471
  tmfree((char*)pids);
6472
  tmfree((char*)infos);
6473

6474
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6475
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6476
  }
H
Hui Li 已提交
6477

6478
  tmfree((char*)pidsOfSub);
6479
  tmfree((char*)infosOfSub);
6480

6481
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6482
  uint64_t endTs = taosGetTimestampMs();
6483

6484
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6485 6486
    g_queryInfo.superQueryInfo.totalQueried;

6487
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6488
          totalQueried,
6489
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6490 6491 6492
  return 0;
}

6493
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6494
  if (res == NULL || taos_errno(res) != 0) {
6495 6496
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6497 6498
    return;
  }
6499

6500 6501
  if (param)
    appendResultToFile(res, (char*)param);
6502
  // tao_unscribe() will free result.
H
hzcheng 已提交
6503 6504
}

6505 6506
static TAOS_SUB* subscribeImpl(
        TAOS *taos, char *sql, char* topic, char* resultFileName) {
6507
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6508

6509
  if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6510
    tsub = taos_subscribe(taos,
6511
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6512
            topic, sql, subscribe_callback, (void*)resultFileName,
6513
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6514
  } else {
6515
    tsub = taos_subscribe(taos,
6516
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6517
            topic, sql, NULL, NULL, 0);
6518
  }
6519

6520 6521 6522
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6523
  }
6524

6525 6526
  return tsub;
}
H
hzcheng 已提交
6527

6528 6529
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6530
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
6531
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6532

6533 6534 6535
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

6536
  if (pThreadInfo->taos == NULL) {
6537 6538 6539 6540 6541 6542 6543 6544
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6545
            pThreadInfo->threadID, taos_errstr(NULL));
6546 6547
      return NULL;
    } else {
6548
      pThreadInfo->taos = taos;
6549 6550 6551
    }
  }

6552 6553
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6554 6555
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6556 6557
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6558 6559
    return NULL;
  }
6560

S
Shengliang Guan 已提交
6561 6562 6563 6564 6565
  char topic[32] = {0};
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
    for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
      sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%d", i, j);
6566
      memset(subSqlstr,0,sizeof(subSqlstr));
S
Shengliang Guan 已提交
6567
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], subSqlstr, i);
6568
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
S
Shengliang Guan 已提交
6569
      if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6570
        sprintf(tmpFile, "%s-%d",
S
Shengliang Guan 已提交
6571
                g_queryInfo.superQueryInfo.result[j], pThreadInfo->threadID);
6572
      }
S
Shengliang Guan 已提交
6573 6574 6575 6576 6577 6578

      uint64_t subSeq = i * g_queryInfo.superQueryInfo.sqlCount + j;
      debugPrint("%s() LN%d, subSeq=%"PRIu64" subSqlstr: %s\n",
              __func__, __LINE__, subSeq, subSqlstr);
      tsub[subSeq] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic, tmpFile);
      if (NULL == tsub[subSeq]) {
6579
        taos_close(pThreadInfo->taos);
6580 6581 6582
        return NULL;
      }
    }
S
Shengliang Guan 已提交
6583
  }
6584 6585 6586

  // start loop to consume result
  TAOS_RES* res = NULL;
6587
  while(1) {
S
Shengliang Guan 已提交
6588 6589 6590 6591 6592
    for (uint64_t i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
        if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
            continue;
        }
6593

S
Shengliang Guan 已提交
6594 6595 6596 6597 6598 6599 6600 6601
        uint64_t subSeq = i * g_queryInfo.superQueryInfo.sqlCount + j;
        taosMsleep(100); // ms
        res = taos_consume(tsub[subSeq]);
        if (res) {
            char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
            if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
                sprintf(tmpFile, "%s-%d",
                  g_queryInfo.superQueryInfo.result[j],
6602
                  pThreadInfo->threadID);
S
Shengliang Guan 已提交
6603 6604
                appendResultToFile(res, tmpFile);
            }
6605
        }
H
hzcheng 已提交
6606 6607 6608
      }
    }
  }
6609
  taos_free_result(res);
6610

S
Shengliang Guan 已提交
6611 6612 6613 6614 6615 6616 6617
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
    for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
        uint64_t subSeq = i * g_queryInfo.superQueryInfo.sqlCount + j;
        taos_unsubscribe(tsub[subSeq],
                g_queryInfo.superQueryInfo.subscribeKeepProgress);
    }
6618
  }
6619

6620
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6621 6622 6623
  return NULL;
}

6624 6625
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6626
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6627

6628 6629 6630
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6631
  if (pThreadInfo->taos == NULL) {
6632 6633 6634 6635 6636 6637 6638 6639
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6640
            pThreadInfo->threadID, taos_errstr(NULL));
6641 6642
      return NULL;
    } else {
6643
      pThreadInfo->taos = taos;
6644 6645 6646
    }
  }

6647 6648
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6649
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6650 6651
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6652 6653
    return NULL;
  }
6654

S
Shengliang Guan 已提交
6655 6656
  char topic[32] = {0};
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6657 6658
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6659
      if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6660
        sprintf(tmpFile, "%s-%d",
6661
                g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6662
      }
6663
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6664
          g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile);
6665
      if (NULL == tsub[i]) {
6666
        taos_close(pThreadInfo->taos);
6667 6668
        return NULL;
      }
S
Shengliang Guan 已提交
6669
  }
6670 6671
  // start loop to consume result
  TAOS_RES* res = NULL;
6672
  while(1) {
6673
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6674
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6675 6676
        continue;
      }
6677

S
Shengliang Guan 已提交
6678
      taosMsleep(1000); // ms
6679
      res = taos_consume(tsub[i]);
6680 6681
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6682
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6683
          sprintf(tmpFile, "%s-%d",
6684
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6685
          appendResultToFile(res, tmpFile);
6686 6687 6688 6689 6690
        }
      }
    }
  }
  taos_free_result(res);
6691

6692
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6693 6694
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6695
  }
6696

6697
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6698 6699 6700
  return NULL;
}

6701
static int subscribeTestProcess() {
6702
  setupForAnsiEscape();
6703
  printfQueryMeta();
6704
  resetAfterAnsiEscape();
6705

6706 6707
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6708
    (void) getchar();
Y
yihaoDeng 已提交
6709
  }
6710

6711 6712 6713 6714 6715
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6716
          g_queryInfo.port);
6717
  if (taos == NULL) {
6718 6719
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6720 6721 6722
    exit(-1);
  }

6723
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6724 6725
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6726 6727 6728
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6729 6730
  }

6731 6732
  taos_close(taos); // TODO: workaround to use separate taos connection;

6733 6734
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
S
Shengliang Guan 已提交
6735 6736 6737
  //==== create sub threads for query for specified table
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
    printf("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
6738
              __func__, __LINE__,
S
Shengliang Guan 已提交
6739 6740 6741 6742 6743 6744 6745 6746
              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);
    }
6747

S
Shengliang Guan 已提交
6748 6749 6750 6751 6752 6753
    pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
    infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
6754

S
Shengliang Guan 已提交
6755
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6756 6757
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6758
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6759
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
S
Shengliang Guan 已提交
6760
    }
H
hzcheng 已提交
6761
  }
6762

S
Shengliang Guan 已提交
6763
  //==== create sub threads for super table query
6764 6765
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6766 6767 6768
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6769
            sizeof(pthread_t));
6770
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6771
            sizeof(threadInfo));
6772
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6773 6774 6775
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6776
      exit(-1);
S
Shuaiqiang Chang 已提交
6777
    }
6778

6779
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6780
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6781

6782
    uint64_t a = ntables / threads;
6783 6784 6785 6786
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6787

6788
    uint64_t b = 0;
6789 6790 6791
    if (threads != 0) {
      b = ntables % threads;
    }
6792

6793
    uint64_t startFrom = 0;
6794
    for (int i = 0; i < threads; i++) {
6795 6796
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6797

6798 6799 6800 6801
      t_info->start_table_from = startFrom;
      t_info->ntables = i<b?a+1:a;
      t_info->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = t_info->end_table_to + 1;
6802
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6803
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6804
    }
6805

6806
    g_queryInfo.superQueryInfo.threadCnt = threads;
6807

6808
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6809 6810
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6811
  }
6812

6813
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6814
    pthread_join(pids[i], NULL);
6815
  }
H
hzcheng 已提交
6816

6817
  tmfree((char*)pids);
6818
  tmfree((char*)infos);
H
hzcheng 已提交
6819

6820
  tmfree((char*)pidsOfSub);
6821
  tmfree((char*)infosOfSub);
6822
//   taos_close(taos);
6823
  return 0;
H
hzcheng 已提交
6824 6825
}

6826
static void initOfInsertMeta() {
6827
  memset(&g_Dbs, 0, sizeof(SDbs));
6828

6829
  // set default values
6830
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6831
  g_Dbs.port = 6030;
6832 6833
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6834
  g_Dbs.threadCount = 2;
6835 6836

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6837 6838
}

6839
static void initOfQueryMeta() {
6840
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6841

6842
  // set default values
6843
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6844
  g_queryInfo.port = 6030;
6845 6846
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6847 6848
}

6849
static void setParaFromArg(){
6850
  if (g_args.host) {
6851
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6852
  } else {
6853
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6854
  }
L
Liu Tao 已提交
6855

6856
  if (g_args.user) {
6857
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6858
  }
6859 6860

  if (g_args.password) {
6861
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6862 6863
  }

6864 6865
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6866
  }
L
Liu Tao 已提交
6867

6868 6869 6870
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6871 6872
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6873

6874
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6875
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6876
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6877

6878
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6879 6880 6881 6882 6883

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

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

6885 6886
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6887

6888
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6889

6890 6891
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6892
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6893
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6894
  }
H
hzcheng 已提交
6895

6896 6897 6898 6899 6900
  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;
6901
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6902
    g_Dbs.asyncMode = g_args.async_mode;
6903

6904 6905 6906 6907
    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;
6908
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6909 6910 6911
            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);
6912
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6913
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6914
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6915

6916
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6917
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6918

6919 6920 6921 6922 6923
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6924

6925
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6926
              data_type[i], MAX_TB_NAME_SIZE);
6927
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6928 6929
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6930

6931 6932 6933 6934 6935
    if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) {
      g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR;
    } else {
      for (int i = g_Dbs.db[0].superTbls[0].columnCount; i < g_args.num_of_CPR; i++) {
        tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, "INT", MAX_TB_NAME_SIZE);
6936
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6937 6938 6939
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6940

6941
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6942
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6943

6944
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6945 6946
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6947
  } else {
6948 6949
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6950
  }
6951 6952 6953 6954 6955 6956
}

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

6958 6959 6960
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6961 6962 6963
    exit(-1);
  }

6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977 6978 6979 6980 6981 6982 6983 6984 6985 6986 6987
  /* 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);
}

6988
static void querySqlFile(TAOS* taos, char* sqlFile)
6989 6990 6991 6992 6993 6994
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6995

6996 6997 6998 6999 7000 7001
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

7002
  double t = taosGetTimestampMs();
7003

7004
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
7005 7006 7007 7008 7009 7010 7011 7012 7013 7014 7015 7016
    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;
7017
    }
7018 7019

    memcpy(cmd + cmd_len, line, read_len);
7020
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
7021 7022 7023
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7024 7025 7026 7027 7028
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7029 7030
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7031 7032
  }

7033
  t = taosGetTimestampMs() - t;
7034
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7035

7036 7037 7038 7039
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7040 7041
}

7042
static void testMetaFile() {
7043
    if (INSERT_TEST == g_args.test_mode) {
7044 7045
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7046

7047
      insertTestProcess();
7048

7049
    } else if (QUERY_TEST == g_args.test_mode) {
7050 7051
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7052

7053
      queryTestProcess();
7054

7055
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7056 7057
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7058

7059
      subscribeTestProcess();
7060

7061 7062 7063
    }  else {
      ;
    }
7064
}
7065

7066
static void queryResult() {
7067
  // query data
7068

7069 7070 7071 7072 7073
  pthread_t read_id;
  threadInfo *rInfo = malloc(sizeof(threadInfo));
  assert(rInfo);
  rInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  rInfo->start_table_from = 0;
7074

7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110
  //rInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
  if (g_args.use_metric) {
    rInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    rInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    rInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(rInfo->tb_prefix,
          g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
  } else {
    rInfo->ntables = g_args.num_of_tables;
    rInfo->end_table_to = g_args.num_of_tables -1;
    tstrncpy(rInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
  }

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

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

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

7113 7114
static void testCmdLine() {

7115 7116 7117 7118 7119 7120 7121 7122 7123 7124
  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);
  }

7125 7126
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7127

7128
  if (false == g_Dbs.insert_only)
7129
    queryResult();
7130 7131
}

7132 7133 7134
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7135
  debugPrint("meta file: %s\n", g_args.metaFile);
7136 7137 7138

  if (g_args.metaFile) {
    initOfInsertMeta();
7139
    initOfQueryMeta();
7140 7141 7142 7143 7144 7145 7146 7147 7148 7149 7150 7151 7152

    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(
7153 7154 7155 7156
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7157
          g_Dbs.port);
7158
      querySqlFile(qtaos, g_args.sqlFile);
7159 7160 7161 7162 7163
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7164
  }
7165 7166

  return 0;
H
hzcheng 已提交
7167
}
7168