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

16 17 18 19 20

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

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

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

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

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

55 56 57
#define REQ_EXTRA_BUF_LEN   1024
#define RESP_BUF_LEN        4096

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

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

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

71 72
#define MAX_RECORDS_PER_REQ     32766

73 74
#define MAX_SQL_SIZE       65536
#define BUFFER_SIZE        (65536*2)
75
#define COND_BUF_LEN        BUFFER_SIZE - 30
76 77
#define MAX_USERNAME_SIZE  64
#define MAX_PASSWORD_SIZE  64
78
#define MAX_DB_NAME_SIZE   64
79
#define MAX_HOSTNAME_SIZE  64
80
#define MAX_TB_NAME_SIZE   64
81
#define MAX_DATA_SIZE      (16*1024)+20     // max record len: 16*1024, timestamp string and ,('') need extra space
82 83 84 85 86 87 88 89 90 91
#define MAX_NUM_DATATYPE   10
#define OPT_ABORT          1 /* –abort */
#define STRING_LEN         60000
#define MAX_PREPARED_RAND  1000000
#define MAX_FILE_NAME_LEN  256

#define   MAX_SAMPLES_ONCE_FROM_FILE   10000
#define   MAX_NUM_DATATYPE 10

#define   MAX_DB_COUNT           8
92
#define   MAX_SUPER_TABLE_COUNT  200
93 94 95
#define   MAX_COLUMN_COUNT       1024
#define   MAX_TAG_COUNT          128

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

#define   MAX_DATABASE_COUNT     256
100
#define INPUT_BUF_LEN   256
101

102
#define DEFAULT_TIMESTAMP_STEP  1
103

104

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

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

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

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

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

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

enum _show_db_index {
  TSDB_SHOW_DB_NAME_INDEX,
  TSDB_SHOW_DB_CREATED_TIME_INDEX,
  TSDB_SHOW_DB_NTABLES_INDEX,
  TSDB_SHOW_DB_VGROUPS_INDEX,
  TSDB_SHOW_DB_REPLICA_INDEX,
148
  TSDB_SHOW_DB_QUORUM_INDEX,
149 150 151 152 153 154 155 156 157 158
  TSDB_SHOW_DB_DAYS_INDEX,
  TSDB_SHOW_DB_KEEP_INDEX,
  TSDB_SHOW_DB_CACHE_INDEX,
  TSDB_SHOW_DB_BLOCKS_INDEX,
  TSDB_SHOW_DB_MINROWS_INDEX,
  TSDB_SHOW_DB_MAXROWS_INDEX,
  TSDB_SHOW_DB_WALLEVEL_INDEX,
  TSDB_SHOW_DB_FSYNC_INDEX,
  TSDB_SHOW_DB_COMP_INDEX,
  TSDB_SHOW_DB_CACHELAST_INDEX,
159
  TSDB_SHOW_DB_PRECISION_INDEX,
160 161 162 163 164 165 166 167 168 169
  TSDB_SHOW_DB_UPDATE_INDEX,
  TSDB_SHOW_DB_STATUS_INDEX,
  TSDB_MAX_SHOW_DB
};

// -----------------------------------------SHOW TABLES CONFIGURE -------------------------------------
enum _show_stables_index {
  TSDB_SHOW_STABLES_NAME_INDEX,
  TSDB_SHOW_STABLES_CREATED_TIME_INDEX,
  TSDB_SHOW_STABLES_COLUMNS_INDEX,
170 171
  TSDB_SHOW_STABLES_METRIC_INDEX,
  TSDB_SHOW_STABLES_UID_INDEX,
172
  TSDB_SHOW_STABLES_TID_INDEX,
173
  TSDB_SHOW_STABLES_VGID_INDEX,
174
  TSDB_MAX_SHOW_STABLES
175 176
};

177 178 179 180 181 182 183 184 185 186 187 188 189 190
enum _describe_table_index {
  TSDB_DESCRIBE_METRIC_FIELD_INDEX,
  TSDB_DESCRIBE_METRIC_TYPE_INDEX,
  TSDB_DESCRIBE_METRIC_LENGTH_INDEX,
  TSDB_DESCRIBE_METRIC_NOTE_INDEX,
  TSDB_MAX_DESCRIBE_METRIC
};

typedef struct {
  char field[TSDB_COL_NAME_LEN + 1];
  char type[16];
  int length;
  char note[128];
} SColDes;
H
hzcheng 已提交
191 192

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

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

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

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

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

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

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

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

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

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

typedef struct {
  char     name[TSDB_DB_NAME_LEN + 1];
  char     create_time[32];
  int32_t  ntables;
295
  int32_t  vgroups;
296 297
  int16_t  replica;
  int16_t  quorum;
298
  int16_t  days;
299 300 301 302 303 304 305 306 307 308 309 310 311 312
  char     keeplist[32];
  int32_t  cache; //MB
  int32_t  blocks;
  int32_t  minrows;
  int32_t  maxrows;
  int8_t   wallevel;
  int32_t  fsync;
  int8_t   comp;
  int8_t   cachelast;
  char     precision[8];   // time resolution
  int8_t   update;
  char     status[16];
} SDbInfo;

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

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

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

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

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

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

362 363
} SDbs;

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

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

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

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

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

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

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

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

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

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

454
#ifdef WINDOWS
455 456
#define _CRT_RAND_S

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

typedef unsigned __int32 uint32_t;

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

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

471
static void setupForAnsiEscape(void) {
472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489
  DWORD mode = 0;
  g_stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);

  if(g_stdoutHandle == INVALID_HANDLE_VALUE) {
    exit(GetLastError());
  }

  if(!GetConsoleMode(g_stdoutHandle, &mode)) {
    exit(GetLastError());
  }

  g_consoleMode = mode;

  // Enable ANSI escape codes
  mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;

  if(!SetConsoleMode(g_stdoutHandle, mode)) {
    exit(GetLastError());
490
  }
491 492
}

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

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

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

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

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

518 519
#include <time.h>

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

525
#endif // ifdef Windows
526

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

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

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

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



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

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

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

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

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


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

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

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

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

625
#ifndef TAOSDEMO_STATUS
626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642
#define TAOSDEMO_STATUS "unknown"
#endif

static void printVersion() {
    char tdengine_ver[] = TD_VERNUMBER;
    char taosdemo_ver[] = TAOSDEMO_COMMIT_SHA1;
    char taosdemo_status[] = TAOSDEMO_STATUS;

    if (strlen(taosdemo_status) == 0) {
        printf("taosdemo verison %s-%s\n",
                tdengine_ver, taosdemo_ver);
    } else {
        printf("taosdemo verison %s-%s, status:%s\n",
                tdengine_ver, taosdemo_ver, taosdemo_status);
    }
}

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

711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
static bool isStringNumber(char *input)
{
  int len = strlen(input);
  if (0 == len) {
    return false;
  }

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

  return true;
}

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

  for (int i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-f") == 0) {
      arguments->metaFile = argv[++i];
    } else if (strcmp(argv[i], "-c") == 0) {
H
Haojun Liao 已提交
733 734 735 736 737
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
738
      tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
739

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

963
      arguments->disorderRatio = atoi(argv[++i]);
964

965
      if (arguments->disorderRatio > 50) {
966
        arguments->disorderRatio = 50;
967
      }
968

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

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

981
      arguments->disorderRange = atoi(argv[++i]);
982 983 984
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

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

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

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

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

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

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

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

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

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

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

1116
  taos_free_result(res);
1117 1118
  return 0;
}
H
hzcheng 已提交
1119

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

1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
  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);

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

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

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

1168
  appendResultBufToFile(databuf, resultFile);
1169 1170
  free(databuf);
}
H
hzcheng 已提交
1171

1172 1173
static void selectAndGetResult(
        threadInfo *pThreadInfo, char *command, char* resultFileName) {
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183
  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;
    }

    appendResultToFile(res, resultFileName);
1184
    taos_free_result(res);
1185

1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
  } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
      int retCode = postProceSql(
              g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
              g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
              resultFileName);
      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);
  }
1199
}
H
hzcheng 已提交
1200

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

1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259
#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

1260
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1261

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

1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
#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)

1312
static int printfInsertMeta() {
1313
    SHOW_PARSE_RESULT_START();
1314

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

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

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

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

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

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

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

1404 1405 1406 1407 1408 1409 1410
      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");
      }
1411

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

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

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

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

  SHOW_PARSE_RESULT_END();
1501 1502

  return 0;
1503 1504 1505
}

static void printfInsertMetaToFile(FILE* fp) {
1506 1507

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1508

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

1519 1520
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1521
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1522
    if (0 == g_Dbs.db[i].drop) {
1523
      fprintf(fp, "  drop:                  no\n");
1524
    }else {
1525
      fprintf(fp, "  drop:                  yes\n");
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 1562 1563 1564
    }

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

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

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

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

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

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

1625 1626 1627 1628
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1629
      fprintf(fp, "      sampleFormat:      %s\n",  g_Dbs.db[i].superTbls[j].sampleFormat);
1630 1631 1632
      fprintf(fp, "      sampleFile:        %s\n",  g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",  g_Dbs.db[i].superTbls[j].tagsFile);

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

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1652 1653
      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);
1654
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1655 1656 1657
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1658 1659
          fprintf(fp, "tag[%d]:%s(%d) ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1660 1661
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1662
        }
1663 1664 1665 1666 1667
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1668

1669
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1670 1671 1672
}

static void printfQueryMeta() {
1673

1674
  SHOW_PARSE_RESULT_START();
1675

1676
  printf("host:                    \033[33m%s:%u\033[0m\n",
1677
          g_queryInfo.host, g_queryInfo.port);
1678 1679 1680 1681
  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");
1682 1683 1684 1685

  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",
1686
      g_queryInfo.specifiedQueryInfo.sqlCount);
1687 1688 1689
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1690
      g_queryInfo.specifiedQueryInfo.queryTimes);
1691 1692 1693 1694 1695 1696
      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",
1697
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1698
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1699
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1700
      printf("restart:        \033[33m%d\033[0m\n",
1701
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1702
      printf("keepProgress:   \033[33m%d\033[0m\n",
1703
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1704

1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
      for (uint64_t i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        printf("  sql[%"PRIu64"]: \033[33m%s\033[0m\n",
            i, g_queryInfo.specifiedQueryInfo.sql[i]);
      }
      printf("\n");
    }

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

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

      printf("mod:            \033[33m%s\033[0m\n",
1729
        (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
1730
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1731
        g_queryInfo.superQueryInfo.subscribeInterval);
1732
      printf("restart:        \033[33m%d\033[0m\n",
1733
        g_queryInfo.superQueryInfo.subscribeRestart);
1734
      printf("keepProgress:   \033[33m%d\033[0m\n",
1735
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1736

1737 1738 1739 1740 1741 1742
      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");
    }
1743
  }
1744

1745
  SHOW_PARSE_RESULT_END();
1746 1747
}

1748
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779
  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;
}

1780
static void xDumpFieldToFile(FILE* fp, const char* val,
1781
        TAOS_FIELD* field, int32_t length, int precision) {
1782

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

1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869
  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;
}

1870 1871
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1872 1873
  TAOS_ROW row = NULL;
  int count = 0;
1874 1875

  res = taos_query(taos, "show databases;");
1876
  int32_t code = taos_errno(res);
1877

1878
  if (code != 0) {
1879
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1880 1881 1882 1883 1884
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1885
  while((row = taos_fetch_row(res)) != NULL) {
1886
    // sys database name : 'log'
1887
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1888
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1889 1890
      continue;
    }
1891 1892 1893

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

1898
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
1899
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1900
    formatTimestamp(dbInfos[count]->create_time,
1901 1902
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
1903
    dbInfos[count]->ntables = *((int32_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1904
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1905 1906
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1907
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1908

1909
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1910
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1911 1912 1913 1914 1915 1916 1917
    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]));
1918
    dbInfos[count]->cachelast =
1919
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1920

1921
    tstrncpy(dbInfos[count]->precision,
1922 1923
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1924
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1925
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1926
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1927

1928 1929
    count++;
    if (count > MAX_DATABASE_COUNT) {
1930
      errorPrint("%s() LN%d, The database count overflow than %d\n",
1931
         __func__, __LINE__, MAX_DATABASE_COUNT);
1932 1933 1934 1935 1936 1937 1938
      break;
    }
  }

  return count;
}

1939
static void printfDbInfoForQueryToFile(
1940
        char* filename, SDbInfo* dbInfos, int index) {
1941

1942
  if (filename[0] == 0)
1943
      return;
1944 1945 1946

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
1947
    errorPrint( "failed to open file: %s\n", filename);
1948
    return;
1949 1950 1951 1952 1953 1954
  }

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

1989 1990
  // show variables
  res = taos_query(taos, "show variables;");
1991
  //appendResultToFile(res, filename);
1992 1993 1994 1995 1996
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
1997
  //appendResultToFile(res, filename);
1998

1999 2000 2001 2002
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
2003
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
2004 2005 2006
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
2007
  if (dbCount <= 0) {
2008 2009
      free(dbInfos);
      return;
2010
  }
2011 2012

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

2016 2017 2018 2019
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
2020

2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031
    // 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);
}

2032 2033
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
        char* sqlstr, char *resultFile)
2034
{
2035
    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";
2036

2037
    char *url = "/rest/sql";
2038

2039 2040 2041 2042
    int bytes, sent, received, req_str_len, resp_len;
    char *request_buf;
    char response_buf[RESP_BUF_LEN];
    uint16_t rest_port = port + TSDB_PORT_HTTP;
2043

2044
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
2045

2046 2047 2048 2049 2050
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2051

2052 2053
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
2054

2055 2056 2057 2058 2059 2060 2061 2062
    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', '+', '/'};
2063

2064 2065 2066 2067
    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);
2068

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

2087
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2088 2089 2090 2091 2092
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2093

2094
    memset(base64_buf, 0, INPUT_BUF_LEN);
2095

2096 2097 2098 2099 2100 2101 2102 2103
    for (int n = 0, m = 0; n < userpass_buf_len;) {
      uint32_t oct_a = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t oct_b = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t oct_c = n < userpass_buf_len ?
        (unsigned char) userpass_buf[n++]:0;
      uint32_t triple = (oct_a << 0x10) + (oct_b << 0x08) + oct_c;
2104

2105 2106 2107 2108 2109
      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];
    }
2110

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

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

2118 2119 2120 2121 2122 2123 2124 2125 2126
    int r = snprintf(request_buf,
            req_buf_len,
            req_fmt, url, host, rest_port,
            auth, strlen(sqlstr), sqlstr);
    if (r >= req_buf_len) {
        free(request_buf);
        ERROR_EXIT("ERROR too long request");
    }
    verbosePrint("%s() LN%d: Request:\n%s\n", __func__, __LINE__, request_buf);
2127

2128 2129 2130
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2131
#ifdef WINDOWS
2132
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2133
#else
2134
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2135
#endif
2136 2137 2138 2139 2140 2141
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2142

2143 2144 2145 2146
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2147
#ifdef WINDOWS
2148
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2149
#else
2150
        bytes = read(sockfd, response_buf + received, resp_len - received);
2151
#endif
2152 2153 2154 2155 2156 2157 2158 2159
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2160

2161 2162 2163 2164
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2165

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

2169 2170 2171 2172
    if (resultFile) {
       appendResultBufToFile(response_buf, resultFile);
    }

2173
    free(request_buf);
2174
#ifdef WINDOWS
2175
    closesocket(sockfd);
2176 2177
    WSACleanup();
#else
2178
    close(sockfd);
2179
#endif
2180

2181
    return 0;
2182 2183
}

2184
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2185 2186
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2187
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2188
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2189 2190
    return NULL;
  }
2191

2192
  int    dataLen = 0;
2193
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2194
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2195

2196 2197 2198
  return dataBuf;
}

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

2218 2219
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2220 2221 2222 2223 2224
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2225 2226 2227 2228 2229 2230 2231

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

2274
  dataLen -= 2;
2275
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2276 2277 2278
  return dataBuf;
}

2279
static int calcRowLen(SSuperTable*  superTbls) {
2280 2281
  int colIndex;
  int  lenOfOneRow = 0;
2282

2283 2284
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2285

2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
    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;
2302
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2303
      lenOfOneRow += 42;
2304
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317
      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;
2318

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

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2344

2345 2346 2347 2348
  return 0;
}


2349
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2350
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2351
        uint64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2352

2353
  char command[BUFFER_SIZE] = "\0";
2354 2355
  char limitBuf[100] = "\0";

2356
  TAOS_RES * res;
2357 2358 2359
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2360 2361

  if (offset >= 0) {
2362
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2363
            limit, offset);
2364 2365
  }

2366
  //get all child table name use cmd: select tbname from superTblName;
2367
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2368
          dbName, sTblName, limitBuf);
2369

2370
  res = taos_query(taos, command);
2371 2372 2373 2374
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2375
    errorPrint("%s() LN%d, failed to run command %s\n",
2376
           __func__, __LINE__, command);
2377 2378 2379
    exit(-1);
  }

2380
  int childTblCount = (limit < 0)?10000:limit;
2381
  int count = 0;
2382 2383 2384
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2385 2386 2387 2388
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2389 2390 2391
    }
  }

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

2419 2420 2421 2422 2423 2424 2425
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2426
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2427
        char* sTblName, char** childTblNameOfSuperTbl,
2428
        uint64_t* childTblCountOfSuperTbl) {
2429

2430 2431
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2432
            -1, 0);
2433 2434
}

2435
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2436
        SSuperTable*  superTbls) {
2437

2438
  char command[BUFFER_SIZE] = "\0";
2439
  TAOS_RES * res;
2440 2441
  TAOS_ROW row = NULL;
  int count = 0;
2442

2443
  //get schema use cmd: describe superTblName;
2444
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2445
  res = taos_query(taos, command);
2446 2447 2448
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2449
    taos_free_result(res);
2450 2451 2452 2453 2454 2455
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2456
  while((row = taos_fetch_row(res)) != NULL) {
2457 2458 2459
    if (0 == count) {
      count++;
      continue;
2460
    }
2461 2462

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

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

  calcRowLen(superTbls);

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

H
Haojun Liao 已提交
2516
static int createSuperTable(
2517 2518
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2519

2520
  char command[BUFFER_SIZE] = "\0";
2521

2522 2523 2524 2525 2526
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2527 2528 2529

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

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

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

2579 2580
  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);
2581 2582

  // save for creating child table
2583 2584 2585
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2586
           __func__, __LINE__, len+1);
2587 2588 2589 2590
    taos_close(taos);
    exit(-1);
  }

2591
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2592
  verbosePrint("%s() LN%d: %s\n",
2593
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2594

2595 2596
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
2597
            __func__, __LINE__, superTbl->tagCount);
2598 2599
    return -1;
  }
2600

2601 2602 2603
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2604

2605 2606 2607 2608
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2609

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

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2665 2666 2667
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2668 2669
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2670 2671 2672
  return 0;
}

2673
static int createDatabasesAndStables() {
2674 2675 2676 2677
  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) {
2678
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2679
    return -1;
2680 2681 2682
  }
  char command[BUFFER_SIZE] = "\0";

2683
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2684 2685
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2686
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2687
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2688 2689 2690 2691
        taos_close(taos);
        return -1;
      }

2692
      int dataLen = 0;
2693
      dataLen += snprintf(command + dataLen,
2694
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2695

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

      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);
2766 2767
    }

2768
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2769
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2770 2771 2772

    int validStbCount = 0;

2773
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2774 2775 2776 2777 2778 2779 2780
      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)) {
2781
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
2782
                &g_Dbs.db[i].superTbls[j]);
2783

2784
        if (0 != ret) {
2785 2786
          errorPrint("create super table %d failed!\n\n", j);
          continue;
2787 2788 2789
        }
      }

2790
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2791
                &g_Dbs.db[i].superTbls[j]);
2792 2793
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2794
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2795
        continue;
2796
      }
2797 2798

      validStbCount ++;
2799
    }
2800 2801

    g_Dbs.db[i].superTblCount = validStbCount;
2802 2803 2804 2805 2806 2807
  }

  taos_close(taos);
  return 0;
}

2808 2809
static void* createTable(void *sarg)
{
2810 2811
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2812 2813 2814

  int64_t  lastPrintTime = taosGetTimestampMs();

2815
  int buff_len;
2816
  buff_len = BUFFER_SIZE / 8;
2817

2818
  char *buffer = calloc(buff_len, 1);
2819
  if (buffer == NULL) {
2820
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2821 2822
    exit(-1);
  }
2823 2824 2825

  int len = 0;
  int batchNum = 0;
2826

2827
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2828 2829
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2830

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

    len = 0;
2881
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2882
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2883
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2884
      free(buffer);
2885 2886 2887 2888 2889
      return NULL;
    }

    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
2890
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2891
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2892 2893 2894
      lastPrintTime = currentPrintTime;
    }
  }
2895

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

2903 2904 2905 2906
  free(buffer);
  return NULL;
}

2907
static int startMultiThreadCreateChildTable(
2908
        char* cols, int threads, uint64_t startFrom, uint64_t ntables,
2909
        char* db_name, SSuperTable* superTblInfo) {
2910

2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922
  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;
  }

2923
  uint64_t a = ntables / threads;
2924 2925 2926 2927 2928
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

2929
  uint64_t b = 0;
2930
  b = ntables % threads;
2931

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

    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;
2956
    t_info->use_metric = true;
2957
    t_info->cols = cols;
2958
    t_info->minDelay = UINT64_MAX;
2959 2960
    pthread_create(pids + i, NULL, createTable, t_info);
  }
2961

2962 2963 2964 2965 2966 2967 2968 2969 2970 2971
  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);
2972
  free(infos);
2973 2974

  return 0;
2975 2976
}

2977
static void createChildTables() {
2978 2979
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
2980

2981
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2982 2983
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
2984
          // with super table
2985 2986
        for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
2987
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
2988 2989
            continue;
          }
2990

2991
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
2992
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
2993 2994 2995 2996
          int startFrom = 0;
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

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

3022
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
3023

3024
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRIu64" schema: %s\n",
3025 3026
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
3027
      startMultiThreadCreateChildTable(
3028 3029 3030 3031 3032 3033
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
3034
    }
3035 3036 3037 3038 3039 3040
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3041
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3042 3043 3044
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3045

3046 3047
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3048
    printf("Failed to open tags file: %s, reason:%s\n",
3049
            superTblInfo->tagsFile, strerror(errno));
3050 3051 3052 3053 3054 3055 3056
    return -1;
  }

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

3058 3059 3060 3061 3062 3063 3064 3065 3066
  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;
  }

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

3121 3122
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3123 3124 3125
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3126
  }
3127

3128
  assert(superTblInfo->sampleDataBuf);
3129
  memset(superTblInfo->sampleDataBuf, 0,
3130
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3131
  while(1) {
3132
    readLen = tgetline(&line, &n, fp);
3133 3134
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3135
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3136
                superTblInfo->sampleFile, strerror(errno));
3137
        fclose(fp);
3138 3139 3140 3141
        return -1;
      }
      continue;
    }
3142

3143 3144 3145 3146 3147 3148 3149 3150 3151
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3152
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3153
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3154 3155 3156
      continue;
    }

3157
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3158
          line, readLen);
3159 3160 3161 3162 3163 3164 3165
    getRows++;

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

3166
  fclose(fp);
3167 3168 3169 3170
  tmfree(line);
  return 0;
}

3171
static bool getColumnAndTagTypeFromInsertJsonFile(
3172
        cJSON* stbInfo, SSuperTable* superTbls) {
3173
  bool  ret = false;
3174

3175
  // columns
3176 3177
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3178
    printf("ERROR: failed to read json, columns not found\n");
3179 3180 3181 3182 3183 3184
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3185

3186
  int columnSize = cJSON_GetArraySize(columns);
3187
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3188
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3189
            __func__, __LINE__, MAX_COLUMN_COUNT);
3190 3191 3192 3193 3194 3195
    goto PARSE_OVER;
  }

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

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

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

3226 3227
    cJSON* dataLen = cJSON_GetObjectItem(column, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3228
      columnCase.dataLen = dataLen->valueint;
3229
    } else if (dataLen && dataLen->type != cJSON_Number) {
3230
      debugPrint("%s() LN%d: failed to read json, column len not found\n",
3231
          __func__, __LINE__);
3232 3233 3234 3235
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 8;
    }
3236

3237
    for (int n = 0; n < count; ++n) {
3238
      tstrncpy(superTbls->columns[index].dataType,
3239
              columnCase.dataType, MAX_TB_NAME_SIZE);
3240
      superTbls->columns[index].dataLen = columnCase.dataLen;
3241 3242
      index++;
    }
3243
  }
3244

3245 3246
  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",
3247
            __func__, __LINE__, MAX_COLUMN_COUNT);
3248 3249 3250
    goto PARSE_OVER;
  }

3251
  superTbls->columnCount = index;
3252

3253 3254
  count = 1;
  index = 0;
3255
  // tags
3256 3257
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3258
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3259
        __func__, __LINE__);
3260 3261
    goto PARSE_OVER;
  }
3262

3263 3264
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3265
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3266
        __func__, __LINE__, MAX_TAG_COUNT);
3267 3268
    goto PARSE_OVER;
  }
3269 3270

  //superTbls->tagCount = tagSize;
3271 3272 3273
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3274

3275 3276 3277
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3278
      count = countObj->valueint;
3279
    } else if (countObj && countObj->type != cJSON_Number) {
3280
      printf("ERROR: failed to read json, column count not found\n");
3281 3282 3283 3284 3285
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3286
    // column info
3287 3288
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3289 3290 3291
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
3292
          __func__, __LINE__);
3293 3294
      goto PARSE_OVER;
    }
3295
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3296

3297 3298
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3299
      columnCase.dataLen = dataLen->valueint;
3300
    } else if (dataLen && dataLen->type != cJSON_Number) {
3301
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
3302
          __func__, __LINE__);
3303 3304 3305
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3306 3307
    }

3308
    for (int n = 0; n < count; ++n) {
3309
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3310
          MAX_TB_NAME_SIZE);
3311
      superTbls->tags[index].dataLen = columnCase.dataLen;
3312 3313
      index++;
    }
3314
  }
3315 3316

  if (index > MAX_TAG_COUNT) {
3317
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3318
        __func__, __LINE__, MAX_TAG_COUNT);
3319 3320 3321
    goto PARSE_OVER;
  }

3322 3323
  superTbls->tagCount = index;

3324 3325
  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",
3326
        __func__, __LINE__, MAX_COLUMN_COUNT);
3327 3328
    goto PARSE_OVER;
  }
3329 3330
  ret = true;

3331
PARSE_OVER:
3332 3333 3334 3335 3336 3337 3338 3339
  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) {
3340
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3341 3342 3343 3344
  }

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

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3369
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3370
  } else if (!password) {
3371
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3372 3373 3374 3375
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3376
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3377
  } else if (!resultfile) {
3378
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3379 3380 3381 3382 3383 3384 3385 3386
  }

  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 {
3387
    printf("ERROR: failed to read json, threads not found\n");
3388
    goto PARSE_OVER;
3389 3390
  }

3391 3392 3393 3394
  cJSON* threads2 = cJSON_GetObjectItem(root, "thread_count_create_tbl");
  if (threads2 && threads2->type == cJSON_Number) {
    g_Dbs.threadCountByCreateTbl = threads2->valueint;
  } else if (!threads2) {
sangshuduo's avatar
sangshuduo 已提交
3395
    g_Dbs.threadCountByCreateTbl = 1;
3396
  } else {
3397
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3398
            __func__, __LINE__);
3399
    goto PARSE_OVER;
3400
  }
3401

3402 3403
  cJSON* gInsertInterval = cJSON_GetObjectItem(root, "insert_interval");
  if (gInsertInterval && gInsertInterval->type == cJSON_Number) {
3404 3405 3406 3407 3408
    if (gInsertInterval->valueint <0) {
      errorPrint("%s() LN%d, failed to read json, insert interval input mistake\n",
            __func__, __LINE__);
      goto PARSE_OVER;
    }
3409 3410 3411 3412
    g_args.insert_interval = gInsertInterval->valueint;
  } else if (!gInsertInterval) {
    g_args.insert_interval = 0;
  } else {
3413
    errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
3414
        __func__, __LINE__);
3415 3416
    goto PARSE_OVER;
  }
3417

3418 3419
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3420 3421 3422 3423 3424 3425
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3426
    g_args.interlace_rows = interlaceRows->valueint;
3427 3428 3429

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

3446 3447
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3448 3449 3450 3451 3452
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3453 3454
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
sangshuduo's avatar
sangshuduo 已提交
3455
    g_args.max_sql_len = (1024*1024);
3456
  } else {
3457
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
3458
        __func__, __LINE__);
3459 3460 3461 3462 3463
    goto PARSE_OVER;
  }

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

3480
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3481
  if (answerPrompt
3482 3483
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3484 3485 3486 3487 3488 3489 3490 3491 3492 3493
    if (0 == strncasecmp(answerPrompt->valuestring, "yes", 3)) {
      g_args.answer_yes = false;
    } else if (0 == strncasecmp(answerPrompt->valuestring, "no", 2)) {
      g_args.answer_yes = true;
    } else {
      g_args.answer_yes = false;
    }
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
3494
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
3495
    goto PARSE_OVER;
3496
  }
3497 3498 3499

  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3500
    printf("ERROR: failed to read json, databases not found\n");
3501 3502 3503 3504 3505
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3506
    errorPrint(
3507 3508
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3509 3510 3511 3512 3513 3514 3515 3516
    goto PARSE_OVER;
  }

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

3517
    // dbinfo
3518 3519
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3520
      printf("ERROR: failed to read json, dbinfo not found\n");
3521 3522
      goto PARSE_OVER;
    }
3523

3524 3525
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3526
      printf("ERROR: failed to read json, db name not found\n");
3527 3528
      goto PARSE_OVER;
    }
3529
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3530 3531 3532

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3533 3534
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3535
      } else {
3536
        g_Dbs.db[i].drop = false;
3537
      }
3538
    } else if (!drop) {
3539
      g_Dbs.db[i].drop = g_args.drop_database;
3540
    } else {
3541
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
3542
              __func__, __LINE__);
3543 3544 3545 3546
      goto PARSE_OVER;
    }

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

3589 3590 3591 3592 3593 3594
    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 {
3595 3596
     printf("ERROR: failed to read json, days not found\n");
     goto PARSE_OVER;
3597
    }
3598

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

3609 3610 3611 3612 3613 3614
    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 {
3615 3616
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632
    }

    //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) {
3633
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3634
    } else {
3635 3636
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3637 3638 3639 3640 3641 3642
    }

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

    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 {
3655 3656
     printf("ERROR: failed to read json, comp not found\n");
     goto PARSE_OVER;
3657 3658 3659 3660 3661 3662 3663 3664
    }

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

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

3679 3680 3681 3682
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3683
      g_Dbs.db[i].dbCfg.quorum = 1;
3684
    } else {
3685 3686
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3687 3688 3689 3690 3691 3692 3693 3694
    }

    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 {
3695
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3696
              __func__, __LINE__);
3697
      goto PARSE_OVER;
3698
    }
3699

3700
    // super_talbes
3701 3702
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3703
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3704
              __func__, __LINE__);
3705
      goto PARSE_OVER;
3706 3707
    }

3708 3709
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3710
      errorPrint(
3711 3712
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3713 3714 3715 3716 3717 3718 3719
      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;
3720 3721

      // dbinfo
3722 3723
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3724
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3725
                __func__, __LINE__);
3726 3727
        goto PARSE_OVER;
      }
3728
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3729

3730 3731
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3732
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3733 3734
        goto PARSE_OVER;
      }
3735
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3736 3737

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3738
      if (autoCreateTbl
3739 3740
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3741 3742 3743 3744 3745 3746 3747 3748 3749 3750
        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 {
3751
        printf("ERROR: failed to read json, auto_create_table not found\n");
3752 3753
        goto PARSE_OVER;
      }
3754

3755 3756 3757 3758
      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) {
3759
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3760
      } else {
3761
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3762
        goto PARSE_OVER;
3763
      }
3764 3765

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

3786 3787
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3788
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3789
                __func__, __LINE__);
3790 3791 3792 3793 3794
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3795
      if (dataSource && dataSource->type == cJSON_String
3796
              && dataSource->valuestring != NULL) {
3797
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
3798
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3799
      } else if (!dataSource) {
3800
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3801
      } else {
3802
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
3803
            __func__, __LINE__);
3804 3805 3806
        goto PARSE_OVER;
      }

3807
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest
3808
      if (insertMode && insertMode->type == cJSON_String
3809
              && insertMode->valuestring != NULL) {
3810
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode,
3811
                insertMode->valuestring, MAX_DB_NAME_SIZE);
3812
      } else if (!insertMode) {
3813
        tstrncpy(g_Dbs.db[i].superTbls[j].insertMode, "taosc", MAX_DB_NAME_SIZE);
3814
      } else {
3815
        printf("ERROR: failed to read json, insert_mode not found\n");
3816 3817 3818
        goto PARSE_OVER;
      }

3819
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3820 3821
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3822
        if (childTbl_limit->type != cJSON_Number) {
3823 3824
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
3825 3826 3827
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
3828
        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.
3829 3830 3831
      }

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

3843 3844
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3845
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3846
                ts->valuestring, MAX_DB_NAME_SIZE);
3847
      } else if (!ts) {
3848
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3849
                "now", MAX_DB_NAME_SIZE);
3850
      } else {
3851
        printf("ERROR: failed to read json, start_timestamp not found\n");
3852 3853
        goto PARSE_OVER;
      }
3854

3855 3856 3857 3858
      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) {
3859
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3860
      } else {
3861
        printf("ERROR: failed to read json, timestamp_step not found\n");
3862 3863 3864 3865
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3866
      if (sampleFormat && sampleFormat->type
3867
              == cJSON_String && sampleFormat->valuestring != NULL) {
3868
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
3869
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3870
      } else if (!sampleFormat) {
3871
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3872
      } else {
3873
        printf("ERROR: failed to read json, sample_format not found\n");
3874
        goto PARSE_OVER;
3875
      }
3876

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

3889 3890
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3891
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
3892
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3893 3894 3895 3896 3897 3898 3899 3900 3901
        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 {
3902
        printf("ERROR: failed to read json, tags_file not found\n");
3903 3904
        goto PARSE_OVER;
      }
3905

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

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
3969 3970 3971 3972 3973 3974
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

3975 3976 3977 3978
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
3979
        printf("ERROR: failed to read json, disorderRatio not found\n");
3980
        goto PARSE_OVER;
3981
      }
3982 3983 3984 3985 3986 3987 3988

      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 {
3989
        printf("ERROR: failed to read json, disorderRange not found\n");
3990 3991
        goto PARSE_OVER;
      }
3992

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

4027
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
4028
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4029 4030
      if (false == retVal) {
        goto PARSE_OVER;
4031 4032
      }
    }
4033 4034 4035 4036
  }

  ret = true;

4037
PARSE_OVER:
4038 4039 4040 4041 4042 4043 4044 4045
  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) {
4046
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4047 4048 4049 4050
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4051
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4052
  } else if (!host) {
4053
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4054
  } else {
4055
    printf("ERROR: failed to read json, host not found\n");
4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067
    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) {
4068
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4069
  } else if (!user) {
4070
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4071 4072 4073 4074
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4075
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4076
  } else if (!password) {
4077
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4078
  }
H
hzcheng 已提交
4079

4080
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4081
  if (answerPrompt && answerPrompt->type == cJSON_String
4082
          && answerPrompt->valuestring != NULL) {
4083 4084 4085 4086
    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 已提交
4087
    } else {
4088
      g_args.answer_yes = false;
H
hzcheng 已提交
4089
    }
4090 4091 4092
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4093
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4094
    goto PARSE_OVER;
4095
  }
4096

4097 4098
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4099 4100 4101
    if (gQueryTimes->valueint <= 0) {
      errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
        __func__, __LINE__, gQueryTimes->valueint);
4102 4103
      goto PARSE_OVER;
    }
4104 4105 4106 4107
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4108
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4109
        __func__, __LINE__);
4110 4111 4112
    goto PARSE_OVER;
  }

4113 4114
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4115
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
4116
  } else if (!dbs) {
4117
    printf("ERROR: failed to read json, databases not found\n");
4118
    goto PARSE_OVER;
H
hzcheng 已提交
4119
  }
4120 4121 4122

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

4131
  // specified_table_query
4132 4133
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4134
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4135 4136
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4137
    printf("ERROR: failed to read json, super_table_query not found\n");
4138
    goto PARSE_OVER;
4139
  } else {
4140 4141 4142 4143 4144
    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;
4145 4146
    }

4147
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4148
        "query_times");
4149
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4150 4151 4152
      if (specifiedQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
                __func__, __LINE__, specifiedQueryTimes->valueint);
4153 4154 4155
        goto PARSE_OVER;

      }
4156 4157 4158 4159
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4160
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4161
          __func__, __LINE__);
4162
      goto PARSE_OVER;
4163
    }
4164

4165
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4166
    if (concurrent && concurrent->type == cJSON_Number) {
4167 4168 4169 4170
      if (concurrent->valueint <= 0) {
        errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4171
              g_queryInfo.specifiedQueryInfo.concurrent);
4172 4173
        goto PARSE_OVER;
      }
4174
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4175
    } else if (!concurrent) {
4176
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4177
    }
4178

4179 4180 4181 4182 4183 4184 4185
    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;
4186
      } else {
4187
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4188
            __func__, __LINE__);
4189 4190 4191
        goto PARSE_OVER;
      }
    } else {
4192
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4193
    }
4194

4195
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4196
    if (interval && interval->type == cJSON_Number) {
4197
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4198
    } else if (!interval) {
4199 4200
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4201
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4202
    }
4203

4204
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4205
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4206
      if (0 == strcmp("yes", restart->valuestring)) {
4207
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4208
      } else if (0 == strcmp("no", restart->valuestring)) {
4209
        g_queryInfo.specifiedQueryInfo.subscribeRestart = 0;
4210
      } else {
4211
        printf("ERROR: failed to read json, subscribe restart error\n");
4212 4213 4214
        goto PARSE_OVER;
      }
    } else {
4215
      g_queryInfo.specifiedQueryInfo.subscribeRestart = 1;
4216
    }
4217

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

4234
    // sqls
4235
    cJSON* superSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
4236
    if (!superSqls) {
4237
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4238
    } else if (superSqls->type != cJSON_Array) {
4239
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
4240
          __func__, __LINE__);
4241
      goto PARSE_OVER;
4242
    } else {
4243 4244
      int superSqlSize = cJSON_GetArraySize(superSqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4245
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4246
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4247 4248
        goto PARSE_OVER;
      }
4249

4250
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4251 4252 4253
      for (int j = 0; j < superSqlSize; ++j) {
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
        if (sql == NULL) continue;
4254

4255 4256
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4257
          printf("ERROR: failed to read json, sql not found\n");
4258 4259
          goto PARSE_OVER;
        }
4260
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j], sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4261

4262 4263
        cJSON *result = cJSON_GetObjectItem(sql, "result");
        if (NULL != result && result->type == cJSON_String && result->valuestring != NULL) {
4264
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j], result->valuestring, MAX_FILE_NAME_LEN);
4265
        } else if (NULL == result) {
4266
          memset(g_queryInfo.specifiedQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4267
        } else {
4268
          printf("ERROR: failed to read json, super query result file not found\n");
4269
          goto PARSE_OVER;
4270
        }
4271 4272 4273
      }
    }
  }
4274

4275
  // super_table_query
4276 4277
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4278
    g_queryInfo.superQueryInfo.threadCnt = 1;
4279 4280
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4281
    printf("ERROR: failed to read json, sub_table_query not found\n");
4282 4283
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4284
  } else {
4285
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4286
    if (subrate && subrate->type == cJSON_Number) {
4287
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4288
    } else if (!subrate) {
4289
      g_queryInfo.superQueryInfo.queryInterval = 0;
4290 4291 4292 4293
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4294 4295 4296
      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);
4297 4298
        goto PARSE_OVER;
      }
4299 4300 4301 4302
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4303
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4304
          __func__, __LINE__);
4305
      goto PARSE_OVER;
4306
    }
4307

4308
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4309
    if (threads && threads->type == cJSON_Number) {
4310 4311 4312 4313 4314 4315
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4316
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4317
    } else if (!threads) {
4318
      g_queryInfo.superQueryInfo.threadCnt = 1;
4319
    }
4320

4321
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4322
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4323
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4324
    //} else if (!subTblCnt) {
4325
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4326
    //}
4327

4328
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4329 4330 4331
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4332
          MAX_TB_NAME_SIZE);
4333
    } else {
4334
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4335
          __func__, __LINE__);
4336 4337
      goto PARSE_OVER;
    }
4338

4339 4340 4341 4342 4343 4344 4345
    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;
4346
      } else {
4347
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4348
            __func__, __LINE__);
4349 4350 4351
        goto PARSE_OVER;
      }
    } else {
4352
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4353
    }
4354

4355 4356 4357 4358 4359 4360 4361 4362 4363
    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) {
4364 4365
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4366
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4367
    }
4368

4369
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4370 4371
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4372
      if (0 == strcmp("yes", subrestart->valuestring)) {
4373
        g_queryInfo.superQueryInfo.subscribeRestart = 1;
4374
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4375
        g_queryInfo.superQueryInfo.subscribeRestart = 0;
4376
      } else {
4377
        printf("ERROR: failed to read json, subscribe restart error\n");
4378 4379 4380
        goto PARSE_OVER;
      }
    } else {
4381
      g_queryInfo.superQueryInfo.subscribeRestart = 1;
4382
    }
4383

4384
    cJSON* subkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
4385
    if (subkeepProgress &&
4386 4387
            subkeepProgress->type == cJSON_String
            && subkeepProgress->valuestring != NULL) {
4388
      if (0 == strcmp("yes", subkeepProgress->valuestring)) {
4389
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4390
      } else if (0 == strcmp("no", subkeepProgress->valuestring)) {
4391
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4392
      } else {
4393
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4394 4395 4396
        goto PARSE_OVER;
      }
    } else {
4397
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4398
    }
4399

4400
    // sqls
4401
    cJSON* subsqls = cJSON_GetObjectItem(superQuery, "sqls");
4402
    if (!subsqls) {
4403
      g_queryInfo.superQueryInfo.sqlCount = 0;
4404
    } else if (subsqls->type != cJSON_Array) {
4405
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
4406
          __func__, __LINE__);
4407
      goto PARSE_OVER;
4408
    } else {
4409 4410
      int superSqlSize = cJSON_GetArraySize(subsqls);
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4411
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4412
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4413 4414
        goto PARSE_OVER;
      }
4415

4416
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4417
      for (int j = 0; j < superSqlSize; ++j) {
4418 4419
        cJSON* sql = cJSON_GetArrayItem(subsqls, j);
        if (sql == NULL) continue;
4420

4421
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4422 4423 4424
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4425
              __func__, __LINE__);
4426 4427
          goto PARSE_OVER;
        }
4428
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4429
            MAX_QUERY_SQL_LENGTH);
4430 4431

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4432 4433 4434
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
4435
              result->valuestring, MAX_FILE_NAME_LEN);
4436
        } else if (NULL == result) {
4437
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4438
        }  else {
4439
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
4440
              __func__, __LINE__);
4441
          goto PARSE_OVER;
4442
        }
4443 4444
      }
    }
H
hzcheng 已提交
4445 4446
  }

4447
  ret = true;
H
hzcheng 已提交
4448

4449
PARSE_OVER:
4450 4451
  return ret;
}
H
hzcheng 已提交
4452

4453
static bool getInfoFromJsonFile(char* file) {
4454
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4455

4456 4457 4458 4459 4460
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4461

4462
  bool  ret = false;
4463
  int   maxLen = 6400000;
4464 4465 4466 4467 4468 4469 4470
  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 已提交
4471
  }
H
Hui Li 已提交
4472

4473 4474 4475
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4476
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4477 4478
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4479

4480 4481 4482
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4483
      g_args.test_mode = INSERT_TEST;
4484
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4485
      g_args.test_mode = QUERY_TEST;
4486
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4487
      g_args.test_mode = SUBSCRIBE_TEST;
4488
    } else {
4489
      printf("ERROR: failed to read json, filetype not support\n");
4490 4491 4492
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4493
    g_args.test_mode = INSERT_TEST;
4494
  } else {
4495
    printf("ERROR: failed to read json, filetype not found\n");
4496 4497
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4498

4499
  if (INSERT_TEST == g_args.test_mode) {
4500
    ret = getMetaFromInsertJsonFile(root);
4501
  } else if ((QUERY_TEST == g_args.test_mode)
4502
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4503 4504
    ret = getMetaFromQueryJsonFile(root);
  } else {
4505
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4506
            __func__, __LINE__);
4507
    goto PARSE_OVER;
4508
  }
4509

4510
PARSE_OVER:
4511 4512
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4513
  fclose(fp);
4514 4515
  return ret;
}
H
hzcheng 已提交
4516

4517
static void prepareSampleData() {
4518
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4519 4520 4521
    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 已提交
4522
      }
4523 4524 4525 4526
    }
  }
}

4527
static void postFreeResource() {
4528
  tmfclose(g_fpOfInsertResult);
4529
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4530
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4531 4532 4533
      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 已提交
4534
      }
4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546
      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 已提交
4547
    }
4548 4549
  }
}
S
Shuaiqiang Chang 已提交
4550

4551 4552 4553
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4554
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4555
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4556
    if (0 != ret) {
4557
      tmfree(superTblInfo->sampleDataBuf);
4558
      superTblInfo->sampleDataBuf = NULL;
4559 4560
      return -1;
    }
4561
*/
4562 4563
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4564

4565
  int    dataLen = 0;
4566

4567
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4568
          "(%" PRId64 ", ", timestamp);
4569
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4570
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4571
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4572

4573
  (*sampleUsePos)++;
4574

4575 4576
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4577

4578 4579
static int64_t generateRowData(char* recBuf, int64_t timestamp, SSuperTable* stbInfo) {
  int64_t   dataLen = 0;
4580
  char  *pstr = recBuf;
4581
  int64_t maxLen = MAX_DATA_SIZE;
4582

4583
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "(%" PRId64 ",", timestamp);
4584

4585
  for (int i = 0; i < stbInfo->columnCount; i++) {
4586 4587
    if ((0 == strncasecmp(stbInfo->columns[i].dataType, "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType, "NCHAR", strlen("NCHAR")))) {
4588
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4589
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4590
                (uint32_t)TSDB_MAX_BINARY_LEN);
4591
        return -1;
4592
      }
4593

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

4640
  dataLen -= 1;
4641
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4642

4643 4644 4645
  verbosePrint("%s() LN%d, recBuf:\n\t%s\n", __func__, __LINE__, recBuf);

  return strlen(recBuf);
4646
}
S
Shuaiqiang Chang 已提交
4647

4648
static int64_t generateData(char *recBuf, char **data_type,
4649
        int num_of_cols, int64_t timestamp, int lenOfBinary) {
4650 4651
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665
  pstr += sprintf(pstr, "(%" PRId64, timestamp);
  int c = 0;

  for (; c < MAX_NUM_DATATYPE; c++) {
    if (data_type[c] == NULL) {
      break;
    }
  }

  if (0 == c) {
    perror("data type error!");
    exit(-1);
  }

H
Haojun Liao 已提交
4666
  for (int i = 0; i < c; i++) {
4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677
    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) {
4678
      double t = rand_double();
4679 4680
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4681
      bool b = taosRandom() & 1;
4682 4683
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4684 4685
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4686
      pstr += sprintf(pstr, ",\"%s\"", s);
4687
      free(s);
4688
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4689 4690
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4691
      pstr += sprintf(pstr, ",\"%s\"", s);
4692 4693 4694
      free(s);
    }

4695
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4696 4697 4698 4699 4700 4701 4702
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4705
  return (int32_t)strlen(recBuf);
4706 4707
}

4708
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4709 4710
  char* sampleDataBuf = NULL;

4711
  sampleDataBuf = calloc(
4712
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4713
  if (sampleDataBuf == NULL) {
4714
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4715 4716 4717 4718
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4719
  }
4720

4721 4722 4723 4724
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4725 4726 4727 4728 4729
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4730
  }
4731

4732 4733 4734
  return 0;
}

4735
static int64_t execInsert(threadInfo *pThreadInfo, char *buffer, uint64_t k)
4736 4737
{
  int affectedRows;
4738
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4739

4740
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
4741
            __func__, __LINE__, buffer);
4742
  if (superTblInfo) {
4743
    if (0 == strncasecmp(superTblInfo->insertMode, "taosc", strlen("taosc"))) {
4744
      affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4745
    } else if (0 == strncasecmp(superTblInfo->insertMode, "rest", strlen("rest"))) {
4746 4747
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
                  buffer, NULL /* not set result file */)) {
4748
        affectedRows = -1;
4749
        printf("========restful return fail, threadID[%d]\n",
4750
            pThreadInfo->threadID);
4751 4752 4753
      } else {
        affectedRows = k;
      }
4754 4755 4756 4757
    } else {
      errorPrint("%s() LN%d: unknown insert mode: %s\n",
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4758
    }
4759
  } else {
4760
    affectedRows = queryDbExec(pThreadInfo->taos, buffer, INSERT_TYPE, false);
4761 4762 4763 4764 4765
  }

  return affectedRows;
}

4766
static void getTableName(char *pTblName, threadInfo* pThreadInfo, uint64_t tableSeq)
4767 4768
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4769
  if (superTblInfo) {
4770
    if (superTblInfo->childTblLimit > 0) {
4771 4772 4773
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4774
    } else {
4775

4776
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRIu64" seq=%"PRIu64"\n",
4777 4778 4779 4780 4781
                pThreadInfo->threadID, __func__, __LINE__,
                pThreadInfo->start_table_from,
                pThreadInfo->ntables, tableSeq);
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName + tableSeq * TSDB_TABLE_NAME_LEN);
4782 4783
    }
  } else {
4784
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4785
        g_args.tb_prefix, tableSeq);
4786 4787 4788
  }
}

4789
static int64_t generateDataTail(
4790
        SSuperTable* superTblInfo,
4791
        uint64_t batch, char* buffer, int64_t remainderBufLen, int64_t insertRows,
4792
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos, int64_t *dataLen) {
4793 4794
  uint64_t len = 0;
  uint32_t ncols_per_record = 1; // count first col ts
4795

4796 4797
  char *pstr = buffer;

4798
  if (superTblInfo == NULL) {
4799
    uint32_t datatypeSeq = 0;
4800
    while(g_args.datatype[datatypeSeq]) {
4801 4802
        datatypeSeq ++;
        ncols_per_record ++;
4803
    }
4804 4805
  }

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

4808
  uint64_t k = 0;
4809
  for (k = 0; k < batch;) {
4810
    char data[MAX_DATA_SIZE];
4811 4812
    memset(data, 0, MAX_DATA_SIZE);

4813
    int64_t retLen = 0;
4814

4815 4816
    if (superTblInfo) {
      if (0 == strncasecmp(superTblInfo->dataSource,
4817 4818 4819 4820 4821 4822 4823
                    "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
                    data,
                    remainderBufLen,
                    startTime + superTblInfo->timeStampStep * k,
                    superTblInfo,
                    pSamplePos);
4824
      } else if (0 == strncasecmp(superTblInfo->dataSource,
4825
                   "rand", strlen("rand"))) {
4826

4827
        int64_t randTail = superTblInfo->timeStampStep * k;
4828 4829 4830 4831
        if (superTblInfo->disorderRatio > 0) {
          int rand_num = taosRandom() % 100;
          if(rand_num < superTblInfo->disorderRatio) {
            randTail = (randTail + (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
4832
            debugPrint("rand data generated, back %"PRId64"\n", randTail);
4833
          }
4834 4835
        }

4836
        int64_t d = startTime
4837
                + randTail;
4838
        retLen = generateRowData(
4839 4840 4841
                      data,
                      d,
                      superTblInfo);
4842
      }
4843

4844 4845 4846
      if (retLen > remainderBufLen) {
        break;
      }
4847

4848
      pstr += snprintf(pstr , retLen + 1, "%s", data);
4849 4850 4851
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4852
    } else {
4853 4854
      char **data_type = g_args.datatype;
      int lenOfBinary = g_args.len_of_binary;
4855

4856 4857 4858 4859 4860 4861
      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);
4862

4863 4864
          debugPrint("rand data generated, back %"PRId64"\n", randTail);
        }
4865
      } else {
4866 4867 4868 4869
        randTail = DEFAULT_TIMESTAMP_STEP * k;
      }

      retLen = generateData(data, data_type,
4870 4871 4872
                  ncols_per_record,
                  startTime + randTail,
                  lenOfBinary);
4873

4874 4875 4876
      if (len > remainderBufLen)
        break;

H
Haojun Liao 已提交
4877
      pstr += sprintf(pstr, "%s", data);
4878 4879 4880
      k++;
      len += retLen;
      remainderBufLen -= retLen;
4881 4882
    }

4883
    verbosePrint("%s() LN%d len=%"PRIu64" k=%"PRIu64" \nbuffer=%s\n",
4884
            __func__, __LINE__, len, k, buffer);
4885 4886

    startFrom ++;
4887

4888
    if (startFrom >= insertRows) {
4889
      break;
4890
    }
4891
  }
4892

4893 4894 4895
  *dataLen = len;
  return k;
}
4896

4897
static int generateSQLHead(char *tableName, int32_t tableSeq,
4898 4899
        threadInfo* pThreadInfo, SSuperTable* superTblInfo,
        char *buffer, int remainderBufLen)
4900 4901
{
  int len;
4902 4903 4904 4905

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

4906 4907 4908 4909
  if (superTblInfo) {
    if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
4910
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
4911
      } else {
4912 4913 4914
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
4915 4916
      }
      if (NULL == tagsValBuf) {
4917
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
4918
            __func__, __LINE__);
4919 4920 4921
        return -1;
      }

4922 4923
      len = snprintf(
          headBuf,
4924 4925 4926 4927 4928 4929 4930
                  HEAD_BUFF_LEN,
                  "%s.%s using %s.%s tags %s values",
                  pThreadInfo->db_name,
                  tableName,
                  pThreadInfo->db_name,
                  superTblInfo->sTblName,
                  tagsValBuf);
4931 4932
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
4933 4934
      len = snprintf(
          headBuf,
4935 4936 4937 4938
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4939
    } else {
4940 4941
      len = snprintf(
          headBuf,
4942 4943 4944 4945
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4946 4947
    }
  } else {
4948 4949 4950 4951 4952 4953
      len = snprintf(
          headBuf,
                  HEAD_BUFF_LEN,
                  "%s.%s values",
                  pThreadInfo->db_name,
                  tableName);
4954 4955
  }

4956 4957 4958 4959 4960
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

4961 4962 4963
  return len;
}

4964
static int64_t generateInterlaceDataBuffer(
4965 4966
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
4967
        threadInfo *pThreadInfo, char *buffer,
4968
        uint64_t insertRows,
4969
        int64_t startTime,
4970
        uint64_t *pRemainderBufLen)
4971
{
4972
  assert(buffer);
4973 4974 4975 4976
  char *pstr = buffer;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int headLen = generateSQLHead(tableName, tableSeq, pThreadInfo,
4977
            superTblInfo, pstr, *pRemainderBufLen);
4978 4979 4980 4981 4982

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
4983
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
4984
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
4985 4986 4987 4988

  pstr += headLen;
  *pRemainderBufLen -= headLen;

4989
  int64_t dataLen = 0;
4990

4991
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
4992 4993
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
4994 4995 4996 4997 4998 4999

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

5003
  int64_t k = generateDataTail(
5004 5005 5006 5007
    superTblInfo,
    batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
    startTime,
    &(pThreadInfo->samplePos), &dataLen);
5008

5009
  if (k == batchPerTbl) {
5010 5011 5012
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5013
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
5014
            __func__, __LINE__, k, batchPerTbl);
5015 5016
    pstr -= headLen;
    pstr[0] = '\0';
5017
    k = 0;
5018 5019 5020 5021 5022
  }

  return k;
}

5023
static int64_t generateProgressiveDataBuffer(
5024
        char *tableName,
5025
        int64_t tableSeq,
5026 5027
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
5028 5029
        int64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
5030 5031 5032 5033 5034 5035 5036 5037
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;

  int ncols_per_record = 1; // count first col ts

  if (superTblInfo == NULL) {
    int datatypeSeq = 0;
    while(g_args.datatype[datatypeSeq]) {
5038 5039
        datatypeSeq ++;
        ncols_per_record ++;
5040 5041 5042 5043
    }
  }

  assert(buffer != NULL);
5044
  char *pstr = buffer;
5045

5046
  int64_t k = 0;
5047

5048
  memset(buffer, 0, *pRemainderBufLen);
5049

5050
  int64_t headLen = generateSQLHead(tableName, tableSeq, pThreadInfo, superTblInfo,
5051
          buffer, *pRemainderBufLen);
5052 5053 5054 5055

  if (headLen <= 0) {
    return 0;
  }
5056
  pstr += headLen;
5057
  *pRemainderBufLen -= headLen;
5058

5059
  int64_t dataLen;
5060
  k = generateDataTail(superTblInfo,
5061 5062 5063
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
          startTime,
          pSamplePos, &dataLen);
5064

5065 5066
  return k;
}
5067

5068 5069 5070 5071 5072 5073 5074 5075 5076
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)));
}

5077
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5078
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5079 5080
         pThreadInfo->threadID, __func__, __LINE__);

5081 5082
  uint64_t insertRows;
  uint64_t interlaceRows;
5083 5084

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5085

5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098
  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;
  }
5099

5100
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5101
    interlaceRows = insertRows;
5102

5103 5104
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5105

5106 5107 5108 5109 5110 5111 5112 5113 5114 5115
  int insertMode;

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

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

5117
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5118
  char* buffer = calloc(maxSqlLen, 1);
5119
  if (NULL == buffer) {
5120
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5121
              __func__, __LINE__, maxSqlLen, strerror(errno));
5122 5123 5124
    return NULL;
  }

5125
  char tableName[TSDB_TABLE_NAME_LEN];
5126 5127 5128 5129

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

5130
  int64_t nTimeStampStep = superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5131

5132
  uint64_t insert_interval =
5133
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5134 5135
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5136

5137 5138 5139
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5140

5141
  uint64_t tableSeq = pThreadInfo->start_table_from;
5142

5143
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRIu64" insertRows=%"PRIu64"\n",
5144 5145
          pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);
5146 5147 5148

  int64_t startTime = pThreadInfo->start_time;

5149 5150
  assert(pThreadInfo->ntables > 0);

5151 5152
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5153

5154
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
5155
    batchPerTblTimes =
5156
        g_args.num_of_RPR / interlaceRows;
5157 5158 5159 5160
  } else {
    batchPerTblTimes = 1;
  }

5161
  uint64_t generatedRecPerTbl = 0;
5162
  bool flagSleep = true;
5163
  uint64_t sleepTimeTotal = 0;
5164

5165 5166 5167
  char *strInsertInto = "insert into ";
  int nInsertBufLen = strlen(strInsertInto);

5168
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5169
    if ((flagSleep) && (insert_interval)) {
5170 5171
        st = taosGetTimestampMs();
        flagSleep = false;
5172 5173
    }
    // generate data
5174
    memset(buffer, 0, maxSqlLen);
5175
    uint64_t remainderBufLen = maxSqlLen;
5176

5177
    char *pstr = buffer;
5178 5179 5180 5181 5182

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

5183
    uint64_t recOfBatch = 0;
5184

5185
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5186
      getTableName(tableName, pThreadInfo, tableSeq);
5187 5188
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5189
            pThreadInfo->threadID, __func__, __LINE__);
5190
        free(buffer);
5191 5192
        return NULL;
      }
5193

5194
      uint64_t oldRemainderLen = remainderBufLen;
5195
      int64_t generated = generateInterlaceDataBuffer(
5196 5197 5198 5199 5200 5201
        tableName, batchPerTbl, i, batchPerTblTimes,
        tableSeq,
        pThreadInfo, pstr,
        insertRows,
        startTime,
        &remainderBufLen);
5202

5203 5204
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5205
      if (generated < 0) {
5206
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5207
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5208
        goto free_of_interlace;
5209 5210
      } else if (generated == 0) {
        break;
5211 5212
      }

5213
      tableSeq ++;
5214
      recOfBatch += batchPerTbl;
5215
      pstr += (oldRemainderLen - remainderBufLen);
5216
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5217
      pThreadInfo->totalInsertRows += batchPerTbl;
5218
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5219 5220
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5221

5222
      if (insertMode == INTERLACE_INSERT_MODE) {
5223 5224 5225 5226
          if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5227

5228 5229
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5230

5231 5232 5233
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5234

5235 5236 5237
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5238

5239 5240 5241 5242
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
          }
      }
5243

5244
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5245 5246
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5247 5248

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5249 5250 5251
        break;
    }

5252
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5253 5254
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5255
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
5256
           pThreadInfo->threadID, __func__, __LINE__, buffer);
5257

5258
    startTs = taosGetTimestampMs();
5259

5260 5261 5262 5263 5264 5265 5266
    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;
    }
5267
    int64_t affectedRows = execInsert(pThreadInfo, buffer, recOfBatch);
5268

5269
    endTs = taosGetTimestampMs();
5270 5271
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5272
            __func__, __LINE__, delay);
5273 5274 5275
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5276 5277 5278 5279 5280 5281

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

5282 5283
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5284 5285
                pThreadInfo->threadID, __func__, __LINE__,
                recOfBatch, affectedRows, buffer);
5286
        goto free_of_interlace;
5287
    }
5288

5289
    pThreadInfo->totalAffectedRows += affectedRows;
5290

5291 5292
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5293
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5294 5295 5296
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5297 5298
      lastPrintTime = currentPrintTime;
    }
5299

5300
    if ((insert_interval) && flagSleep) {
5301
      et = taosGetTimestampMs();
5302

5303 5304
      if (insert_interval > (et - st) ) {
        int sleepTime = insert_interval - (et -st);
5305
        performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
5306
                    __func__, __LINE__, sleepTime);
5307 5308 5309
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5310
    }
5311 5312
  }

5313
free_of_interlace:
5314
  tmfree(buffer);
5315
  printStatPerThread(pThreadInfo);
5316 5317 5318
  return NULL;
}

5319 5320 5321 5322 5323 5324 5325 5326
// 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
*/
5327
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5328
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5329

5330
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5331
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5332

5333
  char* buffer = calloc(maxSqlLen, 1);
5334
  if (NULL == buffer) {
5335
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5336 5337
              maxSqlLen,
              strerror(errno));
5338 5339
    return NULL;
  }
5340

5341 5342 5343
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5344

5345
  int64_t timeStampStep =
5346
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
5347
/*  int insert_interval =
5348
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5349 5350
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5351
  */
5352

5353 5354
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5355

5356
  pThreadInfo->samplePos = 0;
5357

5358
  for (uint64_t tableSeq =
5359 5360
          pThreadInfo->start_table_from; tableSeq <= pThreadInfo->end_table_to;
        tableSeq ++) {
5361
    int64_t start_time = pThreadInfo->start_time;
5362

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

5366
    for (uint64_t i = 0; i < insertRows;) {
5367 5368 5369 5370 5371
        /*
      if (insert_interval) {
            st = taosGetTimestampMs();
      }
      */
5372

5373 5374
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5375
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5376 5377
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5378

5379
      int64_t remainderBufLen = maxSqlLen;
5380 5381 5382 5383 5384 5385 5386 5387
      char *pstr = buffer;
      int nInsertBufLen = strlen("insert into ");

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

      pstr += len;
      remainderBufLen -= len;

5388
      int64_t generated = generateProgressiveDataBuffer(
5389 5390 5391 5392
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5393 5394 5395
      if (generated > 0)
        i += generated;
      else
5396
        goto free_of_progressive;
5397

5398
      start_time +=  generated * timeStampStep;
5399
      pThreadInfo->totalInsertRows += generated;
5400

5401
      startTs = taosGetTimestampMs();
5402

5403
      int64_t affectedRows = execInsert(pThreadInfo, buffer, generated);
5404

5405
      endTs = taosGetTimestampMs();
5406
      uint64_t delay = endTs - startTs;
5407
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5408
              __func__, __LINE__, delay);
5409 5410 5411
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5412

5413 5414 5415 5416
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5417

5418 5419 5420 5421 5422
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5423 5424 5425

      pThreadInfo->totalAffectedRows += affectedRows;

5426 5427
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5428
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5429 5430 5431
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5432 5433 5434
        lastPrintTime = currentPrintTime;
      }

5435
      if (i >= insertRows)
5436
        break;
5437
/*
5438
      if (insert_interval) {
5439
        et = taosGetTimestampMs();
5440

5441 5442
        if (insert_interval > ((et - st)) ) {
            int sleep_time = insert_interval - (et -st);
5443 5444
            performancePrint("%s() LN%d sleep: %d ms for insert interval\n",
                    __func__, __LINE__, sleep_time);
5445 5446
            taosMsleep(sleep_time); // ms
        }
5447
      }
5448
      */
5449 5450
    }   // num_of_DPT

5451 5452
    if (g_args.verbose_print) {
      if ((tableSeq == pThreadInfo->ntables - 1) && superTblInfo &&
5453 5454
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5455
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5456
                  __func__, __LINE__, pThreadInfo->samplePos);
5457
      }
5458
    }
5459
  } // tableSeq
5460

5461
free_of_progressive:
5462
  tmfree(buffer);
5463
  printStatPerThread(pThreadInfo);
5464
  return NULL;
H
Hui Li 已提交
5465 5466
}

5467 5468
static void* syncWrite(void *sarg) {

5469 5470
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5471

5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483
  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;
  }
5484

5485
  if (interlaceRows > 0) {
5486
    // interlace mode
5487
    return syncWriteInterlace(pThreadInfo);
5488 5489
  } else {
    // progressive mode
5490
    return syncWriteProgressive(pThreadInfo);
5491
  }
5492

5493 5494
}

5495
static void callBack(void *param, TAOS_RES *res, int code) {
5496 5497
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5498

5499 5500
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5501
  if (insert_interval) {
5502 5503 5504
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5505
    }
H
Hui Li 已提交
5506
  }
5507

5508
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5509
  char data[MAX_DATA_SIZE];
5510
  char *pstr = buffer;
5511 5512
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5513
          pThreadInfo->start_table_from);
5514 5515 5516 5517 5518 5519 5520
//  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);
5521 5522 5523 5524
    free(buffer);
    taos_free_result(res);
    return;
  }
5525

5526
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5527
    int rand_num = taosRandom() % 100;
5528
    if (0 != pThreadInfo->superTblInfo->disorderRatio
5529
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5530 5531
      int64_t d = pThreadInfo->lastTs - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateRowData(data, d, pThreadInfo->superTblInfo);
5532
    } else {
5533
      generateRowData(data, pThreadInfo->lastTs += 1000, pThreadInfo->superTblInfo);
H
Hui Li 已提交
5534
    }
5535
    pstr += sprintf(pstr, "%s", data);
5536
    pThreadInfo->counter++;
H
Hui Li 已提交
5537

5538
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5539
      break;
H
Hui Li 已提交
5540 5541
    }
  }
5542

5543
  if (insert_interval) {
5544
    pThreadInfo->st = taosGetTimestampMs();
5545
  }
5546
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5547
  free(buffer);
H
Hui Li 已提交
5548

5549
  taos_free_result(res);
H
Hui Li 已提交
5550 5551
}

5552
static void *asyncWrite(void *sarg) {
5553 5554
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5555

5556 5557 5558
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5559

5560
  int insert_interval =
5561
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5562
  if (insert_interval) {
5563
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5564
  }
5565
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5566

5567
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5568 5569 5570 5571

  return NULL;
}

5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597
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;
}

5598
static void startMultiThreadInsertData(int threads, char* db_name,
5599
        char* precision,SSuperTable* superTblInfo) {
5600

5601 5602
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);
H
Hui Li 已提交
5603

5604 5605
  threadInfo *infos = malloc(threads * sizeof(threadInfo));
  assert(infos != NULL);
5606

5607 5608
  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));
5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 5624 5625

  //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 {
5626
      errorPrint("Not support precision: %s\n", precision);
5627 5628 5629 5630
      exit(-1);
    }
  }

5631
  int64_t start_time;
5632 5633
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5634
        start_time = taosGetTimestamp(timePrec);
5635
    } else {
5636
      if (TSDB_CODE_SUCCESS != taosParseTime(
5637 5638 5639 5640 5641
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5642
      }
5643
    }
5644
  } else {
5645
     start_time = 1500000000000;
5646 5647
  }

5648
  int64_t start = taosGetTimestampMs();
5649

5650
  // read sample data from file first
5651
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5652
              "sample", strlen("sample")))) {
5653
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5654
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5655
              __func__, __LINE__);
5656 5657 5658 5659
      exit(-1);
    }
  }

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

  TAOS* taos = taos_connect(
5671 5672
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5673
  if (NULL == taos) {
5674
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5675
                __func__, __LINE__, taos_errstr(NULL));
5676 5677 5678
    exit(-1);
  }

5679 5680
  int ntables = 0;
  int startFrom;
5681

5682
  if (superTblInfo) {
5683 5684
    int64_t limit;
    uint64_t offset;
5685

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

5691
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5692 5693
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5694
            > (superTblInfo->childTblCount))) {
5695 5696 5697 5698 5699 5700
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5701
    } else {
5702 5703
      limit = superTblInfo->childTblCount;
      offset = 0;
5704 5705
    }

5706 5707 5708
    ntables = limit;
    startFrom = offset;

5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719
    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)
5720
            && (0 == superTblInfo->childTblLimit)) {
5721 5722 5723 5724 5725 5726 5727
      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();
      }
    }

5728
    superTblInfo->childTblName = (char*)calloc(1,
5729
        limit * TSDB_TABLE_NAME_LEN);
5730
    if (superTblInfo->childTblName == NULL) {
5731
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5732 5733 5734 5735
      taos_close(taos);
      exit(-1);
    }

5736
    uint64_t childTblCount;
5737 5738 5739 5740 5741 5742
    getChildNameOfSuperTableWithLimitAndOffset(
        taos,
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5743 5744 5745
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5746
  }
5747

5748 5749
  taos_close(taos);

5750
  uint64_t a = ntables / threads;
5751 5752 5753 5754 5755
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

5756
  uint64_t b = 0;
5757 5758 5759 5760
  if (threads != 0) {
    b = ntables % threads;
  }

5761 5762 5763 5764 5765 5766
  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 已提交
5767
  for (int i = 0; i < threads; i++) {
5768
    threadInfo *t_info = infos + i;
H
Hui Li 已提交
5769 5770
    t_info->threadID = i;
    tstrncpy(t_info->db_name, db_name, MAX_DB_NAME_SIZE);
5771
    t_info->time_precision = timePrec;
5772 5773 5774
    t_info->superTblInfo = superTblInfo;

    t_info->start_time = start_time;
5775
    t_info->minDelay = UINT64_MAX;
5776

5777
    if ((NULL == superTblInfo) ||
5778
            (0 == strncasecmp(superTblInfo->insertMode, "taosc", 5))) {
5779
      //t_info->taos = taos;
5780
      t_info->taos = taos_connect(
5781 5782
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5783
      if (NULL == t_info->taos) {
5784
        errorPrint(
5785 5786
                "connect to server fail from insert sub thread, reason: %s\n",
                taos_errstr(NULL));
5787 5788 5789 5790 5791 5792
        exit(-1);
      }
    } else {
      t_info->taos = NULL;
    }

5793
/*    if ((NULL == superTblInfo)
5794
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
5795
            */
5796 5797 5798 5799
      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;
5800
/*    } else {
5801 5802
      t_info->start_table_from = 0;
      t_info->ntables = superTblInfo->childTblCount;
5803 5804
      t_info->start_time = t_info->start_time + rand_int() % 10000 - rand_tinyint();
    }
5805
*/
5806
    tsem_init(&(t_info->lock_sem), 0, 0);
5807
    if (ASYNC_MODE == g_Dbs.asyncMode) {
5808
      pthread_create(pids + i, NULL, asyncWrite, t_info);
5809 5810
    } else {
      pthread_create(pids + i, NULL, syncWrite, t_info);
5811
    }
H
Hui Li 已提交
5812
  }
5813

H
Hui Li 已提交
5814 5815 5816 5817
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

5818 5819 5820 5821
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
5822 5823
  double  avgDelay = 0;

H
Hui Li 已提交
5824
  for (int i = 0; i < threads; i++) {
5825 5826
    threadInfo *t_info = infos + i;

S
TD-1057  
Shengliang Guan 已提交
5827
    tsem_destroy(&(t_info->lock_sem));
5828 5829
    taos_close(t_info->taos);

5830
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
5831 5832 5833
            __func__, __LINE__,
            t_info->threadID, t_info->totalInsertRows,
            t_info->totalAffectedRows);
5834
    if (superTblInfo) {
5835 5836
        superTblInfo->totalAffectedRows += t_info->totalAffectedRows;
        superTblInfo->totalInsertRows += t_info->totalInsertRows;
5837
    } else {
5838 5839
        g_args.totalAffectedRows += t_info->totalAffectedRows;
        g_args.totalInsertRows += t_info->totalInsertRows;
5840
    }
5841 5842 5843 5844

    totalDelay  += t_info->totalDelay;
    cntDelay   += t_info->cntDelay;
    if (t_info->maxDelay > maxDelay) maxDelay = t_info->maxDelay;
5845
    if (t_info->minDelay < minDelay) minDelay = t_info->minDelay;
H
Hui Li 已提交
5846
  }
5847
  cntDelay -= 1;
H
Hui Li 已提交
5848

5849
  if (cntDelay == 0)    cntDelay = 1;
5850 5851
  avgDelay = (double)totalDelay / cntDelay;

5852 5853
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
5854 5855

  if (superTblInfo) {
5856
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
5857 5858 5859 5860
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5861 5862 5863 5864

    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",
5865 5866 5867 5868
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
5869
    }
5870
  } else {
5871
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
5872 5873 5874 5875
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5876 5877 5878
    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",
5879 5880 5881 5882
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
5883
    }
5884
  }
5885

5886
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5887
          avgDelay, maxDelay, minDelay);
5888 5889
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
5890
          avgDelay, maxDelay, minDelay);
5891
  }
5892

5893 5894
  //taos_close(taos);

H
Hui Li 已提交
5895
  free(pids);
5896
  free(infos);
H
Hui Li 已提交
5897 5898
}

5899
static void *readTable(void *sarg) {
5900
#if 1
5901
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5902 5903
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
5904
  uint64_t sTime = rinfo->start_time;
H
hzcheng 已提交
5905 5906
  char *tb_prefix = rinfo->tb_prefix;
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5907
  if (NULL == fp) {
5908
    errorPrint( "fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
H
Hui Li 已提交
5909 5910
    return NULL;
  }
5911

5912
    int num_of_DPT;
5913
/*  if (rinfo->superTblInfo) {
5914 5915
    num_of_DPT = rinfo->superTblInfo->insertRows; //  nrecords_per_table;
  } else {
5916
  */
5917
      num_of_DPT = g_args.num_of_DPT;
5918
//  }
5919

5920
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5921
  int totalData = num_of_DPT * num_of_tables;
5922
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5923 5924 5925 5926 5927 5928 5929 5930

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

5931
  for (uint64_t j = 0; j < n; j++) {
H
hzcheng 已提交
5932
    double totalT = 0;
5933 5934 5935
    uint64_t count = 0;
    for (uint64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRIu64" where ts>= %" PRIu64,
5936
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
5937

5938
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
5939 5940
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
5941

S
Shuaiqiang Chang 已提交
5942
      if (code != 0) {
5943
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
5944
        taos_free_result(pSql);
H
hzcheng 已提交
5945
        taos_close(taos);
5946
        fclose(fp);
5947
        return NULL;
H
hzcheng 已提交
5948 5949
      }

5950
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
5951 5952 5953
        count++;
      }

5954
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
5955 5956
      totalT += t;

S
Shuaiqiang Chang 已提交
5957
      taos_free_result(pSql);
H
hzcheng 已提交
5958 5959 5960
    }

    fprintf(fp, "|%10s  |   %10d   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
5961
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
5962
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
5963
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
5964 5965 5966
  }
  fprintf(fp, "\n");
  fclose(fp);
5967
#endif
H
hzcheng 已提交
5968 5969 5970
  return NULL;
}

5971
static void *readMetric(void *sarg) {
5972
#if 1
5973
  threadInfo *rinfo = (threadInfo *)sarg;
H
hzcheng 已提交
5974 5975 5976
  TAOS *taos = rinfo->taos;
  char command[BUFFER_SIZE] = "\0";
  FILE *fp = fopen(rinfo->fp, "a");
H
Hui Li 已提交
5977 5978 5979 5980
  if (NULL == fp) {
    printf("fopen %s fail, reason:%s.\n", rinfo->fp, strerror(errno));
    return NULL;
  }
5981 5982

  int num_of_DPT = rinfo->superTblInfo->insertRows;
5983
  int num_of_tables = rinfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
H
hzcheng 已提交
5984
  int totalData = num_of_DPT * num_of_tables;
5985
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
5986 5987 5988 5989 5990 5991 5992 5993 5994

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

  for (int j = 0; j < n; j++) {
5995
    char condition[COND_BUF_LEN] = "\0";
B
Bomin Zhang 已提交
5996
    char tempS[64] = "\0";
H
hzcheng 已提交
5997 5998 5999 6000 6001

    int m = 10 < num_of_tables ? 10 : num_of_tables;

    for (int i = 1; i <= m; i++) {
      if (i == 1) {
6002
        sprintf(tempS, "t1 = %d", i);
H
hzcheng 已提交
6003
      } else {
6004
        sprintf(tempS, " or t1 = %d ", i);
H
hzcheng 已提交
6005
      }
6006
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6007

L
liu0x54 已提交
6008
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6009 6010 6011 6012

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

6013
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6014

S
Shuaiqiang Chang 已提交
6015 6016 6017 6018
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6019
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6020
        taos_free_result(pSql);
H
hzcheng 已提交
6021
        taos_close(taos);
6022
        fclose(fp);
6023
        return NULL;
H
hzcheng 已提交
6024 6025
      }
      int count = 0;
6026
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6027 6028
        count++;
      }
6029
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6030

6031
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6032 6033
              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 已提交
6034

S
Shuaiqiang Chang 已提交
6035
      taos_free_result(pSql);
H
hzcheng 已提交
6036 6037 6038 6039
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6040
#endif
H
hzcheng 已提交
6041 6042 6043
  return NULL;
}

H
Hui Li 已提交
6044

6045
static int insertTestProcess() {
6046

6047 6048 6049
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6050

6051 6052 6053
  if (ret == -1)
    exit(EXIT_FAILURE);

6054
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6055 6056
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6057
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6058 6059
    return -1;
  }
6060

6061 6062
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6063

6064 6065 6066 6067
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6068

6069 6070 6071
  init_rand_data();

  // create database and super tables
6072
  if(createDatabasesAndStables() != 0) {
6073 6074
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6075 6076
    return -1;
  }
6077 6078

  // pretreatement
6079
  prepareSampleData();
6080

6081 6082 6083 6084
  double start;
  double end;

  // create child tables
6085
  start = taosGetTimestampMs();
6086
  createChildTables();
6087
  end = taosGetTimestampMs();
6088

6089
  if (g_totalChildTables > 0) {
6090
    fprintf(stderr, "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6091
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6092 6093
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6094
            "Spent %.4f seconds to create %d tables with %d thread(s)\n\n",
6095
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6096
    }
6097
  }
6098

6099
  taosMsleep(1000);
6100
  // create sub threads for inserting data
6101
  //start = taosGetTimestampMs();
6102
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6103 6104 6105 6106 6107 6108 6109 6110
    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(
6111 6112 6113 6114
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6115
          }
6116
        }
6117
      }
6118
    } else {
6119
        startMultiThreadInsertData(
6120 6121 6122
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6123
          NULL);
H
Hui Li 已提交
6124
    }
6125
  }
6126
  //end = taosGetTimestampMs();
6127

6128
  //int64_t    totalInsertRows = 0;
6129
  //int64_t    totalAffectedRows = 0;
6130
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6131
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6132
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6133 6134
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6135
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6136
  postFreeResource();
6137

6138 6139 6140
  return 0;
}

6141 6142
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6143

6144
  if (pThreadInfo->taos == NULL) {
6145 6146
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6147 6148 6149 6150
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6151 6152
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6153
            pThreadInfo->threadID, taos_errstr(NULL));
6154 6155
      return NULL;
    } else {
6156
      pThreadInfo->taos = taos;
6157 6158 6159
    }
  }

6160 6161
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6162 6163
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6164 6165 6166 6167
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6168

6169 6170
  uint64_t st = 0;
  uint64_t et = 0;
6171

6172
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6173

6174 6175 6176
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6177

6178
  while(queryTimes --) {
6179
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6180
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6181
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6182 6183
    }

6184 6185
    char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
    if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6186
        sprintf(tmpFile, "%s-%d",
6187 6188
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
6189 6190 6191 6192 6193
    }

    st = taosGetTimestampMs();

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

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

6200 6201
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6202

6203 6204
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6205
    if (currentPrintTime - lastPrintTime > 30*1000) {
6206
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6207
          __func__, __LINE__, endTs, startTs);
6208
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6209 6210
                    pThreadInfo->threadID,
                    totalQueried,
6211
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6212
      lastPrintTime = currentPrintTime;
6213
    }
H
Hui Li 已提交
6214
  }
6215 6216
  return NULL;
}
H
Hui Li 已提交
6217

6218
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6219 6220
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6221 6222
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6223
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6224 6225

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

6227 6228
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6229
    return;
H
Hui Li 已提交
6230
  }
6231

6232
  tstrncpy(outSql, inSql, pos - inSql + 1);
6233
  //printf("1: %s\n", outSql);
6234
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6235
  //printf("2: %s\n", outSql);
6236
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6237
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6238 6239
}

6240
static void *superTableQuery(void *sarg) {
6241
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6242
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6243

6244
  if (pThreadInfo->taos == NULL) {
6245 6246 6247 6248 6249 6250 6251 6252
    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",
6253
            pThreadInfo->threadID, taos_errstr(NULL));
6254 6255
      return NULL;
    } else {
6256
      pThreadInfo->taos = taos;
6257 6258 6259
    }
  }

6260 6261
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6262

6263 6264 6265
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6266

6267
  uint64_t  lastPrintTime = taosGetTimestampMs();
6268
  while(queryTimes --) {
6269 6270 6271
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6272
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6273
    }
H
Hui Li 已提交
6274

6275
    st = taosGetTimestampMs();
6276
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6277
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6278
        memset(sqlstr,0,sizeof(sqlstr));
6279
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6280
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6281
        if (g_queryInfo.superQueryInfo.result[j][0] != 0) {
6282
          sprintf(tmpFile, "%s-%d",
6283
                  g_queryInfo.superQueryInfo.result[j],
6284
                  pThreadInfo->threadID);
6285
        }
6286
        selectAndGetResult(pThreadInfo, sqlstr, tmpFile);
6287 6288 6289 6290 6291 6292 6293

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6294
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6295 6296
                    pThreadInfo->threadID,
                    totalQueried,
6297
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6298
          lastPrintTime = currentPrintTime;
6299
        }
6300
      }
H
Hui Li 已提交
6301
    }
6302
    et = taosGetTimestampMs();
6303
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6304
            taosGetSelfPthreadId(),
6305 6306
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6307
            (double)(et - st)/1000.0);
6308
  }
6309

6310 6311 6312
  return NULL;
}

6313
static int queryTestProcess() {
6314 6315 6316 6317

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6318 6319 6320 6321 6322 6323

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6324
          g_queryInfo.port);
6325
  if (taos == NULL) {
6326 6327
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6328 6329 6330
    exit(-1);
  }

6331
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6332 6333
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6334 6335 6336
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6337
  }
6338

6339 6340 6341 6342
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
    (void)getchar();
  }
6343

6344
  printfQuerySystemInfo(taos);
6345

6346 6347 6348 6349 6350 6351
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6352 6353 6354
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6355 6356
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
  int nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6357

6358
  uint64_t startTs = taosGetTimestampMs();
6359

6360 6361 6362 6363 6364 6365
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6366
      taos_close(taos);
6367
      ERROR_EXIT("memory allocation failed for create threads\n");
6368
    }
6369

6370 6371 6372 6373 6374
    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;
6375

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

6378 6379 6380 6381
          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)) {
6382
            taos_close(taos);
6383 6384
            free(infos);
            free(pids);
6385 6386 6387
            errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
            return -1;
6388
          }
6389
        }
6390

6391
        t_info->taos = NULL;// TODO: workaround to use separate taos connection;
6392

6393
        pthread_create(pids + i * nSqlCount + j, NULL, specifiedTableQuery,
6394 6395
            t_info);
      }
6396
    }
6397
  } else {
6398
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6399
  }
6400

6401 6402
  taos_close(taos);

6403 6404 6405
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6406 6407 6408 6409
  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));
6410 6411

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6412 6413
      free(infos);
      free(pids);
6414

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

6418
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6419
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6420

6421
    uint64_t a = ntables / threads;
6422 6423 6424 6425
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6426

6427
    uint64_t b = 0;
6428 6429 6430
    if (threads != 0) {
      b = ntables % threads;
    }
6431

6432
    uint64_t startFrom = 0;
6433
    for (int i = 0; i < threads; i++) {
6434 6435
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6436

6437 6438 6439 6440
      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;
6441
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6442
      pthread_create(pidsOfSub + i, NULL, superTableQuery, t_info);
6443 6444
    }

6445
    g_queryInfo.superQueryInfo.threadCnt = threads;
6446
  } else {
6447
    g_queryInfo.superQueryInfo.threadCnt = 0;
6448
  }
6449

6450 6451 6452 6453 6454 6455
  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);
      }
    }
6456
  }
S
Shuaiqiang Chang 已提交
6457

6458
  tmfree((char*)pids);
6459
  tmfree((char*)infos);
6460

6461
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6462
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6463
  }
H
Hui Li 已提交
6464

6465
  tmfree((char*)pidsOfSub);
6466
  tmfree((char*)infosOfSub);
6467

6468
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6469
  uint64_t endTs = taosGetTimestampMs();
6470

6471
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6472 6473
    g_queryInfo.superQueryInfo.totalQueried;

6474
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6475
          totalQueried,
6476
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6477 6478 6479
  return 0;
}

6480
static void subscribe_callback(TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6481
  if (res == NULL || taos_errno(res) != 0) {
6482 6483
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6484 6485
    return;
  }
6486

6487
  appendResultToFile(res, (char*)param);
6488
  // tao_unscribe() will free result.
H
hzcheng 已提交
6489 6490
}

6491 6492
static TAOS_SUB* subscribeImpl(
        TAOS *taos, char *sql, char* topic, char* resultFileName) {
6493
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6494

6495
  if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6496
    tsub = taos_subscribe(taos,
6497
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6498
            topic, sql, subscribe_callback, (void*)resultFileName,
6499
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6500
  } else {
6501
    tsub = taos_subscribe(taos,
6502
            g_queryInfo.specifiedQueryInfo.subscribeRestart,
6503
            topic, sql, NULL, NULL, 0);
6504
  }
6505

6506 6507 6508
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6509
  }
6510

6511 6512
  return tsub;
}
H
hzcheng 已提交
6513

6514 6515
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6516
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
6517
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6518

6519 6520 6521
  if (g_queryInfo.superQueryInfo.sqlCount == 0)
    return NULL;

6522
  if (pThreadInfo->taos == NULL) {
6523 6524 6525 6526 6527 6528 6529 6530
    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",
6531
            pThreadInfo->threadID, taos_errstr(NULL));
6532 6533
      return NULL;
    } else {
6534
      pThreadInfo->taos = taos;
6535 6536 6537
    }
  }

6538 6539
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6540 6541
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6542 6543
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6544 6545
    return NULL;
  }
6546

6547 6548 6549
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6550 6551
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6552
    //  //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6553 6554 6555 6556
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6557
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6558 6559
      sprintf(topic, "taosdemo-subscribe-%d", i);
      memset(subSqlstr,0,sizeof(subSqlstr));
6560
      replaceChildTblName(g_queryInfo.superQueryInfo.sql[i], subSqlstr, i);
6561
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6562
      if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6563
        sprintf(tmpFile, "%s-%d",
6564
                g_queryInfo.superQueryInfo.result[i], pThreadInfo->threadID);
6565
      }
6566
      tsub[i] = subscribeImpl(pThreadInfo->taos, subSqlstr, topic, tmpFile);
6567
      if (NULL == tsub[i]) {
6568
        taos_close(pThreadInfo->taos);
6569 6570 6571 6572
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6573
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6574
  } while(0);
6575 6576 6577

  // start loop to consume result
  TAOS_RES* res = NULL;
6578
  while(1) {
6579
    for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6580
      if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
6581 6582
        continue;
      }
6583

6584
      res = taos_consume(tsub[i]);
6585 6586
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6587
        if (g_queryInfo.superQueryInfo.result[i][0] != 0) {
6588
          sprintf(tmpFile, "%s-%d",
6589
                  g_queryInfo.superQueryInfo.result[i],
6590
                  pThreadInfo->threadID);
6591
        }
6592
        appendResultToFile(res, tmpFile);
H
hzcheng 已提交
6593 6594 6595
      }
    }
  }
6596
  taos_free_result(res);
6597

6598
  for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
6599
    taos_unsubscribe(tsub[i], g_queryInfo.superQueryInfo.subscribeKeepProgress);
6600
  }
6601

6602
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6603 6604 6605
  return NULL;
}

6606 6607
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6608
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
H
hzcheng 已提交
6609

6610 6611 6612
  if (g_queryInfo.specifiedQueryInfo.sqlCount == 0)
    return NULL;

6613
  if (pThreadInfo->taos == NULL) {
6614 6615 6616 6617 6618 6619 6620 6621
    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",
6622
            pThreadInfo->threadID, taos_errstr(NULL));
6623 6624
      return NULL;
    } else {
6625
      pThreadInfo->taos = taos;
6626 6627 6628
    }
  }

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

6637 6638 6639
  //int64_t st = 0;
  //int64_t et = 0;
  do {
6640 6641
    //if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) < g_queryInfo.specifiedQueryInfo.queryInterval) {
    //  taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval- (et - st)); // ms
6642
    //  //printf("========sleep duration:%"PRIu64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6643 6644 6645 6646
    //}

    //st = taosGetTimestampMs();
    char topic[32] = {0};
6647
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6648 6649
      sprintf(topic, "taosdemo-subscribe-%d", i);
      char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6650
      if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6651
        sprintf(tmpFile, "%s-%d",
6652
                g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6653
      }
6654
      tsub[i] = subscribeImpl(pThreadInfo->taos,
6655
          g_queryInfo.specifiedQueryInfo.sql[i], topic, tmpFile);
6656
      if (NULL == tsub[i]) {
6657
        taos_close(pThreadInfo->taos);
6658 6659 6660 6661
        return NULL;
      }
    }
    //et = taosGetTimestampMs();
6662
    //printf("========thread[%"PRIu64"] complete all sqls to super table once queries duration:%.4fs\n", taosGetSelfPthreadId(), (double)(et - st)/1000.0);
6663
  } while(0);
6664 6665 6666

  // start loop to consume result
  TAOS_RES* res = NULL;
6667
  while(1) {
6668
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6669
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6670 6671
        continue;
      }
6672

6673
      res = taos_consume(tsub[i]);
6674 6675
      if (res) {
        char tmpFile[MAX_FILE_NAME_LEN*2] = {0};
6676
        if (g_queryInfo.specifiedQueryInfo.result[i][0] != 0) {
6677
          sprintf(tmpFile, "%s-%d",
6678
                  g_queryInfo.specifiedQueryInfo.result[i], pThreadInfo->threadID);
6679
        }
6680
        appendResultToFile(res, tmpFile);
6681 6682 6683 6684
      }
    }
  }
  taos_free_result(res);
6685

6686
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
6687 6688
    taos_unsubscribe(tsub[i],
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6689
  }
6690

6691
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6692 6693 6694
  return NULL;
}

6695
static int subscribeTestProcess() {
6696
  setupForAnsiEscape();
6697
  printfQueryMeta();
6698
  resetAfterAnsiEscape();
6699

6700 6701
  if (!g_args.answer_yes) {
    printf("Press enter key to continue\n\n");
6702
    (void) getchar();
Y
yihaoDeng 已提交
6703
  }
6704

6705 6706 6707 6708 6709
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
6710
          g_queryInfo.port);
6711
  if (taos == NULL) {
6712 6713
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6714 6715 6716
    exit(-1);
  }

6717
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6718 6719
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6720 6721 6722
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6723 6724
  }

6725 6726
  taos_close(taos); // TODO: workaround to use separate taos connection;

6727 6728 6729
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from super table
6730 6731
  if ((g_queryInfo.specifiedQueryInfo.sqlCount <= 0) ||
          (g_queryInfo.specifiedQueryInfo.concurrent <= 0)) {
6732 6733 6734
    errorPrint("%s() LN%d, query sqlCount %"PRIu64" or concurrent %"PRIu64" is not correct.\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
6735
              g_queryInfo.specifiedQueryInfo.concurrent);
6736 6737 6738
    exit(-1);
  }

6739 6740
  pids  = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(pthread_t));
  infos = malloc(g_queryInfo.specifiedQueryInfo.concurrent * sizeof(threadInfo));
6741
  if ((NULL == pids) || (NULL == infos)) {
6742
      errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
6743
      exit(-1);
6744
  }
6745

6746
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6747 6748
      threadInfo *t_info = infos + i;
      t_info->threadID = i;
6749
      t_info->taos = NULL;  // TODO: workaround to use separate taos connection;
6750
      pthread_create(pids + i, NULL, specifiedSubscribe, t_info);
H
hzcheng 已提交
6751
  }
6752

6753
  //==== create sub threads for query from sub table
6754 6755
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
6756 6757 6758
  if ((g_queryInfo.superQueryInfo.sqlCount > 0)
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
    pidsOfSub  = malloc(g_queryInfo.superQueryInfo.threadCnt *
6759
            sizeof(pthread_t));
6760
    infosOfSub = malloc(g_queryInfo.superQueryInfo.threadCnt *
6761
            sizeof(threadInfo));
6762
    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6763 6764 6765
      errorPrint("%s() LN%d, malloc failed for create threads\n",
              __func__, __LINE__);
      // taos_close(taos);
6766
      exit(-1);
S
Shuaiqiang Chang 已提交
6767
    }
6768

6769
    uint64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6770
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6771

6772
    uint64_t a = ntables / threads;
6773 6774 6775 6776
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6777

6778
    uint64_t b = 0;
6779 6780 6781
    if (threads != 0) {
      b = ntables % threads;
    }
6782

6783
    uint64_t startFrom = 0;
6784
    for (int i = 0; i < threads; i++) {
6785 6786
      threadInfo *t_info = infosOfSub + i;
      t_info->threadID = i;
6787

6788 6789 6790 6791
      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;
6792
      t_info->taos = NULL; // TODO: workaround to use separate taos connection;
6793
      pthread_create(pidsOfSub + i, NULL, superSubscribe, t_info);
H
hzcheng 已提交
6794
    }
6795

6796
    g_queryInfo.superQueryInfo.threadCnt = threads;
6797

6798
    for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6799 6800
      pthread_join(pidsOfSub[i], NULL);
    }
H
hzcheng 已提交
6801
  }
6802

6803
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.concurrent; i++) {
6804
    pthread_join(pids[i], NULL);
6805
  }
H
hzcheng 已提交
6806

6807
  tmfree((char*)pids);
6808
  tmfree((char*)infos);
H
hzcheng 已提交
6809

6810
  tmfree((char*)pidsOfSub);
6811
  tmfree((char*)infosOfSub);
6812
//   taos_close(taos);
6813
  return 0;
H
hzcheng 已提交
6814 6815
}

6816
static void initOfInsertMeta() {
6817
  memset(&g_Dbs, 0, sizeof(SDbs));
6818

6819
  // set default values
6820
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6821
  g_Dbs.port = 6030;
6822 6823
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
6824
  g_Dbs.threadCount = 2;
6825 6826

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
6827 6828
}

6829
static void initOfQueryMeta() {
6830
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
6831

6832
  // set default values
6833
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6834
  g_queryInfo.port = 6030;
6835 6836
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
6837 6838
}

6839
static void setParaFromArg(){
6840
  if (g_args.host) {
6841
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
6842
  } else {
6843
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
6844
  }
L
Liu Tao 已提交
6845

6846
  if (g_args.user) {
6847
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
6848
  }
6849 6850

  if (g_args.password) {
6851
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
6852 6853
  }

6854 6855
  if (g_args.port) {
    g_Dbs.port = g_args.port;
6856
  }
L
Liu Tao 已提交
6857

6858 6859 6860
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

6861 6862
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
6863

6864
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
6865
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
6866
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
6867

6868
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
6869 6870 6871 6872 6873

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

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

6875 6876
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
6877

6878
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
6879

6880 6881
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
6882
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
6883
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
6884
  }
H
hzcheng 已提交
6885

6886 6887 6888 6889 6890
  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;
6891
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
6892
    g_Dbs.asyncMode = g_args.async_mode;
6893

6894 6895 6896 6897
    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;
6898
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
6899 6900 6901
            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);
6902
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
6903
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
6904
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
6905

6906
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
6907
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
6908

6909 6910 6911 6912 6913
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
6914

6915
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
6916
              data_type[i], MAX_TB_NAME_SIZE);
6917
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
6918 6919
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
6920

6921 6922 6923 6924 6925
    if (g_Dbs.db[0].superTbls[0].columnCount > g_args.num_of_CPR) {
      g_Dbs.db[0].superTbls[0].columnCount = g_args.num_of_CPR;
    } else {
      for (int i = g_Dbs.db[0].superTbls[0].columnCount; i < g_args.num_of_CPR; i++) {
        tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType, "INT", MAX_TB_NAME_SIZE);
6926
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
6927 6928 6929
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
6930

6931
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType, "INT", MAX_TB_NAME_SIZE);
6932
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
6933

6934
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType, "BINARY", MAX_TB_NAME_SIZE);
6935 6936
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
6937
  } else {
6938 6939
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
6940
  }
6941 6942 6943 6944 6945 6946
}

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

6948 6949 6950
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
6951 6952 6953
    exit(-1);
  }

6954 6955 6956 6957 6958 6959 6960 6961 6962 6963 6964 6965 6966 6967 6968 6969 6970 6971 6972 6973 6974 6975 6976 6977
  /* 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);
}

6978
static void querySqlFile(TAOS* taos, char* sqlFile)
6979 6980 6981 6982 6983 6984
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
6985

6986 6987 6988 6989 6990 6991
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

6992
  double t = taosGetTimestampMs();
6993

6994
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006
    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;
7007
    }
7008 7009

    memcpy(cmd + cmd_len, line, read_len);
7010
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
7011 7012 7013
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7014 7015 7016 7017 7018
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7019 7020
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7021 7022
  }

7023
  t = taosGetTimestampMs() - t;
7024
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7025

7026 7027 7028 7029
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7030 7031
}

7032
static void testMetaFile() {
7033
    if (INSERT_TEST == g_args.test_mode) {
7034 7035
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7036

7037
      insertTestProcess();
7038

7039
    } else if (QUERY_TEST == g_args.test_mode) {
7040 7041
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7042

7043
      queryTestProcess();
7044

7045
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7046 7047
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7048

7049
      subscribeTestProcess();
7050

7051 7052 7053
    }  else {
      ;
    }
7054
}
7055

7056
static void queryResult() {
7057
  // query data
7058

7059 7060 7061 7062 7063
  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;
7064

7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 7086 7087 7088 7089 7090 7091 7092 7093 7094 7095 7096 7097 7098 7099 7100
  //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);
7101 7102
}

7103 7104
static void testCmdLine() {

7105 7106 7107 7108 7109 7110 7111 7112 7113 7114
  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);
  }

7115 7116
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7117

7118
  if (false == g_Dbs.insert_only)
7119
    queryResult();
7120 7121
}

7122 7123 7124
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7125
  debugPrint("meta file: %s\n", g_args.metaFile);
7126 7127 7128

  if (g_args.metaFile) {
    initOfInsertMeta();
7129
    initOfQueryMeta();
7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142

    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(
7143 7144 7145 7146
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7147
          g_Dbs.port);
7148
      querySqlFile(qtaos, g_args.sqlFile);
7149 7150 7151 7152 7153
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
H
hzcheng 已提交
7154
  }
7155 7156

  return 0;
H
hzcheng 已提交
7157
}
7158