taosdemo.c 240.4 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
typedef enum enum_INSERT_MODE {
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
} INSERT_MODE;

129
typedef enum enumQUERY_TYPE {
130
  NO_INSERT_TYPE,
131
  INSERT_TYPE,
132
  QUERY_TYPE_BUT
133
} QUERY_TYPE;
134 135 136 137 138 139 140

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

170 171 172 173 174 175 176 177 178 179 180 181 182 183
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 已提交
184 185

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

typedef struct SColumn_S {
227 228 229
  char      field[TSDB_COL_NAME_LEN + 1];
  char      dataType[MAX_TB_NAME_SIZE];
  uint32_t  dataLen;
230
  char      note[128];
231 232 233
} StrColumn;

typedef struct SSuperTable_S {
234
  char         sTblName[MAX_TB_NAME_SIZE+1];
235
  int64_t      childTblCount;
236
  bool         childTblExists;          // 0: no, 1: yes
237 238
  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
239
  char         childTblPrefix[MAX_TB_NAME_SIZE];
240
  char         dataSource[MAX_TB_NAME_SIZE+1];  // rand_gen or sample
241
  char         insertMode[MAX_TB_NAME_SIZE];    // taosc, rest
242
  int64_t      childTblLimit;
243
  uint64_t     childTblOffset;
244

245
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
246
  uint64_t     interlaceRows;           //
247 248
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
249
  uint64_t     maxSqlLen;               //
250

251
  uint64_t     insertInterval;          // insert interval, will override global insert interval
252
  int64_t      insertRows;
253
  int64_t      timeStampStep;
254
  char         startTimestamp[MAX_TB_NAME_SIZE];
255
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
256 257
  char         sampleFile[MAX_FILE_NAME_LEN+1];
  char         tagsFile[MAX_FILE_NAME_LEN+1];
258

259
  uint32_t     columnCount;
260
  StrColumn    columns[MAX_COLUMN_COUNT];
261
  uint32_t     tagCount;
262 263 264
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
265
  char*        colsOfCreateChildTable;
266 267
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
268 269 270 271 272

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

273
  uint32_t     tagSource;    // 0: rand, 1: tag sample
274
  char*        tagDataBuf;
275 276
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
277

278
  // statistics
279 280
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
281 282 283 284 285
} SSuperTable;

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

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

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

typedef struct SDbs_S {
332
  char         cfgDir[MAX_FILE_NAME_LEN+1];
333
  char         host[MAX_HOSTNAME_SIZE];
334 335
  struct sockaddr_in serv_addr;

336
  uint16_t     port;
337 338
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
339
  char         resultFile[MAX_FILE_NAME_LEN+1];
340 341 342
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
343
  bool         asyncMode;
344

345 346 347
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
348 349 350
  SDataBase    db[MAX_DB_COUNT];

  // statistics
351 352
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
353

354 355
} SDbs;

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

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

389
  char*        childTblName;
390
  uint64_t     totalQueried;
391
} SuperQueryInfo;
392 393

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

403
  SpecifiedQueryInfo  specifiedQueryInfo;
404
  SuperQueryInfo      superQueryInfo;
405
  uint64_t     totalQueried;
406 407 408
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
409 410 411 412 413 414 415 416
  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;
417
  int64_t   ntables;
418 419 420 421
  uint64_t  data_of_rate;
  int64_t   start_time;
  char*     cols;
  bool      use_metric;
422 423 424
  SSuperTable* superTblInfo;

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

431
  // sample data
432
  int64_t   samplePos;
433
  // statistics
434 435
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
436 437

  // insert delay statistics
438 439 440 441 442
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
443

444
  // query
445
  uint64_t  querySeq;   // sequence number of sql command
446 447
} threadInfo;

448
#ifdef WINDOWS
449 450
#define _CRT_RAND_S

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

typedef unsigned __int32 uint32_t;

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

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

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

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

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

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

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

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

512 513
#include <time.h>

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

519
#endif // ifdef Windows
520

521 522
static void prompt();
static void prompt2();
523
static int createDatabasesAndStables();
524
static void createChildTables();
525
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
526 527
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
        uint16_t port, char* sqlstr, char *resultFile);
528 529 530 531 532 533 534

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

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

538
SArguments g_args = {
539 540
                     NULL,            // metaFile
                     0,               // test_mode
541 542 543
                     "127.0.0.1",     // host
                     6030,            // port
                     "root",          // user
544
                     #ifdef _TD_POWER_
545 546 547 548 549 550 551 552
                     "powerdb",      // password
                     #else
                     "taosdata",      // password
                     #endif
                     "test",          // database
                     1,               // replica
                     "t",             // tb_prefix
                     NULL,            // sqlFile
553
                     true,            // use_metric
554
                     true,            // drop_database
555
                     true,            // insert_only
556
                     false,           // debug_print
557
                     false,           // verbose_print
558
                     false,           // performance statistic print
559 560 561 562
                     false,           // answer_yes;
                     "./output.txt",  // output_file
                     0,               // mode : sync or async
                     {
563 564 565 566
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
                     "INT",           // datatype
567 568
                     },
                     16,              // len_of_binary
569
                     4,               // num_of_CPR
570 571
                     10,              // num_of_connections/thread
                     0,               // insert_interval
572
                     1,               // query_times
573
                     0,               // interlace_rows;
574
                     30000,           // num_of_RPR
575
                     (1024*1024),         // max_sql_len
576 577 578 579 580 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
};



static SDbs            g_Dbs;
588
static int64_t         g_totalChildTables = 0;
589 590 591 592
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

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

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

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

604 605 606 607
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


608
///////////////////////////////////////////////////
H
hzcheng 已提交
609

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

612 613 614 615 616 617 618 619
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

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

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

704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
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;
}

719
static void parse_args(int argc, char *argv[], SArguments *arguments) {
720
  char **sptr;
721 722 723 724 725

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

942
      arguments->disorderRatio = atoi(argv[++i]);
943

944
      if (arguments->disorderRatio > 50) {
945
        arguments->disorderRatio = 50;
946
      }
947

948
      if (arguments->disorderRatio < 0) {
949
        arguments->disorderRatio = 0;
950
      }
951

952
    } else if (strcmp(argv[i], "-R") == 0) {
953 954 955 956 957 958
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
959

960
      arguments->disorderRange = atoi(argv[++i]);
961 962 963
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

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

995 996
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
          || arguments->verbose_print) {
997
    printf("###################################################################\n");
998
    printf("# meta file:                         %s\n", arguments->metaFile);
999
    printf("# Server IP:                         %s:%hu\n",
1000 1001 1002 1003 1004
            arguments->host == NULL ? "localhost" : arguments->host,
            arguments->port );
    printf("# User:                              %s\n", arguments->user);
    printf("# Password:                          %s\n", arguments->password);
    printf("# Use metric:                        %s\n", arguments->use_metric ? "true" : "false");
1005 1006 1007 1008 1009 1010 1011 1012 1013
    if (*(arguments->datatype)) {
        printf("# Specified data type:               ");
        for (int i = 0; i < MAX_NUM_DATATYPE; i++)
            if (arguments->datatype[i])
               printf("%s,", arguments->datatype[i]);
            else
                break;
        printf("\n");
    }
1014
    printf("# Insertion interval:                %"PRIu64"\n",
1015
            arguments->insert_interval);
1016
    printf("# Number of records per req:         %"PRIu64"\n",
1017
            arguments->num_of_RPR);
1018
    printf("# Max SQL length:                    %"PRIu64"\n",
1019
            arguments->max_sql_len);
1020
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1021
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1022
    printf("# Number of Tables:                  %"PRId64"\n",
1023
            arguments->num_of_tables);
1024
    printf("# Number of Data per Table:          %"PRId64"\n",
1025
            arguments->num_of_DPT);
1026 1027 1028 1029 1030
    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);
1031

1032 1033 1034 1035
    }
    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);
1036
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1037
    printf("###################################################################\n");
1038 1039

    prompt();
1040
  }
1041
}
H
hzcheng 已提交
1042

1043 1044 1045 1046
static bool getInfoFromJsonFile(char* file);
//static int generateOneRowDataForStb(SSuperTable* stbInfo);
//static int getDataIntoMemForStb(SSuperTable* stbInfo);
static void init_rand_data();
1047
static void tmfclose(FILE *fp) {
1048 1049 1050 1051
  if (NULL != fp) {
    fclose(fp);
  }
}
1052

1053
static void tmfree(char *buf) {
1054 1055
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1056
  }
1057
}
H
Hui Li 已提交
1058

1059
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1060 1061 1062
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1063

1064 1065 1066 1067
  for (i = 0; i < 5; i++) {
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1068
    }
1069

1070 1071 1072 1073
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1074
    }
H
hzcheng 已提交
1075 1076
  }

1077
  if (code != 0) {
1078 1079
    if (!quiet) {
      debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
1080
      errorPrint("Failed to execute %s, reason: %s\n", command, taos_errstr(res));
1081
    }
1082 1083 1084
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1085
  }
H
hzcheng 已提交
1086

1087 1088 1089 1090
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1091
  }
1092

1093
  taos_free_result(res);
1094 1095
  return 0;
}
H
hzcheng 已提交
1096

1097 1098
static void appendResultBufToFile(char *resultBuf, char *resultFile)
{
1099
  FILE *fp = NULL;
1100 1101
  if (resultFile[0] != 0) {
    fp = fopen(resultFile, "at");
1102
    if (fp == NULL) {
1103 1104 1105 1106
      errorPrint(
              "%s() LN%d, failed to open result file: %s, result will not save to file\n",
              __func__, __LINE__, resultFile);
      return;
1107 1108
    }
  }
1109

1110

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
  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);

1121 1122
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1123 1124
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1125 1126
    return ;
  }
H
hzcheng 已提交
1127

1128 1129
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1130

1131
  // fetch the records row by row
1132
  while((row = taos_fetch_row(res))) {
1133
    if (totalLen >= 100*1024*1024 - 32000) {
1134
      appendResultBufToFile(databuf, resultFile);
1135 1136
      totalLen = 0;
      memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1137
    }
1138 1139 1140 1141 1142 1143
    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 已提交
1144 1145
  }

1146 1147
  verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
          __func__, __LINE__, databuf, resultFile);
1148
  appendResultBufToFile(databuf, resultFile);
1149 1150
  free(databuf);
}
H
hzcheng 已提交
1151

1152 1153
static void selectAndGetResult(
        threadInfo *pThreadInfo, char *command, char* resultFile)
1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166
{
  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;
    }

    if ((resultFile) && (strlen(resultFile))) {
      appendResultToFile(res, resultFile);
    }
1167
    taos_free_result(res);
1168

1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181
  } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
      int retCode = postProceSql(
              g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
              command,
              resultFile);
      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);
  }
1182
}
H
hzcheng 已提交
1183

1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
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;
1223
  return randfloat[cursor];
1224 1225
}

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

1243
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1244

1245
static void rand_string(char *str, int size) {
1246 1247 1248 1249
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1250
    for (n = 0; n < size; n++) {
1251
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267
      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++){
1268 1269 1270 1271
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1272 1273 1274
  }
}

1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
#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)

1295
static int printfInsertMeta() {
1296 1297
    SHOW_PARSE_RESULT_START();

1298 1299
  printf("host:                       \033[33m%s:%u\033[0m\n",
          g_Dbs.host, g_Dbs.port);
1300 1301
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
1302
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1303 1304
  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);
1305 1306
  printf("thread num of create table: \033[33m%d\033[0m\n",
          g_Dbs.threadCountByCreateTbl);
1307
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1308
          g_args.insert_interval);
1309
  printf("number of records per req:  \033[33m%"PRIu64"\033[0m\n",
1310
          g_args.num_of_RPR);
1311
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1312
          g_args.max_sql_len);
1313 1314

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

1316 1317
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1318 1319
    printf("  database[%d] name:      \033[33m%s\033[0m\n",
            i, g_Dbs.db[i].dbName);
1320
    if (0 == g_Dbs.db[i].drop) {
1321 1322 1323
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1324 1325 1326
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
1327 1328
      printf("  blocks:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.blocks);
1329 1330
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
1331 1332
      printf("  cache:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.cache);
1333 1334
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
1335 1336
      printf("  days:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.days);
1337 1338
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
1339 1340
      printf("  keep:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.keep);
1341 1342
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
1343 1344
      printf("  replica:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.replica);
1345 1346
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
1347 1348
      printf("  update:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.update);
1349 1350
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
1351 1352
      printf("  minRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.minRows);
1353 1354
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
1355 1356
      printf("  maxRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.maxRows);
1357 1358 1359 1360 1361
    }
    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) {
1362 1363
      printf("  walLevel:              \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.walLevel);
1364 1365
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
1366 1367
      printf("  fsync:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.fsync);
1368 1369
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
1370 1371
      printf("  quorum:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.quorum);
1372 1373
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1374 1375
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1376 1377
        printf("  precision:             \033[33m%s\033[0m\n",
            g_Dbs.db[i].dbCfg.precision);
1378
      } else {
1379 1380 1381
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
                g_Dbs.db[i].dbCfg.precision);
        return -1;
1382 1383 1384
      }
    }

1385
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1386
        g_Dbs.db[i].superTblCount);
1387 1388
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1389

1390 1391
      printf("      stbName:           \033[33m%s\033[0m\n",
          g_Dbs.db[i].superTbls[j].sTblName);
1392 1393 1394 1395 1396 1397 1398 1399

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

1401 1402 1403 1404 1405 1406 1407
      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");
      }
1408

1409
      printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
1410 1411 1412 1413 1414 1415 1416
              g_Dbs.db[i].superTbls[j].childTblCount);
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].childTblPrefix);
      printf("      dataSource:        \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].dataSource);
      printf("      insertMode:        \033[33m%s\033[0m\n",
              g_Dbs.db[i].superTbls[j].insertMode);
1417
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1418
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1419
                g_Dbs.db[i].superTbls[j].childTblLimit);
1420
      }
1421
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1422
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1423
                g_Dbs.db[i].superTbls[j].childTblOffset);
1424
      }
1425
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
1426
              g_Dbs.db[i].superTbls[j].insertRows);
1427
/*
1428
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1429
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1430
      }else {
1431
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1432
      }
1433
      */
1434
      printf("      interlaceRows:     \033[33m%"PRIu64"\033[0m\n",
1435
              g_Dbs.db[i].superTbls[j].interlaceRows);
1436 1437

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

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

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1478 1479
      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);
1480 1481 1482 1483
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1484
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1485 1486
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1487
        } else {
1488 1489
          printf("tag[%d]:\033[33m%s\033[0m ", k,
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1490
        }
1491 1492 1493 1494 1495
      }
      printf("\n");
    }
    printf("\n");
  }
1496 1497

  SHOW_PARSE_RESULT_END();
1498 1499

  return 0;
1500 1501 1502
}

static void printfInsertMetaToFile(FILE* fp) {
1503 1504

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1505

1506 1507
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1508
  fprintf(fp, "configDir:                  %s\n", configDir);
1509 1510 1511
  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);
1512 1513
  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);
1514
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1515

1516 1517
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1518
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1519
    if (0 == g_Dbs.db[i].drop) {
1520
      fprintf(fp, "  drop:                  no\n");
1521
    }else {
1522
      fprintf(fp, "  drop:                  yes\n");
1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 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
    }

    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) {
1562 1563
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1564 1565
        fprintf(fp, "  precision:             %s\n",
                g_Dbs.db[i].dbCfg.precision);
1566
      } else {
1567 1568
        fprintf(fp, "  precision error:       %s\n",
                g_Dbs.db[i].dbCfg.precision);
1569 1570 1571
      }
    }

1572 1573
    fprintf(fp, "  super table count:     %"PRIu64"\n",
            g_Dbs.db[i].superTblCount);
1574 1575
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1576

1577 1578
      fprintf(fp, "      stbName:           %s\n",
              g_Dbs.db[i].superTbls[j].sTblName);
1579 1580 1581

      if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
        fprintf(fp, "      autoCreateTable:   %s\n",  "no");
1582 1583
      } else if (AUTO_CREATE_SUBTBL
              == g_Dbs.db[i].superTbls[j].autoCreateTable) {
1584 1585 1586 1587
        fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
      } else {
        fprintf(fp, "      autoCreateTable:   %s\n",  "error");
      }
1588

1589 1590
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
1591 1592
      } else if (TBL_ALREADY_EXISTS
              == g_Dbs.db[i].superTbls[j].childTblExists) {
1593 1594 1595 1596
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1597

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

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

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

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

1681
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1682 1683 1684
}

static void printfQueryMeta() {
1685

1686
  SHOW_PARSE_RESULT_START();
1687

1688 1689
  printf("host:                    \033[33m%s:%u\033[0m\n",
          g_queryInfo.host, g_queryInfo.port);
1690 1691 1692 1693
  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");
1694 1695 1696 1697

  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",
1698
      g_queryInfo.specifiedQueryInfo.sqlCount);
1699 1700 1701
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1702
      g_queryInfo.specifiedQueryInfo.queryTimes);
1703 1704 1705 1706 1707 1708
      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",
1709
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1710
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1711
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1712
      printf("restart:        \033[33m%d\033[0m\n",
1713
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1714
      printf("keepProgress:   \033[33m%d\033[0m\n",
1715
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1716

1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732
      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);
1733
      printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
1734 1735 1736 1737 1738 1739 1740
        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",
1741
        (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
1742
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1743
        g_queryInfo.superQueryInfo.subscribeInterval);
1744
      printf("restart:        \033[33m%d\033[0m\n",
1745
        g_queryInfo.superQueryInfo.subscribeRestart);
1746
      printf("keepProgress:   \033[33m%d\033[0m\n",
1747 1748
        g_queryInfo.superQueryInfo.subscribeKeepProgress);

1749 1750 1751 1752 1753 1754
      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");
    }
1755
  }
1756

1757
  SHOW_PARSE_RESULT_END();
1758 1759
}

1760
static char* formatTimestamp(char* buf, int64_t val, int precision) {
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 1787 1788 1789 1790 1791
  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;
}

1792 1793 1794
static void xDumpFieldToFile(FILE* fp, const char* val,
        TAOS_FIELD* field, int32_t length, int precision) {

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 1825 1826 1827 1828 1829
  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:
1830
      formatTimestamp(buf, *(int64_t*)val, precision);
1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
      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) {
1846
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860
    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);
1861

1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881
  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;
}

1882 1883
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1884 1885
  TAOS_ROW row = NULL;
  int count = 0;
1886 1887

  res = taos_query(taos, "show databases;");
1888
  int32_t code = taos_errno(res);
1889

1890
  if (code != 0) {
1891
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1892 1893 1894 1895 1896
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1897
  while((row = taos_fetch_row(res)) != NULL) {
1898
    // sys database name : 'log'
1899 1900 1901 1902
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
      continue;
    }
1903 1904 1905

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

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

1921
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1922
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1923 1924 1925 1926 1927 1928 1929
    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]));
1930 1931
    dbInfos[count]->cachelast =
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1932

1933
    tstrncpy(dbInfos[count]->precision,
1934
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
1935
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1936
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1937
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1938
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1939

1940 1941
    count++;
    if (count > MAX_DATABASE_COUNT) {
1942 1943
      errorPrint("%s() LN%d, The database count overflow than %d\n",
         __func__, __LINE__, MAX_DATABASE_COUNT);
1944 1945 1946 1947 1948 1949 1950
      break;
    }
  }

  return count;
}

1951 1952
static void printfDbInfoForQueryToFile(
        char* filename, SDbInfo* dbInfos, int index) {
1953

1954
  if (filename[0] == 0)
1955
      return;
1956 1957 1958

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1959
    errorPrint( "failed to open file: %s\n", filename);
1960
    return;
1961 1962 1963 1964 1965
  }

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

2001 2002
  // show variables
  res = taos_query(taos, "show variables;");
2003
  //appendResultToFile(res, filename);
2004 2005 2006 2007 2008
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
2009
  //appendResultToFile(res, filename);
2010

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

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

2028 2029 2030 2031
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
2032

2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043
    // 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);
}

2044 2045
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
        char* sqlstr, char *resultFile)
2046
{
2047
    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";
2048 2049 2050

    char *url = "/rest/sql";

2051
    int bytes, sent, received, req_str_len, resp_len;
2052 2053 2054
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
2055

2056 2057 2058
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;

    request_buf = malloc(req_buf_len);
2059 2060 2061 2062
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2063

2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};

    static char base64[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
      'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
      'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
      'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
      'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
      'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
      'w', 'x', 'y', 'z', '0', '1', '2', '3',
      '4', '5', '6', '7', '8', '9', '+', '/'};
2075

2076 2077 2078 2079 2080 2081
    snprintf(userpass_buf, INPUT_BUF_LEN, "%s:%s",
        g_Dbs.user, g_Dbs.password);
    size_t userpass_buf_len = strlen(userpass_buf);
    size_t encoded_len = 4 * ((userpass_buf_len +2) / 3);

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

2099
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2100 2101
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
2102
        free(request_buf);
2103
        ERROR_EXIT("ERROR connecting");
2104
    }
2105

2106 2107 2108
    memset(base64_buf, 0, INPUT_BUF_LEN);

    for (int n = 0, m = 0; n < userpass_buf_len;) {
2109
      uint32_t oct_a = n < userpass_buf_len ?
2110
        (unsigned char) userpass_buf[n++]:0;
2111
      uint32_t oct_b = n < userpass_buf_len ?
2112
        (unsigned char) userpass_buf[n++]:0;
2113
      uint32_t oct_c = n < userpass_buf_len ?
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125
        (unsigned char) userpass_buf[n++]:0;
      uint32_t triple = (oct_a << 0x10) + (oct_b << 0x08) + oct_c;

      base64_buf[m++] = base64[(triple >> 3* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 2* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 1* 6) & 0x3f];
      base64_buf[m++] = base64[(triple >> 0* 6) & 0x3f];
    }

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

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

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

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

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

2173 2174
    if (received == resp_len) {
        free(request_buf);
2175
        ERROR_EXIT("ERROR storing complete response from socket");
2176
    }
2177

2178
    response_buf[RESP_BUF_LEN - 1] = '\0';
2179 2180
    printf("Response:\n%s\n", response_buf);

2181 2182 2183 2184
    if (resultFile) {
       appendResultBufToFile(response_buf, resultFile);
    }

2185
    free(request_buf);
2186 2187 2188 2189
#ifdef WINDOWS
    closesocket(sockfd);
    WSACleanup();
#else
2190
    close(sockfd);
2191
#endif
2192 2193 2194 2195

    return 0;
}

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

2204
  int    dataLen = 0;
2205 2206 2207
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);

2208 2209 2210
  return dataBuf;
}

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

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

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

2286
  dataLen -= 2;
2287
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2288 2289 2290
  return dataBuf;
}

2291
static int calcRowLen(SSuperTable*  superTbls) {
2292 2293
  int colIndex;
  int  lenOfOneRow = 0;
2294

2295 2296
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2297

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

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

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2356

2357 2358 2359 2360
  return 0;
}


2361 2362
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2363
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2364

2365
  char command[BUFFER_SIZE] = "\0";
2366 2367
  char limitBuf[100] = "\0";

2368
  TAOS_RES * res;
2369 2370 2371
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2372 2373

  if (offset >= 0) {
2374
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2375
            limit, offset);
2376 2377
  }

2378
  //get all child table name use cmd: select tbname from superTblName;
2379 2380
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
          dbName, sTblName, limitBuf);
2381

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

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

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

2431 2432 2433 2434 2435 2436 2437
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2438 2439
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
        char* sTblName, char** childTblNameOfSuperTbl,
2440
        int64_t* childTblCountOfSuperTbl) {
2441 2442 2443

    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2444
            -1, 0);
2445 2446
}

2447 2448
static int getSuperTableFromServer(TAOS * taos, char* dbName,
        SSuperTable*  superTbls) {
2449

2450
  char command[BUFFER_SIZE] = "\0";
2451
  TAOS_RES * res;
2452 2453
  TAOS_ROW row = NULL;
  int count = 0;
2454

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

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2468
  while((row = taos_fetch_row(res)) != NULL) {
2469 2470 2471
    if (0 == count) {
      count++;
      continue;
2472
    }
2473 2474

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

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

  calcRowLen(superTbls);

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

2528 2529
static int createSuperTable(
        TAOS * taos, char* dbName,
2530
        SSuperTable*  superTbl) {
2531

2532
  char command[BUFFER_SIZE] = "\0";
2533

2534 2535 2536 2537 2538
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2539 2540 2541 2542 2543 2544 2545 2546 2547

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

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

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

2591 2592
  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);
2593 2594

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

2603
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2604 2605
  verbosePrint("%s() LN%d: %s\n",
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2606

2607 2608 2609 2610 2611
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
            __func__, __LINE__, superTbl->tagCount);
    return -1;
  }
2612

2613 2614 2615
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2616

2617 2618 2619 2620
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2621

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

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2682 2683 2684
  return 0;
}

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

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

2704
      int dataLen = 0;
2705
      dataLen += snprintf(command + dataLen,
2706
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2707

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

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

2780
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2781
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2782 2783 2784

    int validStbCount = 0;

2785
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2786 2787 2788 2789 2790 2791 2792
      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)) {
2793
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
2794
                &g_Dbs.db[i].superTbls[j]);
2795

2796
        if (0 != ret) {
2797 2798
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2799 2800 2801
        }
      }

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

      validStbCount ++;
2811
    }
2812 2813

    g_Dbs.db[i].superTblCount = validStbCount;
2814 2815 2816 2817 2818 2819
  }

  taos_close(taos);
  return 0;
}

2820 2821
static void* createTable(void *sarg)
{
2822 2823
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2824 2825 2826

  int64_t  lastPrintTime = taosGetTimestampMs();

2827
  int buff_len;
2828
  buff_len = BUFFER_SIZE / 8;
2829

2830
  char *buffer = calloc(buff_len, 1);
2831
  if (buffer == NULL) {
2832
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2833 2834
    exit(-1);
  }
2835 2836 2837

  int len = 0;
  int batchNum = 0;
2838

2839
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2840
          __func__, __LINE__,
2841
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2842

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

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

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2902
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2903
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2904 2905 2906
      lastPrintTime = currentPrintTime;
    }
  }
2907

2908
  if (0 != len) {
2909
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2910
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2911
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2912
    }
2913
  }
2914

2915 2916 2917 2918
  free(buffer);
  return NULL;
}

2919
static int startMultiThreadCreateChildTable(
2920
        char* cols, int threads, uint64_t startFrom, int64_t ntables,
2921
        char* db_name, SSuperTable* superTblInfo) {
2922

2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934
  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;
  }

2935
  int64_t a = ntables / threads;
2936 2937 2938 2939 2940
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2941
  int64_t b = 0;
2942
  b = ntables % threads;
2943

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

    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;
2968
    t_info->use_metric = true;
2969
    t_info->cols = cols;
2970
    t_info->minDelay = UINT64_MAX;
2971 2972
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2973

2974 2975 2976 2977 2978 2979 2980 2981 2982 2983
  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);
2984
  free(infos);
2985 2986

  return 0;
2987 2988
}

2989 2990 2991 2992
static void createChildTables() {
    char tblColsBuf[MAX_SQL_SIZE];
    int len;

2993
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2994 2995 2996 2997 2998 2999 3000 3001
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
          // with super table
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
            continue;
          }
3002

3003 3004
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
3005
          uint64_t startFrom = 0;
3006 3007
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

3008
          verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
3009 3010 3011 3012 3013 3014 3015 3016
                  __func__, __LINE__, g_totalChildTables, startFrom);
          startMultiThreadCreateChildTable(
                g_Dbs.db[i].superTbls[j].colsOfCreateChildTable,
                g_Dbs.threadCountByCreateTbl,
                startFrom,
                g_Dbs.db[i].superTbls[j].childTblCount,
                g_Dbs.db[i].dbName, &(g_Dbs.db[i].superTbls[j]));
        }
3017 3018
      }
    } else {
3019 3020
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
3021
      for (int j = 0; j < g_args.num_of_CPR; j++) {
3022 3023 3024 3025
          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,
3026
                      ", COL%d %s(%d)", j, g_args.datatype[j], g_args.len_of_binary);
3027 3028 3029 3030 3031 3032
          } else {
              snprintf(tblColsBuf + len, MAX_SQL_SIZE - len,
                      ", COL%d %s", j, g_args.datatype[j]);
          }
          len = strlen(tblColsBuf);
      }
3033

3034
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
3035

3036
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
3037 3038 3039 3040 3041 3042 3043 3044 3045
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
      startMultiThreadCreateChildTable(
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
3046
    }
3047 3048 3049 3050 3051 3052
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3053
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3054 3055 3056
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3057

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

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

3070 3071 3072 3073 3074 3075 3076 3077 3078
  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;
  }

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

3133 3134
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3135
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
3136 3137 3138
              superTblInfo->sampleFile, strerror(errno));
      return -1;
  }
3139

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

3155 3156 3157 3158 3159 3160 3161 3162 3163
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3164
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3165
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3166 3167 3168
      continue;
    }

3169 3170
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
          line, readLen);
3171 3172 3173 3174 3175 3176 3177
    getRows++;

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

3178
  fclose(fp);
3179 3180 3181 3182
  tmfree(line);
  return 0;
}

3183 3184
static bool getColumnAndTagTypeFromInsertJsonFile(
        cJSON* stbInfo, SSuperTable* superTbls) {
3185
  bool  ret = false;
3186

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

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

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

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

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

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

3249
    for (int n = 0; n < count; ++n) {
3250 3251 3252
      tstrncpy(superTbls->columns[index].dataType,
              columnCase.dataType, MAX_TB_NAME_SIZE);
      superTbls->columns[index].dataLen = columnCase.dataLen;
3253 3254
      index++;
    }
3255
  }
3256

3257 3258
  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",
3259 3260 3261 3262
            __func__, __LINE__, MAX_COLUMN_COUNT);
    goto PARSE_OVER;
  }

3263
  superTbls->columnCount = index;
3264

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

3275 3276
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3277 3278
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
        __func__, __LINE__, MAX_TAG_COUNT);
3279 3280
    goto PARSE_OVER;
  }
3281 3282

  //superTbls->tagCount = tagSize;
3283 3284 3285
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3286

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

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

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

3320
    for (int n = 0; n < count; ++n) {
3321 3322
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
          MAX_TB_NAME_SIZE);
3323
      superTbls->tags[index].dataLen = columnCase.dataLen;
3324 3325
      index++;
    }
3326
  }
3327 3328

  if (index > MAX_TAG_COUNT) {
3329
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3330 3331 3332 3333
        __func__, __LINE__, MAX_TAG_COUNT);
    goto PARSE_OVER;
  }

3334 3335
  superTbls->tagCount = index;

3336 3337 3338
  if ((superTbls->columnCount + superTbls->tagCount + 1 /* ts */) > MAX_COLUMN_COUNT) {
    errorPrint("%s() LN%d, columns + tags is more than allowed max columns count: %d\n",
        __func__, __LINE__, MAX_COLUMN_COUNT);
3339 3340
    goto PARSE_OVER;
  }
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351
  ret = true;

PARSE_OVER:
  return ret;
}

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

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
3352
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3353 3354 3355 3356
  }

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

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3381
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3382
  } else if (!password) {
3383
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3384 3385 3386 3387
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3388
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3389
  } else if (!resultfile) {
3390
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3391 3392 3393 3394 3395 3396 3397 3398
  }

  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 {
3399
    printf("ERROR: failed to read json, threads not found\n");
3400
    goto PARSE_OVER;
3401 3402
  }

3403 3404 3405 3406
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
3407
    g_Dbs.threadCountByCreateTbl = 1;
3408
  } else {
3409 3410
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
            __func__, __LINE__);
3411
    goto PARSE_OVER;
3412
  }
3413

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

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

    }
3438
    g_args.interlace_rows = interlaceRows->valueint;
3439 3440 3441

    // rows per table need be less than insert batch
    if (g_args.interlace_rows > g_args.num_of_RPR) {
3442
      printf("NOTICE: interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
3443
              g_args.interlace_rows, g_args.num_of_RPR);
3444
      printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
3445
              g_args.num_of_RPR);
3446
      prompt2();
3447 3448
      g_args.interlace_rows = g_args.num_of_RPR;
    }
3449
  } else if (!interlaceRows) {
3450
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3451
  } else {
3452 3453
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
3454
    goto PARSE_OVER;
3455
  }
3456

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

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

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

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

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

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

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

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

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

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

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

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

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

    //cJSON* maxtablesPerVnode= cJSON_GetObjectItem(dbinfo, "maxtablesPerVnode");
    //if (maxtablesPerVnode && maxtablesPerVnode->type == cJSON_Number) {
    //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = maxtablesPerVnode->valueint;
    //} else if (!maxtablesPerVnode) {
    //  g_Dbs.db[i].dbCfg.maxtablesPerVnode = TSDB_DEFAULT_TABLES;
    //} else {
    // printf("failed to read json, maxtablesPerVnode not found");
    // goto PARSE_OVER;
    //}

    cJSON* minRows= cJSON_GetObjectItem(dbinfo, "minRows");
    if (minRows && minRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.minRows = minRows->valueint;
    } else if (!minRows) {
3644
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3645
    } else {
3646
     printf("ERROR: failed to read json, minRows not found\n");
3647 3648 3649 3650 3651 3652 3653
     goto PARSE_OVER;
    }

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

    cJSON* comp= cJSON_GetObjectItem(dbinfo, "comp");
    if (comp && comp->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.comp = comp->valueint;
    } else if (!comp) {
      g_Dbs.db[i].dbCfg.comp = -1;
    } else {
3666
     printf("ERROR: failed to read json, comp not found\n");
3667 3668 3669 3670 3671 3672 3673 3674 3675
     goto PARSE_OVER;
    }

    cJSON* walLevel= cJSON_GetObjectItem(dbinfo, "walLevel");
    if (walLevel && walLevel->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.walLevel = walLevel->valueint;
    } else if (!walLevel) {
      g_Dbs.db[i].dbCfg.walLevel = -1;
    } else {
3676
     printf("ERROR: failed to read json, walLevel not found\n");
3677 3678 3679
     goto PARSE_OVER;
    }

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

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

    cJSON* fsync= cJSON_GetObjectItem(dbinfo, "fsync");
    if (fsync && fsync->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.fsync = fsync->valueint;
    } else if (!fsync) {
      g_Dbs.db[i].dbCfg.fsync = -1;
    } else {
3706 3707 3708
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
              __func__, __LINE__);
      goto PARSE_OVER;
3709
    }
3710

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4040 4041
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4042 4043
      if (false == retVal) {
        goto PARSE_OVER;
4044 4045
      }
    }
4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058
  }

  ret = true;

PARSE_OVER:
  return ret;
}

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

  cJSON* cfgdir = cJSON_GetObjectItem(root, "cfgdir");
  if (cfgdir && cfgdir->type == cJSON_String && cfgdir->valuestring != NULL) {
4059
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4060 4061 4062 4063
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4265
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4266 4267 4268
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4269

4270 4271
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4272
          printf("ERROR: failed to read json, sql not found\n");
4273 4274
          goto PARSE_OVER;
        }
4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
                sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);

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

4290
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4291 4292 4293 4294
        if ((NULL != result) && (result->type == cJSON_String)
                && (result->valuestring != NULL)) {
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                  result->valuestring, MAX_FILE_NAME_LEN);
4295
        } else if (NULL == result) {
4296 4297
          memset(g_queryInfo.specifiedQueryInfo.result[j],
                  0, MAX_FILE_NAME_LEN);
4298
        } else {
4299
          printf("ERROR: failed to read json, super query result file not found\n");
4300
          goto PARSE_OVER;
4301
        }
4302 4303 4304
      }
    }
  }
4305

4306
  // super_table_query
4307 4308
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4309
    g_queryInfo.superQueryInfo.threadCnt = 1;
4310 4311
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4312
    printf("ERROR: failed to read json, sub_table_query not found\n");
4313 4314
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4315
  } else {
4316
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4317
    if (subrate && subrate->type == cJSON_Number) {
4318
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4319
    } else if (!subrate) {
4320
      g_queryInfo.superQueryInfo.queryInterval = 0;
4321 4322 4323 4324
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4325 4326 4327
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
          __func__, __LINE__, superQueryTimes->valueint);
4328 4329
        goto PARSE_OVER;
      }
4330 4331 4332 4333
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4334 4335
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
          __func__, __LINE__);
4336
      goto PARSE_OVER;
4337
    }
4338

4339
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4340
    if (threads && threads->type == cJSON_Number) {
4341 4342 4343 4344 4345 4346
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4347
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4348
    } else if (!threads) {
4349
      g_queryInfo.superQueryInfo.threadCnt = 1;
4350
    }
4351

4352
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4353
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4354
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4355
    //} else if (!subTblCnt) {
4356
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4357
    //}
4358

4359
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4360 4361 4362 4363
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
          MAX_TB_NAME_SIZE);
4364
    } else {
4365 4366
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
          __func__, __LINE__);
4367 4368
      goto PARSE_OVER;
    }
4369

4370 4371 4372 4373 4374 4375 4376
    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;
4377
      } else {
4378
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4379
            __func__, __LINE__);
4380 4381 4382
        goto PARSE_OVER;
      }
    } else {
4383
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4384
    }
4385

4386 4387 4388 4389 4390 4391 4392 4393 4394
    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) {
4395 4396
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4397
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4398
    }
4399

4400
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4401 4402
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4403
      if (0 == strcmp("yes", subrestart->valuestring)) {
4404
        g_queryInfo.superQueryInfo.subscribeRestart = true;
4405
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4406
        g_queryInfo.superQueryInfo.subscribeRestart = false;
4407
      } else {
4408
        printf("ERROR: failed to read json, subscribe restart error\n");
4409 4410 4411
        goto PARSE_OVER;
      }
    } else {
4412
      g_queryInfo.superQueryInfo.subscribeRestart = true;
4413
    }
4414

4415 4416 4417 4418 4419
    cJSON* superkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
    if (superkeepProgress &&
            superkeepProgress->type == cJSON_String
            && superkeepProgress->valuestring != NULL) {
      if (0 == strcmp("yes", superkeepProgress->valuestring)) {
4420
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4421
      } else if (0 == strcmp("no", superkeepProgress->valuestring)) {
4422
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4423
      } else {
4424
        printf("ERROR: failed to read json, subscribe super table keepProgress error\n");
4425 4426 4427
        goto PARSE_OVER;
      }
    } else {
4428
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4429
    }
4430

4431
    // sqls
4432
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
4433
    if (!subsqls) {
4434
      g_queryInfo.superQueryInfo.sqlCount = 0;
4435
    } else if (subsqls->type != cJSON_Array) {
4436 4437
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
          __func__, __LINE__);
4438
      goto PARSE_OVER;
4439
    } else {
4440 4441
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4442 4443
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4444 4445
        goto PARSE_OVER;
      }
4446

4447
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4448
      for (int j = 0; j < superSqlSize; ++j) {
4449 4450
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4451

4452
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4453 4454 4455 4456
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
              __func__, __LINE__);
4457 4458
          goto PARSE_OVER;
        }
4459 4460
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
            MAX_QUERY_SQL_LENGTH);
4461

4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473
        cJSON* superResubAfterConsume =
            cJSON_GetObjectItem(sql, "resubAfterConsume");
        if (superResubAfterConsume
                && superResubAfterConsume->type == cJSON_Number) {
            g_queryInfo.superQueryInfo.resubAfterConsume[j] =
                superResubAfterConsume->valueint;
        } else if (!superResubAfterConsume) {
            //printf("failed to read json, subscribe interval no found\n");
            //goto PARSE_OVER;
            g_queryInfo.superQueryInfo.resubAfterConsume[j] = 1;
        }

4474
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4475 4476 4477 4478
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
              result->valuestring, MAX_FILE_NAME_LEN);
4479
        } else if (NULL == result) {
4480
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4481
        }  else {
4482 4483
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
              __func__, __LINE__);
4484
          goto PARSE_OVER;
4485
        }
4486 4487
      }
    }
H
hzcheng 已提交
4488 4489
  }

4490
  ret = true;
H
hzcheng 已提交
4491

4492 4493 4494
PARSE_OVER:
  return ret;
}
H
hzcheng 已提交
4495

4496
static bool getInfoFromJsonFile(char* file) {
4497
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4498

4499 4500 4501 4502 4503
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4504

4505
  bool  ret = false;
4506
  int   maxLen = 6400000;
4507 4508 4509 4510 4511 4512 4513
  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 已提交
4514
  }
H
Hui Li 已提交
4515

4516 4517 4518
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4519
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4520 4521
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4522

4523 4524 4525
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4526
      g_args.test_mode = INSERT_TEST;
4527
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4528
      g_args.test_mode = QUERY_TEST;
4529
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4530
      g_args.test_mode = SUBSCRIBE_TEST;
4531
    } else {
4532
      printf("ERROR: failed to read json, filetype not support\n");
4533 4534 4535
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4536
    g_args.test_mode = INSERT_TEST;
4537
  } else {
4538
    printf("ERROR: failed to read json, filetype not found\n");
4539 4540
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4541

4542
  if (INSERT_TEST == g_args.test_mode) {
4543
    ret = getMetaFromInsertJsonFile(root);
4544 4545
  } else if ((QUERY_TEST == g_args.test_mode)
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4546 4547
    ret = getMetaFromQueryJsonFile(root);
  } else {
4548 4549
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
            __func__, __LINE__);
4550
    goto PARSE_OVER;
4551
  }
4552 4553 4554 4555

PARSE_OVER:
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4556
  fclose(fp);
4557 4558
  return ret;
}
H
hzcheng 已提交
4559

4560
static void prepareSampleData() {
4561
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4562 4563 4564
    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 已提交
4565
      }
4566 4567 4568 4569
    }
  }
}

4570
static void postFreeResource() {
4571
  tmfclose(g_fpOfInsertResult);
4572
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4573
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4574 4575 4576
      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 已提交
4577
      }
4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589
      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 已提交
4590
    }
4591 4592
  }
}
S
Shuaiqiang Chang 已提交
4593

4594 4595 4596
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4597
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4598
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4599
    if (0 != ret) {
4600
      tmfree(superTblInfo->sampleDataBuf);
4601
      superTblInfo->sampleDataBuf = NULL;
4602 4603
      return -1;
    }
4604
*/
4605 4606
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4607

4608
  int    dataLen = 0;
4609

4610 4611 4612 4613
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "(%" PRId64 ", ", timestamp);
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4614
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4615

4616
  (*sampleUsePos)++;
4617

4618 4619
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4620

4621 4622
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4623
  char  *pstr = recBuf;
4624
  int64_t maxLen = MAX_DATA_SIZE;
4625

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

4628
  for (int i = 0; i < stbInfo->columnCount; i++) {
4629 4630
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "NCHAR", strlen("NCHAR")))) {
4631
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4632
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4633
                (uint32_t)TSDB_MAX_BINARY_LEN);
4634
        return -1;
4635
      }
4636

4637 4638
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4639
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4640
        return -1;
4641 4642
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4643
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4644
      tmfree(buf);
4645
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4646
                "INT", 3)) {
4647
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4648
              "%d,", rand_int());
4649
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4650
                "BIGINT", 6)) {
4651
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4652
              "%"PRId64",", rand_bigint());
4653
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4654
                "FLOAT", 5)) {
4655
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4656
              "%f,", rand_float());
4657
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4658
                "DOUBLE", 6)) {
4659
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4660
              "%f,", rand_double());
4661
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4662
                "SMALLINT", 8)) {
4663
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4664
          "%d,", rand_smallint());
4665
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4666
          "TINYINT", strlen("TINYINT"))) {
4667
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4668
          "%d,", rand_tinyint());
4669
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4670
          "BOOL", strlen("BOOL"))) {
4671
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4672
          "%d,", rand_bool());
4673
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4674
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4675
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4676
          "%"PRId64",", rand_bigint());
4677
    }  else {
4678
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4679
      return -1;
4680
    }
S
Shuaiqiang Chang 已提交
4681
  }
4682

4683
  dataLen -= 1;
4684
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4685

4686 4687 4688
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4689
}
S
Shuaiqiang Chang 已提交
4690

4691
static int64_t generateData(char *recBuf, char **data_type,
4692
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4693 4694
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708
  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);
  }

4709
  for (int i = 0; i < c; i++) {
4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720
    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) {
4721
      double t = rand_double();
4722 4723
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4724
      bool b = rand_bool() & 1;
4725 4726
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4727 4728
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4729
      pstr += sprintf(pstr, ",\"%s\"", s);
4730
      free(s);
4731
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4732 4733
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4734
      pstr += sprintf(pstr, ",\"%s\"", s);
4735 4736 4737
      free(s);
    }

4738
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4739 4740 4741 4742 4743 4744 4745
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4748
  return (int32_t)strlen(recBuf);
4749 4750
}

4751
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4752 4753
  char* sampleDataBuf = NULL;

4754
  sampleDataBuf = calloc(
4755
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4756
  if (sampleDataBuf == NULL) {
4757
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4758
              __func__, __LINE__,
4759
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
4760
              strerror(errno));
4761
      return -1;
4762
  }
4763

4764 4765 4766 4767
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4768 4769
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
4770
      tmfree(sampleDataBuf);
4771
      superTblInfo->sampleDataBuf = NULL;
4772
      return -1;
H
Hui Li 已提交
4773
  }
4774

4775 4776 4777
  return 0;
}

4778
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4779 4780
{
  int affectedRows;
4781
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4782

4783 4784
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
            __func__, __LINE__, buffer);
4785
  if (superTblInfo) {
4786
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4787
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4788
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
4789 4790
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
                  buffer, NULL /* not set result file */)) {
4791
        affectedRows = -1;
4792 4793
        printf("========restful return fail, threadID[%d]\n",
            pThreadInfo->threadID);
4794 4795 4796
      } else {
        affectedRows = k;
      }
4797 4798 4799 4800
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4801
    }
4802
  } else {
4803
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4804 4805 4806 4807 4808
  }

  return affectedRows;
}

4809
static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq)
4810 4811
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4812
  if (superTblInfo) {
4813
    if (superTblInfo->childTblLimit > 0) {
4814
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
4815 4816
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4817
    } else {
4818

4819
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
4820 4821
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
4822 4823 4824 4825 4826
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
    }
  } else {
4827
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4828
        g_args.tb_prefix, tableSeq);
4829 4830 4831
  }
}

4832
static int64_t generateDataTail(
4833
        SSuperTable* superTblInfo,
4834
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4835
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4836 4837
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4838

4839 4840
  char *pstr = buffer;

4841
  if (superTblInfo == NULL) {
4842
    uint32_t datatypeSeq = 0;
4843 4844 4845 4846
    while(g_args.datatype[datatypeSeq]) {
        datatypeSeq ++;
        ncols_per_record ++;
    }
4847 4848
  }

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

4851
  uint64_t k = 0;
4852
  for (k = 0; k < batch;) {
4853
    char data[MAX_DATA_SIZE];
4854 4855
    memset(data, 0, MAX_DATA_SIZE);

4856
    int64_t retLen = 0;
4857

4858 4859
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4860 4861
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
4862 4863
                    data,
                    remainderBufLen,
4864
                    startTime + superTblInfo->timeStampStep * k,
4865
                    superTblInfo,
4866
                    pSamplePos);
4867
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4868
                   "rand", strlen("rand"))) {
4869

4870
        int64_t randTail = superTblInfo->timeStampStep * k;
4871 4872 4873 4874
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4875
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4876
          }
4877 4878
        }

4879
        int64_t d = startTime
4880 4881
                + randTail;
        retLen = generateRowData(
4882
                      data,
4883
                      d,
4884
                      superTblInfo);
4885
      }
4886

4887 4888 4889
      if (retLen > remainderBufLen) {
        break;
      }
4890

4891
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4892 4893 4894
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4895
    } else {
4896 4897
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4898

4899 4900 4901 4902 4903 4904
      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);
4905

4906 4907
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4908
      } else {
4909 4910 4911 4912
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4913
                  ncols_per_record,
4914
                  startTime + randTail,
4915
                  lenOfBinary);
4916

4917 4918 4919
      if (len > remainderBufLen)
        break;

4920
      pstr += sprintf(pstr, "%s", data);
4921 4922 4923
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4924 4925
    }

4926
    verbosePrint("%s() LN%d len=%"PRIu64" k=%"PRIu64" \nbuffer=%s\n",
4927
            __func__, __LINE__, len, k, buffer);
4928 4929

    startFrom ++;
4930

4931
    if (startFrom >= insertRows) {
4932
      break;
4933
    }
4934
  }
4935

4936 4937 4938
  *dataLen = len;
  return k;
}
4939

4940
static int generateSQLHead(char *tableName, int32_t tableSeq,
4941 4942
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4943 4944
{
  int len;
4945 4946 4947 4948

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

4949 4950 4951 4952
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4953
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4954 4955 4956 4957 4958 4959
      } else {
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
      }
      if (NULL == tagsValBuf) {
4960 4961
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
            __func__, __LINE__);
4962 4963 4964
        return -1;
      }

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

4999 5000 5001 5002 5003
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

5004 5005 5006
  return len;
}

5007
static int64_t generateInterlaceDataBuffer(
5008 5009
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
5010
        threadInfo *pThreadInfo, char *buffer,
5011
        int64_t insertRows,
5012
        int64_t startTime,
5013
        uint64_t *pRemainderBufLen)
5014
{
5015
  assert(buffer);
5016 5017 5018 5019 5020 5021 5022 5023 5024 5025
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

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

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
5026
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
5027 5028 5029 5030 5031
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5032
  int64_t dataLen = 0;
5033

5034
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
5035 5036 5037 5038 5039 5040 5041 5042 5043 5044
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);

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

5046
  int64_t k = generateDataTail(
5047
    superTblInfo,
5048 5049 5050 5051
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);

5052
  if (k == batchPerTbl) {
5053 5054 5055
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5056
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
5057
            __func__, __LINE__, k, batchPerTbl);
5058 5059
    pstr -= headLen;
    pstr[0] = '\0';
5060
    k = 0;
5061 5062 5063 5064 5065
  }

  return k;
}

5066
static int64_t generateProgressiveDataBuffer(
5067
        char *tableName,
5068
        int64_t tableSeq,
5069 5070
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
5071
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos,
5072
        int64_t *pRemainderBufLen)
5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

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

  assert(buffer != NULL);
5087
  char *pstr = buffer;
5088

5089
  int64_t k = 0;
5090

5091
  memset(buffer, 0, *pRemainderBufLen);
5092

5093
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
5094
          buffer, *pRemainderBufLen);
5095 5096 5097 5098

  if (headLen <= 0) {
    return 0;
  }
5099
  pstr += headLen;
5100
  *pRemainderBufLen -= headLen;
5101

5102
  int64_t dataLen;
5103
  k = generateDataTail(superTblInfo,
5104
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
5105
          startTime,
5106
          pSamplePos, &dataLen);
5107

5108 5109
  return k;
}
5110

5111 5112 5113 5114 5115 5116 5117 5118 5119
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)));
}

5120
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5121 5122
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
         pThreadInfo->threadID, __func__, __LINE__);
5123

5124
  int64_t insertRows;
5125
  uint64_t interlaceRows;
5126

5127
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5128

5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141
  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;
  }
5142

5143
  if (interlaceRows > insertRows)
5144
    interlaceRows = insertRows;
5145

5146 5147
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5148

5149 5150 5151 5152 5153 5154 5155 5156 5157 5158
  int insertMode;

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

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

5160
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5161
  char* buffer = calloc(maxSqlLen, 1);
5162
  if (NULL == buffer) {
5163
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5164
              __func__, __LINE__, maxSqlLen, strerror(errno));
5165 5166 5167
    return NULL;
  }

5168
  char tableName[TSDB_TABLE_NAME_LEN];
5169 5170 5171 5172

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

5173
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5174

5175
  uint64_t insert_interval =
5176
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5177 5178
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5179

5180 5181 5182
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5183

5184
  uint64_t tableSeq = pThreadInfo->start_table_from;
5185

5186
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n",
5187
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
5188 5189 5190 5191
          pThreadInfo->ntables, insertRows);

  int64_t startTime = pThreadInfo->start_time;

5192 5193
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5194

5195
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5196
    batchPerTblTimes =
5197
        g_args.num_of_RPR / interlaceRows;
5198 5199 5200 5201
  } else {
    batchPerTblTimes = 1;
  }

5202
  uint64_t generatedRecPerTbl = 0;
5203
  bool flagSleep = true;
5204
  uint64_t sleepTimeTotal = 0;
5205

5206 5207 5208
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5209
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5210
    if ((flagSleep) && (insert_interval)) {
5211
        st = taosGetTimestampMs();
5212
        flagSleep = false;
5213 5214
    }
    // generate data
5215
    memset(buffer, 0, maxSqlLen);
5216
    uint64_t remainderBufLen = maxSqlLen;
5217

5218
    char *pstr = buffer;
5219 5220 5221 5222 5223

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

5224
    uint64_t recOfBatch = 0;
5225

5226
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5227
      getTableName(tableName, pThreadInfo, tableSeq);
5228 5229 5230
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
            pThreadInfo->threadID, __func__, __LINE__);
5231
        free(buffer);
5232 5233
        return NULL;
      }
5234

5235
      uint64_t oldRemainderLen = remainderBufLen;
5236
      int64_t generated = generateInterlaceDataBuffer(
5237 5238 5239 5240
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
5241
        startTime,
5242
        &remainderBufLen);
5243

5244 5245
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5246
      if (generated < 0) {
5247
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5248
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5249
        goto free_of_interlace;
5250 5251
      } else if (generated == 0) {
        break;
5252 5253
      }

5254
      tableSeq ++;
5255
      recOfBatch += batchPerTbl;
5256
      pstr += (oldRemainderLen - remainderBufLen);
5257
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5258
      pThreadInfo->totalInsertRows += batchPerTbl;
5259
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5260 5261
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5262

5263 5264 5265 5266
      if (insertMode == INTERLACE_INSERT_MODE) {
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
5267
            generatedRecPerTbl += batchPerTbl;
5268 5269

            startTime = pThreadInfo->start_time
5270
              + generatedRecPerTbl * nTimeStampStep;
5271

5272 5273 5274 5275
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;

5276 5277 5278 5279
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;

5280 5281
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
5282
          }
5283 5284
      }

5285
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5286 5287 5288 5289
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5290 5291 5292
        break;
    }

5293
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5294 5295 5296 5297 5298
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
           pThreadInfo->threadID, __func__, __LINE__, buffer);

5299
    startTs = taosGetTimestampMs();
5300

5301 5302 5303 5304 5305 5306 5307
    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;
    }
5308
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5309

5310
    endTs = taosGetTimestampMs();
5311 5312
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5313
            __func__, __LINE__, delay);
5314 5315 5316
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5317 5318 5319 5320 5321 5322

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

5323 5324
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5325
                pThreadInfo->threadID, __func__, __LINE__,
5326
                recOfBatch, affectedRows, buffer);
5327
        goto free_of_interlace;
5328
    }
5329

5330
    pThreadInfo->totalAffectedRows += affectedRows;
5331

5332 5333
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5334
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5335 5336 5337
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5338 5339
      lastPrintTime = currentPrintTime;
    }
5340

5341
    if ((insert_interval) && flagSleep) {
5342
      et = taosGetTimestampMs();
5343

5344 5345
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5346 5347
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleepTime);
5348 5349 5350
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5351
    }
5352 5353
  }

5354
free_of_interlace:
5355
  tmfree(buffer);
5356
  printStatPerThread(pThreadInfo);
5357 5358 5359
  return NULL;
}

5360 5361 5362 5363 5364 5365 5366 5367
// 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
*/
5368
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5369
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5370

5371
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5372
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5373

5374
  char* buffer = calloc(maxSqlLen, 1);
5375
  if (NULL == buffer) {
5376
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5377
              maxSqlLen,
5378 5379 5380
              strerror(errno));
    return NULL;
  }
5381

5382 5383 5384
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5385

5386
  int64_t timeStampStep =
5387
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5388
/*  int insert_interval =
5389
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5390 5391
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5392
  */
5393

5394 5395
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5396

5397
  pThreadInfo->samplePos = 0;
5398

5399
  for (uint64_t tableSeq =
5400
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
5401
        tableSeq ++) {
5402
    int64_t start_time = pThreadInfo->start_time;
5403

5404
    int64_t insertRows = (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
5405

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

5408
    for (uint64_t i = 0; i < insertRows;) {
5409
        /*
5410
      if (insert_interval) {
5411
            st = taosGetTimestampMs();
5412
      }
5413
      */
5414

5415 5416
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5417
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5418 5419 5420
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);

5421
      int64_t remainderBufLen = maxSqlLen;
5422 5423 5424 5425 5426 5427 5428 5429
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5430
      int64_t generated = generateProgressiveDataBuffer(
5431
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
5432
            i, start_time,
5433 5434
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5435 5436 5437
      if (generated > 0)
        i += generated;
      else
5438
        goto free_of_progressive;
5439

5440
      start_time +=  generated * timeStampStep;
5441
      pThreadInfo->totalInsertRows += generated;
5442

5443
      startTs = taosGetTimestampMs();
5444

5445
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5446

5447
      endTs = taosGetTimestampMs();
5448
      uint64_t delay = endTs - startTs;
5449 5450
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
              __func__, __LINE__, delay);
5451 5452 5453
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5454

5455 5456 5457 5458
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5459

5460 5461 5462 5463 5464
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5465 5466 5467

      pThreadInfo->totalAffectedRows += affectedRows;

5468 5469
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5470
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5471 5472 5473
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5474 5475 5476
        lastPrintTime = currentPrintTime;
      }

5477
      if (i >= insertRows)
5478
        break;
5479
/*
5480
      if (insert_interval) {
5481
        et = taosGetTimestampMs();
5482

5483 5484
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5485 5486
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5487 5488
            taosMsleep(sleep_time); // ms
        }
5489
      }
5490
      */
5491 5492
    }   // num_of_DPT

5493 5494
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5495 5496
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5497
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5498
                  __func__, __LINE__, pThreadInfo->samplePos);
5499
      }
5500
    }
5501
  } // tableSeq
5502

5503
free_of_progressive:
5504
  tmfree(buffer);
5505
  printStatPerThread(pThreadInfo);
5506
  return NULL;
H
Hui Li 已提交
5507 5508
}

5509 5510
static void* syncWrite(void *sarg) {

5511 5512
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5513

5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525
  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;
  }
5526

5527
  if (interlaceRows > 0) {
5528
    // interlace mode
5529
    return syncWriteInterlace(pThreadInfo);
5530 5531
  } else {
    // progressive mode
5532
    return syncWriteProgressive(pThreadInfo);
5533
  }
5534

5535 5536
}

5537
static void callBack(void *param, TAOS_RES *res, int code) {
5538 5539
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5540

5541 5542
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5543
  if (insert_interval) {
5544 5545 5546
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5547
    }
H
Hui Li 已提交
5548
  }
5549

5550
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5551
  char data[MAX_DATA_SIZE];
5552
  char *pstr = buffer;
5553 5554
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5555 5556 5557 5558 5559 5560 5561 5562
          pThreadInfo->start_table_from);
//  if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
  if (pThreadInfo->counter >= g_args.num_of_RPR) {
    pThreadInfo->start_table_from++;
    pThreadInfo->counter = 0;
  }
  if (pThreadInfo->start_table_from > pThreadInfo->end_table_to) {
    tsem_post(&pThreadInfo->lock_sem);
5563 5564 5565 5566
    free(buffer);
    taos_free_result(res);
    return;
  }
5567

5568
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5569
    int rand_num = taosRandom() % 100;
5570 5571
    if (0 != pThreadInfo->superTblInfo->disorderRatio
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5572 5573
      int64_t d = pThreadInfo->lastTs
          - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
5574
      generateRowData(data, d, pThreadInfo->superTblInfo);
5575
    } else {
5576
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5577
    }
5578
    pstr += sprintf(pstr, "%s", data);
5579
    pThreadInfo->counter++;
H
Hui Li 已提交
5580

5581
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5582
      break;
H
Hui Li 已提交
5583 5584
    }
  }
5585

5586
  if (insert_interval) {
5587
    pThreadInfo->st = taosGetTimestampMs();
5588
  }
5589
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5590
  free(buffer);
H
Hui Li 已提交
5591

5592
  taos_free_result(res);
H
Hui Li 已提交
5593 5594
}

5595
static void *asyncWrite(void *sarg) {
5596 5597
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5598

5599 5600 5601
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5602

5603
  int insert_interval =
5604
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5605
  if (insert_interval) {
5606
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5607
  }
5608
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5609

5610
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5611 5612 5613 5614

  return NULL;
}

5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625 5626 5627 5628 5629 5630 5631 5632 5633 5634 5635 5636 5637 5638 5639 5640
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;
}

5641 5642
static void startMultiThreadInsertData(int threads, char* db_name,
        char* precision,SSuperTable* superTblInfo) {
5643

5644 5645
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5646

5647 5648
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5649

5650 5651
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5652 5653 5654 5655 5656 5657 5658 5659 5660 5661 5662 5663 5664 5665 5666 5667 5668

  //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 {
5669
      errorPrint("Not support precision: %s\n", precision);
5670 5671 5672 5673
      exit(-1);
    }
  }

5674
  int64_t start_time;
5675 5676 5677
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
        start_time = taosGetTimestamp(timePrec);
5678
    } else {
5679 5680 5681 5682 5683
      if (TSDB_CODE_SUCCESS != taosParseTime(
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
5684
          ERROR_EXIT("failed to parse time!\n");
5685
      }
5686
    }
5687 5688
  } else {
     start_time = 1500000000000;
5689 5690
  }

5691
  int64_t start = taosGetTimestampMs();
5692

5693
  // read sample data from file first
5694
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5695
              "sample", strlen("sample")))) {
5696
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5697 5698
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5699 5700 5701 5702
      exit(-1);
    }
  }

5703
  // read sample data from file first
5704
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5705 5706
              "sample", strlen("sample")))) {
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5707 5708
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
              __func__, __LINE__);
5709 5710 5711 5712 5713 5714 5715 5716
      exit(-1);
    }
  }

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

5722
  int64_t ntables = 0;
5723
  uint64_t startFrom;
5724

5725
  if (superTblInfo) {
5726 5727
    int64_t limit;
    uint64_t offset;
5728

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

5734
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5735 5736
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5737
            > (superTblInfo->childTblCount))) {
5738 5739 5740 5741 5742 5743
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5744
    } else {
5745 5746
      limit = superTblInfo->childTblCount;
      offset = 0;
5747 5748
    }

5749 5750 5751
    ntables = limit;
    startFrom = offset;

5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
      if (!g_args.answer_yes) {
        printf("         Press enter key to continue or Ctrl-C to stop\n\n");
        (void)getchar();
      }
    }

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

5771 5772 5773
    superTblInfo->childTblName = (char*)calloc(1,
        limit * TSDB_TABLE_NAME_LEN);
    if (superTblInfo->childTblName == NULL) {
5774
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5775 5776 5777 5778
      taos_close(taos);
      exit(-1);
    }

5779
    int64_t childTblCount;
5780 5781 5782 5783 5784 5785
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5786 5787 5788
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5789
  }
5790

5791 5792
  taos_close(taos);

5793
  int64_t a = ntables / threads;
5794 5795 5796 5797 5798
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5799
  int64_t b = 0;
5800 5801 5802 5803
  if (threads != 0) {
    b = ntables % threads;
  }

5804 5805 5806 5807 5808 5809
  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 已提交
5810
  for (int i = 0; i < threads; i++) {
5811
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5812 5813
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5814
    t_info->time_precision = timePrec;
5815 5816 5817
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5818
    t_info->minDelay = UINT64_MAX;
5819

5820 5821
    if ((NULL == superTblInfo) ||
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5822
      //t_info->taos = taos;
5823
      t_info->taos = taos_connect(
5824
              g_Dbs.host, g_Dbs.user,
5825
              g_Dbs.password, db_name, g_Dbs.port);
5826
      if (NULL == t_info->taos) {
5827 5828
        errorPrint(
                "connect to server fail from insert sub thread, reason: %s\n",
5829
                taos_errstr(NULL));
5830 5831 5832 5833 5834 5835
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5836
/*    if ((NULL == superTblInfo)
5837
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5838
            */
5839 5840 5841 5842
      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;
5843
/*    } else {
5844 5845
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5846 5847
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5848
*/
5849
    tsem_init(&(t_info->lock_sem), 0, 0);
5850
    if (ASYNC_MODE == g_Dbs.asyncMode) {
5851
      pthread_create(pids + i, NULL, asyncWrite, t_info);
5852 5853
    } else {
      pthread_create(pids + i, NULL, syncWrite, t_info);
5854
    }
H
Hui Li 已提交
5855
  }
5856

H
Hui Li 已提交
5857 5858 5859 5860
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5861 5862 5863 5864
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5865 5866
  double  avgDelay = 0;

H
Hui Li 已提交
5867
  for (int i = 0; i < threads; i++) {
5868 5869
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5870
    tsem_destroy(&(t_info->lock_sem));
5871 5872
    taos_close(t_info->taos);

5873
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5874 5875 5876
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5877 5878
    if (superTblInfo) {
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
5879
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5880 5881 5882
    } else {
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5883
    }
5884 5885 5886 5887

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5888
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5889
  }
5890
  cntDelay -= 1;
H
Hui Li 已提交
5891

5892
  if (cntDelay == 0)    cntDelay = 1;
5893 5894
  avgDelay = (double)totalDelay / cntDelay;

5895 5896
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5897 5898

  if (superTblInfo) {
5899
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5900
          t / 1000.0, superTblInfo->totalInsertRows,
5901 5902
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5903
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5904 5905 5906 5907

    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",
5908
          t / 1000.0, superTblInfo->totalInsertRows,
5909 5910
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
5911
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5912
    }
5913
  } else {
5914
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5915
          t / 1000.0, g_args.totalInsertRows,
5916 5917
          g_args.totalAffectedRows,
          threads, db_name,
5918
          (double)g_args.totalInsertRows / (t / 1000.0));
5919 5920 5921
    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",
5922
          t * 1000.0, g_args.totalInsertRows,
5923 5924
          g_args.totalAffectedRows,
          threads, db_name,
5925
          (double)g_args.totalInsertRows / (t / 1000.0));
5926
    }
5927
  }
5928

5929
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5930
          avgDelay, maxDelay, minDelay);
5931 5932
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5933
          avgDelay, maxDelay, minDelay);
5934
  }
5935

5936 5937
  //taos_close(taos);

H
Hui Li 已提交
5938
  free(pids);
5939
  free(infos);
H
Hui Li 已提交
5940 5941
}

5942
static void *readTable(void *sarg) {
5943
#if 1
5944
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5945 5946
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5947
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5948 5949
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5950
  if (NULL == fp) {
5951
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5952 5953
    return NULL;
  }
5954

5955
  int64_t num_of_DPT;
5956
/*  if (rinfo->superTblInfo) {
5957 5958
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5959
  */
5960
      num_of_DPT = g_args.num_of_DPT;
5961
//  }
5962

5963 5964
  int64_t num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
  int64_t totalData = num_of_DPT * num_of_tables;
5965
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5966 5967 5968 5969 5970

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

5974
  for (int j = 0; j < n; j++) {
H
hzcheng 已提交
5975
    double totalT = 0;
5976
    uint64_t count = 0;
5977 5978
    for (int64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
5979
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5980

5981
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5982 5983
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5984

S
Shuaiqiang Chang 已提交
5985
      if (code != 0) {
5986
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5987
        taos_free_result(pSql);
H
hzcheng 已提交
5988
        taos_close(taos);
5989
        fclose(fp);
5990
        return NULL;
H
hzcheng 已提交
5991 5992
      }

5993
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5994 5995 5996
        count++;
      }

5997
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5998 5999
      totalT += t;

S
Shuaiqiang Chang 已提交
6000
      taos_free_result(pSql);
H
hzcheng 已提交
6001 6002
    }

6003
    fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
6004
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
6005
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
6006
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
6007 6008 6009
  }
  fprintf(fp, "\n");
  fclose(fp);
6010
#endif
H
hzcheng 已提交
6011 6012 6013
  return NULL;
}

6014
static void *readMetric(void *sarg) {
6015
#if 1
6016
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
6017 6018 6019
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
6020 6021 6022 6023
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
6024

6025 6026 6027
  int64_t num_of_DPT = rinfo->superTblInfo->insertRows;
  int64_t num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
  int64_t totalData = num_of_DPT * num_of_tables;
6028
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6029 6030 6031 6032 6033

  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");
  }
6034 6035
  printf("%"PRId64" records:\n", totalData);
  fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
6036 6037

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

6041
    int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
6042

6043
    for (int64_t i = 1; i <= m; i++) {
H
hzcheng 已提交
6044
      if (i == 1) {
6045
        sprintf(tempS, "t1 = %"PRId64"", i);
H
hzcheng 已提交
6046
      } else {
6047
        sprintf(tempS, " or t1 = %"PRId64" ", i);
H
hzcheng 已提交
6048
      }
6049
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6050

L
liu0x54 已提交
6051
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6052 6053 6054 6055

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

6056
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6057

S
Shuaiqiang Chang 已提交
6058 6059 6060 6061
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6062
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6063
        taos_free_result(pSql);
H
hzcheng 已提交
6064
        taos_close(taos);
6065
        fclose(fp);
6066
        return NULL;
H
hzcheng 已提交
6067 6068
      }
      int count = 0;
6069
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6070 6071
        count++;
      }
6072
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6073

6074
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6075 6076
              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 已提交
6077

S
Shuaiqiang Chang 已提交
6078
      taos_free_result(pSql);
H
hzcheng 已提交
6079 6080 6081 6082
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6083
#endif
H
hzcheng 已提交
6084 6085 6086
  return NULL;
}

6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101
static void prompt()
{
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
}

static void prompt2()
{
    if (!g_args.answer_yes) {
        printf("        press Enter key to continue or Ctrl-C to stop.");
        (void)getchar();
    }
}
H
Hui Li 已提交
6102

6103
static int insertTestProcess() {
6104

6105 6106 6107
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6108

6109 6110 6111
  if (ret == -1)
    exit(EXIT_FAILURE);

6112
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6113 6114
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6115
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6116 6117
    return -1;
  }
6118

6119 6120
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6121

6122
  prompt();
6123

6124 6125 6126
  init_rand_data();

  // create database and super tables
6127
  if(createDatabasesAndStables() != 0) {
6128 6129
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6130 6131
    return -1;
  }
6132 6133

  // pretreatement
6134
  prepareSampleData();
6135

6136 6137 6138 6139
  double start;
  double end;

  // create child tables
6140
  start = taosGetTimestampMs();
6141
  createChildTables();
6142
  end = taosGetTimestampMs();
6143

6144
  if (g_totalChildTables > 0) {
6145
    fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6146
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6147 6148
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6149
            "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6150
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6151
    }
6152
  }
6153

6154
  taosMsleep(1000);
6155
  // create sub threads for inserting data
6156
  //start = taosGetTimestampMs();
6157
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {

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

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
          }
6171
        }
6172
      }
6173 6174
    } else {
        startMultiThreadInsertData(
6175 6176 6177
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6178
          NULL);
H
Hui Li 已提交
6179
    }
6180
  }
6181
  //end = taosGetTimestampMs();
6182

6183
  //int64_t    totalInsertRows = 0;
6184
  //int64_t    totalAffectedRows = 0;
6185
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6186
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6187
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6188 6189
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6190
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6191
  postFreeResource();
6192

6193 6194 6195
  return 0;
}

6196 6197
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6198

6199
  if (pThreadInfo->taos == NULL) {
6200 6201 6202 6203 6204 6205 6206 6207
    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",
6208
            pThreadInfo->threadID, taos_errstr(NULL));
6209 6210
      return NULL;
    } else {
6211
      pThreadInfo->taos = taos;
6212 6213 6214
    }
  }

6215 6216
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6217 6218
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6219 6220 6221 6222
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6223

6224 6225
  uint64_t st = 0;
  uint64_t et = 0;
6226

6227
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6228

6229 6230 6231
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6232

6233
  while(queryTimes --) {
6234 6235 6236
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6237 6238
    }

6239 6240
    char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6241
        sprintf(tmpFile, "%s-%d",
6242 6243
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6244 6245 6246 6247 6248
    }

    st = taosGetTimestampMs();

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

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

6255 6256
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6257

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

6273
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6274 6275
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6276 6277
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6278
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6279 6280

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

6282 6283
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6284
    return;
H
Hui Li 已提交
6285
  }
6286

6287
  tstrncpy(outSql, inSql, pos - inSql + 1);
6288
  //printf("1: %s\n", outSql);
6289
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6290
  //printf("2: %s\n", outSql);
6291
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6292
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6293 6294
}

6295
static void *superTableQuery(void *sarg) {
6296
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6297
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6298

6299
  if (pThreadInfo->taos == NULL) {
6300 6301 6302 6303 6304 6305 6306 6307
    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",
6308
            pThreadInfo->threadID, taos_errstr(NULL));
6309 6310
      return NULL;
    } else {
6311
      pThreadInfo->taos = taos;
6312 6313 6314
    }
  }

6315 6316
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6317

6318 6319 6320
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6321

6322
  uint64_t  lastPrintTime = taosGetTimestampMs();
6323
  while(queryTimes --) {
6324 6325 6326
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6327
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6328
    }
H
Hui Li 已提交
6329

6330
    st = taosGetTimestampMs();
6331
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6332
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6333
        memset(sqlstr,0,sizeof(sqlstr));
6334
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6335
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6336
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6337
          sprintf(tmpFile, "%s-%d",
6338
                  g_queryInfo.superQueryInfo.result[j],
6339
                  pThreadInfo->threadID);
6340
        }
6341
        selectAndGetResult(pThreadInfo, sqlstr, tmpFile);
6342 6343 6344 6345 6346 6347 6348

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

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

6365 6366 6367
  return NULL;
}

6368
static int queryTestProcess() {
6369 6370 6371 6372

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6373 6374 6375 6376 6377 6378

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6379
          g_queryInfo.port);
6380
  if (taos == NULL) {
6381 6382
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6383 6384 6385
    exit(-1);
  }

6386
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6387 6388
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6389 6390 6391
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6392
  }
6393

6394
  prompt();
6395

6396 6397 6398
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
6399

6400 6401 6402 6403 6404 6405
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6406 6407 6408
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6409 6410
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6411

6412
  uint64_t startTs = taosGetTimestampMs();
6413

6414 6415 6416 6417 6418 6419
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6420
      taos_close(taos);
6421
      ERROR_EXIT("memory allocation failed for create threads\n");
6422
    }
6423

6424 6425 6426 6427 6428
    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;
6429

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

6432 6433 6434 6435
          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)) {
6436
            taos_close(taos);
6437 6438
            free(infos);
            free(pids);
6439 6440 6441
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6442
          }
6443
        }
6444

6445
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6446

6447
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6448 6449
            t_info);
      }
6450
    }
6451
  } else {
6452
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6453
  }
6454

6455 6456
  taos_close(taos);

6457 6458 6459
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6460 6461 6462 6463
  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));
6464 6465

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6466 6467
      free(infos);
      free(pids);
6468

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

6472
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6473
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6474

6475
    int64_t a = ntables / threads;
6476 6477 6478 6479
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6480

6481
    int64_t b = 0;
6482 6483 6484
    if (threads != 0) {
      b = ntables % threads;
    }
6485

6486
    uint64_t startFrom = 0;
6487
    for (int i = 0; i < threads; i++) {
6488 6489
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6490

6491 6492 6493 6494
      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;
6495
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6496
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6497 6498
    }

6499
    g_queryInfo.superQueryInfo.threadCnt = threads;
6500
  } else {
6501
    g_queryInfo.superQueryInfo.threadCnt = 0;
6502
  }
6503

6504 6505 6506 6507 6508 6509
  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);
      }
    }
6510
  }
S
Shuaiqiang Chang 已提交
6511

6512
  tmfree((char*)pids);
6513
  tmfree((char*)infos);
6514

6515
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6516
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6517
  }
H
Hui Li 已提交
6518

6519
  tmfree((char*)pidsOfSub);
6520
  tmfree((char*)infosOfSub);
6521

6522
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6523
  uint64_t endTs = taosGetTimestampMs();
6524

6525
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6526 6527
    g_queryInfo.superQueryInfo.totalQueried;

6528
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6529
          totalQueried,
6530
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6531 6532 6533
  return 0;
}

6534
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6535
  if (res == NULL || taos_errno(res) != 0) {
6536 6537
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6538 6539
    return;
  }
6540

6541 6542
  if (param)
    appendResultToFile(res, (char*)param);
6543
  // tao_unscribe() will free result.
H
hzcheng 已提交
6544 6545
}

6546
static TAOS_SUB* subscribeImpl(
6547 6548
        TAOS *taos, char *sql, char* topic, bool restart,
        char* resultFileName) {
6549
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6550

6551
  if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6552
    tsub = taos_subscribe(taos,
6553
            restart,
6554
            topic, sql, subscribe_callback, (void*)resultFileName,
6555
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6556
  } else {
6557
    tsub = taos_subscribe(taos,
6558
            restart,
6559
            topic, sql, NULL, NULL, 0);
6560
  }
6561

6562 6563 6564
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6565
  }
6566

6567 6568
  return tsub;
}
H
hzcheng 已提交
6569

6570 6571
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6572
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
6573
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6574

6575 6576 6577
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

6578 6579 6580 6581 6582 6583 6584 6585 6586
  if (g_queryInfo.superQueryInfo.sqlCount * pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
      errorPrint("The number %"PRId64" of sql count(%"PRIu64") multiple the table number(%"PRId64") of the thread is more than max query sql count: %d\n",
              g_queryInfo.superQueryInfo.sqlCount * pThreadInfo->ntables,
              g_queryInfo.superQueryInfo.sqlCount,
              pThreadInfo->ntables,
              MAX_QUERY_SQL_COUNT);
      exit(-1);
  }

6587
  if (pThreadInfo->taos == NULL) {
6588 6589 6590 6591 6592 6593 6594 6595
    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",
6596
            pThreadInfo->threadID, taos_errstr(NULL));
6597 6598
      return NULL;
    } else {
6599
      pThreadInfo->taos = taos;
6600 6601 6602
    }
  }

6603 6604
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6605 6606
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6607 6608
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6609 6610
    return NULL;
  }
6611

6612 6613 6614 6615 6616
  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);
6617
      memset(subSqlstr,0,sizeof(subSqlstr));
6618
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], subSqlstr, i);
6619
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6620
      if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6621
        sprintf(tmpFile, "%s-%d",
6622
                g_queryInfo.superQueryInfo.result[j], pThreadInfo->threadID);
6623
      }
6624 6625 6626 6627

      uint64_t subSeq = i * g_queryInfo.superQueryInfo.sqlCount + j;
      debugPrint("%s() LN%d, subSeq=%"PRIu64" subSqlstr: %s\n",
              __func__, __LINE__, subSeq, subSqlstr);
6628 6629 6630
      tsub[subSeq] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic,
              g_queryInfo.superQueryInfo.subscribeRestart,
              tmpFile);
6631
      if (NULL == tsub[subSeq]) {
6632
        taos_close(pThreadInfo->taos);
6633 6634 6635
        return NULL;
      }
    }
6636
  }
6637

6638 6639 6640 6641
  int consumed[MAX_QUERY_SQL_COUNT];
  for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++)
      consumed[i] = 0;

6642 6643
  // start loop to consume result
  TAOS_RES* res = NULL;
6644
  while(1) {
6645 6646
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
6647 6648 6649 6650
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
        if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
            continue;
        }
6651

6652
        uint64_t subSeq = i * g_queryInfo.superQueryInfo.sqlCount + j;
6653
        taosMsleep(g_queryInfo.superQueryInfo.subscribeInterval); // ms
6654 6655 6656 6657 6658 6659
        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],
6660
                  pThreadInfo->threadID);
6661 6662
                appendResultToFile(res, tmpFile);
            }
6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684
            consumed[j] ++;

            if ((g_queryInfo.superQueryInfo.subscribeKeepProgress)
                && (consumed[j] >=
                    g_queryInfo.superQueryInfo.resubAfterConsume[j])) {
                printf("keepProgress:%d, resub super table query: %d\n",
                    g_queryInfo.superQueryInfo.subscribeKeepProgress, j);
                taos_unsubscribe(tsub[subSeq],
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);
                consumed[j]= 0;
                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,
                    g_queryInfo.superQueryInfo.subscribeRestart,
                    tmpFile);
                if (NULL == tsub[subSeq]) {
                    taos_close(pThreadInfo->taos);
                    return NULL;
                }
            }
6685
        }
H
hzcheng 已提交
6686 6687 6688
      }
    }
  }
6689
  taos_free_result(res);
6690

6691 6692 6693 6694
  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;
6695
        taos_unsubscribe(tsub[subSeq], 0);
6696
    }
6697
  }
6698

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

6703 6704
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6705
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6706

6707 6708 6709
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6710
  if (pThreadInfo->taos == NULL) {
6711 6712 6713 6714 6715 6716 6717 6718
    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",
6719
            pThreadInfo->threadID, taos_errstr(NULL));
6720 6721
      return NULL;
    } else {
6722
      pThreadInfo->taos = taos;
6723 6724 6725
    }
  }

6726 6727
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6728
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6729 6730
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6731 6732
    return NULL;
  }
6733

6734 6735
  char topic[32] = {0};
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6736 6737
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6738
      if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6739
        sprintf(tmpFile, "%s-%d",
6740 6741
                g_queryInfo.specifiedQueryInfo.result[i],
                pThreadInfo->threadID);
6742
      }
6743
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6744 6745 6746
          g_queryInfo.specifiedQueryInfo.sql[i], topic,
          g_queryInfo.specifiedQueryInfo.subscribeRestart,
          tmpFile);
6747
      if (NULL == tsub[i]) {
6748
        taos_close(pThreadInfo->taos);
6749 6750
        return NULL;
      }
6751
  }
6752

6753 6754
  // start loop to consume result
  TAOS_RES* res = NULL;
6755 6756 6757 6758 6759

  int consumed[MAX_QUERY_SQL_COUNT];
  for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++)
      consumed[i] = 0;

6760
  while(1) {
6761
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6762
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6763 6764
        continue;
      }
6765

6766
      taosMsleep(g_queryInfo.specifiedQueryInfo.subscribeInterval); // ms
6767
      res = taos_consume(tsub[i]);
6768 6769
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6770
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6771
          sprintf(tmpFile, "%s-%d",
6772 6773
                  g_queryInfo.specifiedQueryInfo.result[i],
                  pThreadInfo->threadID);
6774
          appendResultToFile(res, tmpFile);
6775
        }
6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 6787 6788 6789 6790 6791 6792 6793 6794
        consumed[i] ++;

        if ((g_queryInfo.specifiedQueryInfo.subscribeKeepProgress)
                && (consumed[i] >=
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[i])) {
            printf("keepProgress:%d, resub specified query: %d\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress, i);
            consumed[i] = 0;
            taos_unsubscribe(tsub[i],
                g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
            tsub[i] = subscribeImpl(pThreadInfo->taos,
                g_queryInfo.specifiedQueryInfo.sql[i], topic,
                g_queryInfo.specifiedQueryInfo.subscribeRestart,
                tmpFile);
            if (NULL == tsub[i]) {
                taos_close(pThreadInfo->taos);
                return NULL;
            }
        }
6795 6796 6797 6798
      }
    }
  }
  taos_free_result(res);
6799

6800
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6801
    taos_unsubscribe(tsub[i], 0);
6802
  }
6803

6804
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6805 6806 6807
  return NULL;
}

6808
static int subscribeTestProcess() {
6809
  setupForAnsiEscape();
6810
  printfQueryMeta();
6811
  resetAfterAnsiEscape();
6812

6813
  prompt();
6814

6815 6816 6817 6818 6819
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6820
          g_queryInfo.port);
6821
  if (taos == NULL) {
6822 6823
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6824 6825 6826
    exit(-1);
  }

6827
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6828 6829
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6830 6831 6832
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6833 6834
  }

6835 6836
  taos_close(taos); // TODO: workaround to use separate taos connection;

6837 6838
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
6839 6840 6841
  //==== create sub threads for query for specified table
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
    printf("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
6842
              __func__, __LINE__,
6843 6844 6845 6846 6847 6848 6849 6850
              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);
    }
6851

6852 6853 6854 6855
    pids  = malloc(
            g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
    infos = malloc(
            g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6856 6857 6858 6859
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
6860

6861
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6862 6863
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6864
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6865
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
6866
    }
H
hzcheng 已提交
6867
  }
6868

6869
  //==== create sub threads for super table query
6870 6871
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6872 6873 6874
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6875
            sizeof(pthread_t));
6876
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6877
            sizeof(threadInfo));
6878
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6879 6880 6881
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6882
      exit(-1);
S
Shuaiqiang Chang 已提交
6883
    }
6884

6885
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6886
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6887

6888
    int64_t a = ntables / threads;
6889 6890 6891 6892
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6893

6894
    int64_t b = 0;
6895 6896 6897
    if (threads != 0) {
      b = ntables % threads;
    }
6898

6899
    uint64_t startFrom = 0;
6900
    for (int i = 0; i < threads; i++) {
6901 6902
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6903

6904 6905 6906 6907
      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;
6908
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6909
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6910
    }
6911

6912
    g_queryInfo.superQueryInfo.threadCnt = threads;
6913

6914
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6915 6916
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6917
  }
6918

6919
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6920
    pthread_join(pids[i], NULL);
6921
  }
H
hzcheng 已提交
6922

6923
  tmfree((char*)pids);
6924
  tmfree((char*)infos);
H
hzcheng 已提交
6925

6926
  tmfree((char*)pidsOfSub);
6927
  tmfree((char*)infosOfSub);
6928
//   taos_close(taos);
6929
  return 0;
H
hzcheng 已提交
6930 6931
}

6932
static void initOfInsertMeta() {
6933
  memset(&g_Dbs, 0, sizeof(SDbs));
6934

6935
  // set default values
6936
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6937
  g_Dbs.port = 6030;
6938 6939
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6940
  g_Dbs.threadCount = 2;
6941 6942

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6943 6944
}

6945
static void initOfQueryMeta() {
6946
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6947

6948
  // set default values
6949
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6950
  g_queryInfo.port = 6030;
6951 6952
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6953 6954
}

6955
static void setParaFromArg(){
6956
  if (g_args.host) {
6957
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6958
  } else {
6959
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6960
  }
L
Liu Tao 已提交
6961

6962
  if (g_args.user) {
6963
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6964
  }
6965 6966

  if (g_args.password) {
6967
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6968 6969
  }

6970 6971
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6972
  }
L
Liu Tao 已提交
6973

6974 6975 6976
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6977 6978
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6979

6980
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6981
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6982
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6983

6984
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6985 6986 6987 6988 6989

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

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

6991 6992
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6993

6994
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6995

6996 6997
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6998
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6999
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
7000
  }
H
hzcheng 已提交
7001

7002 7003 7004 7005 7006
  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;
7007
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
7008
    g_Dbs.asyncMode = g_args.async_mode;
7009

7010 7011 7012 7013
    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;
7014
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
7015 7016 7017
            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);
7018
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
7019
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
7020
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
7021

7022
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
7023
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
7024

7025 7026 7027 7028 7029
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
7030

7031
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7032
              data_type[i], MAX_TB_NAME_SIZE);
7033
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
7034 7035
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
7036

7037 7038 7039
    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 {
7040 7041 7042 7043
      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);
7044
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
7045 7046 7047
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
7048

7049 7050
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
            "INT", MAX_TB_NAME_SIZE);
7051
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
7052

7053 7054
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
            "BINARY", MAX_TB_NAME_SIZE);
7055 7056
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
7057
  } else {
7058 7059
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
7060
  }
7061 7062 7063 7064 7065 7066
}

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

7068 7069 7070
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
7071 7072 7073
    exit(-1);
  }

7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097
  /* 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);
}

7098
static void querySqlFile(TAOS* taos, char* sqlFile)
7099 7100 7101 7102 7103 7104
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
7105

7106 7107 7108 7109 7110 7111
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

7112
  double t = taosGetTimestampMs();
7113

7114
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126
    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;
7127
    }
7128 7129

    memcpy(cmd + cmd_len, line, read_len);
7130
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
7131 7132 7133
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7134 7135 7136 7137 7138
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7139 7140
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7141 7142
  }

7143
  t = taosGetTimestampMs() - t;
7144
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7145

7146 7147 7148 7149
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7150 7151
}

7152
static void testMetaFile() {
7153
    if (INSERT_TEST == g_args.test_mode) {
7154 7155
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7156

7157
      insertTestProcess();
7158

7159
    } else if (QUERY_TEST == g_args.test_mode) {
7160 7161
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7162

7163
      queryTestProcess();
7164

7165
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7166 7167
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7168

7169
      subscribeTestProcess();
7170

7171 7172 7173
    }  else {
      ;
    }
7174
}
7175

7176
static void queryResult() {
7177
  // query data
7178

7179 7180 7181 7182 7183
  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;
7184

7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220
  //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);
7221 7222
}

7223 7224
static void testCmdLine() {

7225 7226 7227 7228 7229 7230 7231 7232 7233 7234
  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);
  }

7235 7236
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7237

7238
  if (false == g_Dbs.insert_only)
7239
    queryResult();
7240 7241
}

7242 7243 7244
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7245
  debugPrint("meta file: %s\n", g_args.metaFile);
7246 7247 7248

  if (g_args.metaFile) {
    initOfInsertMeta();
7249
    initOfQueryMeta();
7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262

    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(
7263 7264 7265 7266
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7267
          g_Dbs.port);
7268
      querySqlFile(qtaos, g_args.sqlFile);
7269 7270 7271 7272 7273
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7274
  }
7275 7276

  return 0;
H
hzcheng 已提交
7277
}
7278