taosdemo.c 249.8 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
#define STR_INSERT_INTO     "INSERT INTO "

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

73 74
#define MAX_RECORDS_PER_REQ     32766

75 76
#define HEAD_BUFF_LEN    1024*24  // 16*1024 + (192+32)*2 + insert into ..

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

100
#define   MAX_QUERY_SQL_COUNT    100
101
#define   MAX_QUERY_SQL_LENGTH   1024
102 103

#define   MAX_DATABASE_COUNT     256
104
#define INPUT_BUF_LEN   256
105

106
#define DEFAULT_TIMESTAMP_STEP  1
107

108

109 110 111 112 113
typedef enum CREATE_SUB_TALBE_MOD_EN {
  PRE_CREATE_SUBTBL,
  AUTO_CREATE_SUBTBL,
  NO_CREATE_SUBTBL
} CREATE_SUB_TALBE_MOD_EN;
114

115 116
typedef enum TALBE_EXISTS_EN {
  TBL_NO_EXISTS,
117
  TBL_ALREADY_EXISTS,
118 119 120
  TBL_EXISTS_BUTT
} TALBE_EXISTS_EN;

121
enum enumSYNC_MODE {
122 123
  SYNC_MODE,
  ASYNC_MODE,
124 125
  MODE_BUT
};
126

S
Shuduo Sang 已提交
127
enum enum_TAOS_INTERFACE {
128 129 130
    TAOSC_IFACE,
    REST_IFACE,
    STMT_IFACE,
131 132 133
    INTERFACE_BUT
};

134 135 136 137 138 139
typedef enum enumQUERY_CLASS {
    SPECIFIED_CLASS,
    STABLE_CLASS,
    CLASS_BUT
} QUERY_CLASS;

S
Shuduo Sang 已提交
140
typedef enum enum_PROGRESSIVE_OR_INTERLACE {
141 142 143
    PROGRESSIVE_INSERT_MODE,
    INTERLACE_INSERT_MODE,
    INVALID_INSERT_MODE
144
} PROG_OR_INTERLACE_MODE;
145

146
typedef enum enumQUERY_TYPE {
147
  NO_INSERT_TYPE,
148
  INSERT_TYPE,
149
  QUERY_TYPE_BUT
150
} QUERY_TYPE;
151 152 153 154 155 156 157

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,
158
  TSDB_SHOW_DB_QUORUM_INDEX,
159 160 161 162 163 164 165 166 167 168
  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,
169
  TSDB_SHOW_DB_PRECISION_INDEX,
170 171 172 173 174 175 176 177 178 179
  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,
180 181
  TSDB_SHOW_STABLES_METRIC_INDEX,
  TSDB_SHOW_STABLES_UID_INDEX,
182
  TSDB_SHOW_STABLES_TID_INDEX,
183
  TSDB_SHOW_STABLES_VGID_INDEX,
184
  TSDB_MAX_SHOW_STABLES
185 186
};

187 188 189 190 191 192 193 194 195 196 197 198 199 200
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 已提交
201 202

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

205 206
typedef struct SArguments_S {
  char *   metaFile;
207
  uint32_t test_mode;
208 209
  char *   host;
  uint16_t port;
S
Shuduo Sang 已提交
210
  uint16_t iface;
211 212 213 214 215 216 217
  char *   user;
  char *   password;
  char *   database;
  int      replica;
  char *   tb_prefix;
  char *   sqlFile;
  bool     use_metric;
218
  bool     drop_database;
219
  bool     insert_only;
220
  bool     answer_yes;
221
  bool     debug_print;
222
  bool     verbose_print;
223
  bool     performance_print;
224
  char *   output_file;
225
  bool     async_mode;
226
  char *   datatype[MAX_NUM_DATATYPE + 1];
227 228 229 230
  uint32_t len_of_binary;
  uint32_t num_of_CPR;
  uint32_t num_of_threads;
  uint64_t insert_interval;
231
  int64_t  query_times;
232 233 234
  uint64_t interlace_rows;
  uint64_t num_of_RPR;                  // num_of_records_per_req
  uint64_t max_sql_len;
235 236
  int64_t  num_of_tables;
  int64_t  num_of_DPT;
237
  int      abort;
238 239
  int      disorderRatio;               // 0: no disorder, >0: x%
  int      disorderRange;               // ms or us by database precision
240
  uint32_t method_of_delete;
241
  char **  arg_list;
242 243
  uint64_t totalInsertRows;
  uint64_t totalAffectedRows;
244 245 246
} SArguments;

typedef struct SColumn_S {
247 248 249
  char      field[TSDB_COL_NAME_LEN + 1];
  char      dataType[MAX_TB_NAME_SIZE];
  uint32_t  dataLen;
250
  char      note[128];
251 252 253
} StrColumn;

typedef struct SSuperTable_S {
254
  char         sTblName[MAX_TB_NAME_SIZE+1];
255
  int64_t      childTblCount;
256
  bool         childTblExists;          // 0: no, 1: yes
257 258
  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
259
  char         childTblPrefix[MAX_TB_NAME_SIZE];
260
  char         dataSource[MAX_TB_NAME_SIZE+1];  // rand_gen or sample
261
  uint16_t     insertMode;              // 0: taosc, 1: rest, 2: stmt
262
  int64_t      childTblLimit;
263
  uint64_t     childTblOffset;
264

265
//  int          multiThreadWriteOneTbl;  // 0: no, 1: yes
266
  uint64_t     interlaceRows;           //
267 268
  int          disorderRatio;           // 0: no disorder, >0: x%
  int          disorderRange;           // ms or us by database precision
269
  uint64_t     maxSqlLen;               //
270

271
  uint64_t     insertInterval;          // insert interval, will override global insert interval
272
  int64_t      insertRows;
273
  int64_t      timeStampStep;
274
  char         startTimestamp[MAX_TB_NAME_SIZE];
275
  char         sampleFormat[MAX_TB_NAME_SIZE];  // csv, json
276 277
  char         sampleFile[MAX_FILE_NAME_LEN+1];
  char         tagsFile[MAX_FILE_NAME_LEN+1];
278

279
  uint32_t     columnCount;
280
  StrColumn    columns[MAX_COLUMN_COUNT];
281
  uint32_t     tagCount;
282 283 284
  StrColumn    tags[MAX_TAG_COUNT];

  char*        childTblName;
285
  char*        colsOfCreateChildTable;
286 287
  uint64_t     lenOfOneRow;
  uint64_t     lenOfTagOfOneRow;
288 289 290 291 292

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

293
  uint32_t     tagSource;    // 0: rand, 1: tag sample
294
  char*        tagDataBuf;
295 296
  uint32_t     tagSampleCount;
  uint32_t     tagUsePos;
297

298
  // statistics
299 300
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
301 302 303 304 305
} SSuperTable;

typedef struct {
  char     name[TSDB_DB_NAME_LEN + 1];
  char     create_time[32];
S
Shuduo Sang 已提交
306
  int64_t  ntables;
307
  int32_t  vgroups;
308 309
  int16_t  replica;
  int16_t  quorum;
310
  int16_t  days;
311 312 313 314 315 316 317 318 319 320 321 322 323 324
  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;

325
typedef struct SDbCfg_S {
326
//  int       maxtablesPerVnode;
327 328
  uint32_t  minRows;        // 0 means default
  uint32_t  maxRows;        // 0 means default
329 330
  int       comp;
  int       walLevel;
331
  int       cacheLast;
332
  int       fsync;
333 334 335 336 337 338 339
  int       replica;
  int       update;
  int       keep;
  int       days;
  int       cache;
  int       blocks;
  int       quorum;
340
  char      precision[MAX_TB_NAME_SIZE];
341 342 343 344
} SDbCfg;

typedef struct SDataBase_S {
  char         dbName[MAX_DB_NAME_SIZE];
345
  bool         drop;  // 0: use exists, 1: if exists, drop then new create
346
  SDbCfg       dbCfg;
347
  uint64_t     superTblCount;
348 349 350 351
  SSuperTable  superTbls[MAX_SUPER_TABLE_COUNT];
} SDataBase;

typedef struct SDbs_S {
352
  char         cfgDir[MAX_FILE_NAME_LEN+1];
353
  char         host[MAX_HOSTNAME_SIZE];
354 355
  struct sockaddr_in serv_addr;

356
  uint16_t     port;
357 358
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
359
  char         resultFile[MAX_FILE_NAME_LEN+1];
360 361 362
  bool         use_metric;
  bool         insert_only;
  bool         do_aggreFunc;
363
  bool         asyncMode;
364

365 366 367
  uint32_t     threadCount;
  uint32_t     threadCountByCreateTbl;
  uint32_t     dbCount;
368 369 370
  SDataBase    db[MAX_DB_COUNT];

  // statistics
371 372
  uint64_t     totalInsertRows;
  uint64_t     totalAffectedRows;
373

374 375
} SDbs;

376
typedef struct SpecifiedQueryInfo_S {
377
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
378
  uint32_t     concurrent;
379
  uint64_t     sqlCount;
380
  uint32_t     asyncMode; // 0: sync, 1: async
381 382
  uint64_t     subscribeInterval; // ms
  uint64_t     queryTimes;
383
  bool         subscribeRestart;
384
  int          subscribeKeepProgress;
385
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
386
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
387
  int          resubAfterConsume[MAX_QUERY_SQL_COUNT];
388
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
389 390 391
  char         topic[MAX_QUERY_SQL_COUNT][32];
  int          consumed[MAX_QUERY_SQL_COUNT];
  TAOS_RES*    res[MAX_QUERY_SQL_COUNT];
392
  uint64_t     totalQueried;
393
} SpecifiedQueryInfo;
394

395
typedef struct SuperQueryInfo_S {
396
  char         sTblName[MAX_TB_NAME_SIZE+1];
397 398
  uint64_t     queryInterval;  // 0: unlimit  > 0   loop/s
  uint32_t     threadCnt;
399
  uint32_t     asyncMode; // 0: sync, 1: async
400
  uint64_t     subscribeInterval; // ms
401
  bool         subscribeRestart;
402
  int          subscribeKeepProgress;
403
  uint64_t     queryTimes;
404
  int64_t      childTblCount;
405
  char         childTblPrefix[MAX_TB_NAME_SIZE];
406
  uint64_t     sqlCount;
407
  char         sql[MAX_QUERY_SQL_COUNT][MAX_QUERY_SQL_LENGTH+1];
408
  char         result[MAX_QUERY_SQL_COUNT][MAX_FILE_NAME_LEN+1];
409
  int          resubAfterConsume;
410
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT];
411

412
  char*        childTblName;
413
  uint64_t     totalQueried;
414
} SuperQueryInfo;
415 416

typedef struct SQueryMetaInfo_S {
417
  char         cfgDir[MAX_FILE_NAME_LEN+1];
418
  char         host[MAX_HOSTNAME_SIZE];
419
  uint16_t     port;
420
  struct       sockaddr_in serv_addr;
421 422
  char         user[MAX_USERNAME_SIZE];
  char         password[MAX_PASSWORD_SIZE];
423
  char         dbName[MAX_DB_NAME_SIZE+1];
424
  char         queryMode[MAX_TB_NAME_SIZE];  // taosc, rest
425

426
  SpecifiedQueryInfo  specifiedQueryInfo;
427
  SuperQueryInfo      superQueryInfo;
428
  uint64_t     totalQueried;
429 430 431
} SQueryMetaInfo;

typedef struct SThreadInfo_S {
432
  TAOS *    taos;
433
  TAOS_STMT *stmt;
434 435 436
  int       threadID;
  char      db_name[MAX_DB_NAME_SIZE+1];
  uint32_t  time_precision;
437 438
  char      filePath[4096];
  FILE      *fp;
439 440 441
  char      tb_prefix[MAX_TB_NAME_SIZE];
  uint64_t  start_table_from;
  uint64_t  end_table_to;
S
Shuduo Sang 已提交
442
  int64_t   ntables;
443 444 445 446
  uint64_t  data_of_rate;
  int64_t   start_time;
  char*     cols;
  bool      use_metric;
447
  SSuperTable* superTblInfo;
S
Shuduo Sang 已提交
448
  char      *buffer;    // sql cmd buffer
449 450

  // for async insert
451 452
  tsem_t    lock_sem;
  int64_t   counter;
453 454
  uint64_t  st;
  uint64_t  et;
455
  uint64_t  lastTs;
456

457
  // sample data
458
  int64_t   samplePos;
459
  // statistics
460 461
  uint64_t  totalInsertRows;
  uint64_t  totalAffectedRows;
462 463

  // insert delay statistics
464 465 466 467 468
  uint64_t  cntDelay;
  uint64_t  totalDelay;
  uint64_t  avgDelay;
  uint64_t  maxDelay;
  uint64_t  minDelay;
469

470
  // seq of query or subscribe
471
  uint64_t  querySeq;   // sequence number of sql command
472

473 474
} threadInfo;

475
#ifdef WINDOWS
476 477
#define _CRT_RAND_S

478
#include <windows.h>
479 480 481 482 483
#include <winsock2.h>

typedef unsigned __int32 uint32_t;

#pragma comment ( lib, "ws2_32.lib" )
484 485
// Some old MinGW/CYGWIN distributions don't define this:
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
486 487
  #define ENABLE_VIRTUAL_TERMINAL_PROCESSING  0x0004
#endif // ENABLE_VIRTUAL_TERMINAL_PROCESSING
488 489 490 491

static HANDLE g_stdoutHandle;
static DWORD g_consoleMode;

492
static void setupForAnsiEscape(void) {
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
  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());
511
  }
512 513
}

514
static void resetAfterAnsiEscape(void) {
515
  // Reset colors
516
  printf("\x1b[0m");
517 518 519 520 521 522

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

524
static int taosRandom()
525 526 527 528 529 530
{
    int number;
    rand_s(&number);

    return number;
}
531
#else   // Not windows
532
static void setupForAnsiEscape(void) {}
533

534
static void resetAfterAnsiEscape(void) {
535 536 537
  // Reset colors
  printf("\x1b[0m");
}
538

539 540
#include <time.h>

541
static int taosRandom()
542
{
543
  return rand();
544 545
}

546
#endif // ifdef Windows
547

548
static void prompt();
549
static int createDatabasesAndStables();
550
static void createChildTables();
551
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet);
552
static int postProceSql(char *host, struct sockaddr_in *pServAddr,
553
        uint16_t port, char* sqlstr, threadInfo *pThreadInfo);
554 555 556 557 558 559 560

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

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

564
SArguments g_args = {
565 566 567 568
                     NULL,            // metaFile
                     0,               // test_mode
                     "127.0.0.1",     // host
                     6030,            // port
S
Shuduo Sang 已提交
569
                     TAOSC_IFACE,     // iface
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601
                     "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 已提交
602
                     (1024*1024),         // max_sql_len
603 604 605 606 607 608 609
                     10000,           // num_of_tables
                     10000,           // num_of_DPT
                     0,               // abort
                     0,               // disorderRatio
                     1000,            // disorderRange
                     1,               // method_of_delete
                     NULL             // arg_list
610 611 612 613 614
};



static SDbs            g_Dbs;
615
static int64_t         g_totalChildTables = 0;
616 617 618 619
static SQueryMetaInfo  g_queryInfo;
static FILE *          g_fpOfInsertResult = NULL;

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

623
#define verbosePrint(fmt, ...) \
624 625
    do { if (g_args.verbose_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)
626

627 628 629 630
#define performancePrint(fmt, ...) \
    do { if (g_args.performance_print) \
        fprintf(stderr, "VERB: "fmt, __VA_ARGS__); } while(0)

631 632 633 634
#define errorPrint(fmt, ...) \
    do { fprintf(stderr, "ERROR: "fmt, __VA_ARGS__); } while(0)


635
///////////////////////////////////////////////////
H
hzcheng 已提交
636

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

639 640 641 642 643 644 645 646
#ifndef TAOSDEMO_COMMIT_SHA1
#define TAOSDEMO_COMMIT_SHA1 "unknown"
#endif

#ifndef TD_VERNUMBER
#define TD_VERNUMBER    "unknown"
#endif

647
#ifndef TAOSDEMO_STATUS
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
#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);
    }
}

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

734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
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;
}

749
static void parse_args(int argc, char *argv[], SArguments *arguments) {
750 751 752 753 754

  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 已提交
755 756 757 758 759
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-c need a valid path following!\n");
        exit(EXIT_FAILURE);
      }
760
      tstrncpy(configDir, argv[++i], TSDB_FILENAME_LEN);
761
    } else if (strcmp(argv[i], "-h") == 0) {
H
Haojun Liao 已提交
762 763 764 765 766
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-h need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
767 768
      arguments->host = argv[++i];
    } else if (strcmp(argv[i], "-p") == 0) {
769
      if ((argc == i+1) ||
770
        (!isStringNumber(argv[i+1]))) {
771 772 773 774
        printHelp();
        errorPrint("%s", "\n\t-p need a number following!\n");
        exit(EXIT_FAILURE);
      }
775
      arguments->port = atoi(argv[++i]);
776 777 778 779 780 781 782 783
    } 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")) {
S
Shuduo Sang 已提交
784
          arguments->iface = TAOSC_IFACE;
785
      } else if (0 == strcasecmp(argv[i], "rest")) {
S
Shuduo Sang 已提交
786
          arguments->iface = REST_IFACE;
787
      } else if (0 == strcasecmp(argv[i], "stmt")) {
S
Shuduo Sang 已提交
788
          arguments->iface = STMT_IFACE;
789 790 791 792
      } else {
        errorPrint("%s", "\n\t-I need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
793
    } else if (strcmp(argv[i], "-u") == 0) {
H
Haojun Liao 已提交
794 795 796 797 798
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-u need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
799 800
      arguments->user = argv[++i];
    } else if (strcmp(argv[i], "-P") == 0) {
H
Haojun Liao 已提交
801 802 803 804 805
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-P need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
806 807
      arguments->password = argv[++i];
    } else if (strcmp(argv[i], "-o") == 0) {
H
Haojun Liao 已提交
808 809 810 811 812
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-o need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
813 814
      arguments->output_file = argv[++i];
    } else if (strcmp(argv[i], "-s") == 0) {
H
Haojun Liao 已提交
815 816 817 818 819
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-s need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
820 821
      arguments->sqlFile = argv[++i];
    } else if (strcmp(argv[i], "-q") == 0) {
822 823
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
824
        printHelp();
825
        errorPrint("%s", "\n\t-q need a number following!\nQuery mode -- 0: SYNC, 1: ASYNC. Default is SYNC.\n");
826 827
        exit(EXIT_FAILURE);
      }
828
      arguments->async_mode = atoi(argv[++i]);
829
    } else if (strcmp(argv[i], "-T") == 0) {
830 831
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
832 833 834 835
        printHelp();
        errorPrint("%s", "\n\t-T need a number following!\n");
        exit(EXIT_FAILURE);
      }
836 837
      arguments->num_of_threads = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-i") == 0) {
838 839
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
840 841 842 843
        printHelp();
        errorPrint("%s", "\n\t-i need a number following!\n");
        exit(EXIT_FAILURE);
      }
844
      arguments->insert_interval = atoi(argv[++i]);
845
    } else if (strcmp(argv[i], "-qt") == 0) {
846
      if ((argc == i+1)
847
              || (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
848
        printHelp();
849
        errorPrint("%s", "\n\t-qt need a number following!\n");
H
Haojun Liao 已提交
850 851
        exit(EXIT_FAILURE);
      }
852
      arguments->query_times = atoi(argv[++i]);
853
    } else if (strcmp(argv[i], "-B") == 0) {
854 855
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
856 857 858 859
        printHelp();
        errorPrint("%s", "\n\t-B need a number following!\n");
        exit(EXIT_FAILURE);
      }
860
      arguments->interlace_rows = atoi(argv[++i]);
861
    } else if (strcmp(argv[i], "-r") == 0) {
862 863
      if ((argc == i+1)
              || (!isStringNumber(argv[i+1]))) {
864 865 866 867
        printHelp();
        errorPrint("%s", "\n\t-r need a number following!\n");
        exit(EXIT_FAILURE);
      }
868 869
      arguments->num_of_RPR = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-t") == 0) {
870 871 872 873 874 875
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-t need a number following!\n");
        exit(EXIT_FAILURE);
      }
876 877
      arguments->num_of_tables = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-n") == 0) {
878 879 880 881 882 883
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-n need a number following!\n");
        exit(EXIT_FAILURE);
      }
884 885
      arguments->num_of_DPT = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-d") == 0) {
H
Haojun Liao 已提交
886 887 888 889 890
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-d need a valid string following!\n");
        exit(EXIT_FAILURE);
      }
891 892
      arguments->database = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0) {
893 894 895 896 897 898
      if (argc == i+1) {
        if (!isStringNumber(argv[i+1])) {
            printHelp();
            errorPrint("%s", "\n\t-l need a number following!\n");
            exit(EXIT_FAILURE);
        }
899
      }
900
      arguments->num_of_CPR = atoi(argv[++i]);
901 902 903 904 905 906 907 908 909 910 911

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

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

912
    } else if (strcmp(argv[i], "-b") == 0) {
913 914 915 916 917
      if (argc == i+1) {
        printHelp();
        errorPrint("%s", "\n\t-b need valid string following!\n");
        exit(EXIT_FAILURE);
      }
918 919
      ++i;
      if (strstr(argv[i], ",") == NULL) {
920
        // only one col
921
        if (strcasecmp(argv[i], "INT")
922 923 924 925 926 927 928 929
                && 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")) {
930
          printHelp();
931
          errorPrint("%s", "-b: Invalid data_type!\n");
932
          exit(EXIT_FAILURE);
933
        }
934
        arguments->datatype[0] = argv[i];
935
      } else {
936
        // more than one col
937
        int index = 0;
938 939
        g_dupstr = strdup(argv[i]);
        char *running = g_dupstr;
940
        char *token = strsep(&running, ",");
941
        while(token != NULL) {
942
          if (strcasecmp(token, "INT")
943 944 945 946 947 948 949 950
                  && strcasecmp(token, "FLOAT")
                  && strcasecmp(token, "TINYINT")
                  && strcasecmp(token, "BOOL")
                  && strcasecmp(token, "SMALLINT")
                  && strcasecmp(token, "BIGINT")
                  && strcasecmp(token, "DOUBLE")
                  && strcasecmp(token, "BINARY")
                  && strcasecmp(token, "NCHAR")) {
951
            printHelp();
952
            free(g_dupstr);
953
            errorPrint("%s", "-b: Invalid data_type!\n");
954
            exit(EXIT_FAILURE);
H
hzcheng 已提交
955
          }
956
          arguments->datatype[index++] = token;
957 958
          token = strsep(&running, ",");
          if (index >= MAX_NUM_DATATYPE) break;
S
TD-1057  
Shengliang Guan 已提交
959
        }
960
        arguments->datatype[index] = NULL;
961
      }
962
    } else if (strcmp(argv[i], "-w") == 0) {
963
      if ((argc == i+1) ||
964
        (!isStringNumber(argv[i+1]))) {
965 966 967 968
        printHelp();
        errorPrint("%s", "\n\t-w need a number following!\n");
        exit(EXIT_FAILURE);
      }
969 970
      arguments->len_of_binary = atoi(argv[++i]);
    } else if (strcmp(argv[i], "-m") == 0) {
H
Haojun Liao 已提交
971
      if ((argc == i+1) ||
972
        (!isStringNumber(argv[i+1]))) {
H
Haojun Liao 已提交
973 974 975 976
        printHelp();
        errorPrint("%s", "\n\t-m need a number following!\n");
        exit(EXIT_FAILURE);
      }
977
      arguments->tb_prefix = argv[++i];
978 979
    } else if (strcmp(argv[i], "-N") == 0) {
      arguments->use_metric = false;
980
    } else if (strcmp(argv[i], "-x") == 0) {
981
      arguments->insert_only = false;
982
    } else if (strcmp(argv[i], "-y") == 0) {
983
      arguments->answer_yes = true;
984 985
    } else if (strcmp(argv[i], "-g") == 0) {
      arguments->debug_print = true;
986 987
    } else if (strcmp(argv[i], "-gg") == 0) {
      arguments->verbose_print = true;
988 989
    } else if (strcmp(argv[i], "-pp") == 0) {
      arguments->performance_print = true;
990
    } else if (strcmp(argv[i], "-O") == 0) {
991 992 993 994 995 996
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-O need a number following!\n");
        exit(EXIT_FAILURE);
      }
997

998
      arguments->disorderRatio = atoi(argv[++i]);
999

1000
      if (arguments->disorderRatio > 50) {
1001
        arguments->disorderRatio = 50;
1002
      }
1003

1004
      if (arguments->disorderRatio < 0) {
1005
        arguments->disorderRatio = 0;
1006
      }
1007

1008
    } else if (strcmp(argv[i], "-R") == 0) {
1009 1010 1011 1012 1013 1014
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-R need a number following!\n");
        exit(EXIT_FAILURE);
      }
1015

1016
      arguments->disorderRange = atoi(argv[++i]);
1017 1018 1019
      if (arguments->disorderRange < 0)
        arguments->disorderRange = 1000;

1020
    } else if (strcmp(argv[i], "-a") == 0) {
1021 1022 1023 1024 1025 1026
      if ((argc == i+1) ||
        (!isStringNumber(argv[i+1]))) {
        printHelp();
        errorPrint("%s", "\n\t-a need a number following!\n");
        exit(EXIT_FAILURE);
      }
1027 1028 1029
      arguments->replica = atoi(argv[++i]);
      if (arguments->replica > 3 || arguments->replica < 1) {
          arguments->replica = 1;
1030
      }
1031 1032
    } else if (strcmp(argv[i], "-D") == 0) {
      arguments->method_of_delete = atoi(argv[++i]);
1033 1034 1035
      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 已提交
1036
      }
1037 1038 1039 1040
    } else if ((strcmp(argv[i], "--version") == 0) ||
        (strcmp(argv[i], "-V") == 0)){
      printVersion();
      exit(0);
1041 1042 1043 1044 1045
    } else if (strcmp(argv[i], "--help") == 0) {
      printHelp();
      exit(0);
    } else {
      printHelp();
1046
      errorPrint("%s", "ERROR: wrong options\n");
1047
      exit(EXIT_FAILURE);
S
TD-1057  
Shengliang Guan 已提交
1048 1049
    }
  }
1050

1051
  if (((arguments->debug_print) && (arguments->metaFile == NULL))
1052
          || arguments->verbose_print) {
1053
    printf("###################################################################\n");
1054
    printf("# meta file:                         %s\n", arguments->metaFile);
1055
    printf("# Server IP:                         %s:%hu\n",
1056 1057
            arguments->host == NULL ? "localhost" : arguments->host,
            arguments->port );
1058 1059
    printf("# User:                              %s\n", arguments->user);
    printf("# Password:                          %s\n", arguments->password);
1060 1061
    printf("# Use metric:                        %s\n",
            arguments->use_metric ? "true" : "false");
1062
    if (*(arguments->datatype)) {
1063 1064 1065 1066 1067 1068 1069
        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");
1070
    }
1071
    printf("# Insertion interval:                %"PRIu64"\n",
1072
            arguments->insert_interval);
1073
    printf("# Number of records per req:         %"PRIu64"\n",
1074
            arguments->num_of_RPR);
1075
    printf("# Max SQL length:                    %"PRIu64"\n",
1076
            arguments->max_sql_len);
1077
    printf("# Length of Binary:                  %d\n", arguments->len_of_binary);
1078
    printf("# Number of Threads:                 %d\n", arguments->num_of_threads);
1079
    printf("# Number of Tables:                  %"PRId64"\n",
1080
            arguments->num_of_tables);
1081
    printf("# Number of Data per Table:          %"PRId64"\n",
1082
            arguments->num_of_DPT);
1083 1084 1085 1086 1087
    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);
1088

1089 1090 1091 1092
    }
    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);
1093
    printf("# Print verbose info:                %d\n", arguments->verbose_print);
1094
    printf("###################################################################\n");
1095 1096

    prompt();
1097
  }
1098
}
H
hzcheng 已提交
1099

1100 1101
static bool getInfoFromJsonFile(char* file);
static void init_rand_data();
1102
static void tmfclose(FILE *fp) {
1103 1104 1105 1106
  if (NULL != fp) {
    fclose(fp);
  }
}
1107

1108
static void tmfree(char *buf) {
1109 1110
  if (NULL != buf) {
    free(buf);
H
Hui Li 已提交
1111
  }
1112
}
H
Hui Li 已提交
1113

1114
static int queryDbExec(TAOS *taos, char *command, QUERY_TYPE type, bool quiet) {
1115 1116 1117
  int i;
  TAOS_RES *res = NULL;
  int32_t   code = -1;
1118

S
Shuduo Sang 已提交
1119
  for (i = 0; i < 5 /* retry */; i++) {
1120 1121 1122
    if (NULL != res) {
      taos_free_result(res);
      res = NULL;
H
hzcheng 已提交
1123
    }
1124

1125 1126 1127 1128
    res = taos_query(taos, command);
    code = taos_errno(res);
    if (0 == code) {
      break;
1129
    }
H
hzcheng 已提交
1130 1131
  }

1132
  if (code != 0) {
1133 1134
    if (!quiet) {
      debugPrint("%s() LN%d - command: %s\n", __func__, __LINE__, command);
1135 1136
      errorPrint("Failed to execute %s, command length: %d, reason: %s\n",
              command, (int)strlen(command), taos_errstr(res));
1137
    }
1138 1139 1140
    taos_free_result(res);
    //taos_close(taos);
    return -1;
1141
  }
H
hzcheng 已提交
1142

1143 1144 1145 1146
  if (INSERT_TYPE == type) {
    int affectedRows = taos_affected_rows(res);
    taos_free_result(res);
    return affectedRows;
H
hzcheng 已提交
1147
  }
1148

1149
  taos_free_result(res);
1150 1151
  return 0;
}
H
hzcheng 已提交
1152

1153
static void appendResultBufToFile(char *resultBuf, threadInfo *pThreadInfo)
1154
{
1155 1156
  pThreadInfo->fp = fopen(pThreadInfo->filePath, "at");
  if (pThreadInfo->fp == NULL) {
1157 1158
      errorPrint(
              "%s() LN%d, failed to open result file: %s, result will not save to file\n",
1159
              __func__, __LINE__, pThreadInfo->filePath);
1160 1161 1162
      return;
  }

1163 1164 1165
  fprintf(pThreadInfo->fp, "%s", resultBuf);
  tmfclose(pThreadInfo->fp);
  pThreadInfo->fp = NULL;
1166 1167
}

1168
static void fetchResult(TAOS_RES *res, threadInfo* pThreadInfo) {
1169 1170 1171 1172 1173
  TAOS_ROW    row = NULL;
  int         num_rows = 0;
  int         num_fields = taos_field_count(res);
  TAOS_FIELD *fields     = taos_fetch_fields(res);

1174 1175
  char* databuf = (char*) calloc(1, 100*1024*1024);
  if (databuf == NULL) {
1176 1177
    errorPrint("%s() LN%d, failed to malloc, warning: save result to file slowly!\n",
            __func__, __LINE__);
1178 1179
    return ;
  }
H
hzcheng 已提交
1180

1181 1182
  int   totalLen = 0;
  char  temp[16000];
H
hzcheng 已提交
1183

1184
  // fetch the records row by row
1185
  while((row = taos_fetch_row(res))) {
1186
    if ((strlen(pThreadInfo->filePath) > 0)
1187
            && (totalLen >= 100*1024*1024 - 32000)) {
1188
        appendResultBufToFile(databuf, pThreadInfo);
1189 1190
        totalLen = 0;
        memset(databuf, 0, 100*1024*1024);
H
hzcheng 已提交
1191
    }
1192 1193 1194 1195 1196 1197
    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 已提交
1198 1199
  }

1200
  verbosePrint("%s() LN%d, databuf=%s resultFile=%s\n",
1201 1202 1203
          __func__, __LINE__, databuf, pThreadInfo->filePath);
  if (strlen(pThreadInfo->filePath) > 0) {
    appendResultBufToFile(databuf, pThreadInfo);
1204
  }
1205 1206
  free(databuf);
}
H
hzcheng 已提交
1207

1208
static void selectAndGetResult(
1209 1210
        threadInfo *pThreadInfo, char *command)
{
1211 1212 1213 1214 1215 1216 1217 1218 1219
  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;
    }

1220
    fetchResult(res, pThreadInfo);
1221
    taos_free_result(res);
1222

1223 1224 1225
  } else if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
      int retCode = postProceSql(
              g_queryInfo.host, &(g_queryInfo.serv_addr), g_queryInfo.port,
1226
              command,
1227
              pThreadInfo);
1228 1229 1230 1231 1232 1233 1234 1235
      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);
  }
1236
}
H
hzcheng 已提交
1237

1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276
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;
1277
  return randfloat[cursor];
1278 1279
}

1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296
#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

1297
static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
1298

1299
static void rand_string(char *str, int size) {
1300 1301 1302 1303
  str[0] = 0;
  if (size > 0) {
    //--size;
    int n;
1304
    for (n = 0; n < size; n++) {
1305
      int key = abs(rand_tinyint()) % (int)(sizeof(charset) - 1);
1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
      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++){
1322 1323 1324 1325
    randint[i] = (int)(taosRandom() % 65535);
    randbigint[i] = (int64_t)(taosRandom() % 2147483648);
    randfloat[i] = (float)(taosRandom() / 1000.0);
    randdouble[i] = (double)(taosRandom() / 1000000.0);
1326 1327 1328
  }
}

1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348
#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)

1349
static int printfInsertMeta() {
1350
    SHOW_PARSE_RESULT_START();
1351

1352
  printf("interface:                  \033[33m%s\033[0m\n",
S
Shuduo Sang 已提交
1353
          (g_args.iface==TAOSC_IFACE)?"taosc":(g_args.iface==REST_IFACE)?"rest":"stmt");
1354 1355
  printf("host:                       \033[33m%s:%u\033[0m\n",
          g_Dbs.host, g_Dbs.port);
1356 1357
  printf("user:                       \033[33m%s\033[0m\n", g_Dbs.user);
  printf("password:                   \033[33m%s\033[0m\n", g_Dbs.password);
1358
  printf("configDir:                  \033[33m%s\033[0m\n", configDir);
1359 1360
  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);
1361 1362
  printf("thread num of create table: \033[33m%d\033[0m\n",
          g_Dbs.threadCountByCreateTbl);
1363
  printf("top insert interval:        \033[33m%"PRIu64"\033[0m\n",
1364
          g_args.insert_interval);
1365
  printf("number of records per req:  \033[33m%"PRIu64"\033[0m\n",
1366
          g_args.num_of_RPR);
1367
  printf("max sql length:             \033[33m%"PRIu64"\033[0m\n",
1368
          g_args.max_sql_len);
1369 1370

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

1372 1373
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    printf("database[\033[33m%d\033[0m]:\n", i);
1374 1375
    printf("  database[%d] name:      \033[33m%s\033[0m\n",
            i, g_Dbs.db[i].dbName);
1376
    if (0 == g_Dbs.db[i].drop) {
1377 1378 1379
      printf("  drop:                  \033[33mno\033[0m\n");
    } else {
      printf("  drop:                  \033[33myes\033[0m\n");
1380 1381 1382
    }

    if (g_Dbs.db[i].dbCfg.blocks > 0) {
1383 1384
      printf("  blocks:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.blocks);
1385 1386
    }
    if (g_Dbs.db[i].dbCfg.cache > 0) {
1387 1388
      printf("  cache:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.cache);
1389 1390
    }
    if (g_Dbs.db[i].dbCfg.days > 0) {
1391 1392
      printf("  days:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.days);
1393 1394
    }
    if (g_Dbs.db[i].dbCfg.keep > 0) {
1395 1396
      printf("  keep:                  \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.keep);
1397 1398
    }
    if (g_Dbs.db[i].dbCfg.replica > 0) {
1399 1400
      printf("  replica:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.replica);
1401 1402
    }
    if (g_Dbs.db[i].dbCfg.update > 0) {
1403 1404
      printf("  update:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.update);
1405 1406
    }
    if (g_Dbs.db[i].dbCfg.minRows > 0) {
1407 1408
      printf("  minRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.minRows);
1409 1410
    }
    if (g_Dbs.db[i].dbCfg.maxRows > 0) {
1411 1412
      printf("  maxRows:               \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.maxRows);
1413 1414 1415 1416 1417
    }
    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) {
1418 1419
      printf("  walLevel:              \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.walLevel);
1420 1421
    }
    if (g_Dbs.db[i].dbCfg.fsync > 0) {
1422 1423
      printf("  fsync:                 \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.fsync);
1424 1425
    }
    if (g_Dbs.db[i].dbCfg.quorum > 0) {
1426 1427
      printf("  quorum:                \033[33m%d\033[0m\n",
              g_Dbs.db[i].dbCfg.quorum);
1428 1429
    }
    if (g_Dbs.db[i].dbCfg.precision[0] != 0) {
1430
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1431
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1432
        printf("  precision:             \033[33m%s\033[0m\n",
1433
            g_Dbs.db[i].dbCfg.precision);
1434
      } else {
1435
        printf("\033[1m\033[40;31m  precision error:       %s\033[0m\n",
1436
                g_Dbs.db[i].dbCfg.precision);
1437
        return -1;
1438 1439 1440
      }
    }

1441
    printf("  super table count:     \033[33m%"PRIu64"\033[0m\n",
1442
        g_Dbs.db[i].superTblCount);
1443 1444
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      printf("  super table[\033[33m%"PRIu64"\033[0m]:\n", j);
1445

1446
      printf("      stbName:           \033[33m%s\033[0m\n",
1447
          g_Dbs.db[i].superTbls[j].sTblName);
1448 1449 1450 1451 1452 1453 1454 1455

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

1457 1458 1459 1460 1461 1462 1463
      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");
      }
1464

1465
      printf("      childTblCount:     \033[33m%"PRId64"\033[0m\n",
1466
              g_Dbs.db[i].superTbls[j].childTblCount);
1467
      printf("      childTblPrefix:    \033[33m%s\033[0m\n",
1468
              g_Dbs.db[i].superTbls[j].childTblPrefix);
1469
      printf("      dataSource:        \033[33m%s\033[0m\n",
1470
              g_Dbs.db[i].superTbls[j].dataSource);
1471
      printf("      insertMode:        \033[33m%s\033[0m\n",
1472 1473
          (g_Dbs.db[i].superTbls[j].insertMode==TAOSC_IFACE)?"taosc":
          (g_Dbs.db[i].superTbls[j].insertMode==REST_IFACE)?"rest":"stmt");
1474
      if (g_Dbs.db[i].superTbls[j].childTblLimit > 0) {
1475
        printf("      childTblLimit:     \033[33m%"PRId64"\033[0m\n",
1476
                g_Dbs.db[i].superTbls[j].childTblLimit);
1477
      }
1478
      if (g_Dbs.db[i].superTbls[j].childTblOffset > 0) {
1479
        printf("      childTblOffset:    \033[33m%"PRIu64"\033[0m\n",
1480
                g_Dbs.db[i].superTbls[j].childTblOffset);
1481
      }
1482
      printf("      insertRows:        \033[33m%"PRId64"\033[0m\n",
1483
              g_Dbs.db[i].superTbls[j].insertRows);
1484
/*
1485
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1486
        printf("      multiThreadWriteOneTbl:  \033[33mno\033[0m\n");
1487
      }else {
1488
        printf("      multiThreadWriteOneTbl:  \033[33myes\033[0m\n");
1489
      }
1490
      */
1491
      printf("      interlaceRows:     \033[33m%"PRIu64"\033[0m\n",
1492
              g_Dbs.db[i].superTbls[j].interlaceRows);
1493 1494

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

1499
      printf("      disorderRange:     \033[33m%d\033[0m\n",
1500
              g_Dbs.db[i].superTbls[j].disorderRange);
1501
      printf("      disorderRatio:     \033[33m%d\033[0m\n",
1502
              g_Dbs.db[i].superTbls[j].disorderRatio);
1503
      printf("      maxSqlLen:         \033[33m%"PRIu64"\033[0m\n",
1504
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1505
      printf("      timeStampStep:     \033[33m%"PRId64"\033[0m\n",
1506
              g_Dbs.db[i].superTbls[j].timeStampStep);
1507
      printf("      startTimestamp:    \033[33m%s\033[0m\n",
1508
              g_Dbs.db[i].superTbls[j].startTimestamp);
1509
      printf("      sampleFormat:      \033[33m%s\033[0m\n",
1510
              g_Dbs.db[i].superTbls[j].sampleFormat);
1511
      printf("      sampleFile:        \033[33m%s\033[0m\n",
1512
              g_Dbs.db[i].superTbls[j].sampleFile);
1513
      printf("      tagsFile:          \033[33m%s\033[0m\n",
1514
              g_Dbs.db[i].superTbls[j].tagsFile);
1515
      printf("      columnCount:       \033[33m%d\033[0m\n",
1516
              g_Dbs.db[i].superTbls[j].columnCount);
1517 1518
      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);
1519
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
1520 1521 1522
                       "binary", 6))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].columns[k].dataType,
                       "nchar", 5))) {
1523
          printf("column[\033[33m%d\033[0m]:\033[33m%s(%d)\033[0m ", k,
1524 1525
                  g_Dbs.db[i].superTbls[j].columns[k].dataType,
                  g_Dbs.db[i].superTbls[j].columns[k].dataLen);
1526
        } else {
1527
          printf("column[%d]:\033[33m%s\033[0m ", k,
1528
                  g_Dbs.db[i].superTbls[j].columns[k].dataType);
1529 1530 1531
        }
      }
      printf("\n");
1532 1533

      printf("      tagCount:            \033[33m%d\033[0m\n        ",
1534
              g_Dbs.db[i].superTbls[j].tagCount);
1535 1536
      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);
1537
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1538 1539 1540
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1541
          printf("tag[%d]:\033[33m%s(%d)\033[0m ", k,
1542 1543
                  g_Dbs.db[i].superTbls[j].tags[k].dataType,
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1544
        } else {
1545
          printf("tag[%d]:\033[33m%s\033[0m ", k,
1546
                  g_Dbs.db[i].superTbls[j].tags[k].dataType);
1547
        }
1548 1549 1550 1551 1552
      }
      printf("\n");
    }
    printf("\n");
  }
1553 1554

  SHOW_PARSE_RESULT_END();
1555 1556

  return 0;
1557 1558 1559
}

static void printfInsertMetaToFile(FILE* fp) {
1560 1561

  SHOW_PARSE_RESULT_START_TO_FILE(fp);
1562

1563 1564
  fprintf(fp, "host:                       %s:%u\n", g_Dbs.host, g_Dbs.port);
  fprintf(fp, "user:                       %s\n", g_Dbs.user);
1565
  fprintf(fp, "configDir:                  %s\n", configDir);
1566 1567 1568
  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);
1569 1570
  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);
1571
  fprintf(fp, "database count:          %d\n", g_Dbs.dbCount);
1572

1573 1574
  for (int i = 0; i < g_Dbs.dbCount; i++) {
    fprintf(fp, "database[%d]:\n", i);
1575
    fprintf(fp, "  database[%d] name:       %s\n", i, g_Dbs.db[i].dbName);
1576
    if (0 == g_Dbs.db[i].drop) {
1577
      fprintf(fp, "  drop:                  no\n");
1578
    }else {
1579
      fprintf(fp, "  drop:                  yes\n");
1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618
    }

    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) {
1619
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", 2))
1620
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "us", 2))) {
1621 1622
        fprintf(fp, "  precision:             %s\n",
                g_Dbs.db[i].dbCfg.precision);
1623
      } else {
1624 1625
        fprintf(fp, "  precision error:       %s\n",
                g_Dbs.db[i].dbCfg.precision);
1626 1627 1628
      }
    }

1629 1630
    fprintf(fp, "  super table count:     %"PRIu64"\n",
            g_Dbs.db[i].superTblCount);
1631 1632
    for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
      fprintf(fp, "  super table[%d]:\n", j);
1633

1634 1635
      fprintf(fp, "      stbName:           %s\n",
              g_Dbs.db[i].superTbls[j].sTblName);
1636 1637 1638

      if (PRE_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable) {
        fprintf(fp, "      autoCreateTable:   %s\n",  "no");
1639 1640
      } else if (AUTO_CREATE_SUBTBL
              == g_Dbs.db[i].superTbls[j].autoCreateTable) {
1641 1642 1643 1644
        fprintf(fp, "      autoCreateTable:   %s\n",  "yes");
      } else {
        fprintf(fp, "      autoCreateTable:   %s\n",  "error");
      }
1645

1646 1647
      if (TBL_NO_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists) {
        fprintf(fp, "      childTblExists:    %s\n",  "no");
1648 1649
      } else if (TBL_ALREADY_EXISTS
              == g_Dbs.db[i].superTbls[j].childTblExists) {
1650 1651 1652 1653
        fprintf(fp, "      childTblExists:    %s\n",  "yes");
      } else {
        fprintf(fp, "      childTblExists:    %s\n",  "error");
      }
1654

1655
      fprintf(fp, "      childTblCount:     %"PRId64"\n",
1656 1657 1658 1659 1660 1661
              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",
1662 1663
          (g_Dbs.db[i].superTbls[j].insertMode==TAOSC_IFACE)?"taosc":
          (g_Dbs.db[i].superTbls[j].insertMode==REST_IFACE)?"rest":"stmt");
1664
      fprintf(fp, "      insertRows:        %"PRId64"\n",
1665
              g_Dbs.db[i].superTbls[j].insertRows);
1666
      fprintf(fp, "      interlace rows:    %"PRIu64"\n",
1667
              g_Dbs.db[i].superTbls[j].interlaceRows);
1668
      if (g_Dbs.db[i].superTbls[j].interlaceRows > 0) {
1669
        fprintf(fp, "      stable insert interval:   %"PRIu64"\n",
1670
                g_Dbs.db[i].superTbls[j].insertInterval);
1671
      }
1672
/*
1673
      if (0 == g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl) {
1674
        fprintf(fp, "      multiThreadWriteOneTbl:  no\n");
1675
      }else {
1676
        fprintf(fp, "      multiThreadWriteOneTbl:  yes\n");
1677
      }
1678
      */
1679
      fprintf(fp, "      interlaceRows:     %"PRIu64"\n",
1680
              g_Dbs.db[i].superTbls[j].interlaceRows);
1681 1682 1683 1684
      fprintf(fp, "      disorderRange:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRange);
      fprintf(fp, "      disorderRatio:     %d\n",
              g_Dbs.db[i].superTbls[j].disorderRatio);
1685
      fprintf(fp, "      maxSqlLen:         %"PRIu64"\n",
1686
              g_Dbs.db[i].superTbls[j].maxSqlLen);
1687

1688 1689 1690 1691
      fprintf(fp, "      timeStampStep:     %"PRId64"\n",
              g_Dbs.db[i].superTbls[j].timeStampStep);
      fprintf(fp, "      startTimestamp:    %s\n",
              g_Dbs.db[i].superTbls[j].startTimestamp);
1692 1693 1694 1695 1696 1697
      fprintf(fp, "      sampleFormat:      %s\n",
              g_Dbs.db[i].superTbls[j].sampleFormat);
      fprintf(fp, "      sampleFile:        %s\n",
              g_Dbs.db[i].superTbls[j].sampleFile);
      fprintf(fp, "      tagsFile:          %s\n",
              g_Dbs.db[i].superTbls[j].tagsFile);
1698

1699 1700
      fprintf(fp, "      columnCount:       %d\n        ",
              g_Dbs.db[i].superTbls[j].columnCount);
1701 1702
      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);
1703
        if ((0 == strncasecmp(
1704 1705
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
                        "binary", strlen("binary")))
1706 1707
                || (0 == strncasecmp(
                        g_Dbs.db[i].superTbls[j].columns[k].dataType,
1708
                        "nchar", strlen("nchar")))) {
1709 1710 1711
          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);
1712
        } else {
1713 1714
          fprintf(fp, "column[%d]:%s ",
                  k, g_Dbs.db[i].superTbls[j].columns[k].dataType);
1715 1716 1717
        }
      }
      fprintf(fp, "\n");
1718 1719 1720

      fprintf(fp, "      tagCount:            %d\n        ",
              g_Dbs.db[i].superTbls[j].tagCount);
1721 1722
      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);
1723
        if ((0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
1724 1725 1726
                        "binary", strlen("binary")))
                || (0 == strncasecmp(g_Dbs.db[i].superTbls[j].tags[k].dataType,
                        "nchar", strlen("nchar")))) {
1727 1728
          fprintf(fp, "tag[%d]:%s(%d) ",
                  k, g_Dbs.db[i].superTbls[j].tags[k].dataType,
1729
                  g_Dbs.db[i].superTbls[j].tags[k].dataLen);
1730 1731
        } else {
          fprintf(fp, "tag[%d]:%s ", k, g_Dbs.db[i].superTbls[j].tags[k].dataType);
1732
        }
1733 1734 1735 1736 1737
      }
      fprintf(fp, "\n");
    }
    fprintf(fp, "\n");
  }
1738

1739
  SHOW_PARSE_RESULT_END_TO_FILE(fp);
1740 1741 1742
}

static void printfQueryMeta() {
1743

1744
  SHOW_PARSE_RESULT_START();
1745

1746
  printf("host:                    \033[33m%s:%u\033[0m\n",
1747
          g_queryInfo.host, g_queryInfo.port);
1748 1749 1750 1751
  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");
1752 1753 1754 1755

  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",
1756
      g_queryInfo.specifiedQueryInfo.sqlCount);
1757 1758 1759
    if (g_queryInfo.specifiedQueryInfo.sqlCount > 0) {
      printf("specified tbl query times:\n");
      printf("                \033[33m%"PRIu64"\033[0m\n",
1760
      g_queryInfo.specifiedQueryInfo.queryTimes);
1761 1762 1763
      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);
1764
      printf("concurrent:     \033[33m%d\033[0m\n",
1765 1766
      g_queryInfo.specifiedQueryInfo.concurrent);
      printf("mod:            \033[33m%s\033[0m\n",
1767
        (g_queryInfo.specifiedQueryInfo.asyncMode)?"async":"sync");
1768
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1769
        g_queryInfo.specifiedQueryInfo.subscribeInterval);
1770
      printf("restart:        \033[33m%d\033[0m\n",
1771
        g_queryInfo.specifiedQueryInfo.subscribeRestart);
1772
      printf("keepProgress:   \033[33m%d\033[0m\n",
1773
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
1774

1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790
      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);
1791
      printf("childTblCount:  \033[33m%"PRId64"\033[0m\n",
1792 1793 1794 1795 1796 1797 1798
        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",
1799
        (g_queryInfo.superQueryInfo.asyncMode)?"async":"sync");
1800
      printf("interval:       \033[33m%"PRIu64"\033[0m\n",
1801
        g_queryInfo.superQueryInfo.subscribeInterval);
1802
      printf("restart:        \033[33m%d\033[0m\n",
1803
        g_queryInfo.superQueryInfo.subscribeRestart);
1804
      printf("keepProgress:   \033[33m%d\033[0m\n",
1805
        g_queryInfo.superQueryInfo.subscribeKeepProgress);
1806

1807 1808 1809 1810 1811 1812
      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");
    }
1813
  }
1814

1815
  SHOW_PARSE_RESULT_END();
1816 1817
}

1818
static char* formatTimestamp(char* buf, int64_t val, int precision) {
1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849
  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;
}

1850
static void xDumpFieldToFile(FILE* fp, const char* val,
1851
        TAOS_FIELD* field, int32_t length, int precision) {
1852

1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
  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:
1888
      formatTimestamp(buf, *(int64_t*)val, precision);
1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903
      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) {
1904
    errorPrint("%s() LN%d, failed to open file: %s\n", __func__, __LINE__, fname);
1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
    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);
1919

1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939
  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;
}

1940 1941
static int getDbFromServer(TAOS * taos, SDbInfo** dbInfos) {
  TAOS_RES * res;
1942 1943
  TAOS_ROW row = NULL;
  int count = 0;
1944 1945

  res = taos_query(taos, "show databases;");
1946
  int32_t code = taos_errno(res);
1947

1948
  if (code != 0) {
1949
    errorPrint( "failed to run <show databases>, reason: %s\n", taos_errstr(res));
1950 1951 1952 1953 1954
    return -1;
  }

  TAOS_FIELD *fields = taos_fetch_fields(res);

1955
  while((row = taos_fetch_row(res)) != NULL) {
1956
    // sys database name : 'log'
1957
    if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "log",
1958
                fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) {
1959 1960
      continue;
    }
1961 1962 1963

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

1968
    tstrncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX],
1969
            fields[TSDB_SHOW_DB_NAME_INDEX].bytes);
1970
    formatTimestamp(dbInfos[count]->create_time,
1971 1972
            *(int64_t*)row[TSDB_SHOW_DB_CREATED_TIME_INDEX],
            TSDB_TIME_PRECISION_MILLI);
S
Shuduo Sang 已提交
1973
    dbInfos[count]->ntables = *((int64_t *)row[TSDB_SHOW_DB_NTABLES_INDEX]);
1974
    dbInfos[count]->vgroups = *((int32_t *)row[TSDB_SHOW_DB_VGROUPS_INDEX]);
1975 1976
    dbInfos[count]->replica = *((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX]);
    dbInfos[count]->quorum = *((int16_t *)row[TSDB_SHOW_DB_QUORUM_INDEX]);
1977
    dbInfos[count]->days = *((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX]);
1978

1979
    tstrncpy(dbInfos[count]->keeplist, (char *)row[TSDB_SHOW_DB_KEEP_INDEX],
1980
            fields[TSDB_SHOW_DB_KEEP_INDEX].bytes);
1981 1982 1983 1984 1985 1986 1987
    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]));
1988
    dbInfos[count]->cachelast =
1989
      (int8_t)(*((int8_t *)row[TSDB_SHOW_DB_CACHELAST_INDEX]));
1990

1991
    tstrncpy(dbInfos[count]->precision,
1992 1993
            (char *)row[TSDB_SHOW_DB_PRECISION_INDEX],
            fields[TSDB_SHOW_DB_PRECISION_INDEX].bytes);
1994
    dbInfos[count]->update = *((int8_t *)row[TSDB_SHOW_DB_UPDATE_INDEX]);
1995
    tstrncpy(dbInfos[count]->status, (char *)row[TSDB_SHOW_DB_STATUS_INDEX],
1996
            fields[TSDB_SHOW_DB_STATUS_INDEX].bytes);
1997

1998 1999
    count++;
    if (count > MAX_DATABASE_COUNT) {
2000
      errorPrint("%s() LN%d, The database count overflow than %d\n",
2001
         __func__, __LINE__, MAX_DATABASE_COUNT);
2002 2003 2004 2005 2006 2007 2008
      break;
    }
  }

  return count;
}

2009
static void printfDbInfoForQueryToFile(
2010
        char* filename, SDbInfo* dbInfos, int index) {
2011

2012
  if (filename[0] == 0)
2013
      return;
2014 2015 2016

  FILE *fp = fopen(filename, "at");
  if (fp == NULL) {
2017
    errorPrint( "failed to open file: %s\n", filename);
2018
    return;
2019 2020 2021 2022 2023
  }

  fprintf(fp, "================ database[%d] ================\n", index);
  fprintf(fp, "name: %s\n", dbInfos->name);
  fprintf(fp, "created_time: %s\n", dbInfos->create_time);
S
Shuduo Sang 已提交
2024
  fprintf(fp, "ntables: %"PRId64"\n", dbInfos->ntables);
2025
  fprintf(fp, "vgroups: %d\n", dbInfos->vgroups);
2026 2027
  fprintf(fp, "replica: %d\n", dbInfos->replica);
  fprintf(fp, "quorum: %d\n", dbInfos->quorum);
2028 2029
  fprintf(fp, "days: %d\n", dbInfos->days);
  fprintf(fp, "keep0,keep1,keep(D): %s\n", dbInfos->keeplist);
2030 2031 2032 2033 2034 2035 2036
  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);
2037 2038
  fprintf(fp, "cachelast: %d\n", dbInfos->cachelast);
  fprintf(fp, "precision: %s\n", dbInfos->precision);
2039
  fprintf(fp, "update: %d\n", dbInfos->update);
2040
  fprintf(fp, "status: %s\n", dbInfos->status);
2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054
  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);
2055
  snprintf(filename, MAX_QUERY_SQL_LENGTH, "querySystemInfo-%d-%d-%d %d:%d:%d",
2056 2057
          lt->tm_year+1900, lt->tm_mon, lt->tm_mday, lt->tm_hour, lt->tm_min,
          lt->tm_sec);
2058

2059 2060
  // show variables
  res = taos_query(taos, "show variables;");
2061
  //fetchResult(res, filename);
2062 2063 2064 2065 2066
  xDumpResultToFile(filename, res);

  // show dnodes
  res = taos_query(taos, "show dnodes;");
  xDumpResultToFile(filename, res);
2067
  //fetchResult(res, filename);
2068

2069 2070 2071 2072
  // show databases
  res = taos_query(taos, "show databases;");
  SDbInfo** dbInfos = (SDbInfo **)calloc(MAX_DATABASE_COUNT, sizeof(SDbInfo *));
  if (dbInfos == NULL) {
2073
    errorPrint("%s() LN%d, failed to allocate memory\n", __func__, __LINE__);
2074 2075 2076
    return;
  }
  int dbCount = getDbFromServer(taos, dbInfos);
2077
  if (dbCount <= 0) {
2078 2079
      free(dbInfos);
      return;
2080
  }
2081 2082

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

2086 2087 2088 2089
    // show db.vgroups
    snprintf(buffer, MAX_QUERY_SQL_LENGTH, "show %s.vgroups;", dbInfos[i]->name);
    res = taos_query(taos, buffer);
    xDumpResultToFile(filename, res);
2090

2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101
    // 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);
}

2102
static int postProceSql(char *host, struct sockaddr_in *pServAddr, uint16_t port,
2103
        char* sqlstr, threadInfo *pThreadInfo)
2104
{
2105
    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";
2106

2107
    char *url = "/rest/sql";
2108

2109 2110 2111 2112
    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;
2113

2114
    int req_buf_len = strlen(sqlstr) + REQ_EXTRA_BUF_LEN;
2115

2116 2117 2118 2119 2120
    request_buf = malloc(req_buf_len);
    if (NULL == request_buf) {
      errorPrint("%s", "ERROR, cannot allocate memory.\n");
      exit(EXIT_FAILURE);
    }
2121

2122 2123
    char userpass_buf[INPUT_BUF_LEN];
    int mod_table[] = {0, 2, 1};
2124

2125 2126 2127 2128 2129 2130 2131 2132
    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', '+', '/'};
2133

2134 2135 2136 2137
    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);
2138

2139
    char base64_buf[INPUT_BUF_LEN];
2140
#ifdef WINDOWS
2141
    WSADATA wsaData;
2142
    WSAStartup(MAKEWORD(2, 2), &wsaData);
2143 2144
    SOCKET sockfd;
#else
2145
    int sockfd;
2146
#endif
2147 2148
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
2149
#ifdef WINDOWS
2150
        errorPrint( "Could not create socket : %d" , WSAGetLastError());
2151
#endif
2152 2153 2154 2155
        debugPrint("%s() LN%d, sockfd=%d\n", __func__, __LINE__, sockfd);
        free(request_buf);
        ERROR_EXIT("ERROR opening socket");
    }
2156

2157
    int retConn = connect(sockfd, (struct sockaddr *)pServAddr, sizeof(struct sockaddr));
2158 2159 2160 2161 2162
    debugPrint("%s() LN%d connect() return %d\n", __func__, __LINE__, retConn);
    if (retConn < 0) {
        free(request_buf);
        ERROR_EXIT("ERROR connecting");
    }
2163

2164
    memset(base64_buf, 0, INPUT_BUF_LEN);
2165

2166 2167 2168 2169 2170 2171 2172 2173
    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;
2174

2175 2176 2177 2178 2179
      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];
    }
2180

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

2184 2185 2186
    debugPrint("%s() LN%d: auth string base64 encoded: %s\n",
            __func__, __LINE__, base64_buf);
    char *auth = base64_buf;
2187

2188 2189 2190 2191 2192 2193 2194 2195 2196
    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);
2197

2198 2199 2200
    req_str_len = strlen(request_buf);
    sent = 0;
    do {
2201
#ifdef WINDOWS
2202
        bytes = send(sockfd, request_buf + sent, req_str_len - sent, 0);
2203
#else
2204
        bytes = write(sockfd, request_buf + sent, req_str_len - sent);
2205
#endif
2206 2207 2208 2209 2210 2211
        if (bytes < 0)
            ERROR_EXIT("ERROR writing message to socket");
        if (bytes == 0)
            break;
        sent+=bytes;
    } while(sent < req_str_len);
2212

2213 2214 2215 2216
    memset(response_buf, 0, RESP_BUF_LEN);
    resp_len = sizeof(response_buf) - 1;
    received = 0;
    do {
2217
#ifdef WINDOWS
2218
        bytes = recv(sockfd, response_buf + received, resp_len - received, 0);
2219
#else
2220
        bytes = read(sockfd, response_buf + received, resp_len - received);
2221
#endif
2222 2223 2224 2225 2226 2227 2228 2229
        if (bytes < 0) {
            free(request_buf);
            ERROR_EXIT("ERROR reading response from socket");
        }
        if (bytes == 0)
            break;
        received += bytes;
    } while(received < resp_len);
2230

2231 2232 2233 2234
    if (received == resp_len) {
        free(request_buf);
        ERROR_EXIT("ERROR storing complete response from socket");
    }
H
Haojun Liao 已提交
2235

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

2239 2240
    if (strlen(pThreadInfo->filePath) > 0) {
       appendResultBufToFile(response_buf, pThreadInfo);
2241 2242
    }

2243
    free(request_buf);
2244
#ifdef WINDOWS
2245
    closesocket(sockfd);
2246 2247
    WSACleanup();
#else
2248
    close(sockfd);
2249
#endif
2250

2251
    return 0;
2252 2253
}

2254
static char* getTagValueFromTagSample(SSuperTable* stbInfo, int tagUsePos) {
2255 2256
  char*  dataBuf = (char*)calloc(TSDB_MAX_SQL_LEN+1, 1);
  if (NULL == dataBuf) {
2257
    errorPrint("%s() LN%d, calloc failed! size:%d\n",
2258
        __func__, __LINE__, TSDB_MAX_SQL_LEN+1);
2259 2260
    return NULL;
  }
2261

2262
  int    dataLen = 0;
2263
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2264
          "(%s)", stbInfo->tagDataBuf + stbInfo->lenOfTagOfOneRow * tagUsePos);
2265

2266 2267 2268
  return dataBuf;
}

2269
static char* generateTagVaulesForStb(SSuperTable* stbInfo, int32_t tableSeq) {
2270 2271 2272 2273 2274 2275 2276 2277 2278
  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++) {
2279
    if ((0 == strncasecmp(stbInfo->tags[i].dataType, "binary", strlen("binary")))
2280
            || (0 == strncasecmp(stbInfo->tags[i].dataType, "nchar", strlen("nchar")))) {
2281
      if (stbInfo->tags[i].dataLen > TSDB_MAX_BINARY_LEN) {
2282
        printf("binary or nchar length overflow, max size:%u\n",
2283
                (uint32_t)TSDB_MAX_BINARY_LEN);
2284 2285 2286
        tmfree(dataBuf);
        return NULL;
      }
2287

2288 2289
      int tagBufLen = stbInfo->tags[i].dataLen + 1;
      char* buf = (char*)calloc(tagBufLen, 1);
2290 2291 2292 2293 2294
      if (NULL == buf) {
        printf("calloc failed! size:%d\n", stbInfo->tags[i].dataLen);
        tmfree(dataBuf);
        return NULL;
      }
2295 2296 2297 2298 2299 2300 2301

      if (tableSeq % 2) {
        tstrncpy(buf, "beijing", tagBufLen);
      } else {
        tstrncpy(buf, "shanghai", tagBufLen);
      }
      //rand_string(buf, stbInfo->tags[i].dataLen);
2302
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2303
              "\'%s\', ", buf);
2304
      tmfree(buf);
2305
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2306
                "int", strlen("int"))) {
2307
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2308
              "%d, ", tableSeq);
2309
    } else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2310
                "bigint", strlen("bigint"))) {
2311
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2312
              "%"PRId64", ", rand_bigint());
2313
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2314
                "float", strlen("float"))) {
2315
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2316
              "%f, ", rand_float());
2317
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2318
                "double", strlen("double"))) {
2319
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2320
              "%f, ", rand_double());
2321
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2322
                "smallint", strlen("smallint"))) {
2323
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2324
              "%d, ", rand_smallint());
2325
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2326
                "tinyint", strlen("tinyint"))) {
2327
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2328
              "%d, ", rand_tinyint());
2329
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2330
                "bool", strlen("bool"))) {
2331
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2332
              "%d, ", rand_bool());
2333
    }  else if (0 == strncasecmp(stbInfo->tags[i].dataType,
2334
                "timestamp", strlen("timestamp"))) {
2335
      dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen,
2336
              "%"PRId64", ", rand_bigint());
2337 2338 2339 2340 2341 2342
    }  else {
      printf("No support data type: %s\n", stbInfo->tags[i].dataType);
      tmfree(dataBuf);
      return NULL;
    }
  }
2343

2344
  dataLen -= 2;
2345
  dataLen += snprintf(dataBuf + dataLen, TSDB_MAX_SQL_LEN - dataLen, ")");
2346 2347 2348
  return dataBuf;
}

2349
static int calcRowLen(SSuperTable*  superTbls) {
2350 2351
  int colIndex;
  int  lenOfOneRow = 0;
2352

2353 2354
  for (colIndex = 0; colIndex < superTbls->columnCount; colIndex++) {
    char* dataType = superTbls->columns[colIndex].dataType;
2355

2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
    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;
2372
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2373
      lenOfOneRow += 42;
2374
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
      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;
2388

2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404
    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;
2405
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2406 2407 2408 2409 2410 2411 2412 2413
      lenOfTagOfOneRow += superTbls->tags[tagIndex].dataLen + 42;
    } else {
      printf("get error tag type : %s\n", dataType);
      exit(-1);
    }
  }

  superTbls->lenOfTagOfOneRow = lenOfTagOfOneRow;
2414

2415 2416 2417 2418
  return 0;
}


2419
static int getChildNameOfSuperTableWithLimitAndOffset(TAOS * taos,
2420
        char* dbName, char* sTblName, char** childTblNameOfSuperTbl,
2421
        int64_t* childTblCountOfSuperTbl, int64_t limit, uint64_t offset) {
2422

2423
  char command[BUFFER_SIZE] = "\0";
2424 2425
  char limitBuf[100] = "\0";

2426
  TAOS_RES * res;
2427 2428 2429
  TAOS_ROW row = NULL;

  char* childTblName = *childTblNameOfSuperTbl;
2430 2431

  if (offset >= 0) {
2432
    snprintf(limitBuf, 100, " limit %"PRId64" offset %"PRIu64"",
2433
            limit, offset);
2434 2435
  }

2436
  //get all child table name use cmd: select tbname from superTblName;
2437
  snprintf(command, BUFFER_SIZE, "select tbname from %s.%s %s",
2438
          dbName, sTblName, limitBuf);
2439

2440
  res = taos_query(taos, command);
2441 2442 2443 2444
  int32_t code = taos_errno(res);
  if (code != 0) {
    taos_free_result(res);
    taos_close(taos);
2445
    errorPrint("%s() LN%d, failed to run command %s\n",
2446
           __func__, __LINE__, command);
2447 2448 2449
    exit(-1);
  }

2450 2451
  int64_t childTblCount = (limit < 0)?10000:limit;
  int64_t count = 0;
2452 2453 2454
  if (childTblName == NULL) {
    childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (NULL ==  childTblName) {
2455 2456 2457 2458
    taos_free_result(res);
        taos_close(taos);
        errorPrint("%s() LN%d, failed to allocate memory!\n", __func__, __LINE__);
        exit(-1);
2459 2460 2461
    }
  }

2462
  char* pTblName = childTblName;
2463
  while((row = taos_fetch_row(res)) != NULL) {
2464
    int32_t* len = taos_fetch_lengths(res);
2465
    tstrncpy(pTblName, (char *)row[0], len[0]+1);
2466 2467 2468
    //printf("==== sub table name: %s\n", pTblName);
    count++;
    if (count >= childTblCount - 1) {
2469
      char *tmp = realloc(childTblName,
2470
              (size_t)childTblCount*1.5*TSDB_TABLE_NAME_LEN+1);
2471 2472 2473
      if (tmp != NULL) {
        childTblName = tmp;
        childTblCount = (int)(childTblCount*1.5);
2474
        memset(childTblName + count*TSDB_TABLE_NAME_LEN, 0,
2475
                (size_t)((childTblCount-count)*TSDB_TABLE_NAME_LEN));
2476 2477
      } else {
        // exit, if allocate more memory failed
2478
        errorPrint("%s() LN%d, realloc fail for save child table name of %s.%s\n",
2479
               __func__, __LINE__, dbName, sTblName);
2480 2481 2482 2483 2484 2485
        tmfree(childTblName);
        taos_free_result(res);
        taos_close(taos);
        exit(-1);
      }
    }
2486
    pTblName = childTblName + count * TSDB_TABLE_NAME_LEN;
2487
  }
2488

2489 2490 2491 2492 2493 2494 2495
  *childTblCountOfSuperTbl = count;
  *childTblNameOfSuperTbl  = childTblName;

  taos_free_result(res);
  return 0;
}

2496
static int getAllChildNameOfSuperTable(TAOS * taos, char* dbName,
2497
        char* sTblName, char** childTblNameOfSuperTbl,
2498
        int64_t* childTblCountOfSuperTbl) {
2499

2500 2501
    return getChildNameOfSuperTableWithLimitAndOffset(taos, dbName, sTblName,
            childTblNameOfSuperTbl, childTblCountOfSuperTbl,
2502
            -1, 0);
2503 2504
}

2505
static int getSuperTableFromServer(TAOS * taos, char* dbName,
2506
        SSuperTable*  superTbls) {
2507

2508
  char command[BUFFER_SIZE] = "\0";
2509
  TAOS_RES * res;
2510 2511
  TAOS_ROW row = NULL;
  int count = 0;
2512

2513
  //get schema use cmd: describe superTblName;
2514
  snprintf(command, BUFFER_SIZE, "describe %s.%s", dbName, superTbls->sTblName);
2515
  res = taos_query(taos, command);
2516 2517 2518
  int32_t code = taos_errno(res);
  if (code != 0) {
    printf("failed to run command %s\n", command);
2519
    taos_free_result(res);
2520 2521 2522 2523 2524 2525
    return -1;
  }

  int tagIndex = 0;
  int columnIndex = 0;
  TAOS_FIELD *fields = taos_fetch_fields(res);
2526
  while((row = taos_fetch_row(res)) != NULL) {
2527 2528 2529
    if (0 == count) {
      count++;
      continue;
2530
    }
2531 2532

    if (strcmp((char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], "TAG") == 0) {
2533
      tstrncpy(superTbls->tags[tagIndex].field,
2534 2535
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2536
      tstrncpy(superTbls->tags[tagIndex].dataType,
2537 2538
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2539 2540 2541
      superTbls->tags[tagIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->tags[tagIndex].note,
2542 2543
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2544
      tagIndex++;
2545
    } else {
2546
      tstrncpy(superTbls->columns[columnIndex].field,
2547 2548
              (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX],
              fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes);
2549
      tstrncpy(superTbls->columns[columnIndex].dataType,
2550 2551
              (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes);
2552 2553 2554
      superTbls->columns[columnIndex].dataLen =
          *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]);
      tstrncpy(superTbls->columns[columnIndex].note,
2555 2556
              (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX],
              fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes);
2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567
      columnIndex++;
    }
    count++;
  }

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

  calcRowLen(superTbls);

2568
/*
2569
  if (TBL_ALREADY_EXISTS == superTbls->childTblExists) {
2570
    //get all child table name use cmd: select tbname from superTblName;
2571 2572 2573
    int childTblCount = 10000;
    superTbls->childTblName = (char*)calloc(1, childTblCount * TSDB_TABLE_NAME_LEN);
    if (superTbls->childTblName == NULL) {
2574
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
2575 2576
      return -1;
    }
2577
    getAllChildNameOfSuperTable(taos, dbName,
2578 2579 2580
            superTbls->sTblName,
            &superTbls->childTblName,
            &superTbls->childTblCount);
2581
  }
2582
  */
2583 2584 2585
  return 0;
}

H
Haojun Liao 已提交
2586
static int createSuperTable(
2587 2588
        TAOS * taos, char* dbName,
        SSuperTable*  superTbl) {
H
Haojun Liao 已提交
2589

2590
  char command[BUFFER_SIZE] = "\0";
2591

2592 2593 2594 2595 2596
  char cols[STRING_LEN] = "\0";
  int colIndex;
  int len = 0;

  int  lenOfOneRow = 0;
2597 2598 2599

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

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

2607
    if (strcasecmp(dataType, "BINARY") == 0) {
2608
      len += snprintf(cols + len, STRING_LEN - len,
2609 2610
          ", col%d %s(%d)", colIndex, "BINARY",
          superTbl->columns[colIndex].dataLen);
2611
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2612
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
2613
      len += snprintf(cols + len, STRING_LEN - len,
2614 2615
          ", col%d %s(%d)", colIndex, "NCHAR",
          superTbl->columns[colIndex].dataLen);
2616
      lenOfOneRow += superTbl->columns[colIndex].dataLen + 3;
2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634
    } 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;
2635
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
2636 2637
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "DOUBLE");
      lenOfOneRow += 42;
2638
    }  else if (strcasecmp(dataType, "TIMESTAMP") == 0) {
2639 2640 2641 2642
      len += snprintf(cols + len, STRING_LEN - len, ", col%d %s", colIndex, "TIMESTAMP");
      lenOfOneRow += 21;
    } else {
      taos_close(taos);
2643
      errorPrint("%s() LN%d, config error data type : %s\n",
2644
         __func__, __LINE__, dataType);
2645 2646 2647 2648
      exit(-1);
    }
  }

2649 2650
  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);
2651 2652

  // save for creating child table
2653 2654 2655
  superTbl->colsOfCreateChildTable = (char*)calloc(len+20, 1);
  if (NULL == superTbl->colsOfCreateChildTable) {
    errorPrint("%s() LN%d, Failed when calloc, size:%d",
2656
           __func__, __LINE__, len+1);
2657 2658 2659 2660
    taos_close(taos);
    exit(-1);
  }

2661
  snprintf(superTbl->colsOfCreateChildTable, len+20, "(ts timestamp%s)", cols);
2662
  verbosePrint("%s() LN%d: %s\n",
2663
      __func__, __LINE__, superTbl->colsOfCreateChildTable);
2664

2665 2666
  if (superTbl->tagCount == 0) {
    errorPrint("%s() LN%d, super table tag count is %d\n",
2667
            __func__, __LINE__, superTbl->tagCount);
2668 2669
    return -1;
  }
2670

2671 2672 2673
  char tags[STRING_LEN] = "\0";
  int tagIndex;
  len = 0;
2674

2675 2676 2677 2678
  int lenOfTagOfOneRow = 0;
  len += snprintf(tags + len, STRING_LEN - len, "(");
  for (tagIndex = 0; tagIndex < superTbl->tagCount; tagIndex++) {
    char* dataType = superTbl->tags[tagIndex].dataType;
2679

2680 2681
    if (strcasecmp(dataType, "BINARY") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2682
              "BINARY", superTbl->tags[tagIndex].dataLen);
2683 2684 2685
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "NCHAR") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s(%d), ", tagIndex,
2686
              "NCHAR", superTbl->tags[tagIndex].dataLen);
2687 2688 2689
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 3;
    } else if (strcasecmp(dataType, "INT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2690
              "INT");
2691 2692 2693
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 11;
    } else if (strcasecmp(dataType, "BIGINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2694
              "BIGINT");
2695 2696 2697
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 21;
    } else if (strcasecmp(dataType, "SMALLINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2698
              "SMALLINT");
2699 2700 2701
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "TINYINT") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2702
              "TINYINT");
2703 2704 2705
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 4;
    } else if (strcasecmp(dataType, "BOOL") == 0)  {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2706
              "BOOL");
2707 2708 2709
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 6;
    } else if (strcasecmp(dataType, "FLOAT") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2710
              "FLOAT");
2711 2712 2713
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 22;
    } else if (strcasecmp(dataType, "DOUBLE") == 0) {
      len += snprintf(tags + len, STRING_LEN - len, "t%d %s, ", tagIndex,
2714
              "DOUBLE");
2715 2716 2717
      lenOfTagOfOneRow += superTbl->tags[tagIndex].dataLen + 42;
    } else {
      taos_close(taos);
2718
      errorPrint("%s() LN%d, config error tag type : %s\n",
2719
         __func__, __LINE__, dataType);
2720
      exit(-1);
2721 2722
    }
  }
2723 2724 2725 2726 2727 2728 2729

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

  superTbl->lenOfTagOfOneRow = lenOfTagOfOneRow;

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

  if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2735 2736 2737
      errorPrint( "create supertable %s failed!\n\n",
              superTbl->sTblName);
      return -1;
2738 2739
  }
  debugPrint("create supertable %s success!\n\n", superTbl->sTblName);
2740 2741 2742
  return 0;
}

2743
static int createDatabasesAndStables() {
2744 2745 2746 2747
  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) {
2748
    errorPrint( "Failed to connect to TDengine, reason:%s\n", taos_errstr(NULL));
2749
    return -1;
2750 2751 2752
  }
  char command[BUFFER_SIZE] = "\0";

2753
  for (int i = 0; i < g_Dbs.dbCount; i++) {
2754 2755
    if (g_Dbs.db[i].drop) {
      sprintf(command, "drop database if exists %s;", g_Dbs.db[i].dbName);
2756
      verbosePrint("%s() %d command: %s\n", __func__, __LINE__, command);
2757
      if (0 != queryDbExec(taos, command, NO_INSERT_TYPE, false)) {
2758 2759 2760 2761
        taos_close(taos);
        return -1;
      }

2762
      int dataLen = 0;
2763
      dataLen += snprintf(command + dataLen,
2764
          BUFFER_SIZE - dataLen, "create database if not exists %s", g_Dbs.db[i].dbName);
2765

2766 2767
      if (g_Dbs.db[i].dbCfg.blocks > 0) {
        dataLen += snprintf(command + dataLen,
2768
            BUFFER_SIZE - dataLen, " blocks %d", g_Dbs.db[i].dbCfg.blocks);
2769 2770 2771
      }
      if (g_Dbs.db[i].dbCfg.cache > 0) {
        dataLen += snprintf(command + dataLen,
2772
            BUFFER_SIZE - dataLen, " cache %d", g_Dbs.db[i].dbCfg.cache);
2773 2774 2775
      }
      if (g_Dbs.db[i].dbCfg.days > 0) {
        dataLen += snprintf(command + dataLen,
2776
            BUFFER_SIZE - dataLen, " days %d", g_Dbs.db[i].dbCfg.days);
2777 2778 2779
      }
      if (g_Dbs.db[i].dbCfg.keep > 0) {
        dataLen += snprintf(command + dataLen,
2780
            BUFFER_SIZE - dataLen, " keep %d", g_Dbs.db[i].dbCfg.keep);
2781 2782 2783
      }
      if (g_Dbs.db[i].dbCfg.quorum > 1) {
        dataLen += snprintf(command + dataLen,
2784
            BUFFER_SIZE - dataLen, " quorum %d", g_Dbs.db[i].dbCfg.quorum);
2785 2786 2787
      }
      if (g_Dbs.db[i].dbCfg.replica > 0) {
        dataLen += snprintf(command + dataLen,
2788
            BUFFER_SIZE - dataLen, " replica %d", g_Dbs.db[i].dbCfg.replica);
2789 2790 2791
      }
      if (g_Dbs.db[i].dbCfg.update > 0) {
        dataLen += snprintf(command + dataLen,
2792
            BUFFER_SIZE - dataLen, " update %d", g_Dbs.db[i].dbCfg.update);
2793 2794 2795 2796 2797 2798 2799
      }
      //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,
2800
            BUFFER_SIZE - dataLen, " minrows %d", g_Dbs.db[i].dbCfg.minRows);
2801 2802 2803
      }
      if (g_Dbs.db[i].dbCfg.maxRows > 0) {
        dataLen += snprintf(command + dataLen,
2804
            BUFFER_SIZE - dataLen, " maxrows %d", g_Dbs.db[i].dbCfg.maxRows);
2805 2806 2807
      }
      if (g_Dbs.db[i].dbCfg.comp > 0) {
        dataLen += snprintf(command + dataLen,
2808
            BUFFER_SIZE - dataLen, " comp %d", g_Dbs.db[i].dbCfg.comp);
2809 2810 2811
      }
      if (g_Dbs.db[i].dbCfg.walLevel > 0) {
        dataLen += snprintf(command + dataLen,
2812
            BUFFER_SIZE - dataLen, " wal %d", g_Dbs.db[i].dbCfg.walLevel);
2813 2814 2815
      }
      if (g_Dbs.db[i].dbCfg.cacheLast > 0) {
        dataLen += snprintf(command + dataLen,
2816
            BUFFER_SIZE - dataLen, " cachelast %d", g_Dbs.db[i].dbCfg.cacheLast);
2817 2818 2819
      }
      if (g_Dbs.db[i].dbCfg.fsync > 0) {
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2820
                " fsync %d", g_Dbs.db[i].dbCfg.fsync);
2821 2822
      }
      if ((0 == strncasecmp(g_Dbs.db[i].dbCfg.precision, "ms", strlen("ms")))
2823 2824
              || (0 == strncasecmp(g_Dbs.db[i].dbCfg.precision,
                      "us", strlen("us")))) {
2825
        dataLen += snprintf(command + dataLen, BUFFER_SIZE - dataLen,
2826
                " precision \'%s\';", g_Dbs.db[i].dbCfg.precision);
2827 2828 2829 2830 2831 2832 2833 2834 2835
      }

      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);
2836 2837
    }

2838
    debugPrint("%s() LN%d supertbl count:%"PRIu64"\n",
2839
            __func__, __LINE__, g_Dbs.db[i].superTblCount);
2840 2841 2842

    int validStbCount = 0;

S
Shuduo Sang 已提交
2843
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
2844 2845 2846 2847 2848 2849 2850
      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)) {
2851
        ret = createSuperTable(taos, g_Dbs.db[i].dbName,
2852
                &g_Dbs.db[i].superTbls[j]);
2853

2854
        if (0 != ret) {
S
Shuduo Sang 已提交
2855
          errorPrint("create super table %"PRIu64" failed!\n\n", j);
2856
          continue;
2857 2858 2859
        }
      }

2860
      ret = getSuperTableFromServer(taos, g_Dbs.db[i].dbName,
2861
                &g_Dbs.db[i].superTbls[j]);
2862 2863
      if (0 != ret) {
        errorPrint("\nget super table %s.%s info failed!\n\n",
2864
                g_Dbs.db[i].dbName, g_Dbs.db[i].superTbls[j].sTblName);
2865
        continue;
2866
      }
2867 2868

      validStbCount ++;
2869
    }
2870 2871

    g_Dbs.db[i].superTblCount = validStbCount;
2872 2873 2874 2875 2876 2877
  }

  taos_close(taos);
  return 0;
}

2878 2879
static void* createTable(void *sarg)
{
2880 2881
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
2882

S
Shuduo Sang 已提交
2883
  uint64_t  lastPrintTime = taosGetTimestampMs();
2884

2885
  int buff_len;
2886
  buff_len = BUFFER_SIZE / 8;
2887

2888
  char *buffer = calloc(buff_len, 1);
2889
  if (buffer == NULL) {
2890
    errorPrint("%s() LN%d, Memory allocated failed!\n", __func__, __LINE__);
2891 2892
    exit(-1);
  }
2893 2894 2895

  int len = 0;
  int batchNum = 0;
2896

2897
  verbosePrint("%s() LN%d: Creating table from %"PRIu64" to %"PRIu64"\n",
2898 2899
          __func__, __LINE__,
          pThreadInfo->start_table_from, pThreadInfo->end_table_to);
2900

2901
  for (uint64_t i = pThreadInfo->start_table_from;
2902
          i <= pThreadInfo->end_table_to; i++) {
2903
    if (0 == g_Dbs.use_metric) {
2904
      snprintf(buffer, buff_len,
2905
              "create table if not exists %s.%s%"PRIu64" %s;",
2906 2907 2908
              pThreadInfo->db_name,
              g_args.tb_prefix, i,
              pThreadInfo->cols);
2909
    } else {
2910 2911
      if (superTblInfo == NULL) {
        errorPrint("%s() LN%d, use metric, but super table info is NULL\n",
2912
                  __func__, __LINE__);
2913
        free(buffer);
2914 2915 2916 2917 2918 2919
        exit(-1);
      } else {
        if (0 == len) {
          batchNum = 0;
          memset(buffer, 0, buff_len);
          len += snprintf(buffer + len,
2920
                  buff_len - len, "create table ");
2921 2922 2923
        }
        char* tagsValBuf = NULL;
        if (0 == superTblInfo->tagSource) {
2924
          tagsValBuf = generateTagVaulesForStb(superTblInfo, i);
2925 2926
        } else {
          tagsValBuf = getTagValueFromTagSample(
2927 2928
                  superTblInfo,
                  i % superTblInfo->tagSampleCount);
2929 2930 2931 2932 2933 2934
        }
        if (NULL == tagsValBuf) {
          free(buffer);
          return NULL;
        }
        len += snprintf(buffer + len,
2935
                buff_len - len,
2936
                "if not exists %s.%s%"PRIu64" using %s.%s tags %s ",
2937 2938 2939
                pThreadInfo->db_name, superTblInfo->childTblPrefix,
                i, pThreadInfo->db_name,
                superTblInfo->sTblName, tagsValBuf);
2940 2941 2942
        free(tagsValBuf);
        batchNum++;
        if ((batchNum < superTblInfo->batchCreateTableNum)
2943 2944
                && ((buff_len - len)
                    >= (superTblInfo->lenOfTagOfOneRow + 256))) {
2945 2946
          continue;
        }
2947 2948 2949 2950
      }
    }

    len = 0;
2951
    verbosePrint("%s() LN%d %s\n", __func__, __LINE__, buffer);
2952
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)){
2953
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2954
      free(buffer);
2955 2956 2957
      return NULL;
    }

S
Shuduo Sang 已提交
2958
    uint64_t  currentPrintTime = taosGetTimestampMs();
2959
    if (currentPrintTime - lastPrintTime > 30*1000) {
2960
      printf("thread[%d] already create %"PRIu64" - %"PRIu64" tables\n",
2961
              pThreadInfo->threadID, pThreadInfo->start_table_from, i);
2962 2963 2964
      lastPrintTime = currentPrintTime;
    }
  }
2965

2966
  if (0 != len) {
2967
    verbosePrint("%s() %d buffer: %s\n", __func__, __LINE__, buffer);
2968
    if (0 != queryDbExec(pThreadInfo->taos, buffer, NO_INSERT_TYPE, false)) {
2969
      errorPrint( "queryDbExec() failed. buffer:\n%s\n", buffer);
2970
    }
2971
  }
2972

2973 2974 2975 2976
  free(buffer);
  return NULL;
}

2977
static int startMultiThreadCreateChildTable(
S
Shuduo Sang 已提交
2978
        char* cols, int threads, uint64_t startFrom, int64_t ntables,
2979
        char* db_name, SSuperTable* superTblInfo) {
2980

2981
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
2982
  threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
2983 2984 2985 2986 2987 2988 2989 2990 2991 2992

  if ((NULL == pids) || (NULL == infos)) {
    printf("malloc failed\n");
    exit(-1);
  }

  if (threads < 1) {
    threads = 1;
  }

S
Shuduo Sang 已提交
2993
  int64_t a = ntables / threads;
2994 2995 2996 2997 2998
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

S
Shuduo Sang 已提交
2999
  int64_t b = 0;
3000
  b = ntables % threads;
3001

3002 3003 3004 3005 3006
  for (int64_t i = 0; i < threads; i++) {
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
    tstrncpy(pThreadInfo->db_name, db_name, MAX_DB_NAME_SIZE);
    pThreadInfo->superTblInfo = superTblInfo;
3007
    verbosePrint("%s() %d db_name: %s\n", __func__, __LINE__, db_name);
3008
    pThreadInfo->taos = taos_connect(
3009 3010 3011 3012 3013
            g_Dbs.host,
            g_Dbs.user,
            g_Dbs.password,
            db_name,
            g_Dbs.port);
3014
    if (pThreadInfo->taos == NULL) {
3015
      errorPrint( "%s() LN%d, Failed to connect to TDengine, reason:%s\n",
3016
         __func__, __LINE__, taos_errstr(NULL));
3017
      free(pids);
3018
      free(infos);
3019 3020
      return -1;
    }
3021

3022 3023 3024 3025 3026 3027 3028 3029
    pThreadInfo->start_table_from = startFrom;
    pThreadInfo->ntables = i<b?a+1:a;
    pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
    startFrom = pThreadInfo->end_table_to + 1;
    pThreadInfo->use_metric = true;
    pThreadInfo->cols = cols;
    pThreadInfo->minDelay = UINT64_MAX;
    pthread_create(pids + i, NULL, createTable, pThreadInfo);
3030
  }
3031

3032 3033 3034 3035 3036
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

  for (int i = 0; i < threads; i++) {
3037 3038
    threadInfo *pThreadInfo = infos + i;
    taos_close(pThreadInfo->taos);
3039 3040 3041
  }

  free(pids);
3042
  free(infos);
3043 3044

  return 0;
3045 3046
}

3047
static void createChildTables() {
3048 3049
    char tblColsBuf[MAX_SQL_SIZE];
    int len;
3050

3051
  for (int i = 0; i < g_Dbs.dbCount; i++) {
3052 3053
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
3054
          // with super table
S
Shuduo Sang 已提交
3055
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
3056
          if ((AUTO_CREATE_SUBTBL == g_Dbs.db[i].superTbls[j].autoCreateTable)
3057
                || (TBL_ALREADY_EXISTS == g_Dbs.db[i].superTbls[j].childTblExists)) {
3058 3059
            continue;
          }
3060

3061
          verbosePrint("%s() LN%d: %s\n", __func__, __LINE__,
3062
                  g_Dbs.db[i].superTbls[j].colsOfCreateChildTable);
S
Shuduo Sang 已提交
3063
          uint64_t startFrom = 0;
3064 3065
          g_totalChildTables += g_Dbs.db[i].superTbls[j].childTblCount;

3066
          verbosePrint("%s() LN%d: create %"PRId64" child tables from %"PRIu64"\n",
3067
                  __func__, __LINE__, g_totalChildTables, startFrom);
3068
          startMultiThreadCreateChildTable(
3069 3070 3071 3072 3073
                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]));
3074
        }
3075 3076
      }
    } else {
3077 3078
      // normal table
      len = snprintf(tblColsBuf, MAX_SQL_SIZE, "(TS TIMESTAMP");
H
Haojun Liao 已提交
3079
      for (int j = 0; j < g_args.num_of_CPR; j++) {
3080 3081 3082 3083 3084 3085 3086 3087 3088 3089
          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);
3090
      }
3091

3092
      snprintf(tblColsBuf + len, MAX_SQL_SIZE - len, ")");
3093

3094
      verbosePrint("%s() LN%d: dbName: %s num of tb: %"PRId64" schema: %s\n",
3095 3096
              __func__, __LINE__,
              g_Dbs.db[i].dbName, g_args.num_of_tables, tblColsBuf);
3097
      startMultiThreadCreateChildTable(
3098 3099 3100 3101 3102 3103
            tblColsBuf,
            g_Dbs.threadCountByCreateTbl,
            0,
            g_args.num_of_tables,
            g_Dbs.db[i].dbName,
            NULL);
3104
    }
3105 3106 3107 3108 3109 3110
  }
}

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3111
static int readTagFromCsvFileToMem(SSuperTable  * superTblInfo) {
3112 3113 3114
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
3115

3116 3117
  FILE *fp = fopen(superTblInfo->tagsFile, "r");
  if (fp == NULL) {
3118
    printf("Failed to open tags file: %s, reason:%s\n",
3119
            superTblInfo->tagsFile, strerror(errno));
3120 3121 3122 3123 3124 3125 3126
    return -1;
  }

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

3128 3129 3130 3131 3132 3133 3134 3135 3136
  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;
  }

3137
  while((readLen = tgetline(&line, &n, fp)) != -1) {
3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149
    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) {
3150
      char *tmp = realloc(tagDataBuf,
3151
              (size_t)tagCount*1.5*superTblInfo->lenOfTagOfOneRow);
3152 3153 3154
      if (tmp != NULL) {
        tagDataBuf = tmp;
        tagCount = (int)(tagCount*1.5);
3155
        memset(tagDataBuf + count*superTblInfo->lenOfTagOfOneRow,
3156
                0, (size_t)((tagCount-count)*superTblInfo->lenOfTagOfOneRow));
3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175
      } 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;
}

3176
#if 0
3177 3178 3179 3180
int readSampleFromJsonFileToMem(SSuperTable  * superTblInfo) {
  // TODO
  return 0;
}
3181
#endif
3182 3183 3184 3185

/*
  Read 10000 lines at most. If more than 10000 lines, continue to read after using
*/
3186
static int readSampleFromCsvFileToMem(
3187
        SSuperTable* superTblInfo) {
3188 3189 3190 3191
  size_t  n = 0;
  ssize_t readLen = 0;
  char *  line = NULL;
  int getRows = 0;
3192

3193 3194
  FILE*  fp = fopen(superTblInfo->sampleFile, "r");
  if (fp == NULL) {
3195 3196 3197
      errorPrint( "Failed to open sample file: %s, reason:%s\n",
              superTblInfo->sampleFile, strerror(errno));
      return -1;
3198
  }
3199

3200
  assert(superTblInfo->sampleDataBuf);
3201
  memset(superTblInfo->sampleDataBuf, 0,
3202
          MAX_SAMPLES_ONCE_FROM_FILE * superTblInfo->lenOfOneRow);
3203
  while(1) {
3204
    readLen = tgetline(&line, &n, fp);
3205 3206
    if (-1 == readLen) {
      if(0 != fseek(fp, 0, SEEK_SET)) {
3207
        errorPrint( "Failed to fseek file: %s, reason:%s\n",
3208
                superTblInfo->sampleFile, strerror(errno));
3209
        fclose(fp);
3210 3211 3212 3213
        return -1;
      }
      continue;
    }
3214

3215 3216 3217 3218 3219 3220 3221 3222 3223
    if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
      line[--readLen] = 0;
    }

    if (readLen == 0) {
      continue;
    }

    if (readLen > superTblInfo->lenOfOneRow) {
3224
      printf("sample row len[%d] overflow define schema len[%"PRIu64"], so discard this row\n",
3225
              (int32_t)readLen, superTblInfo->lenOfOneRow);
3226 3227 3228
      continue;
    }

3229
    memcpy(superTblInfo->sampleDataBuf + getRows * superTblInfo->lenOfOneRow,
3230
          line, readLen);
3231 3232 3233 3234 3235 3236 3237
    getRows++;

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

3238
  fclose(fp);
3239 3240 3241 3242
  tmfree(line);
  return 0;
}

3243
static bool getColumnAndTagTypeFromInsertJsonFile(
3244
        cJSON* stbInfo, SSuperTable* superTbls) {
3245
  bool  ret = false;
3246

3247
  // columns
3248 3249
  cJSON *columns = cJSON_GetObjectItem(stbInfo, "columns");
  if (columns && columns->type != cJSON_Array) {
3250
    printf("ERROR: failed to read json, columns not found\n");
3251 3252 3253 3254 3255 3256
    goto PARSE_OVER;
  } else if (NULL == columns) {
    superTbls->columnCount = 0;
    superTbls->tagCount    = 0;
    return true;
  }
3257

3258
  int columnSize = cJSON_GetArraySize(columns);
3259
  if ((columnSize + 1/* ts */) > MAX_COLUMN_COUNT) {
3260
    errorPrint("%s() LN%d, failed to read json, column size overflow, max column size is %d\n",
3261
            __func__, __LINE__, MAX_COLUMN_COUNT);
3262 3263 3264 3265 3266 3267
    goto PARSE_OVER;
  }

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

3269
  //superTbls->columnCount = columnSize;
3270 3271 3272 3273 3274 3275 3276
  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) {
3277
      count = countObj->valueint;
3278
    } else if (countObj && countObj->type != cJSON_Number) {
3279
      errorPrint("%s() LN%d, failed to read json, column count not found\n",
3280
          __func__, __LINE__);
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(column, "type");
3289 3290 3291
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d: failed to read json, column type not found\n",
3292
          __func__, __LINE__);
3293 3294
      goto PARSE_OVER;
    }
3295 3296
    //tstrncpy(superTbls->columns[k].dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3297

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

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

3317 3318
  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",
3319
            __func__, __LINE__, MAX_COLUMN_COUNT);
3320 3321 3322
    goto PARSE_OVER;
  }

3323
  superTbls->columnCount = index;
3324

3325 3326
  count = 1;
  index = 0;
3327
  // tags
3328 3329
  cJSON *tags = cJSON_GetObjectItem(stbInfo, "tags");
  if (!tags || tags->type != cJSON_Array) {
3330
    errorPrint("%s() LN%d, failed to read json, tags not found\n",
3331
        __func__, __LINE__);
3332 3333
    goto PARSE_OVER;
  }
3334

3335 3336
  int tagSize = cJSON_GetArraySize(tags);
  if (tagSize > MAX_TAG_COUNT) {
3337
    errorPrint("%s() LN%d, failed to read json, tags size overflow, max tag size is %d\n",
3338
        __func__, __LINE__, MAX_TAG_COUNT);
3339 3340
    goto PARSE_OVER;
  }
3341 3342

  //superTbls->tagCount = tagSize;
3343 3344 3345
  for (int k = 0; k < tagSize; ++k) {
    cJSON* tag = cJSON_GetArrayItem(tags, k);
    if (tag == NULL) continue;
3346

3347 3348 3349
    count = 1;
    cJSON* countObj = cJSON_GetObjectItem(tag, "count");
    if (countObj && countObj->type == cJSON_Number) {
3350
      count = countObj->valueint;
3351
    } else if (countObj && countObj->type != cJSON_Number) {
3352
      printf("ERROR: failed to read json, column count not found\n");
3353 3354 3355 3356 3357
      goto PARSE_OVER;
    } else {
      count = 1;
    }

3358
    // column info
3359 3360
    memset(&columnCase, 0, sizeof(StrColumn));
    cJSON *dataType = cJSON_GetObjectItem(tag, "type");
3361 3362 3363
    if (!dataType || dataType->type != cJSON_String
        || dataType->valuestring == NULL) {
      errorPrint("%s() LN%d, failed to read json, tag type not found\n",
3364
          __func__, __LINE__);
3365 3366
      goto PARSE_OVER;
    }
3367
    tstrncpy(columnCase.dataType, dataType->valuestring, MAX_TB_NAME_SIZE);
3368

3369 3370
    cJSON* dataLen = cJSON_GetObjectItem(tag, "len");
    if (dataLen && dataLen->type == cJSON_Number) {
3371
      columnCase.dataLen = dataLen->valueint;
3372
    } else if (dataLen && dataLen->type != cJSON_Number) {
3373
      errorPrint("%s() LN%d, failed to read json, column len not found\n",
3374
          __func__, __LINE__);
3375 3376 3377
      goto PARSE_OVER;
    } else {
      columnCase.dataLen = 0;
3378 3379
    }

3380
    for (int n = 0; n < count; ++n) {
3381
      tstrncpy(superTbls->tags[index].dataType, columnCase.dataType,
3382
          MAX_TB_NAME_SIZE);
3383
      superTbls->tags[index].dataLen = columnCase.dataLen;
3384 3385
      index++;
    }
3386
  }
3387 3388

  if (index > MAX_TAG_COUNT) {
3389
    errorPrint("%s() LN%d, failed to read json, tags size overflow, allowed max tag count is %d\n",
3390
        __func__, __LINE__, MAX_TAG_COUNT);
3391 3392 3393
    goto PARSE_OVER;
  }

3394 3395
  superTbls->tagCount = index;

3396 3397
  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",
3398
        __func__, __LINE__, MAX_COLUMN_COUNT);
3399 3400
    goto PARSE_OVER;
  }
3401 3402
  ret = true;

3403
PARSE_OVER:
3404 3405 3406 3407 3408 3409 3410 3411
  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) {
3412
    tstrncpy(g_Dbs.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
3413 3414 3415 3416
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
3417
    tstrncpy(g_Dbs.host, host->valuestring, MAX_HOSTNAME_SIZE);
3418
  } else if (!host) {
3419
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
3420
  } else {
3421
    printf("ERROR: failed to read json, host not found\n");
3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433
    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) {
3434
    tstrncpy(g_Dbs.user, user->valuestring, MAX_USERNAME_SIZE);
3435
  } else if (!user) {
3436
    tstrncpy(g_Dbs.user, "root", MAX_USERNAME_SIZE);
3437 3438 3439 3440
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
3441
    tstrncpy(g_Dbs.password, password->valuestring, MAX_PASSWORD_SIZE);
3442
  } else if (!password) {
3443
    tstrncpy(g_Dbs.password, "taosdata", MAX_PASSWORD_SIZE);
3444 3445 3446 3447
  }

  cJSON* resultfile = cJSON_GetObjectItem(root, "result_file");
  if (resultfile && resultfile->type == cJSON_String && resultfile->valuestring != NULL) {
3448
    tstrncpy(g_Dbs.resultFile, resultfile->valuestring, MAX_FILE_NAME_LEN);
3449
  } else if (!resultfile) {
3450
    tstrncpy(g_Dbs.resultFile, "./insert_res.txt", MAX_FILE_NAME_LEN);
3451 3452 3453 3454 3455 3456 3457 3458
  }

  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 {
3459
    printf("ERROR: failed to read json, threads not found\n");
3460
    goto PARSE_OVER;
3461 3462
  }

3463 3464 3465 3466
  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 已提交
3467
    g_Dbs.threadCountByCreateTbl = 1;
3468
  } else {
3469
    errorPrint("%s() LN%d, failed to read json, threads2 not found\n",
3470
            __func__, __LINE__);
3471
    goto PARSE_OVER;
3472
  }
3473

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

3490 3491
  cJSON* interlaceRows = cJSON_GetObjectItem(root, "interlace_rows");
  if (interlaceRows && interlaceRows->type == cJSON_Number) {
3492 3493 3494 3495 3496 3497
    if (interlaceRows->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;

    }
3498 3499
    g_args.interlace_rows = interlaceRows->valueint;
  } else if (!interlaceRows) {
3500
    g_args.interlace_rows = 0; // 0 means progressive mode, > 0 mean interlace mode. max value is less or equ num_of_records_per_req
3501
  } else {
3502
    errorPrint("%s() LN%d, failed to read json, interlace_rows input mistake\n",
3503
        __func__, __LINE__);
3504
    goto PARSE_OVER;
3505
  }
3506

3507 3508
  cJSON* maxSqlLen = cJSON_GetObjectItem(root, "max_sql_len");
  if (maxSqlLen && maxSqlLen->type == cJSON_Number) {
3509 3510 3511 3512 3513
    if (maxSqlLen->valueint < 0) {
      errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
    }
3514 3515
    g_args.max_sql_len = maxSqlLen->valueint;
  } else if (!maxSqlLen) {
sangshuduo's avatar
sangshuduo 已提交
3516
    g_args.max_sql_len = (1024*1024);
3517
  } else {
3518
    errorPrint("%s() LN%d, failed to read json, max_sql_len input mistake\n",
3519
        __func__, __LINE__);
3520 3521 3522 3523 3524
    goto PARSE_OVER;
  }

  cJSON* numRecPerReq = cJSON_GetObjectItem(root, "num_of_records_per_req");
  if (numRecPerReq && numRecPerReq->type == cJSON_Number) {
3525
    if (numRecPerReq->valueint <= 0) {
3526 3527 3528
      errorPrint("%s() LN%d, failed to read json, num_of_records_per_req input mistake\n",
        __func__, __LINE__);
      goto PARSE_OVER;
3529
    } else if (numRecPerReq->valueint > MAX_RECORDS_PER_REQ) {
3530 3531 3532 3533 3534
      printf("NOTICE: number of records per request value %"PRIu64" > %d\n\n",
              numRecPerReq->valueint, MAX_RECORDS_PER_REQ);
      printf("        number of records per request value will be set to %d\n\n",
              MAX_RECORDS_PER_REQ);
      prompt();
3535
      numRecPerReq->valueint = MAX_RECORDS_PER_REQ;
3536
    }
3537 3538
    g_args.num_of_RPR = numRecPerReq->valueint;
  } else if (!numRecPerReq) {
3539
    g_args.num_of_RPR = MAX_RECORDS_PER_REQ;
3540
  } else {
3541
    errorPrint("%s() LN%d, failed to read json, num_of_records_per_req not found\n",
3542
        __func__, __LINE__);
3543 3544 3545
    goto PARSE_OVER;
  }

3546
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
3547
  if (answerPrompt
3548 3549
          && answerPrompt->type == cJSON_String
          && answerPrompt->valuestring != NULL) {
3550 3551 3552 3553 3554 3555 3556 3557
    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) {
3558
    g_args.answer_yes = true;   // default is no, mean answer_yes.
3559
  } else {
3560
    errorPrint("%s", "failed to read json, confirm_parameter_prompt input mistake\n");
3561
    goto PARSE_OVER;
3562
  }
3563

3564 3565 3566 3567 3568 3569 3570 3571 3572 3573
  // rows per table need be less than insert batch
  if (g_args.interlace_rows > g_args.num_of_RPR) {
      printf("NOTICE: interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
              g_args.interlace_rows, g_args.num_of_RPR);
      printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
              g_args.num_of_RPR);
      prompt();
      g_args.interlace_rows = g_args.num_of_RPR;
  }

3574 3575
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (!dbs || dbs->type != cJSON_Array) {
3576
    printf("ERROR: failed to read json, databases not found\n");
3577 3578 3579 3580 3581
    goto PARSE_OVER;
  }

  int dbSize = cJSON_GetArraySize(dbs);
  if (dbSize > MAX_DB_COUNT) {
3582
    errorPrint(
3583 3584
            "ERROR: failed to read json, databases size overflow, max database is %d\n",
            MAX_DB_COUNT);
3585 3586 3587 3588 3589 3590 3591 3592
    goto PARSE_OVER;
  }

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

3593
    // dbinfo
3594 3595
    cJSON *dbinfo = cJSON_GetObjectItem(dbinfos, "dbinfo");
    if (!dbinfo || dbinfo->type != cJSON_Object) {
3596
      printf("ERROR: failed to read json, dbinfo not found\n");
3597 3598
      goto PARSE_OVER;
    }
3599

3600 3601
    cJSON *dbName = cJSON_GetObjectItem(dbinfo, "name");
    if (!dbName || dbName->type != cJSON_String || dbName->valuestring == NULL) {
3602
      printf("ERROR: failed to read json, db name not found\n");
3603 3604
      goto PARSE_OVER;
    }
3605
    tstrncpy(g_Dbs.db[i].dbName, dbName->valuestring, MAX_DB_NAME_SIZE);
3606 3607 3608

    cJSON *drop = cJSON_GetObjectItem(dbinfo, "drop");
    if (drop && drop->type == cJSON_String && drop->valuestring != NULL) {
3609 3610
      if (0 == strncasecmp(drop->valuestring, "yes", strlen("yes"))) {
        g_Dbs.db[i].drop = true;
3611
      } else {
3612
        g_Dbs.db[i].drop = false;
3613
      }
3614
    } else if (!drop) {
3615
      g_Dbs.db[i].drop = g_args.drop_database;
3616
    } else {
3617
      errorPrint("%s() LN%d, failed to read json, drop input mistake\n",
3618
              __func__, __LINE__);
3619 3620 3621 3622
      goto PARSE_OVER;
    }

    cJSON *precision = cJSON_GetObjectItem(dbinfo, "precision");
3623
    if (precision && precision->type == cJSON_String
3624
            && precision->valuestring != NULL) {
3625
      tstrncpy(g_Dbs.db[i].dbCfg.precision, precision->valuestring,
3626
              MAX_DB_NAME_SIZE);
3627
    } else if (!precision) {
3628
      //tstrncpy(g_Dbs.db[i].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
3629 3630
      memset(g_Dbs.db[i].dbCfg.precision, 0, MAX_DB_NAME_SIZE);
    } else {
3631
      printf("ERROR: failed to read json, precision not found\n");
3632 3633 3634 3635 3636 3637 3638 3639 3640
      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 {
3641
      printf("ERROR: failed to read json, update not found\n");
3642 3643 3644 3645 3646 3647 3648 3649 3650
      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 {
3651
      printf("ERROR: failed to read json, replica not found\n");
3652 3653 3654 3655 3656 3657 3658 3659 3660
      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 {
3661 3662
     printf("ERROR: failed to read json, keep not found\n");
     goto PARSE_OVER;
3663
    }
3664

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

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

3685 3686 3687 3688 3689 3690
    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 {
3691 3692
     printf("ERROR: failed to read json, block not found\n");
     goto PARSE_OVER;
3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708
    }

    //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) {
3709
      g_Dbs.db[i].dbCfg.minRows = 0;    // 0 means default
3710
    } else {
3711 3712
     printf("ERROR: failed to read json, minRows not found\n");
     goto PARSE_OVER;
3713 3714 3715 3716 3717 3718
    }

    cJSON* maxRows= cJSON_GetObjectItem(dbinfo, "maxRows");
    if (maxRows && maxRows->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.maxRows = maxRows->valueint;
    } else if (!maxRows) {
3719
      g_Dbs.db[i].dbCfg.maxRows = 0;    // 0 means default
3720
    } else {
3721 3722
     printf("ERROR: failed to read json, maxRows not found\n");
     goto PARSE_OVER;
3723 3724 3725 3726 3727 3728 3729 3730
    }

    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 {
3731 3732
     printf("ERROR: failed to read json, comp not found\n");
     goto PARSE_OVER;
3733 3734 3735 3736 3737 3738 3739 3740
    }

    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 {
3741 3742
     printf("ERROR: failed to read json, walLevel not found\n");
     goto PARSE_OVER;
3743 3744
    }

3745 3746 3747 3748 3749 3750
    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 {
3751 3752
     printf("ERROR: failed to read json, cacheLast not found\n");
     goto PARSE_OVER;
3753 3754
    }

3755 3756 3757 3758
    cJSON* quorum= cJSON_GetObjectItem(dbinfo, "quorum");
    if (quorum && quorum->type == cJSON_Number) {
      g_Dbs.db[i].dbCfg.quorum = quorum->valueint;
    } else if (!quorum) {
3759
      g_Dbs.db[i].dbCfg.quorum = 1;
3760
    } else {
3761 3762
     printf("failed to read json, quorum input mistake");
     goto PARSE_OVER;
3763 3764 3765 3766 3767 3768 3769 3770
    }

    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 {
3771
      errorPrint("%s() LN%d, failed to read json, fsync input mistake\n",
3772
              __func__, __LINE__);
3773
      goto PARSE_OVER;
3774
    }
3775

3776
    // super_talbes
3777 3778
    cJSON *stables = cJSON_GetObjectItem(dbinfos, "super_tables");
    if (!stables || stables->type != cJSON_Array) {
3779
      errorPrint("%s() LN%d, failed to read json, super_tables not found\n",
3780
              __func__, __LINE__);
3781
      goto PARSE_OVER;
3782 3783
    }

3784 3785
    int stbSize = cJSON_GetArraySize(stables);
    if (stbSize > MAX_SUPER_TABLE_COUNT) {
3786
      errorPrint(
3787 3788
              "%s() LN%d, failed to read json, supertable size overflow, max supertable is %d\n",
              __func__, __LINE__, MAX_SUPER_TABLE_COUNT);
3789 3790 3791 3792 3793 3794 3795
      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;
3796 3797

      // dbinfo
3798 3799
      cJSON *stbName = cJSON_GetObjectItem(stbInfo, "name");
      if (!stbName || stbName->type != cJSON_String || stbName->valuestring == NULL) {
3800
        errorPrint("%s() LN%d, failed to read json, stb name not found\n",
3801
                __func__, __LINE__);
3802 3803
        goto PARSE_OVER;
      }
3804
      tstrncpy(g_Dbs.db[i].superTbls[j].sTblName, stbName->valuestring, MAX_TB_NAME_SIZE);
3805

3806 3807
      cJSON *prefix = cJSON_GetObjectItem(stbInfo, "childtable_prefix");
      if (!prefix || prefix->type != cJSON_String || prefix->valuestring == NULL) {
3808
        printf("ERROR: failed to read json, childtable_prefix not found\n");
3809 3810
        goto PARSE_OVER;
      }
3811
      tstrncpy(g_Dbs.db[i].superTbls[j].childTblPrefix, prefix->valuestring, MAX_DB_NAME_SIZE);
3812 3813

      cJSON *autoCreateTbl = cJSON_GetObjectItem(stbInfo, "auto_create_table"); // yes, no, null
3814
      if (autoCreateTbl
3815 3816
              && autoCreateTbl->type == cJSON_String
              && autoCreateTbl->valuestring != NULL) {
3817 3818 3819 3820 3821 3822 3823 3824 3825 3826
        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 {
3827
        printf("ERROR: failed to read json, auto_create_table not found\n");
3828 3829
        goto PARSE_OVER;
      }
3830

3831 3832 3833 3834
      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) {
3835
        g_Dbs.db[i].superTbls[j].batchCreateTableNum = 1000;
3836
      } else {
3837
        printf("ERROR: failed to read json, batch_create_tbl_num not found\n");
3838
        goto PARSE_OVER;
3839
      }
3840 3841

      cJSON *childTblExists = cJSON_GetObjectItem(stbInfo, "child_table_exists"); // yes, no
3842
      if (childTblExists
3843 3844
              && childTblExists->type == cJSON_String
              && childTblExists->valuestring != NULL) {
3845 3846
        if ((0 == strncasecmp(childTblExists->valuestring, "yes", 3))
            && (g_Dbs.db[i].drop == false)) {
3847
          g_Dbs.db[i].superTbls[j].childTblExists = TBL_ALREADY_EXISTS;
3848
        } else if ((0 == strncasecmp(childTblExists->valuestring, "no", 2)
3849
              || (g_Dbs.db[i].drop == true))) {
3850 3851 3852 3853 3854 3855 3856
          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 {
3857
        errorPrint("%s() LN%d, failed to read json, child_table_exists not found\n",
3858
                __func__, __LINE__);
3859 3860
        goto PARSE_OVER;
      }
3861

3862 3863
      cJSON* count = cJSON_GetObjectItem(stbInfo, "childtable_count");
      if (!count || count->type != cJSON_Number || 0 >= count->valueint) {
3864
        errorPrint("%s() LN%d, failed to read json, childtable_count input mistake\n",
3865
                __func__, __LINE__);
3866 3867 3868 3869 3870
        goto PARSE_OVER;
      }
      g_Dbs.db[i].superTbls[j].childTblCount = count->valueint;

      cJSON *dataSource = cJSON_GetObjectItem(stbInfo, "data_source");
3871
      if (dataSource && dataSource->type == cJSON_String
3872
              && dataSource->valuestring != NULL) {
3873
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource,
3874
                dataSource->valuestring, MAX_DB_NAME_SIZE);
3875
      } else if (!dataSource) {
3876
        tstrncpy(g_Dbs.db[i].superTbls[j].dataSource, "rand", MAX_DB_NAME_SIZE);
3877
      } else {
3878
        errorPrint("%s() LN%d, failed to read json, data_source not found\n",
3879
            __func__, __LINE__);
3880 3881 3882
        goto PARSE_OVER;
      }

3883
      cJSON *insertMode = cJSON_GetObjectItem(stbInfo, "insert_mode"); // taosc , rest, stmt
3884
      if (insertMode && insertMode->type == cJSON_String
3885
              && insertMode->valuestring != NULL) {
3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896
        if (0 == strcasecmp(insertMode->valuestring, "taosc")) {
            g_Dbs.db[i].superTbls[j].insertMode = TAOSC_IFACE;
        } else if (0 == strcasecmp(insertMode->valuestring, "rest")) {
            g_Dbs.db[i].superTbls[j].insertMode = REST_IFACE;
        } else if (0 == strcasecmp(insertMode->valuestring, "stmt")) {
            g_Dbs.db[i].superTbls[j].insertMode = STMT_IFACE;
        } else {
            errorPrint("%s() LN%d, failed to read json, insert_mode %s not recognized\n",
                    __func__, __LINE__, insertMode->valuestring);
            goto PARSE_OVER;
        }
3897
      } else if (!insertMode) {
3898
        g_Dbs.db[i].superTbls[j].insertMode = TAOSC_IFACE;
3899
      } else {
3900
        errorPrint("%s", "failed to read json, insert_mode not found\n");
3901 3902 3903
        goto PARSE_OVER;
      }

3904
      cJSON* childTbl_limit = cJSON_GetObjectItem(stbInfo, "childtable_limit");
3905 3906
      if ((childTbl_limit) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3907
        if (childTbl_limit->type != cJSON_Number) {
3908 3909
            printf("ERROR: failed to read json, childtable_limit\n");
            goto PARSE_OVER;
3910 3911 3912
        }
        g_Dbs.db[i].superTbls[j].childTblLimit = childTbl_limit->valueint;
      } else {
3913
        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.
3914 3915 3916
      }

      cJSON* childTbl_offset = cJSON_GetObjectItem(stbInfo, "childtable_offset");
3917 3918
      if ((childTbl_offset) && (g_Dbs.db[i].drop != true)
          && (g_Dbs.db[i].superTbls[j].childTblExists == TBL_ALREADY_EXISTS)) {
3919
        if (childTbl_offset->type != cJSON_Number || 0 > childTbl_offset->valueint) {
3920 3921
            printf("ERROR: failed to read json, childtable_offset\n");
            goto PARSE_OVER;
3922 3923 3924 3925 3926 3927
        }
        g_Dbs.db[i].superTbls[j].childTblOffset = childTbl_offset->valueint;
      } else {
        g_Dbs.db[i].superTbls[j].childTblOffset = 0;
      }

3928 3929
      cJSON *ts = cJSON_GetObjectItem(stbInfo, "start_timestamp");
      if (ts && ts->type == cJSON_String && ts->valuestring != NULL) {
3930
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3931
                ts->valuestring, MAX_DB_NAME_SIZE);
3932
      } else if (!ts) {
3933
        tstrncpy(g_Dbs.db[i].superTbls[j].startTimestamp,
3934
                "now", MAX_DB_NAME_SIZE);
3935
      } else {
3936
        printf("ERROR: failed to read json, start_timestamp not found\n");
3937 3938
        goto PARSE_OVER;
      }
3939

3940 3941 3942 3943
      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) {
3944
        g_Dbs.db[i].superTbls[j].timeStampStep = DEFAULT_TIMESTAMP_STEP;
3945
      } else {
3946
        printf("ERROR: failed to read json, timestamp_step not found\n");
3947 3948 3949 3950
        goto PARSE_OVER;
      }

      cJSON *sampleFormat = cJSON_GetObjectItem(stbInfo, "sample_format");
3951
      if (sampleFormat && sampleFormat->type
3952
              == cJSON_String && sampleFormat->valuestring != NULL) {
3953
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat,
3954
                sampleFormat->valuestring, MAX_DB_NAME_SIZE);
3955
      } else if (!sampleFormat) {
3956
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFormat, "csv", MAX_DB_NAME_SIZE);
3957
      } else {
3958
        printf("ERROR: failed to read json, sample_format not found\n");
3959
        goto PARSE_OVER;
3960
      }
3961

3962
      cJSON *sampleFile = cJSON_GetObjectItem(stbInfo, "sample_file");
3963 3964
      if (sampleFile && sampleFile->type == cJSON_String
          && sampleFile->valuestring != NULL) {
3965
        tstrncpy(g_Dbs.db[i].superTbls[j].sampleFile,
3966
                sampleFile->valuestring, MAX_FILE_NAME_LEN);
3967 3968 3969
      } else if (!sampleFile) {
        memset(g_Dbs.db[i].superTbls[j].sampleFile, 0, MAX_FILE_NAME_LEN);
      } else {
3970
        printf("ERROR: failed to read json, sample_file not found\n");
3971
        goto PARSE_OVER;
3972
      }
3973

3974 3975
      cJSON *tagsFile = cJSON_GetObjectItem(stbInfo, "tags_file");
      if (tagsFile && tagsFile->type == cJSON_String && tagsFile->valuestring != NULL) {
3976
        tstrncpy(g_Dbs.db[i].superTbls[j].tagsFile,
3977
                tagsFile->valuestring, MAX_FILE_NAME_LEN);
3978 3979 3980 3981 3982 3983 3984 3985 3986
        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 {
3987
        printf("ERROR: failed to read json, tags_file not found\n");
3988 3989
        goto PARSE_OVER;
      }
3990

sangshuduo's avatar
sangshuduo 已提交
3991 3992 3993
      cJSON* stbMaxSqlLen = cJSON_GetObjectItem(stbInfo, "max_sql_len");
      if (stbMaxSqlLen && stbMaxSqlLen->type == cJSON_Number) {
        int32_t len = stbMaxSqlLen->valueint;
3994 3995
        if (len > TSDB_MAX_ALLOWED_SQL_LEN) {
          len = TSDB_MAX_ALLOWED_SQL_LEN;
3996 3997
        } else if (len < 5) {
          len = 5;
3998
        }
3999 4000
        g_Dbs.db[i].superTbls[j].maxSqlLen = len;
      } else if (!maxSqlLen) {
4001
        g_Dbs.db[i].superTbls[j].maxSqlLen = g_args.max_sql_len;
4002
      } else {
sangshuduo's avatar
sangshuduo 已提交
4003
        errorPrint("%s() LN%d, failed to read json, stbMaxSqlLen input mistake\n",
4004
            __func__, __LINE__);
4005
        goto PARSE_OVER;
4006
      }
4007
/*
4008 4009 4010 4011 4012
      cJSON *multiThreadWriteOneTbl =
          cJSON_GetObjectItem(stbInfo, "multi_thread_write_one_tbl"); // no , yes
      if (multiThreadWriteOneTbl
              && multiThreadWriteOneTbl->type == cJSON_String
              && multiThreadWriteOneTbl->valuestring != NULL) {
4013 4014 4015 4016
        if (0 == strncasecmp(multiThreadWriteOneTbl->valuestring, "yes", 3)) {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 1;
        } else {
          g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
4017
        }
4018 4019 4020
      } else if (!multiThreadWriteOneTbl) {
        g_Dbs.db[i].superTbls[j].multiThreadWriteOneTbl = 0;
      } else {
4021
        printf("ERROR: failed to read json, multiThreadWriteOneTbl not found\n");
4022 4023
        goto PARSE_OVER;
      }
4024
*/
sangshuduo's avatar
sangshuduo 已提交
4025 4026 4027
      cJSON* stbInterlaceRows = cJSON_GetObjectItem(stbInfo, "interlace_rows");
      if (stbInterlaceRows && stbInterlaceRows->type == cJSON_Number) {
        if (stbInterlaceRows->valueint < 0) {
4028 4029 4030 4031
          errorPrint("%s() LN%d, failed to read json, interlace rows input mistake\n",
            __func__, __LINE__);
          goto PARSE_OVER;
        }
sangshuduo's avatar
sangshuduo 已提交
4032
        g_Dbs.db[i].superTbls[j].interlaceRows = stbInterlaceRows->valueint;
4033 4034
        // rows per table need be less than insert batch
        if (g_Dbs.db[i].superTbls[j].interlaceRows > g_args.num_of_RPR) {
4035
          printf("NOTICE: db[%d].superTbl[%d]'s interlace rows value %"PRIu64" > num_of_records_per_req %"PRIu64"\n\n",
4036
                  i, j, g_Dbs.db[i].superTbls[j].interlaceRows, g_args.num_of_RPR);
4037
          printf("        interlace rows value will be set to num_of_records_per_req %"PRIu64"\n\n",
4038
                  g_args.num_of_RPR);
4039
          prompt();
4040 4041
          g_Dbs.db[i].superTbls[j].interlaceRows = g_args.num_of_RPR;
        }
sangshuduo's avatar
sangshuduo 已提交
4042
      } else if (!stbInterlaceRows) {
4043
        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
4044
      } else {
4045
        errorPrint(
4046 4047
                "%s() LN%d, failed to read json, interlace rows input mistake\n",
                __func__, __LINE__);
4048
        goto PARSE_OVER;
4049
      }
4050 4051 4052

      cJSON* disorderRatio = cJSON_GetObjectItem(stbInfo, "disorder_ratio");
      if (disorderRatio && disorderRatio->type == cJSON_Number) {
4053 4054 4055 4056 4057 4058
        if (disorderRatio->valueint > 50)
          disorderRatio->valueint = 50;

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

4059 4060 4061 4062
        g_Dbs.db[i].superTbls[j].disorderRatio = disorderRatio->valueint;
      } else if (!disorderRatio) {
        g_Dbs.db[i].superTbls[j].disorderRatio = 0;
      } else {
4063
        printf("ERROR: failed to read json, disorderRatio not found\n");
4064
        goto PARSE_OVER;
4065
      }
4066 4067 4068 4069 4070 4071 4072

      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 {
4073
        printf("ERROR: failed to read json, disorderRange not found\n");
4074 4075
        goto PARSE_OVER;
      }
4076

4077 4078
      cJSON* insertRows = cJSON_GetObjectItem(stbInfo, "insert_rows");
      if (insertRows && insertRows->type == cJSON_Number) {
4079 4080 4081 4082 4083
        if (insertRows->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4084 4085 4086 4087
        g_Dbs.db[i].superTbls[j].insertRows = insertRows->valueint;
      } else if (!insertRows) {
        g_Dbs.db[i].superTbls[j].insertRows = 0x7FFFFFFFFFFFFFFF;
      } else {
4088
        errorPrint("%s() LN%d, failed to read json, insert_rows input mistake\n",
4089
                __func__, __LINE__);
4090 4091 4092 4093 4094 4095
        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;
4096 4097 4098 4099 4100
        if (insertInterval->valueint < 0) {
          errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
                __func__, __LINE__);
          goto PARSE_OVER;
        }
4101
      } else if (!insertInterval) {
4102
        verbosePrint("%s() LN%d: stable insert interval be overrided by global %"PRIu64".\n",
4103
                __func__, __LINE__, g_args.insert_interval);
4104 4105
        g_Dbs.db[i].superTbls[j].insertInterval = g_args.insert_interval;
      } else {
4106
        errorPrint("%s() LN%d, failed to read json, insert_interval input mistake\n",
4107
                __func__, __LINE__);
4108 4109 4110
        goto PARSE_OVER;
      }

4111
      int retVal = getColumnAndTagTypeFromInsertJsonFile(
4112
              stbInfo, &g_Dbs.db[i].superTbls[j]);
4113 4114
      if (false == retVal) {
        goto PARSE_OVER;
4115 4116
      }
    }
4117 4118 4119 4120
  }

  ret = true;

4121
PARSE_OVER:
4122 4123 4124 4125 4126 4127 4128 4129
  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) {
4130
    tstrncpy(g_queryInfo.cfgDir, cfgdir->valuestring, MAX_FILE_NAME_LEN);
4131 4132 4133 4134
  }

  cJSON* host = cJSON_GetObjectItem(root, "host");
  if (host && host->type == cJSON_String && host->valuestring != NULL) {
4135
    tstrncpy(g_queryInfo.host, host->valuestring, MAX_HOSTNAME_SIZE);
4136
  } else if (!host) {
4137
    tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
4138
  } else {
4139
    printf("ERROR: failed to read json, host not found\n");
4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151
    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) {
4152
    tstrncpy(g_queryInfo.user, user->valuestring, MAX_USERNAME_SIZE);
4153
  } else if (!user) {
4154
    tstrncpy(g_queryInfo.user, "root", MAX_USERNAME_SIZE); ;
4155 4156 4157 4158
  }

  cJSON* password = cJSON_GetObjectItem(root, "password");
  if (password && password->type == cJSON_String && password->valuestring != NULL) {
4159
    tstrncpy(g_queryInfo.password, password->valuestring, MAX_PASSWORD_SIZE);
4160
  } else if (!password) {
4161
    tstrncpy(g_queryInfo.password, "taosdata", MAX_PASSWORD_SIZE);;
4162
  }
H
hzcheng 已提交
4163

4164
  cJSON *answerPrompt = cJSON_GetObjectItem(root, "confirm_parameter_prompt"); // yes, no,
4165
  if (answerPrompt && answerPrompt->type == cJSON_String
4166
          && answerPrompt->valuestring != NULL) {
4167 4168 4169 4170
    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 已提交
4171
    } else {
4172
      g_args.answer_yes = false;
H
hzcheng 已提交
4173
    }
4174 4175 4176
  } else if (!answerPrompt) {
    g_args.answer_yes = false;
  } else {
4177
    printf("ERROR: failed to read json, confirm_parameter_prompt not found\n");
4178
    goto PARSE_OVER;
4179
  }
4180

4181 4182
  cJSON* gQueryTimes = cJSON_GetObjectItem(root, "query_times");
  if (gQueryTimes && gQueryTimes->type == cJSON_Number) {
4183
    if (gQueryTimes->valueint <= 0) {
4184 4185
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
        __func__, __LINE__);
4186 4187
      goto PARSE_OVER;
    }
4188 4189 4190 4191
    g_args.query_times = gQueryTimes->valueint;
  } else if (!gQueryTimes) {
    g_args.query_times = 1;
  } else {
4192
    errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4193
        __func__, __LINE__);
4194 4195 4196
    goto PARSE_OVER;
  }

4197 4198
  cJSON* dbs = cJSON_GetObjectItem(root, "databases");
  if (dbs && dbs->type == cJSON_String && dbs->valuestring != NULL) {
4199
    tstrncpy(g_queryInfo.dbName, dbs->valuestring, MAX_DB_NAME_SIZE);
4200
  } else if (!dbs) {
4201
    printf("ERROR: failed to read json, databases not found\n");
4202
    goto PARSE_OVER;
H
hzcheng 已提交
4203
  }
4204 4205 4206

  cJSON* queryMode = cJSON_GetObjectItem(root, "query_mode");
  if (queryMode && queryMode->type == cJSON_String && queryMode->valuestring != NULL) {
4207
    tstrncpy(g_queryInfo.queryMode, queryMode->valuestring, MAX_TB_NAME_SIZE);
4208
  } else if (!queryMode) {
4209
    tstrncpy(g_queryInfo.queryMode, "taosc", MAX_TB_NAME_SIZE);
4210
  } else {
4211
    printf("ERROR: failed to read json, query_mode not found\n");
4212
    goto PARSE_OVER;
H
hzcheng 已提交
4213
  }
4214

4215
  // specified_table_query
4216 4217
  cJSON *specifiedQuery = cJSON_GetObjectItem(root, "specified_table_query");
  if (!specifiedQuery) {
4218
    g_queryInfo.specifiedQueryInfo.concurrent = 1;
4219 4220
    g_queryInfo.specifiedQueryInfo.sqlCount = 0;
  } else if (specifiedQuery->type != cJSON_Object) {
4221
    printf("ERROR: failed to read json, super_table_query not found\n");
4222
    goto PARSE_OVER;
4223
  } else {
4224 4225 4226 4227 4228
    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;
4229 4230
    }

4231
    cJSON* specifiedQueryTimes = cJSON_GetObjectItem(specifiedQuery,
4232
        "query_times");
4233
    if (specifiedQueryTimes && specifiedQueryTimes->type == cJSON_Number) {
4234
      if (specifiedQueryTimes->valueint <= 0) {
4235 4236
        errorPrint(
                "%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4237
          __func__, __LINE__, specifiedQueryTimes->valueint);
4238 4239 4240
        goto PARSE_OVER;

      }
4241 4242 4243 4244
      g_queryInfo.specifiedQueryInfo.queryTimes = specifiedQueryTimes->valueint;
    } else if (!specifiedQueryTimes) {
      g_queryInfo.specifiedQueryInfo.queryTimes = g_args.query_times;
    } else {
4245
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4246
          __func__, __LINE__);
4247
      goto PARSE_OVER;
4248
    }
4249

4250
    cJSON* concurrent = cJSON_GetObjectItem(specifiedQuery, "concurrent");
4251
    if (concurrent && concurrent->type == cJSON_Number) {
4252
      if (concurrent->valueint <= 0) {
4253
        errorPrint(
4254
                "%s() LN%d, query sqlCount %"PRIu64" or concurrent %d is not correct.\n",
4255 4256
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount,
4257
              g_queryInfo.specifiedQueryInfo.concurrent);
4258 4259
        goto PARSE_OVER;
      }
4260
      g_queryInfo.specifiedQueryInfo.concurrent = concurrent->valueint;
4261
    } else if (!concurrent) {
4262
      g_queryInfo.specifiedQueryInfo.concurrent = 1;
4263
    }
4264

4265 4266 4267 4268 4269 4270 4271
    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;
4272
      } else {
4273
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4274
            __func__, __LINE__);
4275 4276 4277
        goto PARSE_OVER;
      }
    } else {
4278
      g_queryInfo.specifiedQueryInfo.asyncMode = SYNC_MODE;
4279
    }
4280

4281
    cJSON* interval = cJSON_GetObjectItem(specifiedQuery, "interval");
4282
    if (interval && interval->type == cJSON_Number) {
4283
      g_queryInfo.specifiedQueryInfo.subscribeInterval = interval->valueint;
4284
    } else if (!interval) {
4285 4286
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4287
      g_queryInfo.specifiedQueryInfo.subscribeInterval = 10000;
4288
    }
4289

4290
    cJSON* restart = cJSON_GetObjectItem(specifiedQuery, "restart");
4291
    if (restart && restart->type == cJSON_String && restart->valuestring != NULL) {
4292
      if (0 == strcmp("yes", restart->valuestring)) {
4293
        g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4294
      } else if (0 == strcmp("no", restart->valuestring)) {
4295
        g_queryInfo.specifiedQueryInfo.subscribeRestart = false;
4296
      } else {
4297
        printf("ERROR: failed to read json, subscribe restart error\n");
4298 4299 4300
        goto PARSE_OVER;
      }
    } else {
4301
      g_queryInfo.specifiedQueryInfo.subscribeRestart = true;
4302
    }
4303

4304
    cJSON* keepProgress = cJSON_GetObjectItem(specifiedQuery, "keepProgress");
4305
    if (keepProgress
4306 4307
            && keepProgress->type == cJSON_String
            && keepProgress->valuestring != NULL) {
4308
      if (0 == strcmp("yes", keepProgress->valuestring)) {
4309
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 1;
4310
      } else if (0 == strcmp("no", keepProgress->valuestring)) {
4311
        g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4312
      } else {
4313
        printf("ERROR: failed to read json, subscribe keepProgress error\n");
4314 4315 4316
        goto PARSE_OVER;
      }
    } else {
4317
      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress = 0;
4318 4319
    }

4320
    // sqls
4321 4322
    cJSON* specifiedSqls = cJSON_GetObjectItem(specifiedQuery, "sqls");
    if (!specifiedSqls) {
4323
      g_queryInfo.specifiedQueryInfo.sqlCount = 0;
4324
    } else if (specifiedSqls->type != cJSON_Array) {
4325
      errorPrint("%s() LN%d, failed to read json, super sqls not found\n",
4326
          __func__, __LINE__);
4327
      goto PARSE_OVER;
4328
    } else {
4329 4330 4331 4332 4333 4334 4335 4336
      int superSqlSize = cJSON_GetArraySize(specifiedSqls);
      if (superSqlSize * g_queryInfo.specifiedQueryInfo.concurrent
              > MAX_QUERY_SQL_COUNT) {
        errorPrint("%s() LN%d, failed to read json, query sql(%d) * concurrent(%d) overflow, max is %d\n",
           __func__, __LINE__,
           superSqlSize,
           g_queryInfo.specifiedQueryInfo.concurrent,
           MAX_QUERY_SQL_COUNT);
4337 4338
        goto PARSE_OVER;
      }
4339

4340
      g_queryInfo.specifiedQueryInfo.sqlCount = superSqlSize;
4341
      for (int j = 0; j < superSqlSize; ++j) {
4342
        cJSON* sql = cJSON_GetArrayItem(specifiedSqls, j);
4343
        if (sql == NULL) continue;
4344

4345 4346
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
        if (!sqlStr || sqlStr->type != cJSON_String || sqlStr->valuestring == NULL) {
4347
          printf("ERROR: failed to read json, sql not found\n");
4348 4349
          goto PARSE_OVER;
        }
4350 4351
        tstrncpy(g_queryInfo.specifiedQueryInfo.sql[j],
                sqlStr->valuestring, MAX_QUERY_SQL_LENGTH);
H
hzcheng 已提交
4352

4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364
        cJSON* resubAfterConsume =
            cJSON_GetObjectItem(specifiedQuery, "resubAfterConsume");
        if (resubAfterConsume
                && resubAfterConsume->type == cJSON_Number) {
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j]
                = resubAfterConsume->valueint;
        } else if (!resubAfterConsume) {
            //printf("failed to read json, subscribe interval no found\n");
            //goto PARSE_OVER;
            g_queryInfo.specifiedQueryInfo.resubAfterConsume[j] = 1;
        }

4365
        cJSON *result = cJSON_GetObjectItem(sql, "result");
4366 4367 4368 4369
        if ((NULL != result) && (result->type == cJSON_String)
                && (result->valuestring != NULL)) {
          tstrncpy(g_queryInfo.specifiedQueryInfo.result[j],
                  result->valuestring, MAX_FILE_NAME_LEN);
4370
        } else if (NULL == result) {
4371 4372
          memset(g_queryInfo.specifiedQueryInfo.result[j],
                  0, MAX_FILE_NAME_LEN);
4373
        } else {
4374
          printf("ERROR: failed to read json, super query result file not found\n");
4375
          goto PARSE_OVER;
4376
        }
4377 4378 4379
      }
    }
  }
4380

4381
  // super_table_query
4382 4383
  cJSON *superQuery = cJSON_GetObjectItem(root, "super_table_query");
  if (!superQuery) {
4384
    g_queryInfo.superQueryInfo.threadCnt = 1;
4385 4386
    g_queryInfo.superQueryInfo.sqlCount = 0;
  } else if (superQuery->type != cJSON_Object) {
4387
    printf("ERROR: failed to read json, sub_table_query not found\n");
4388 4389
    ret = true;
    goto PARSE_OVER;
H
hzcheng 已提交
4390
  } else {
4391
    cJSON* subrate = cJSON_GetObjectItem(superQuery, "query_interval");
4392
    if (subrate && subrate->type == cJSON_Number) {
4393
      g_queryInfo.superQueryInfo.queryInterval = subrate->valueint;
4394
    } else if (!subrate) {
4395
      g_queryInfo.superQueryInfo.queryInterval = 0;
4396 4397 4398 4399
    }

    cJSON* superQueryTimes = cJSON_GetObjectItem(superQuery, "query_times");
    if (superQueryTimes && superQueryTimes->type == cJSON_Number) {
4400 4401
      if (superQueryTimes->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, query_times: %"PRId64", need be a valid (>0) number\n",
4402
          __func__, __LINE__, superQueryTimes->valueint);
4403 4404
        goto PARSE_OVER;
      }
4405 4406 4407 4408
      g_queryInfo.superQueryInfo.queryTimes = superQueryTimes->valueint;
    } else if (!superQueryTimes) {
      g_queryInfo.superQueryInfo.queryTimes = g_args.query_times;
    } else {
4409
      errorPrint("%s() LN%d, failed to read json, query_times input mistake\n",
4410
          __func__, __LINE__);
4411
      goto PARSE_OVER;
4412
    }
4413

4414
    cJSON* threads = cJSON_GetObjectItem(superQuery, "threads");
4415
    if (threads && threads->type == cJSON_Number) {
4416 4417 4418 4419 4420 4421
      if (threads->valueint <= 0) {
        errorPrint("%s() LN%d, failed to read json, threads input mistake\n",
          __func__, __LINE__);
        goto PARSE_OVER;

      }
4422
      g_queryInfo.superQueryInfo.threadCnt = threads->valueint;
4423
    } else if (!threads) {
4424
      g_queryInfo.superQueryInfo.threadCnt = 1;
4425
    }
4426

4427
    //cJSON* subTblCnt = cJSON_GetObjectItem(superQuery, "childtable_count");
4428
    //if (subTblCnt && subTblCnt->type == cJSON_Number) {
4429
    //  g_queryInfo.superQueryInfo.childTblCount = subTblCnt->valueint;
4430
    //} else if (!subTblCnt) {
4431
    //  g_queryInfo.superQueryInfo.childTblCount = 0;
4432
    //}
4433

4434
    cJSON* stblname = cJSON_GetObjectItem(superQuery, "stblname");
4435 4436 4437
    if (stblname && stblname->type == cJSON_String
        && stblname->valuestring != NULL) {
      tstrncpy(g_queryInfo.superQueryInfo.sTblName, stblname->valuestring,
4438
          MAX_TB_NAME_SIZE);
4439
    } else {
4440
      errorPrint("%s() LN%d, failed to read json, super table name input error\n",
4441
          __func__, __LINE__);
4442 4443
      goto PARSE_OVER;
    }
4444

4445 4446 4447 4448 4449 4450 4451
    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;
4452
      } else {
4453
        errorPrint("%s() LN%d, failed to read json, async mode input error\n",
4454
            __func__, __LINE__);
4455 4456 4457
        goto PARSE_OVER;
      }
    } else {
4458
      g_queryInfo.superQueryInfo.asyncMode = SYNC_MODE;
4459
    }
4460

4461 4462 4463 4464 4465 4466 4467 4468 4469
    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) {
4470 4471
      //printf("failed to read json, subscribe interval no found\n");
      //goto PARSE_OVER;
4472
      g_queryInfo.superQueryInfo.subscribeInterval = 10000;
4473
    }
4474

4475
    cJSON* subrestart = cJSON_GetObjectItem(superQuery, "restart");
4476 4477
    if (subrestart && subrestart->type == cJSON_String
        && subrestart->valuestring != NULL) {
4478
      if (0 == strcmp("yes", subrestart->valuestring)) {
4479
        g_queryInfo.superQueryInfo.subscribeRestart = true;
4480
      } else if (0 == strcmp("no", subrestart->valuestring)) {
4481
        g_queryInfo.superQueryInfo.subscribeRestart = false;
4482
      } else {
4483
        printf("ERROR: failed to read json, subscribe restart error\n");
4484 4485 4486
        goto PARSE_OVER;
      }
    } else {
4487
      g_queryInfo.superQueryInfo.subscribeRestart = true;
4488
    }
4489

4490 4491 4492 4493 4494
    cJSON* superkeepProgress = cJSON_GetObjectItem(superQuery, "keepProgress");
    if (superkeepProgress &&
            superkeepProgress->type == cJSON_String
            && superkeepProgress->valuestring != NULL) {
      if (0 == strcmp("yes", superkeepProgress->valuestring)) {
4495
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 1;
4496
      } else if (0 == strcmp("no", superkeepProgress->valuestring)) {
4497
        g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4498
      } else {
4499
        printf("ERROR: failed to read json, subscribe super table keepProgress error\n");
4500 4501 4502
        goto PARSE_OVER;
      }
    } else {
4503
      g_queryInfo.superQueryInfo.subscribeKeepProgress = 0;
4504
    }
4505

4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517
    cJSON* superResubAfterConsume =
            cJSON_GetObjectItem(superQuery, "resubAfterConsume");
    if (superResubAfterConsume
            && superResubAfterConsume->type == cJSON_Number) {
        g_queryInfo.superQueryInfo.resubAfterConsume =
            superResubAfterConsume->valueint;
    } else if (!superResubAfterConsume) {
        //printf("failed to read json, subscribe interval no found\n");
        ////goto PARSE_OVER;
        g_queryInfo.superQueryInfo.resubAfterConsume = 1;
    }

4518 4519 4520
    // supert table sqls
    cJSON* superSqls = cJSON_GetObjectItem(superQuery, "sqls");
    if (!superSqls) {
4521
      g_queryInfo.superQueryInfo.sqlCount = 0;
4522
    } else if (superSqls->type != cJSON_Array) {
4523
      errorPrint("%s() LN%d: failed to read json, super sqls not found\n",
4524
          __func__, __LINE__);
4525
      goto PARSE_OVER;
4526
    } else {
4527
      int superSqlSize = cJSON_GetArraySize(superSqls);
4528
      if (superSqlSize > MAX_QUERY_SQL_COUNT) {
4529
        errorPrint("%s() LN%d, failed to read json, query sql size overflow, max is %d\n",
4530
           __func__, __LINE__, MAX_QUERY_SQL_COUNT);
4531 4532
        goto PARSE_OVER;
      }
4533

4534
      g_queryInfo.superQueryInfo.sqlCount = superSqlSize;
4535
      for (int j = 0; j < superSqlSize; ++j) {
4536
        cJSON* sql = cJSON_GetArrayItem(superSqls, j);
4537
        if (sql == NULL) continue;
4538

4539
        cJSON *sqlStr = cJSON_GetObjectItem(sql, "sql");
4540 4541 4542
        if (!sqlStr || sqlStr->type != cJSON_String
            || sqlStr->valuestring == NULL) {
          errorPrint("%s() LN%d, failed to read json, sql not found\n",
4543
              __func__, __LINE__);
4544 4545
          goto PARSE_OVER;
        }
4546
        tstrncpy(g_queryInfo.superQueryInfo.sql[j], sqlStr->valuestring,
4547
            MAX_QUERY_SQL_LENGTH);
4548 4549

        cJSON *result = cJSON_GetObjectItem(sql, "result");
4550 4551 4552
        if (result != NULL && result->type == cJSON_String
            && result->valuestring != NULL){
          tstrncpy(g_queryInfo.superQueryInfo.result[j],
4553
              result->valuestring, MAX_FILE_NAME_LEN);
4554
        } else if (NULL == result) {
4555
          memset(g_queryInfo.superQueryInfo.result[j], 0, MAX_FILE_NAME_LEN);
4556
        }  else {
4557
          errorPrint("%s() LN%d, failed to read json, sub query result file not found\n",
4558
              __func__, __LINE__);
4559
          goto PARSE_OVER;
4560
        }
4561 4562
      }
    }
H
hzcheng 已提交
4563 4564
  }

4565
  ret = true;
H
hzcheng 已提交
4566

4567
PARSE_OVER:
4568 4569
  return ret;
}
H
hzcheng 已提交
4570

4571
static bool getInfoFromJsonFile(char* file) {
4572
    debugPrint("%s %d %s\n", __func__, __LINE__, file);
4573

4574 4575 4576 4577 4578
  FILE *fp = fopen(file, "r");
  if (!fp) {
    printf("failed to read %s, reason:%s\n", file, strerror(errno));
    return false;
  }
H
Hui Li 已提交
4579

4580
  bool  ret = false;
4581
  int   maxLen = 6400000;
4582 4583 4584 4585 4586 4587 4588
  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 已提交
4589
  }
H
Hui Li 已提交
4590

4591 4592 4593
  content[len] = 0;
  cJSON* root = cJSON_Parse(content);
  if (root == NULL) {
4594
    printf("ERROR: failed to cjson parse %s, invalid json format\n", file);
4595 4596
    goto PARSE_OVER;
  }
H
Hui Li 已提交
4597

4598 4599 4600
  cJSON* filetype = cJSON_GetObjectItem(root, "filetype");
  if (filetype && filetype->type == cJSON_String && filetype->valuestring != NULL) {
    if (0 == strcasecmp("insert", filetype->valuestring)) {
4601
      g_args.test_mode = INSERT_TEST;
4602
    } else if (0 == strcasecmp("query", filetype->valuestring)) {
4603
      g_args.test_mode = QUERY_TEST;
4604
    } else if (0 == strcasecmp("subscribe", filetype->valuestring)) {
4605
      g_args.test_mode = SUBSCRIBE_TEST;
4606
    } else {
4607
      printf("ERROR: failed to read json, filetype not support\n");
4608 4609 4610
      goto PARSE_OVER;
    }
  } else if (!filetype) {
4611
    g_args.test_mode = INSERT_TEST;
4612
  } else {
4613
    printf("ERROR: failed to read json, filetype not found\n");
4614 4615
    goto PARSE_OVER;
  }
H
hzcheng 已提交
4616

4617
  if (INSERT_TEST == g_args.test_mode) {
4618
    ret = getMetaFromInsertJsonFile(root);
4619
  } else if ((QUERY_TEST == g_args.test_mode)
4620
          || (SUBSCRIBE_TEST == g_args.test_mode)) {
4621 4622
    ret = getMetaFromQueryJsonFile(root);
  } else {
4623
    errorPrint("%s() LN%d, input json file type error! please input correct file type: insert or query or subscribe\n",
4624
            __func__, __LINE__);
4625
    goto PARSE_OVER;
4626
  }
4627

4628
PARSE_OVER:
4629 4630
  free(content);
  cJSON_Delete(root);
H
hzcheng 已提交
4631
  fclose(fp);
4632 4633
  return ret;
}
H
hzcheng 已提交
4634

4635
static void prepareSampleData() {
4636
  for (int i = 0; i < g_Dbs.dbCount; i++) {
4637 4638 4639
    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 已提交
4640
      }
4641 4642 4643 4644
    }
  }
}

4645
static void postFreeResource() {
4646
  tmfclose(g_fpOfInsertResult);
4647
  for (int i = 0; i < g_Dbs.dbCount; i++) {
S
Shuduo Sang 已提交
4648
    for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
4649 4650 4651
      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 已提交
4652
      }
4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664
      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 已提交
4665
    }
4666 4667
  }
}
S
Shuaiqiang Chang 已提交
4668

4669 4670 4671
static int getRowDataFromSample(
        char* dataBuf, int64_t maxLen, int64_t timestamp,
      SSuperTable* superTblInfo, int64_t* sampleUsePos) {
4672
  if ((*sampleUsePos) == MAX_SAMPLES_ONCE_FROM_FILE) {
4673
/*    int ret = readSampleFromCsvFileToMem(superTblInfo);
4674
    if (0 != ret) {
4675
      tmfree(superTblInfo->sampleDataBuf);
4676
      superTblInfo->sampleDataBuf = NULL;
4677 4678
      return -1;
    }
4679
*/
4680 4681
    *sampleUsePos = 0;
  }
S
Shuaiqiang Chang 已提交
4682

4683
  int    dataLen = 0;
4684

4685
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4686
          "(%" PRId64 ", ", timestamp);
4687
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen,
4688
          "%s", superTblInfo->sampleDataBuf + superTblInfo->lenOfOneRow * (*sampleUsePos));
4689
  dataLen += snprintf(dataBuf + dataLen, maxLen - dataLen, ")");
S
Shuaiqiang Chang 已提交
4690

4691
  (*sampleUsePos)++;
4692

4693 4694
  return dataLen;
}
S
Shuaiqiang Chang 已提交
4695

4696 4697 4698 4699
static int64_t generateStbRowData(
        SSuperTable* stbInfo,
        char* recBuf, int64_t timestamp
        ) {
4700
  int64_t   dataLen = 0;
4701
  char  *pstr = recBuf;
4702
  int64_t maxLen = MAX_DATA_SIZE;
4703

4704 4705
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
          "(%" PRId64 ",", timestamp);
4706

4707
  for (int i = 0; i < stbInfo->columnCount; i++) {
4708 4709 4710 4711
    if ((0 == strncasecmp(stbInfo->columns[i].dataType,
                    "BINARY", strlen("BINARY")))
            || (0 == strncasecmp(stbInfo->columns[i].dataType,
                    "NCHAR", strlen("NCHAR")))) {
4712
      if (stbInfo->columns[i].dataLen > TSDB_MAX_BINARY_LEN) {
4713
        errorPrint( "binary or nchar length overflow, max size:%u\n",
4714
                (uint32_t)TSDB_MAX_BINARY_LEN);
4715
        return -1;
4716
      }
4717

4718 4719
      char* buf = (char*)calloc(stbInfo->columns[i].dataLen+1, 1);
      if (NULL == buf) {
4720
        errorPrint( "calloc failed! size:%d\n", stbInfo->columns[i].dataLen);
4721
        return -1;
4722 4723
      }
      rand_string(buf, stbInfo->columns[i].dataLen);
4724
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen, "\'%s\',", buf);
4725
      tmfree(buf);
4726
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4727
                "INT", 3)) {
4728
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4729
              "%d,", rand_int());
4730
    } else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4731
                "BIGINT", 6)) {
4732
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4733
              "%"PRId64",", rand_bigint());
4734
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4735
                "FLOAT", 5)) {
4736
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4737
              "%f,", rand_float());
4738
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4739
                "DOUBLE", 6)) {
4740
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4741
              "%f,", rand_double());
4742
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4743
                "SMALLINT", 8)) {
4744
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4745
          "%d,", rand_smallint());
4746
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4747
          "TINYINT", strlen("TINYINT"))) {
4748
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4749
          "%d,", rand_tinyint());
4750
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4751
          "BOOL", strlen("BOOL"))) {
4752
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4753
          "%d,", rand_bool());
4754
    }  else if (0 == strncasecmp(stbInfo->columns[i].dataType,
4755
          "TIMESTAMP", strlen("TIMESTAMP"))) {
4756
      dataLen += snprintf(pstr + dataLen, maxLen - dataLen,
4757
          "%"PRId64",", rand_bigint());
4758
    }  else {
4759
      errorPrint( "No support data type: %s\n", stbInfo->columns[i].dataType);
4760
      return -1;
4761
    }
S
Shuaiqiang Chang 已提交
4762
  }
4763

4764
  dataLen -= 1;
4765
  dataLen += snprintf(pstr + dataLen, maxLen - dataLen, ")");
4766

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

  return strlen(recBuf);
4770
}
S
Shuaiqiang Chang 已提交
4771

4772
static int64_t generateData(char *recBuf, char **data_type,
4773
        int64_t timestamp, int lenOfBinary) {
4774 4775
  memset(recBuf, 0, MAX_DATA_SIZE);
  char *pstr = recBuf;
4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789
  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 已提交
4790
  for (int i = 0; i < c; i++) {
4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801
    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) {
4802
      double t = rand_double();
4803 4804
      pstr += sprintf(pstr, ",%20.8f", t);
    } else if (strcasecmp(data_type[i % c], "BOOL") == 0) {
4805
      bool b = rand_bool() & 1;
4806 4807
      pstr += sprintf(pstr, ",%s", b ? "true" : "false");
    } else if (strcasecmp(data_type[i % c], "BINARY") == 0) {
4808 4809
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4810
      pstr += sprintf(pstr, ",\"%s\"", s);
4811
      free(s);
4812
    } else if (strcasecmp(data_type[i % c], "NCHAR") == 0) {
4813 4814
      char *s = malloc(lenOfBinary);
      rand_string(s, lenOfBinary);
4815
      pstr += sprintf(pstr, ",\"%s\"", s);
4816 4817 4818
      free(s);
    }

4819
    if (strlen(recBuf) > MAX_DATA_SIZE) {
4820 4821 4822 4823 4824 4825 4826
      perror("column length too long, abort");
      exit(-1);
    }
  }

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

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

4829
  return (int32_t)strlen(recBuf);
4830 4831
}

4832
static int prepareSampleDataForSTable(SSuperTable *superTblInfo) {
4833 4834
  char* sampleDataBuf = NULL;

4835
  sampleDataBuf = calloc(
4836
            superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE, 1);
4837
  if (sampleDataBuf == NULL) {
4838
      errorPrint("%s() LN%d, Failed to calloc %"PRIu64" Bytes, reason:%s\n",
4839 4840 4841 4842
              __func__, __LINE__,
              superTblInfo->lenOfOneRow * MAX_SAMPLES_ONCE_FROM_FILE,
              strerror(errno));
      return -1;
4843
  }
4844

4845 4846 4847 4848
  superTblInfo->sampleDataBuf = sampleDataBuf;
  int ret = readSampleFromCsvFileToMem(superTblInfo);

  if (0 != ret) {
4849 4850 4851 4852 4853
      errorPrint("%s() LN%d, read sample from csv file failed.\n",
          __func__, __LINE__);
      tmfree(sampleDataBuf);
      superTblInfo->sampleDataBuf = NULL;
      return -1;
H
Hui Li 已提交
4854
  }
4855

4856 4857 4858
  return 0;
}

S
Shuduo Sang 已提交
4859
static int64_t execInsert(threadInfo *pThreadInfo, uint64_t k)
4860 4861
{
  int affectedRows;
4862
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4863

4864
  verbosePrint("[%d] %s() LN%d %s\n", pThreadInfo->threadID,
S
Shuduo Sang 已提交
4865
            __func__, __LINE__, pThreadInfo->buffer);
4866
  if (superTblInfo) {
4867
    if (superTblInfo->insertMode == TAOSC_IFACE) {
S
Shuduo Sang 已提交
4868 4869 4870
      affectedRows = queryDbExec(
              pThreadInfo->taos,
              pThreadInfo->buffer, INSERT_TYPE, false);
4871
    } else if (superTblInfo->insertMode == REST_IFACE) {
4872
      if (0 != postProceSql(g_Dbs.host, &g_Dbs.serv_addr, g_Dbs.port,
S
Shuduo Sang 已提交
4873
                  pThreadInfo->buffer, NULL /* not set result file */)) {
4874
        affectedRows = -1;
4875
        printf("========restful return fail, threadID[%d]\n",
4876
            pThreadInfo->threadID);
4877 4878 4879
      } else {
        affectedRows = k;
      }
4880
    } else if (superTblInfo->insertMode == STMT_IFACE) {
S
Shuduo Sang 已提交
4881 4882 4883 4884 4885 4886
      debugPrint("%s() LN%d, stmt=%p", __func__, __LINE__, pThreadInfo->stmt);
      if (0 != taos_stmt_execute(pThreadInfo->stmt)) {
        errorPrint("%s() LN%d, failied to execute insert statement\n",
                    __func__, __LINE__);
        exit(-1);
      }
S
Shuduo Sang 已提交
4887 4888

      affectedRows = k;
4889
    } else {
4890
      errorPrint("%s() LN%d: unknown insert mode: %d\n",
4891 4892
        __func__, __LINE__, superTblInfo->insertMode);
      affectedRows = 0;
4893
    }
4894
  } else {
S
Shuduo Sang 已提交
4895
    affectedRows = queryDbExec(pThreadInfo->taos, pThreadInfo->buffer, INSERT_TYPE, false);
4896 4897 4898 4899 4900
  }

  return affectedRows;
}

4901 4902
static void getTableName(char *pTblName,
        threadInfo* pThreadInfo, uint64_t tableSeq)
4903 4904
{
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
4905 4906
  if ((superTblInfo)
          && (AUTO_CREATE_SUBTBL != superTblInfo->autoCreateTable)) {
4907
    if (superTblInfo->childTblLimit > 0) {
4908 4909 4910
        snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s",
            superTblInfo->childTblName +
            (tableSeq - superTblInfo->childTblOffset) * TSDB_TABLE_NAME_LEN);
4911
    } else {
4912

4913
        verbosePrint("[%d] %s() LN%d: from=%"PRIu64" count=%"PRId64" seq=%"PRIu64"\n",
4914 4915 4916 4917 4918
                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);
4919 4920
    }
  } else {
4921
    snprintf(pTblName, TSDB_TABLE_NAME_LEN, "%s%"PRIu64"",
4922
        g_args.tb_prefix, tableSeq);
4923 4924 4925
  }
}

4926 4927 4928 4929 4930
static int64_t generateDataTailWithoutStb(
        uint64_t batch, char* buffer,
        int64_t remainderBufLen, int64_t insertRows,
        uint64_t startFrom, int64_t startTime,
        /* int64_t *pSamplePos, */int64_t *dataLen) {
4931

4932
  uint64_t len = 0;
4933 4934
  char *pstr = buffer;

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

4937
  int64_t k = 0;
4938
  for (k = 0; k < batch;) {
4939
    char data[MAX_DATA_SIZE];
4940 4941
    memset(data, 0, MAX_DATA_SIZE);

4942
    int64_t retLen = 0;
4943

4944 4945
    char **data_type = g_args.datatype;
    int lenOfBinary = g_args.len_of_binary;
4946

4947 4948 4949 4950 4951 4952 4953 4954 4955
    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);

          debugPrint("rand data generated, back %"PRId64"\n", randTail);
4956
        }
4957 4958 4959
    } else {
        randTail = DEFAULT_TIMESTAMP_STEP * k;
    }
4960

4961 4962 4963
    retLen = generateData(data, data_type,
            startTime + randTail,
            lenOfBinary);
4964

4965
    if (len > remainderBufLen)
4966
        break;
4967

4968 4969 4970 4971 4972 4973 4974
    pstr += sprintf(pstr, "%s", data);
    k++;
    len += retLen;
    remainderBufLen -= retLen;

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

4976
    startFrom ++;
4977

4978 4979 4980 4981
    if (startFrom >= insertRows) {
      break;
    }
  }
4982

4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023
  *dataLen = len;
  return k;
}

static int64_t generateStbDataTail(
        SSuperTable* superTblInfo,
        uint64_t batch, char* buffer,
        int64_t remainderBufLen, int64_t insertRows,
        uint64_t startFrom, int64_t startTime,
        int64_t *pSamplePos, int64_t *dataLen) {
  uint64_t len = 0;

  char *pstr = buffer;

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

  int64_t k = 0;
  for (k = 0; k < batch;) {
    char data[MAX_DATA_SIZE];
    memset(data, 0, MAX_DATA_SIZE);

    int64_t retLen = 0;

    if (0 == strncasecmp(superTblInfo->dataSource,
                "sample", strlen("sample"))) {
          retLen = getRowDataFromSample(
                  data,
                  remainderBufLen,
                  startTime + superTblInfo->timeStampStep * k,
                  superTblInfo,
                  pSamplePos);
    } else if (0 == strncasecmp(superTblInfo->dataSource,
                "rand", strlen("rand"))) {
        int64_t randTail = superTblInfo->timeStampStep * k;
        if (superTblInfo->disorderRatio > 0) {
            int rand_num = taosRandom() % 100;
            if(rand_num < superTblInfo->disorderRatio) {
                randTail = (randTail +
                        (taosRandom() % superTblInfo->disorderRange + 1)) * (-1);
                debugPrint("rand data generated, back %"PRId64"\n", randTail);
            }
5024
        }
5025

5026 5027 5028
        int64_t d = startTime + randTail;
        retLen = generateStbRowData(superTblInfo, data, d);
    }
5029

5030
    if (retLen > remainderBufLen) {
5031
        break;
5032 5033
    }

5034 5035 5036 5037 5038
    pstr += snprintf(pstr , retLen + 1, "%s", data);
    k++;
    len += retLen;
    remainderBufLen -= retLen;

5039
    verbosePrint("%s() LN%d len=%"PRIu64" k=%"PRIu64" \nbuffer=%s\n",
5040
            __func__, __LINE__, len, k, buffer);
5041 5042

    startFrom ++;
5043

5044
    if (startFrom >= insertRows) {
5045
      break;
5046
    }
5047
  }
5048

5049 5050 5051
  *dataLen = len;
  return k;
}
5052

5053 5054 5055

static int generateSQLHeadWithoutStb(char *tableName,
        char *dbName,
5056
        char *buffer, int remainderBufLen)
5057 5058
{
  int len;
5059 5060 5061

  char headBuf[HEAD_BUFF_LEN];

5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087
  len = snprintf(
          headBuf,
          HEAD_BUFF_LEN,
          "%s.%s values",
          dbName,
          tableName);

  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

  return len;
}

static int generateStbSQLHead(
        SSuperTable* superTblInfo,
        char *tableName, int32_t tableSeq,
        char *dbName,
        char *buffer, int remainderBufLen)
{
  int len;

  char headBuf[HEAD_BUFF_LEN];

  if (AUTO_CREATE_SUBTBL == superTblInfo->autoCreateTable) {
5088 5089
      char* tagsValBuf = NULL;
      if (0 == superTblInfo->tagSource) {
5090
            tagsValBuf = generateTagVaulesForStb(superTblInfo, tableSeq);
5091
      } else {
5092 5093 5094
            tagsValBuf = getTagValueFromTagSample(
                    superTblInfo,
                    tableSeq % superTblInfo->tagSampleCount);
5095 5096
      }
      if (NULL == tagsValBuf) {
5097
        errorPrint("%s() LN%d, tag buf failed to allocate  memory\n",
5098
            __func__, __LINE__);
5099 5100 5101
        return -1;
      }

5102 5103
      len = snprintf(
          headBuf,
5104 5105
                  HEAD_BUFF_LEN,
                  "%s.%s using %s.%s tags %s values",
5106
                  dbName,
5107
                  tableName,
5108
                  dbName,
5109 5110
                  superTblInfo->sTblName,
                  tagsValBuf);
5111 5112
      tmfree(tagsValBuf);
    } else if (TBL_ALREADY_EXISTS == superTblInfo->childTblExists) {
5113 5114
      len = snprintf(
          headBuf,
5115 5116
                  HEAD_BUFF_LEN,
                  "%s.%s values",
5117
                  dbName,
5118
                  tableName);
5119
    } else {
5120 5121
      len = snprintf(
          headBuf,
5122 5123
                  HEAD_BUFF_LEN,
                  "%s.%s values",
5124
                  dbName,
5125
                  tableName);
5126 5127
  }

5128 5129 5130 5131 5132
  if (len > remainderBufLen)
    return -1;

  tstrncpy(buffer, headBuf, len + 1);

5133 5134 5135
  return len;
}

5136 5137
static int64_t generateStbInterlaceData(
        SSuperTable *superTblInfo,
5138 5139
        char *tableName, uint64_t batchPerTbl, uint64_t i, uint64_t batchPerTblTimes,
        uint64_t tableSeq,
5140
        threadInfo *pThreadInfo, char *buffer,
5141
        int64_t insertRows,
5142
        int64_t startTime,
5143
        uint64_t *pRemainderBufLen)
5144
{
5145
  assert(buffer);
5146 5147
  char *pstr = buffer;

5148 5149 5150
  int headLen = generateStbSQLHead(
          superTblInfo,
          tableName, tableSeq, pThreadInfo->db_name,
5151
          pstr, *pRemainderBufLen);
5152 5153 5154 5155 5156

  if (headLen <= 0) {
    return 0;
  }
  // generate data buffer
5157
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" buffer:\n%s\n",
5158
            pThreadInfo->threadID, __func__, __LINE__, i, buffer);
5159 5160 5161 5162

  pstr += headLen;
  *pRemainderBufLen -= headLen;

5163
  int64_t dataLen = 0;
5164

5165
  verbosePrint("[%d] %s() LN%d i=%"PRIu64" batchPerTblTimes=%"PRIu64" batchPerTbl = %"PRIu64"\n",
5166 5167
            pThreadInfo->threadID, __func__, __LINE__,
            i, batchPerTblTimes, batchPerTbl);
5168

5169
  if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5170
      startTime = taosGetTimestamp(pThreadInfo->time_precision);
5171
  }
5172

5173
  int64_t  k = generateStbDataTail(
5174 5175 5176 5177
            superTblInfo,
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
            &(pThreadInfo->samplePos), &dataLen);
5178 5179 5180 5181

  if (k == batchPerTbl) {
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
5182
  } else {
5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
            __func__, __LINE__, k, batchPerTbl);
    pstr -= headLen;
    pstr[0] = '\0';
    k = 0;
  }

  return k;
}

static int64_t generateInterlaceDataWithoutStb(
        char *tableName, uint64_t batchPerTbl,
        uint64_t tableSeq,
        char *dbName, char *buffer,
        int64_t insertRows,
        uint64_t *pRemainderBufLen)
{
  assert(buffer);
  char *pstr = buffer;

  int headLen = generateSQLHeadWithoutStb(
          tableName, dbName,
            pstr, *pRemainderBufLen);

  if (headLen <= 0) {
    return 0;
  }

  pstr += headLen;
  *pRemainderBufLen -= headLen;

  int64_t dataLen = 0;

  int64_t startTime = 1500000000000;
  int64_t  k = generateDataTailWithoutStb(
5218 5219
            batchPerTbl, pstr, *pRemainderBufLen, insertRows, 0,
            startTime,
5220
            &dataLen);
5221 5222

  if (k == batchPerTbl) {
5223 5224 5225
    pstr += dataLen;
    *pRemainderBufLen -= dataLen;
  } else {
5226
    debugPrint("%s() LN%d, generated data tail: %"PRIu64", not equal batch per table: %"PRIu64"\n",
5227
            __func__, __LINE__, k, batchPerTbl);
5228 5229
    pstr -= headLen;
    pstr[0] = '\0';
5230
    k = 0;
5231 5232 5233 5234 5235
  }

  return k;
}

5236 5237
static int64_t generateStbProgressiveData(
        SSuperTable *superTblInfo,
5238
        char *tableName,
5239
        int64_t tableSeq,
5240
        char *dbName, char *buffer,
5241
        int64_t insertRows,
5242
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos,
5243
        int64_t *pRemainderBufLen)
5244 5245
{
  assert(buffer != NULL);
5246
  char *pstr = buffer;
5247

5248
  memset(buffer, 0, *pRemainderBufLen);
5249

5250
  int64_t headLen = generateStbSQLHead(
5251
              superTblInfo,
5252
          tableName, tableSeq, dbName,
5253
          buffer, *pRemainderBufLen);
5254 5255 5256 5257

  if (headLen <= 0) {
    return 0;
  }
5258
  pstr += headLen;
5259
  *pRemainderBufLen -= headLen;
5260

5261
  int64_t dataLen;
5262

5263
  return generateStbDataTail(superTblInfo,
5264 5265
          g_args.num_of_RPR, pstr, *pRemainderBufLen,
          insertRows, startFrom,
5266 5267
          startTime,
          pSamplePos, &dataLen);
5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295
}

static int64_t generateProgressiveDataWithoutStb(
        char *tableName,
        int64_t tableSeq,
        threadInfo *pThreadInfo, char *buffer,
        int64_t insertRows,
        uint64_t startFrom, int64_t startTime, int64_t *pSamplePos,
        int64_t *pRemainderBufLen)
{
  assert(buffer != NULL);
  char *pstr = buffer;

  memset(buffer, 0, *pRemainderBufLen);

  int64_t headLen = generateSQLHeadWithoutStb(
          tableName, pThreadInfo->db_name,
          buffer, *pRemainderBufLen);

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

  int64_t dataLen;

  return generateDataTailWithoutStb(
5296 5297 5298
          g_args.num_of_RPR, pstr, *pRemainderBufLen, insertRows, startFrom,
          startTime,
          /*pSamplePos, */&dataLen);
5299
}
5300

5301 5302 5303 5304 5305 5306 5307 5308 5309
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)));
}

5310
// sync write interlace data
5311
static void* syncWriteInterlace(threadInfo *pThreadInfo) {
5312
  debugPrint("[%d] %s() LN%d: ### interlace write\n",
5313 5314
         pThreadInfo->threadID, __func__, __LINE__);

5315
  int64_t insertRows;
5316
  uint64_t interlaceRows;
5317 5318 5319
  uint64_t maxSqlLen;
  int64_t nTimeStampStep;
  uint64_t insert_interval;
5320 5321

  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5322

5323 5324 5325 5326 5327 5328 5329 5330 5331
  if (superTblInfo) {
    insertRows = superTblInfo->insertRows;

    if ((superTblInfo->interlaceRows == 0)
        && (g_args.interlace_rows > 0)) {
      interlaceRows = g_args.interlace_rows;
    } else {
      interlaceRows = superTblInfo->interlaceRows;
    }
5332 5333 5334
    maxSqlLen = superTblInfo->maxSqlLen;
    nTimeStampStep = superTblInfo->timeStampStep;
    insert_interval = superTblInfo->insertInterval;
5335 5336 5337
  } else {
    insertRows = g_args.num_of_DPT;
    interlaceRows = g_args.interlace_rows;
5338 5339 5340
    maxSqlLen = g_args.max_sql_len;
    nTimeStampStep = DEFAULT_TIMESTAMP_STEP;
    insert_interval = g_args.insert_interval;
5341
  }
5342

5343 5344 5345 5346 5347
  debugPrint("[%d] %s() LN%d: start_table_from=%"PRIu64" ntables=%"PRId64" insertRows=%"PRIu64"\n",
          pThreadInfo->threadID, __func__, __LINE__,
          pThreadInfo->start_table_from,
          pThreadInfo->ntables, insertRows);

5348
  if (interlaceRows > insertRows)
H
Haojun Liao 已提交
5349
    interlaceRows = insertRows;
5350

5351 5352
  if (interlaceRows > g_args.num_of_RPR)
    interlaceRows = g_args.num_of_RPR;
5353

5354 5355
  uint64_t batchPerTbl = interlaceRows;
  uint64_t batchPerTblTimes;
5356

5357 5358 5359
  if ((interlaceRows > 0) && (pThreadInfo->ntables > 1)) {
    batchPerTblTimes =
        g_args.num_of_RPR / interlaceRows;
5360
  } else {
5361
    batchPerTblTimes = 1;
5362 5363
  }

S
Shuduo Sang 已提交
5364 5365
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
5366
    errorPrint( "%s() LN%d, Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5367
              __func__, __LINE__, maxSqlLen, strerror(errno));
5368 5369 5370 5371 5372 5373
    return NULL;
  }

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

5374 5375
  uint64_t st = 0;
  uint64_t et = UINT64_MAX;
5376

5377 5378 5379
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5380

5381
  uint64_t tableSeq = pThreadInfo->start_table_from;
5382 5383
  int64_t startTime = pThreadInfo->start_time;

5384
  uint64_t generatedRecPerTbl = 0;
5385
  bool flagSleep = true;
5386
  uint64_t sleepTimeTotal = 0;
5387

5388
  while(pThreadInfo->totalInsertRows < pThreadInfo->ntables * insertRows) {
5389
    if ((flagSleep) && (insert_interval)) {
5390 5391
        st = taosGetTimestampMs();
        flagSleep = false;
5392 5393
    }
    // generate data
S
Shuduo Sang 已提交
5394
    memset(pThreadInfo->buffer, 0, maxSqlLen);
5395
    uint64_t remainderBufLen = maxSqlLen;
5396

S
Shuduo Sang 已提交
5397
    char *pstr = pThreadInfo->buffer;
5398

5399 5400
    int len = snprintf(pstr,
            strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
5401 5402 5403
    pstr += len;
    remainderBufLen -= len;

5404
    uint64_t recOfBatch = 0;
5405

5406
    for (uint64_t i = 0; i < batchPerTblTimes; i ++) {
5407 5408
        char tableName[TSDB_TABLE_NAME_LEN];

5409
      getTableName(tableName, pThreadInfo, tableSeq);
5410 5411
      if (0 == strlen(tableName)) {
        errorPrint("[%d] %s() LN%d, getTableName return null\n",
5412
            pThreadInfo->threadID, __func__, __LINE__);
S
Shuduo Sang 已提交
5413
        free(pThreadInfo->buffer);
5414 5415
        return NULL;
      }
5416

5417
      uint64_t oldRemainderLen = remainderBufLen;
5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436

      int64_t generated;
      if (superTblInfo) {
        generated = generateStbInterlaceData(
                superTblInfo,
                tableName, batchPerTbl, i, batchPerTblTimes,
                tableSeq,
                pThreadInfo, pstr,
                insertRows,
                startTime,
                &remainderBufLen);
      } else {
        generated = generateInterlaceDataWithoutStb(
                tableName, batchPerTbl,
                tableSeq,
                pThreadInfo->db_name, pstr,
                insertRows,
                &remainderBufLen);
      }
5437

5438 5439
      debugPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5440
      if (generated < 0) {
5441
        errorPrint("[%d] %s() LN%d, generated records is %"PRId64"\n",
5442
                  pThreadInfo->threadID, __func__, __LINE__, generated);
5443
        goto free_of_interlace;
5444 5445
      } else if (generated == 0) {
        break;
5446 5447
      }

5448
      tableSeq ++;
5449
      recOfBatch += batchPerTbl;
5450
      pstr += (oldRemainderLen - remainderBufLen);
5451
//      startTime += batchPerTbl * superTblInfo->timeStampStep;
5452
      pThreadInfo->totalInsertRows += batchPerTbl;
5453
      verbosePrint("[%d] %s() LN%d batchPerTbl=%"PRId64" recOfBatch=%"PRId64"\n",
5454 5455
                pThreadInfo->threadID, __func__, __LINE__,
                batchPerTbl, recOfBatch);
5456

5457
      if (tableSeq == pThreadInfo->start_table_from + pThreadInfo->ntables) {
5458 5459 5460
            // turn to first table
            tableSeq = pThreadInfo->start_table_from;
            generatedRecPerTbl += batchPerTbl;
5461

5462 5463
            startTime = pThreadInfo->start_time
              + generatedRecPerTbl * nTimeStampStep;
5464

5465 5466 5467
            flagSleep = true;
            if (generatedRecPerTbl >= insertRows)
              break;
5468

5469 5470 5471
            int remainRows = insertRows - generatedRecPerTbl;
            if ((remainRows > 0) && (batchPerTbl > remainRows))
              batchPerTbl = remainRows;
5472

5473 5474 5475
            if (pThreadInfo->ntables * batchPerTbl < g_args.num_of_RPR)
                break;
      }
5476

5477
      verbosePrint("[%d] %s() LN%d generatedRecPerTbl=%"PRId64" insertRows=%"PRId64"\n",
5478 5479
                pThreadInfo->threadID, __func__, __LINE__,
                generatedRecPerTbl, insertRows);
5480 5481

      if ((g_args.num_of_RPR - recOfBatch) < batchPerTbl)
5482 5483 5484
        break;
    }

5485
    verbosePrint("[%d] %s() LN%d recOfBatch=%"PRIu64" totalInsertRows=%"PRIu64"\n",
5486 5487
              pThreadInfo->threadID, __func__, __LINE__, recOfBatch,
              pThreadInfo->totalInsertRows);
5488
    verbosePrint("[%d] %s() LN%d, buffer=%s\n",
S
Shuduo Sang 已提交
5489
           pThreadInfo->threadID, __func__, __LINE__, pThreadInfo->buffer);
5490

5491
    startTs = taosGetTimestampMs();
5492

5493 5494 5495 5496 5497 5498 5499
    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;
    }
S
Shuduo Sang 已提交
5500
    int64_t affectedRows = execInsert(pThreadInfo, recOfBatch);
5501

5502
    endTs = taosGetTimestampMs();
5503 5504
    uint64_t delay = endTs - startTs;
    performancePrint("%s() LN%d, insert execution time is %"PRIu64"ms\n",
5505
            __func__, __LINE__, delay);
5506 5507 5508
    verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5509 5510 5511 5512 5513 5514

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

5515 5516
    if (recOfBatch != affectedRows) {
        errorPrint("[%d] %s() LN%d execInsert insert %"PRIu64", affected rows: %"PRId64"\n%s\n",
5517
                pThreadInfo->threadID, __func__, __LINE__,
S
Shuduo Sang 已提交
5518
                recOfBatch, affectedRows, pThreadInfo->buffer);
5519
        goto free_of_interlace;
5520
    }
5521

5522
    pThreadInfo->totalAffectedRows += affectedRows;
5523

5524 5525
    int64_t  currentPrintTime = taosGetTimestampMs();
    if (currentPrintTime - lastPrintTime > 30*1000) {
5526
      printf("thread[%d] has currently inserted rows: %"PRIu64 ", affected rows: %"PRIu64 "\n",
5527 5528 5529
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5530 5531
      lastPrintTime = currentPrintTime;
    }
5532

5533
    if ((insert_interval) && flagSleep) {
5534
      et = taosGetTimestampMs();
5535

5536
      if (insert_interval > (et - st) ) {
S
Shuduo Sang 已提交
5537 5538
        uint64_t sleepTime = insert_interval - (et -st);
        performancePrint("%s() LN%d sleep: %"PRId64" ms for insert interval\n",
5539
                    __func__, __LINE__, sleepTime);
5540 5541 5542
        taosMsleep(sleepTime); // ms
        sleepTimeTotal += insert_interval;
      }
5543
    }
5544 5545
  }

5546
free_of_interlace:
S
Shuduo Sang 已提交
5547
  tmfree(pThreadInfo->buffer);
5548
  printStatPerThread(pThreadInfo);
5549 5550 5551
  return NULL;
}

5552
// sync insertion progressive data
5553
static void* syncWriteProgressive(threadInfo *pThreadInfo) {
5554
  debugPrint("%s() LN%d: ### progressive write\n", __func__, __LINE__);
5555

5556
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5557
  uint64_t maxSqlLen = superTblInfo?superTblInfo->maxSqlLen:g_args.max_sql_len;
5558 5559 5560 5561 5562 5563
  int64_t timeStampStep =
      superTblInfo?superTblInfo->timeStampStep:DEFAULT_TIMESTAMP_STEP;
  int64_t insertRows =
        (superTblInfo)?superTblInfo->insertRows:g_args.num_of_DPT;
  verbosePrint("%s() LN%d insertRows=%"PRId64"\n",
            __func__, __LINE__, insertRows);
5564

S
Shuduo Sang 已提交
5565 5566
  pThreadInfo->buffer = calloc(maxSqlLen, 1);
  if (NULL == pThreadInfo->buffer) {
5567
    errorPrint( "Failed to alloc %"PRIu64" Bytes, reason:%s\n",
5568 5569
              maxSqlLen,
              strerror(errno));
5570 5571
    return NULL;
  }
5572

5573 5574 5575
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
  uint64_t endTs;
5576

5577
/*  int insert_interval =
5578
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5579 5580
  uint64_t st = 0;
  uint64_t et = 0xffffffff;
5581
  */
5582

5583 5584
  pThreadInfo->totalInsertRows = 0;
  pThreadInfo->totalAffectedRows = 0;
5585

5586
  pThreadInfo->samplePos = 0;
5587

5588 5589 5590
  for (uint64_t tableSeq = pThreadInfo->start_table_from;
          tableSeq <= pThreadInfo->end_table_to;
          tableSeq ++) {
5591
    int64_t start_time = pThreadInfo->start_time;
5592

5593
    for (uint64_t i = 0; i < insertRows;) {
5594 5595
      char tableName[TSDB_TABLE_NAME_LEN];
      getTableName(tableName, pThreadInfo, tableSeq);
5596
      verbosePrint("%s() LN%d: tid=%d seq=%"PRId64" tableName=%s\n",
5597 5598
             __func__, __LINE__,
             pThreadInfo->threadID, tableSeq, tableName);
5599

5600
      int64_t remainderBufLen = maxSqlLen;
S
Shuduo Sang 已提交
5601
      char *pstr = pThreadInfo->buffer;
5602

5603 5604
      int len = snprintf(pstr,
              strlen(STR_INSERT_INTO) + 1, "%s", STR_INSERT_INTO);
5605 5606 5607 5608

      pstr += len;
      remainderBufLen -= len;

5609 5610 5611 5612 5613 5614 5615 5616 5617 5618
      int64_t generated;
      if (superTblInfo) {
        generated = generateStbProgressiveData(
                superTblInfo,
              tableName, tableSeq, pThreadInfo->db_name, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
      } else {
        generated = generateProgressiveDataWithoutStb(
5619 5620 5621 5622
              tableName, tableSeq, pThreadInfo, pstr, insertRows,
            i, start_time,
            &(pThreadInfo->samplePos),
            &remainderBufLen);
5623
      }
5624 5625 5626
      if (generated > 0)
        i += generated;
      else
5627
        goto free_of_progressive;
5628

5629
      start_time +=  generated * timeStampStep;
5630
      pThreadInfo->totalInsertRows += generated;
5631

5632
      startTs = taosGetTimestampMs();
5633

S
Shuduo Sang 已提交
5634
      int64_t affectedRows = execInsert(pThreadInfo, generated);
5635

5636
      endTs = taosGetTimestampMs();
5637
      uint64_t delay = endTs - startTs;
5638
      performancePrint("%s() LN%d, insert execution time is %"PRId64"ms\n",
5639
              __func__, __LINE__, delay);
5640 5641 5642
      verbosePrint("[%d] %s() LN%d affectedRows=%"PRId64"\n",
            pThreadInfo->threadID,
            __func__, __LINE__, affectedRows);
5643

5644 5645 5646 5647
      if (delay > pThreadInfo->maxDelay) pThreadInfo->maxDelay = delay;
      if (delay < pThreadInfo->minDelay) pThreadInfo->minDelay = delay;
      pThreadInfo->cntDelay++;
      pThreadInfo->totalDelay += delay;
5648

5649 5650 5651 5652 5653
      if (affectedRows < 0) {
        errorPrint("%s() LN%d, affected rows: %"PRId64"\n",
                __func__, __LINE__, affectedRows);
        goto free_of_progressive;
      }
5654 5655 5656

      pThreadInfo->totalAffectedRows += affectedRows;

5657 5658
      int64_t  currentPrintTime = taosGetTimestampMs();
      if (currentPrintTime - lastPrintTime > 30*1000) {
5659
        printf("thread[%d] has currently inserted rows: %"PRId64 ", affected rows: %"PRId64 "\n",
5660 5661 5662
                    pThreadInfo->threadID,
                    pThreadInfo->totalInsertRows,
                    pThreadInfo->totalAffectedRows);
5663 5664 5665
        lastPrintTime = currentPrintTime;
      }

5666
      if (i >= insertRows)
5667 5668 5669
        break;
    }   // num_of_DPT

5670 5671
    if ((g_args.verbose_print) &&
      (tableSeq == pThreadInfo->ntables - 1) && (superTblInfo) &&
5672 5673
        (0 == strncasecmp(
                    superTblInfo->dataSource, "sample", strlen("sample")))) {
5674
          verbosePrint("%s() LN%d samplePos=%"PRId64"\n",
5675
                  __func__, __LINE__, pThreadInfo->samplePos);
5676
    }
5677
  } // tableSeq
5678

5679
free_of_progressive:
S
Shuduo Sang 已提交
5680
  tmfree(pThreadInfo->buffer);
5681
  printStatPerThread(pThreadInfo);
5682
  return NULL;
H
Hui Li 已提交
5683 5684
}

5685 5686
static void* syncWrite(void *sarg) {

5687 5688
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5689

5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701
  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;
  }
5702

5703
  if (interlaceRows > 0) {
5704
    // interlace mode
5705
    return syncWriteInterlace(pThreadInfo);
5706 5707
  } else {
    // progressive mode
5708
    return syncWriteProgressive(pThreadInfo);
5709 5710 5711
  }
}

5712
static void callBack(void *param, TAOS_RES *res, int code) {
5713 5714
  threadInfo* pThreadInfo = (threadInfo*)param;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5715

5716 5717
  int insert_interval =
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5718
  if (insert_interval) {
5719 5720 5721
    pThreadInfo->et = taosGetTimestampMs();
    if ((pThreadInfo->et - pThreadInfo->st) < insert_interval) {
      taosMsleep(insert_interval - (pThreadInfo->et - pThreadInfo->st)); // ms
5722
    }
H
Hui Li 已提交
5723
  }
5724

5725
  char *buffer = calloc(1, pThreadInfo->superTblInfo->maxSqlLen);
5726
  char data[MAX_DATA_SIZE];
5727
  char *pstr = buffer;
5728 5729
  pstr += sprintf(pstr, "insert into %s.%s%"PRId64" values",
          pThreadInfo->db_name, pThreadInfo->tb_prefix,
5730
          pThreadInfo->start_table_from);
5731 5732 5733 5734 5735 5736 5737
//  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);
5738 5739 5740 5741
    free(buffer);
    taos_free_result(res);
    return;
  }
5742

5743
  for (int i = 0; i < g_args.num_of_RPR; i++) {
5744
    int rand_num = taosRandom() % 100;
5745
    if (0 != pThreadInfo->superTblInfo->disorderRatio
5746
            && rand_num < pThreadInfo->superTblInfo->disorderRatio) {
5747 5748 5749
      int64_t d = pThreadInfo->lastTs
          - (taosRandom() % pThreadInfo->superTblInfo->disorderRange + 1);
      generateStbRowData(pThreadInfo->superTblInfo, data, d);
5750
    } else {
5751 5752
      generateStbRowData(pThreadInfo->superTblInfo,
              data, pThreadInfo->lastTs += 1000);
H
Hui Li 已提交
5753
    }
5754
    pstr += sprintf(pstr, "%s", data);
5755
    pThreadInfo->counter++;
H
Hui Li 已提交
5756

5757
    if (pThreadInfo->counter >= pThreadInfo->superTblInfo->insertRows) {
5758
      break;
H
Hui Li 已提交
5759 5760
    }
  }
5761

5762
  if (insert_interval) {
5763
    pThreadInfo->st = taosGetTimestampMs();
5764
  }
5765
  taos_query_a(pThreadInfo->taos, buffer, callBack, pThreadInfo);
5766
  free(buffer);
H
Hui Li 已提交
5767

5768
  taos_free_result(res);
H
Hui Li 已提交
5769 5770
}

5771
static void *asyncWrite(void *sarg) {
5772 5773
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  SSuperTable* superTblInfo = pThreadInfo->superTblInfo;
5774

5775 5776 5777
  pThreadInfo->st = 0;
  pThreadInfo->et = 0;
  pThreadInfo->lastTs = pThreadInfo->start_time;
5778

5779
  int insert_interval =
5780
      superTblInfo?superTblInfo->insertInterval:g_args.insert_interval;
5781
  if (insert_interval) {
5782
    pThreadInfo->st = taosGetTimestampMs();
H
Hui Li 已提交
5783
  }
5784
  taos_query_a(pThreadInfo->taos, "show databases", callBack, pThreadInfo);
5785

5786
  tsem_wait(&(pThreadInfo->lock_sem));
H
Hui Li 已提交
5787 5788 5789 5790

  return NULL;
}

5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816
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;
}

5817
static void startMultiThreadInsertData(int threads, char* db_name,
5818
        char* precision,SSuperTable* superTblInfo) {
5819

5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835
  //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 {
5836
      errorPrint("Not support precision: %s\n", precision);
5837 5838 5839 5840
      exit(-1);
    }
  }

5841
  int64_t start_time;
5842 5843
  if (superTblInfo) {
    if (0 == strncasecmp(superTblInfo->startTimestamp, "now", 3)) {
5844
        start_time = taosGetTimestamp(timePrec);
5845
    } else {
5846
      if (TSDB_CODE_SUCCESS != taosParseTime(
5847 5848 5849 5850 5851
        superTblInfo->startTimestamp,
        &start_time,
        strlen(superTblInfo->startTimestamp),
        timePrec, 0)) {
          ERROR_EXIT("failed to parse time!\n");
5852
      }
5853
    }
5854
  } else {
5855
     start_time = 1500000000000;
5856 5857
  }

5858
  int64_t start = taosGetTimestampMs();
5859

5860
  // read sample data from file first
5861
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5862
              "sample", strlen("sample")))) {
5863
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5864
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5865
              __func__, __LINE__);
5866 5867 5868 5869
      exit(-1);
    }
  }

5870
  // read sample data from file first
5871
  if ((superTblInfo) && (0 == strncasecmp(superTblInfo->dataSource,
5872
              "sample", strlen("sample")))) {
5873
    if (0 != prepareSampleDataForSTable(superTblInfo)) {
5874
      errorPrint("%s() LN%d, prepare sample data for stable failed!\n",
5875
              __func__, __LINE__);
5876 5877 5878 5879
      exit(-1);
    }
  }

5880
  TAOS* taos0 = taos_connect(
5881 5882
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5883
  if (NULL == taos0) {
5884
    errorPrint("%s() LN%d, connect to server fail , reason: %s\n",
5885
                __func__, __LINE__, taos_errstr(NULL));
5886 5887 5888
    exit(-1);
  }

S
Shuduo Sang 已提交
5889
  int64_t ntables = 0;
S
Shuduo Sang 已提交
5890
  uint64_t startFrom;
5891

5892
  if (superTblInfo) {
5893 5894
    int64_t limit;
    uint64_t offset;
5895

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

5901
    if (superTblInfo->childTblExists == TBL_ALREADY_EXISTS) {
5902 5903
      if ((superTblInfo->childTblLimit < 0)
          || ((superTblInfo->childTblOffset + superTblInfo->childTblLimit)
5904
            > (superTblInfo->childTblCount))) {
5905 5906 5907 5908 5909 5910
        superTblInfo->childTblLimit =
            superTblInfo->childTblCount - superTblInfo->childTblOffset;
      }

      offset = superTblInfo->childTblOffset;
      limit = superTblInfo->childTblLimit;
5911
    } else {
5912 5913
      limit = superTblInfo->childTblCount;
      offset = 0;
5914 5915
    }

5916 5917 5918
    ntables = limit;
    startFrom = offset;

5919 5920 5921 5922
    if ((superTblInfo->childTblExists != TBL_NO_EXISTS)
        && ((superTblInfo->childTblOffset + superTblInfo->childTblLimit )
            > superTblInfo->childTblCount)) {
      printf("WARNING: specified offset + limit > child table count!\n");
5923
      prompt();
5924 5925 5926
    }

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

5932
    superTblInfo->childTblName = (char*)calloc(1,
5933
        limit * TSDB_TABLE_NAME_LEN);
5934
    if (superTblInfo->childTblName == NULL) {
5935
      errorPrint("%s() LN%d, alloc memory failed!\n", __func__, __LINE__);
5936
      taos_close(taos0);
5937 5938 5939
      exit(-1);
    }

5940
    int64_t childTblCount;
5941
    getChildNameOfSuperTableWithLimitAndOffset(
5942
        taos0,
5943 5944 5945 5946
        db_name, superTblInfo->sTblName,
        &superTblInfo->childTblName, &childTblCount,
        limit,
        offset);
5947 5948 5949
  } else {
    ntables = g_args.num_of_tables;
    startFrom = 0;
5950
  }
5951

5952
  taos_close(taos0);
5953

S
Shuduo Sang 已提交
5954
  int64_t a = ntables / threads;
5955 5956 5957 5958 5959
  if (a < 1) {
    threads = ntables;
    a = 1;
  }

S
Shuduo Sang 已提交
5960
  int64_t b = 0;
5961 5962 5963 5964
  if (threads != 0) {
    b = ntables % threads;
  }

5965
  if ((superTblInfo)
5966 5967 5968 5969
      && (superTblInfo->insertMode == REST_IFACE)) {
      if (convertHostToServAddr(g_Dbs.host, g_Dbs.port, &(g_Dbs.serv_addr)) != 0) {
        exit(-1);
      }
5970 5971
  }

5972 5973 5974 5975 5976 5977 5978 5979 5980
  pthread_t *pids = malloc(threads * sizeof(pthread_t));
  assert(pids != NULL);

  threadInfo *infos = calloc(1, threads * sizeof(threadInfo));
  assert(infos != NULL);

  memset(pids, 0, threads * sizeof(pthread_t));
  memset(infos, 0, threads * sizeof(threadInfo));

H
Hui Li 已提交
5981
  for (int i = 0; i < threads; i++) {
5982 5983 5984 5985 5986
    threadInfo *pThreadInfo = infos + i;
    pThreadInfo->threadID = i;
    tstrncpy(pThreadInfo->db_name, db_name, MAX_DB_NAME_SIZE);
    pThreadInfo->time_precision = timePrec;
    pThreadInfo->superTblInfo = superTblInfo;
5987

5988 5989
    pThreadInfo->start_time = start_time;
    pThreadInfo->minDelay = UINT64_MAX;
5990

5991
    if ((NULL == superTblInfo) ||
5992
            (superTblInfo->insertMode != REST_IFACE)) {
5993 5994
      //pThreadInfo->taos = taos;
      pThreadInfo->taos = taos_connect(
5995 5996
              g_Dbs.host, g_Dbs.user,
              g_Dbs.password, db_name, g_Dbs.port);
5997
      if (NULL == pThreadInfo->taos) {
5998
        errorPrint(
5999 6000
                "%s() LN%d, connect to server fail from insert sub thread, reason: %s\n",
                __func__, __LINE__,
6001
                taos_errstr(NULL));
6002
        free(infos);
6003 6004
        exit(-1);
      }
6005 6006

      if ((superTblInfo) && (superTblInfo->insertMode == STMT_IFACE)) {
6007 6008
        pThreadInfo->stmt = taos_stmt_init(pThreadInfo->taos);
        if (NULL == pThreadInfo->stmt) {
6009 6010 6011 6012 6013 6014 6015 6016 6017
            errorPrint(
                "%s() LN%d, failed init stmt, reason: %s\n",
                __func__, __LINE__,
                taos_errstr(NULL));
            free(pids);
            free(infos);
            exit(-1);
        }
      }
6018
    } else {
6019
      pThreadInfo->taos = NULL;
6020 6021
    }

6022
/*    if ((NULL == superTblInfo)
6023
            || (0 == superTblInfo->multiThreadWriteOneTbl)) {
6024
            */
6025 6026 6027 6028
      pThreadInfo->start_table_from = startFrom;
      pThreadInfo->ntables = i<b?a+1:a;
      pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = pThreadInfo->end_table_to + 1;
6029
/*    } else {
6030 6031 6032
      pThreadInfo->start_table_from = 0;
      pThreadInfo->ntables = superTblInfo->childTblCount;
      pThreadInfo->start_time = pThreadInfo->start_time + rand_int() % 10000 - rand_tinyint();
6033
    }
6034
*/
6035
    tsem_init(&(pThreadInfo->lock_sem), 0, 0);
6036
    if (ASYNC_MODE == g_Dbs.asyncMode) {
6037
      pthread_create(pids + i, NULL, asyncWrite, pThreadInfo);
6038
    } else {
6039
      pthread_create(pids + i, NULL, syncWrite, pThreadInfo);
6040
    }
H
Hui Li 已提交
6041
  }
6042

H
Hui Li 已提交
6043 6044 6045 6046
  for (int i = 0; i < threads; i++) {
    pthread_join(pids[i], NULL);
  }

6047 6048 6049 6050
  uint64_t totalDelay = 0;
  uint64_t maxDelay = 0;
  uint64_t minDelay = UINT64_MAX;
  uint64_t cntDelay = 1;
6051 6052
  double  avgDelay = 0;

H
Hui Li 已提交
6053
  for (int i = 0; i < threads; i++) {
6054
    threadInfo *pThreadInfo = infos + i;
6055

6056
    tsem_destroy(&(pThreadInfo->lock_sem));
6057

6058 6059
    if (pThreadInfo->stmt) {
      taos_stmt_close(pThreadInfo->stmt);
6060
    }
6061 6062
    tsem_destroy(&(pThreadInfo->lock_sem));
    taos_close(pThreadInfo->taos);
6063

6064
    debugPrint("%s() LN%d, [%d] totalInsert=%"PRIu64" totalAffected=%"PRIu64"\n",
6065
            __func__, __LINE__,
6066 6067
            pThreadInfo->threadID, pThreadInfo->totalInsertRows,
            pThreadInfo->totalAffectedRows);
6068
    if (superTblInfo) {
6069 6070
        superTblInfo->totalAffectedRows += pThreadInfo->totalAffectedRows;
        superTblInfo->totalInsertRows += pThreadInfo->totalInsertRows;
6071
    } else {
6072 6073
        g_args.totalAffectedRows += pThreadInfo->totalAffectedRows;
        g_args.totalInsertRows += pThreadInfo->totalInsertRows;
6074
    }
6075

6076 6077 6078 6079
    totalDelay  += pThreadInfo->totalDelay;
    cntDelay   += pThreadInfo->cntDelay;
    if (pThreadInfo->maxDelay > maxDelay) maxDelay = pThreadInfo->maxDelay;
    if (pThreadInfo->minDelay < minDelay) minDelay = pThreadInfo->minDelay;
H
Hui Li 已提交
6080
  }
6081
  cntDelay -= 1;
H
Hui Li 已提交
6082

6083
  if (cntDelay == 0)    cntDelay = 1;
6084 6085
  avgDelay = (double)totalDelay / cntDelay;

6086 6087
  int64_t end = taosGetTimestampMs();
  int64_t t = end - start;
6088 6089

  if (superTblInfo) {
6090
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s.%s. %.2f records/second\n\n",
6091 6092 6093 6094
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6095 6096 6097 6098

    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",
6099 6100 6101 6102
          t / 1000.0, superTblInfo->totalInsertRows,
          superTblInfo->totalAffectedRows,
          threads, db_name, superTblInfo->sTblName,
          (double)superTblInfo->totalInsertRows / (t / 1000.0));
6103
    }
6104
  } else {
6105
    fprintf(stderr, "Spent %.2f seconds to insert rows: %"PRIu64", affected rows: %"PRIu64" with %d thread(s) into %s %.2f records/second\n\n",
6106 6107 6108 6109
          t / 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
6110 6111 6112
    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",
6113 6114 6115 6116
          t * 1000.0, g_args.totalInsertRows,
          g_args.totalAffectedRows,
          threads, db_name,
          (double)g_args.totalInsertRows / (t / 1000.0));
6117
    }
6118
  }
6119

6120
  fprintf(stderr, "insert delay, avg: %10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6121
          avgDelay, maxDelay, minDelay);
6122 6123
  if (g_fpOfInsertResult) {
    fprintf(g_fpOfInsertResult, "insert delay, avg:%10.2fms, max: %"PRIu64"ms, min: %"PRIu64"ms\n\n",
6124
          avgDelay, maxDelay, minDelay);
6125
  }
6126

6127 6128
  //taos_close(taos);

H
Hui Li 已提交
6129
  free(pids);
6130
  free(infos);
H
Hui Li 已提交
6131 6132
}

6133
static void *readTable(void *sarg) {
6134
#if 1
6135 6136
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6137
  char command[BUFFER_SIZE] = "\0";
6138 6139 6140
  uint64_t sTime = pThreadInfo->start_time;
  char *tb_prefix = pThreadInfo->tb_prefix;
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6141
  if (NULL == fp) {
6142
    errorPrint( "fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6143 6144
    return NULL;
  }
6145

6146
  int64_t num_of_DPT;
6147 6148
/*  if (pThreadInfo->superTblInfo) {
    num_of_DPT = pThreadInfo->superTblInfo->insertRows; //  nrecords_per_table;
6149
  } else {
6150
  */
6151
      num_of_DPT = g_args.num_of_DPT;
6152
//  }
6153

6154
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
S
Shuduo Sang 已提交
6155
  int64_t totalData = num_of_DPT * num_of_tables;
6156
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6157 6158 6159 6160 6161

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

6165
  for (int j = 0; j < n; j++) {
H
hzcheng 已提交
6166
    double totalT = 0;
6167
    uint64_t count = 0;
6168 6169
    for (int64_t i = 0; i < num_of_tables; i++) {
      sprintf(command, "select %s from %s%"PRId64" where ts>= %" PRIu64,
6170
              aggreFunc[j], tb_prefix, i, sTime);
H
hzcheng 已提交
6171

6172
      double t = taosGetTimestampMs();
S
Shuaiqiang Chang 已提交
6173 6174
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);
H
hzcheng 已提交
6175

S
Shuaiqiang Chang 已提交
6176
      if (code != 0) {
6177
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6178
        taos_free_result(pSql);
H
hzcheng 已提交
6179
        taos_close(taos);
6180
        fclose(fp);
6181
        return NULL;
H
hzcheng 已提交
6182 6183
      }

6184
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6185 6186 6187
        count++;
      }

6188
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6189 6190
      totalT += t;

S
Shuaiqiang Chang 已提交
6191
      taos_free_result(pSql);
H
hzcheng 已提交
6192 6193
    }

6194
    fprintf(fp, "|%10s  |   %"PRId64"   |  %12.2f   |   %10.2f  |\n",
S
slguan 已提交
6195
            aggreFunc[j][0] == '*' ? "   *   " : aggreFunc[j], totalData,
H
hzcheng 已提交
6196
            (double)(num_of_tables * num_of_DPT) / totalT, totalT * 1000);
6197
    printf("select %10s took %.6f second(s)\n", aggreFunc[j], totalT * 1000);
H
hzcheng 已提交
6198 6199 6200
  }
  fprintf(fp, "\n");
  fclose(fp);
6201
#endif
H
hzcheng 已提交
6202 6203 6204
  return NULL;
}

6205
static void *readMetric(void *sarg) {
6206
#if 1
6207 6208
  threadInfo *pThreadInfo = (threadInfo *)sarg;
  TAOS *taos = pThreadInfo->taos;
H
hzcheng 已提交
6209
  char command[BUFFER_SIZE] = "\0";
6210
  FILE *fp = fopen(pThreadInfo->filePath, "a");
H
Hui Li 已提交
6211
  if (NULL == fp) {
6212
    printf("fopen %s fail, reason:%s.\n", pThreadInfo->filePath, strerror(errno));
H
Hui Li 已提交
6213 6214
    return NULL;
  }
6215

6216 6217
  int64_t num_of_DPT = pThreadInfo->superTblInfo->insertRows;
  int64_t num_of_tables = pThreadInfo->ntables; // rinfo->end_table_to - rinfo->start_table_from + 1;
S
Shuduo Sang 已提交
6218
  int64_t totalData = num_of_DPT * num_of_tables;
6219
  bool do_aggreFunc = g_Dbs.do_aggreFunc;
H
hzcheng 已提交
6220 6221 6222 6223 6224

  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");
  }
S
Shuduo Sang 已提交
6225 6226
  printf("%"PRId64" records:\n", totalData);
  fprintf(fp, "Querying On %"PRId64" records:\n", totalData);
H
hzcheng 已提交
6227 6228

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

6232
    int64_t m = 10 < num_of_tables ? 10 : num_of_tables;
H
hzcheng 已提交
6233

6234
    for (int64_t i = 1; i <= m; i++) {
H
hzcheng 已提交
6235
      if (i == 1) {
6236
        sprintf(tempS, "t1 = %"PRId64"", i);
H
hzcheng 已提交
6237
      } else {
6238
        sprintf(tempS, " or t1 = %"PRId64" ", i);
H
hzcheng 已提交
6239
      }
6240
      strncat(condition, tempS, COND_BUF_LEN - 1);
H
hzcheng 已提交
6241

L
liu0x54 已提交
6242
      sprintf(command, "select %s from meters where %s", aggreFunc[j], condition);
H
hzcheng 已提交
6243 6244 6245 6246

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

6247
      double t = taosGetTimestampMs();
H
hzcheng 已提交
6248

S
Shuaiqiang Chang 已提交
6249 6250 6251 6252
      TAOS_RES *pSql = taos_query(taos, command);
      int32_t code = taos_errno(pSql);

      if (code != 0) {
6253
        errorPrint( "Failed to query:%s\n", taos_errstr(pSql));
S
Shuaiqiang Chang 已提交
6254
        taos_free_result(pSql);
H
hzcheng 已提交
6255
        taos_close(taos);
6256
        fclose(fp);
6257
        return NULL;
H
hzcheng 已提交
6258 6259
      }
      int count = 0;
6260
      while(taos_fetch_row(pSql) != NULL) {
H
hzcheng 已提交
6261 6262
        count++;
      }
6263
      t = taosGetTimestampMs() - t;
H
hzcheng 已提交
6264

6265
      fprintf(fp, "| Speed: %12.2f(per s) | Latency: %.4f(ms) |\n",
6266 6267
              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 已提交
6268

S
Shuaiqiang Chang 已提交
6269
      taos_free_result(pSql);
H
hzcheng 已提交
6270 6271 6272 6273
    }
    fprintf(fp, "\n");
  }
  fclose(fp);
6274
#endif
H
hzcheng 已提交
6275 6276 6277
  return NULL;
}

6278 6279 6280 6281 6282 6283 6284
static void prompt()
{
  if (!g_args.answer_yes) {
    printf("         Press enter key to continue or Ctrl-C to stop\n\n");
    (void)getchar();
  }
}
H
Hui Li 已提交
6285

6286
static int insertTestProcess() {
6287

6288 6289 6290
  setupForAnsiEscape();
  int ret = printfInsertMeta();
  resetAfterAnsiEscape();
6291

6292 6293 6294
  if (ret == -1)
    exit(EXIT_FAILURE);

6295
  debugPrint("%d result file: %s\n", __LINE__, g_Dbs.resultFile);
6296 6297
  g_fpOfInsertResult = fopen(g_Dbs.resultFile, "a");
  if (NULL == g_fpOfInsertResult) {
6298
    errorPrint( "Failed to open %s for save result\n", g_Dbs.resultFile);
6299 6300
    return -1;
  }
6301

6302 6303
  if (g_fpOfInsertResult)
    printfInsertMetaToFile(g_fpOfInsertResult);
6304

6305
  prompt();
6306

6307 6308 6309
  init_rand_data();

  // create database and super tables
6310
  if(createDatabasesAndStables() != 0) {
6311 6312
    if (g_fpOfInsertResult)
      fclose(g_fpOfInsertResult);
6313 6314
    return -1;
  }
6315 6316

  // pretreatement
6317
  prepareSampleData();
6318

6319 6320 6321 6322
  double start;
  double end;

  // create child tables
6323
  start = taosGetTimestampMs();
6324
  createChildTables();
6325
  end = taosGetTimestampMs();
6326

6327
  if (g_totalChildTables > 0) {
6328
    fprintf(stderr, "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6329
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6330 6331
    if (g_fpOfInsertResult) {
      fprintf(g_fpOfInsertResult,
6332
            "Spent %.4f seconds to create %"PRId64" tables with %d thread(s)\n\n",
6333
            (end - start)/1000.0, g_totalChildTables, g_Dbs.threadCountByCreateTbl);
6334
    }
6335
  }
6336

6337
  taosMsleep(1000);
6338
  // create sub threads for inserting data
6339
  //start = taosGetTimestampMs();
6340
  for (int i = 0; i < g_Dbs.dbCount; i++) {
6341 6342
    if (g_Dbs.use_metric) {
      if (g_Dbs.db[i].superTblCount > 0) {
S
Shuduo Sang 已提交
6343
        for (uint64_t j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6344 6345 6346 6347 6348

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

          if (superTblInfo && (superTblInfo->insertRows > 0)) {
            startMultiThreadInsertData(
6349 6350 6351 6352
              g_Dbs.threadCount,
              g_Dbs.db[i].dbName,
              g_Dbs.db[i].dbCfg.precision,
              superTblInfo);
6353
          }
6354
        }
6355
      }
6356
    } else {
6357
        startMultiThreadInsertData(
6358 6359 6360
          g_Dbs.threadCount,
          g_Dbs.db[i].dbName,
          g_Dbs.db[i].dbCfg.precision,
6361
          NULL);
H
Hui Li 已提交
6362
    }
6363
  }
6364
  //end = taosGetTimestampMs();
6365

6366
  //int64_t    totalInsertRows = 0;
6367
  //int64_t    totalAffectedRows = 0;
6368
  //for (int i = 0; i < g_Dbs.dbCount; i++) {
6369
  //  for (int j = 0; j < g_Dbs.db[i].superTblCount; j++) {
6370
  //  totalInsertRows+= g_Dbs.db[i].superTbls[j].totalInsertRows;
6371 6372
  //  totalAffectedRows += g_Dbs.db[i].superTbls[j].totalAffectedRows;
  //}
6373
  //printf("Spent %.4f seconds to insert rows: %"PRId64", affected rows: %"PRId64" with %d thread(s)\n\n", end - start, totalInsertRows, totalAffectedRows, g_Dbs.threadCount);
6374
  postFreeResource();
6375

6376 6377 6378
  return 0;
}

6379 6380
static void *specifiedTableQuery(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6381

6382
  if (pThreadInfo->taos == NULL) {
6383 6384
    TAOS * taos = NULL;
    taos = taos_connect(g_queryInfo.host,
6385 6386 6387 6388
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
          g_queryInfo.port);
6389 6390
    if (taos == NULL) {
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6391
            pThreadInfo->threadID, taos_errstr(NULL));
6392 6393
      return NULL;
    } else {
6394
      pThreadInfo->taos = taos;
6395 6396 6397
    }
  }

6398 6399
  char sqlStr[MAX_DB_NAME_SIZE + 5];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6400 6401
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6402 6403 6404 6405
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
    return NULL;
  }
6406

6407 6408
  uint64_t st = 0;
  uint64_t et = 0;
6409

6410
  uint64_t queryTimes = g_queryInfo.specifiedQueryInfo.queryTimes;
6411

6412 6413 6414
  uint64_t totalQueried = 0;
  uint64_t lastPrintTime = taosGetTimestampMs();
  uint64_t startTs = taosGetTimestampMs();
6415

6416 6417
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) {
    sprintf(pThreadInfo->filePath, "%s-%d",
6418 6419 6420 6421
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }

6422
  while(queryTimes --) {
6423
    if (g_queryInfo.specifiedQueryInfo.queryInterval && (et - st) <
6424
            (int64_t)g_queryInfo.specifiedQueryInfo.queryInterval) {
6425
      taosMsleep(g_queryInfo.specifiedQueryInfo.queryInterval - (et - st)); // ms
6426 6427
    }

6428 6429 6430
    st = taosGetTimestampMs();

    selectAndGetResult(pThreadInfo,
6431
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq]);
6432

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

6437 6438
    totalQueried ++;
    g_queryInfo.specifiedQueryInfo.totalQueried ++;
6439

6440 6441
    uint64_t  currentPrintTime = taosGetTimestampMs();
    uint64_t  endTs = taosGetTimestampMs();
6442
    if (currentPrintTime - lastPrintTime > 30*1000) {
6443
      debugPrint("%s() LN%d, endTs=%"PRIu64"ms, startTs=%"PRIu64"ms\n",
6444
          __func__, __LINE__, endTs, startTs);
6445
      printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.6f\n",
6446 6447
                    pThreadInfo->threadID,
                    totalQueried,
6448
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6449
      lastPrintTime = currentPrintTime;
6450
    }
H
Hui Li 已提交
6451
  }
6452 6453
  return NULL;
}
H
Hui Li 已提交
6454

6455
static void replaceChildTblName(char* inSql, char* outSql, int tblIndex) {
6456 6457
  char sourceString[32] = "xxxx";
  char subTblName[MAX_TB_NAME_SIZE*3];
6458 6459
  sprintf(subTblName, "%s.%s",
          g_queryInfo.dbName,
6460
          g_queryInfo.superQueryInfo.childTblName + tblIndex*TSDB_TABLE_NAME_LEN);
6461 6462

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

6464 6465
  char* pos = strstr(inSql, sourceString);
  if (0 == pos) {
6466
    return;
H
Hui Li 已提交
6467
  }
6468

6469
  tstrncpy(outSql, inSql, pos - inSql + 1);
6470
  //printf("1: %s\n", outSql);
6471
  strncat(outSql, subTblName, MAX_QUERY_SQL_LENGTH - 1);
6472
  //printf("2: %s\n", outSql);
6473
  strncat(outSql, pos+strlen(sourceString), MAX_QUERY_SQL_LENGTH - 1);
6474
  //printf("3: %s\n", outSql);
H
Hui Li 已提交
6475 6476
}

6477
static void *superTableQuery(void *sarg) {
6478
  char sqlstr[MAX_QUERY_SQL_LENGTH];
6479
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6480

6481
  if (pThreadInfo->taos == NULL) {
6482 6483 6484 6485 6486 6487 6488 6489
    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",
6490
            pThreadInfo->threadID, taos_errstr(NULL));
6491 6492
      return NULL;
    } else {
6493
      pThreadInfo->taos = taos;
6494 6495 6496
    }
  }

6497 6498
  uint64_t st = 0;
  uint64_t et = (int64_t)g_queryInfo.superQueryInfo.queryInterval;
6499

6500 6501 6502
  uint64_t queryTimes = g_queryInfo.superQueryInfo.queryTimes;
  uint64_t totalQueried = 0;
  uint64_t  startTs = taosGetTimestampMs();
6503

6504
  uint64_t  lastPrintTime = taosGetTimestampMs();
6505
  while(queryTimes --) {
6506 6507 6508
    if (g_queryInfo.superQueryInfo.queryInterval
            && (et - st) < (int64_t)g_queryInfo.superQueryInfo.queryInterval) {
      taosMsleep(g_queryInfo.superQueryInfo.queryInterval - (et - st)); // ms
6509
      //printf("========sleep duration:%"PRId64 "========inserted rows:%d, table range:%d - %d\n", (1000 - (et - st)), i, pThreadInfo->start_table_from, pThreadInfo->end_table_to);
6510
    }
H
Hui Li 已提交
6511

6512
    st = taosGetTimestampMs();
6513
    for (int i = pThreadInfo->start_table_from; i <= pThreadInfo->end_table_to; i++) {
6514
      for (int j = 0; j < g_queryInfo.superQueryInfo.sqlCount; j++) {
6515
        memset(sqlstr,0,sizeof(sqlstr));
6516
        replaceChildTblName(g_queryInfo.superQueryInfo.sql[j], sqlstr, i);
6517 6518
        if (g_queryInfo.superQueryInfo.result[j] != NULL) {
          sprintf(pThreadInfo->filePath, "%s-%d",
6519
                  g_queryInfo.superQueryInfo.result[j],
6520
                  pThreadInfo->threadID);
6521
        }
6522
        selectAndGetResult(pThreadInfo, sqlstr);
6523 6524 6525 6526 6527 6528 6529

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

        int64_t  currentPrintTime = taosGetTimestampMs();
        int64_t  endTs = taosGetTimestampMs();
        if (currentPrintTime - lastPrintTime > 30*1000) {
6530
          printf("thread[%d] has currently completed queries: %"PRIu64", QPS: %10.3f\n",
6531 6532
                    pThreadInfo->threadID,
                    totalQueried,
6533
                    (double)(totalQueried/((endTs-startTs)/1000.0)));
6534
          lastPrintTime = currentPrintTime;
6535
        }
6536
      }
H
Hui Li 已提交
6537
    }
6538
    et = taosGetTimestampMs();
6539
    printf("####thread[%"PRId64"] complete all sqls to allocate all sub-tables[%"PRIu64" - %"PRIu64"] once queries duration:%.4fs\n\n",
6540
            taosGetSelfPthreadId(),
6541 6542
            pThreadInfo->start_table_from,
            pThreadInfo->end_table_to,
6543
            (double)(et - st)/1000.0);
6544
  }
6545

6546 6547 6548
  return NULL;
}

6549
static int queryTestProcess() {
6550 6551 6552 6553

  setupForAnsiEscape();
  printfQueryMeta();
  resetAfterAnsiEscape();
6554 6555 6556 6557 6558 6559

  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          NULL,
6560
          g_queryInfo.port);
6561
  if (taos == NULL) {
6562 6563
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
6564 6565 6566
    exit(-1);
  }

6567
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
6568 6569
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
6570 6571 6572
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
6573
  }
6574

6575
  prompt();
6576

6577 6578 6579
  if (g_args.debug_print || g_args.verbose_print) {
    printfQuerySystemInfo(taos);
  }
6580

6581 6582 6583 6584 6585 6586
  if (0 == strncasecmp(g_queryInfo.queryMode, "rest", strlen("rest"))) {
    if (convertHostToServAddr(
        g_queryInfo.host, g_queryInfo.port, &g_queryInfo.serv_addr) != 0)
      exit(-1);
  }

6587 6588 6589
  pthread_t  *pids  = NULL;
  threadInfo *infos = NULL;
  //==== create sub threads for query from specify table
6590
  int nConcurrent = g_queryInfo.specifiedQueryInfo.concurrent;
6591
  uint64_t nSqlCount = g_queryInfo.specifiedQueryInfo.sqlCount;
6592

6593
  uint64_t startTs = taosGetTimestampMs();
6594

6595 6596 6597 6598 6599 6600
  if ((nSqlCount > 0) && (nConcurrent > 0)) {

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

    if ((NULL == pids) || (NULL == infos)) {
6601
      taos_close(taos);
6602
      ERROR_EXIT("memory allocation failed for create threads\n");
6603
    }
6604

6605 6606 6607
    for (uint64_t i = 0; i < nSqlCount; i++) {
        for (int j = 0; j < nConcurrent; j++) {
            uint64_t seq = i * nConcurrent + j;
6608 6609 6610
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625

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

                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)) {
                    taos_close(taos);
                    free(infos);
                    free(pids);
                    errorPrint( "use database %s failed!\n\n",
                        g_queryInfo.dbName);
                    return -1;
                }
            }
6626

6627
            pThreadInfo->taos = NULL;// TODO: workaround to use separate taos connection;
6628

6629
            pthread_create(pids + seq, NULL, specifiedTableQuery,
6630
                pThreadInfo);
6631
        }
6632
    }
6633
  } else {
6634
    g_queryInfo.specifiedQueryInfo.concurrent = 0;
6635
  }
6636

6637 6638
  taos_close(taos);

6639 6640 6641
  pthread_t  *pidsOfSub  = NULL;
  threadInfo *infosOfSub = NULL;
  //==== create sub threads for query from all sub table of the super table
6642 6643 6644 6645
  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));
6646 6647

    if ((NULL == pidsOfSub) || (NULL == infosOfSub)) {
6648 6649
      free(infos);
      free(pids);
6650

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

S
Shuduo Sang 已提交
6654
    int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
6655
    int threads = g_queryInfo.superQueryInfo.threadCnt;
6656

S
Shuduo Sang 已提交
6657
    int64_t a = ntables / threads;
6658 6659 6660 6661
    if (a < 1) {
      threads = ntables;
      a = 1;
    }
6662

S
Shuduo Sang 已提交
6663
    int64_t b = 0;
6664 6665 6666
    if (threads != 0) {
      b = ntables % threads;
    }
6667

6668
    uint64_t startFrom = 0;
6669
    for (int i = 0; i < threads; i++) {
6670 6671
      threadInfo *pThreadInfo = infosOfSub + i;
      pThreadInfo->threadID = i;
6672

6673 6674 6675 6676 6677 6678
      pThreadInfo->start_table_from = startFrom;
      pThreadInfo->ntables = i<b?a+1:a;
      pThreadInfo->end_table_to = i < b ? startFrom + a : startFrom + a - 1;
      startFrom = pThreadInfo->end_table_to + 1;
      pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
      pthread_create(pidsOfSub + i, NULL, superTableQuery, pThreadInfo);
6679 6680
    }

6681
    g_queryInfo.superQueryInfo.threadCnt = threads;
6682
  } else {
6683
    g_queryInfo.superQueryInfo.threadCnt = 0;
6684
  }
6685

6686 6687 6688 6689 6690 6691
  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);
      }
    }
6692
  }
S
Shuaiqiang Chang 已提交
6693

6694
  tmfree((char*)pids);
6695
  tmfree((char*)infos);
6696

6697
  for (int i = 0; i < g_queryInfo.superQueryInfo.threadCnt; i++) {
6698
    pthread_join(pidsOfSub[i], NULL);
H
hzcheng 已提交
6699
  }
H
Hui Li 已提交
6700

6701
  tmfree((char*)pidsOfSub);
6702
  tmfree((char*)infosOfSub);
6703

6704
//  taos_close(taos);// TODO: workaround to use separate taos connection;
6705
  uint64_t endTs = taosGetTimestampMs();
6706

6707
  uint64_t totalQueried = g_queryInfo.specifiedQueryInfo.totalQueried +
6708 6709
    g_queryInfo.superQueryInfo.totalQueried;

6710
  fprintf(stderr, "==== completed total queries: %"PRIu64", the QPS of all threads: %10.3f====\n",
6711
          totalQueried,
6712
          (double)(totalQueried/((endTs-startTs)/1000.0)));
6713 6714 6715
  return 0;
}

6716 6717 6718 6719 6720 6721 6722 6723 6724
static void stable_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
  if (res == NULL || taos_errno(res) != 0) {
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
    return;
  }

  if (param)
6725
    fetchResult(res, (threadInfo *)param);
6726 6727 6728 6729 6730
  // tao_unscribe() will free result.
}

static void specified_sub_callback(
        TAOS_SUB* tsub, TAOS_RES *res, void* param, int code) {
6731
  if (res == NULL || taos_errno(res) != 0) {
6732 6733
    errorPrint("%s() LN%d, failed to subscribe result, code:%d, reason:%s\n",
           __func__, __LINE__, code, taos_errstr(res));
6734 6735
    return;
  }
6736

6737
  if (param)
6738
    fetchResult(res, (threadInfo *)param);
6739
  // tao_unscribe() will free result.
H
hzcheng 已提交
6740 6741
}

6742
static TAOS_SUB* subscribeImpl(
6743 6744 6745 6746
        QUERY_CLASS class,
        threadInfo *pThreadInfo,
        char *sql, char* topic, bool restart, uint64_t interval)
{
6747
  TAOS_SUB* tsub = NULL;
H
hzcheng 已提交
6748

6749 6750 6751 6752
  if ((SPECIFIED_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode)) {
    tsub = taos_subscribe(
            pThreadInfo->taos,
6753
            restart,
6754
            topic, sql, specified_sub_callback, (void*)pThreadInfo,
6755
            g_queryInfo.specifiedQueryInfo.subscribeInterval);
6756 6757 6758 6759 6760 6761 6762
  } else if ((STABLE_CLASS == class)
          && (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode)) {
    tsub = taos_subscribe(
            pThreadInfo->taos,
            restart,
            topic, sql, stable_sub_callback, (void*)pThreadInfo,
            g_queryInfo.superQueryInfo.subscribeInterval);
6763
  } else {
6764 6765
    tsub = taos_subscribe(
            pThreadInfo->taos,
6766
            restart,
6767
            topic, sql, NULL, NULL, interval);
6768
  }
6769

6770 6771 6772
  if (tsub == NULL) {
    printf("failed to create subscription. topic:%s, sql:%s\n", topic, sql);
    return NULL;
6773
  }
6774

6775 6776
  return tsub;
}
H
hzcheng 已提交
6777

6778 6779
static void *superSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6780
  char subSqlstr[MAX_QUERY_SQL_LENGTH];
6781
  TAOS_SUB*    tsub[MAX_QUERY_SQL_COUNT] = {0};
6782
  uint64_t tsubSeq;
H
hzcheng 已提交
6783

6784 6785
  if (pThreadInfo->ntables > MAX_QUERY_SQL_COUNT) {
      errorPrint("The table number(%"PRId64") of the thread is more than max query sql count: %d\n",
6786 6787 6788 6789 6790
              pThreadInfo->ntables,
              MAX_QUERY_SQL_COUNT);
      exit(-1);
  }

6791
  if (pThreadInfo->taos == NULL) {
6792
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
6793 6794 6795 6796
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
6797
    if (pThreadInfo->taos == NULL) {
6798
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6799
            pThreadInfo->threadID, taos_errstr(NULL));
6800 6801 6802 6803
      return NULL;
    }
  }

6804 6805
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6806 6807
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6808 6809
    errorPrint( "use database %s failed!\n\n",
                g_queryInfo.dbName);
6810 6811
    return NULL;
  }
6812

S
Shengliang Guan 已提交
6813 6814 6815
  char topic[32] = {0};
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
6816 6817

      tsubSeq = i - pThreadInfo->start_table_from;
6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829
      verbosePrint("%s() LN%d, [%d], start=%"PRId64" end=%"PRId64" i=%"PRIu64"\n",
              __func__, __LINE__,
              pThreadInfo->threadID,
              pThreadInfo->start_table_from,
              pThreadInfo->end_table_to, i);
      sprintf(topic, "taosdemo-subscribe-%"PRIu64"-%"PRIu64"",
              i, pThreadInfo->querySeq);
      memset(subSqlstr, 0, sizeof(subSqlstr));
      replaceChildTblName(
              g_queryInfo.superQueryInfo.sql[pThreadInfo->querySeq],
              subSqlstr, i);
      if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6830
        sprintf(pThreadInfo->filePath, "%s-%d",
6831 6832 6833 6834 6835 6836
                g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
      }

      debugPrint("%s() LN%d, [%d] subSqlstr: %s\n",
              __func__, __LINE__, pThreadInfo->threadID, subSqlstr);
6837
      tsub[tsubSeq] = subscribeImpl(
6838 6839 6840 6841
              STABLE_CLASS,
              pThreadInfo, subSqlstr, topic,
              g_queryInfo.superQueryInfo.subscribeRestart,
              g_queryInfo.superQueryInfo.subscribeInterval);
6842
      if (NULL == tsub[tsubSeq]) {
6843
        taos_close(pThreadInfo->taos);
6844 6845
        return NULL;
      }
S
Shengliang Guan 已提交
6846
  }
6847 6848

  // start loop to consume result
6849 6850 6851 6852
  int consumed[MAX_QUERY_SQL_COUNT];
  for (int i = 0; i < MAX_QUERY_SQL_COUNT; i++) {
    consumed[i] = 0;
  }
6853
  TAOS_RES* res = NULL;
6854

6855 6856
  uint64_t st = 0, et = 0;

6857
  while(1) {
6858 6859
    for (uint64_t i = pThreadInfo->start_table_from;
            i <= pThreadInfo->end_table_to; i++) {
6860 6861 6862 6863
      tsubSeq = i - pThreadInfo->start_table_from;
      if (ASYNC_MODE == g_queryInfo.superQueryInfo.asyncMode) {
          continue;
      }
6864

6865 6866
      st = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" st-et: %"PRIu64"\n", st, et, (st - et));
6867
      res = taos_consume(tsub[tsubSeq]);
6868 6869 6870
      et = taosGetTimestampMs();
      performancePrint("st: %"PRIu64" et: %"PRIu64" delta: %"PRIu64"\n", st, et, (et - st));

6871 6872
      if (res) {
          if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6873
              sprintf(pThreadInfo->filePath, "%s-%d",
6874 6875
                      g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6876
              fetchResult(res, pThreadInfo);
6877 6878
          }
          if (g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6879
              sprintf(pThreadInfo->filePath, "%s-%d",
6880 6881
                      g_queryInfo.superQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6882
              fetchResult(res, pThreadInfo);
6883 6884 6885 6886 6887
          }
          consumed[tsubSeq] ++;

          if ((g_queryInfo.superQueryInfo.subscribeKeepProgress)
                  && (consumed[tsubSeq] >=
6888
                      g_queryInfo.superQueryInfo.resubAfterConsume)) {
6889 6890 6891 6892
              printf("keepProgress:%d, resub super table query: %"PRIu64"\n",
                      g_queryInfo.superQueryInfo.subscribeKeepProgress,
                      pThreadInfo->querySeq);
              taos_unsubscribe(tsub[tsubSeq],
6893
                    g_queryInfo.superQueryInfo.subscribeKeepProgress);
6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906
              consumed[tsubSeq]= 0;
              tsub[tsubSeq] = subscribeImpl(
                      STABLE_CLASS,
                      pThreadInfo, subSqlstr, topic,
                      g_queryInfo.superQueryInfo.subscribeRestart,
                      g_queryInfo.superQueryInfo.subscribeInterval
                      );
              if (NULL == tsub[tsubSeq]) {
                  taos_close(pThreadInfo->taos);
                  return NULL;
              }
          }
      }
H
hzcheng 已提交
6907 6908
    }
  }
6909
  taos_free_result(res);
6910

S
Shengliang Guan 已提交
6911 6912
  for (uint64_t i = pThreadInfo->start_table_from;
          i <= pThreadInfo->end_table_to; i++) {
6913 6914
    tsubSeq = i - pThreadInfo->start_table_from;
    taos_unsubscribe(tsub[tsubSeq], 0);
6915
  }
6916

6917
  taos_close(pThreadInfo->taos);
H
hzcheng 已提交
6918 6919 6920
  return NULL;
}

6921 6922
static void *specifiedSubscribe(void *sarg) {
  threadInfo *pThreadInfo = (threadInfo *)sarg;
6923
//  TAOS_SUB*  tsub = NULL;
6924

6925
  if (pThreadInfo->taos == NULL) {
6926
    pThreadInfo->taos = taos_connect(g_queryInfo.host,
6927 6928 6929 6930
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
          g_queryInfo.port);
6931
    if (pThreadInfo->taos == NULL) {
6932
      errorPrint("[%d] Failed to connect to TDengine, reason:%s\n",
6933
            pThreadInfo->threadID, taos_errstr(NULL));
6934 6935 6936 6937
      return NULL;
    }
  }

6938 6939
  char sqlStr[MAX_TB_NAME_SIZE*2];
  sprintf(sqlStr, "use %s", g_queryInfo.dbName);
6940
  debugPrint("%s() %d sqlStr: %s\n", __func__, __LINE__, sqlStr);
6941 6942
  if (0 != queryDbExec(pThreadInfo->taos, sqlStr, NO_INSERT_TYPE, false)) {
    taos_close(pThreadInfo->taos);
6943 6944
    return NULL;
  }
6945

6946 6947 6948 6949 6950 6951
  sprintf(g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
          "taosdemo-subscribe-%"PRIu64"-%d",
          pThreadInfo->querySeq,
          pThreadInfo->threadID);
  if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq] != NULL) {
      sprintf(pThreadInfo->filePath, "%s-%d",
6952 6953 6954
                g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                pThreadInfo->threadID);
  }
6955 6956
  g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
          SPECIFIED_CLASS, pThreadInfo,
6957
          g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
6958
          g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
6959
          g_queryInfo.specifiedQueryInfo.subscribeRestart,
6960
          g_queryInfo.specifiedQueryInfo.subscribeInterval);
6961
  if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
6962 6963
      taos_close(pThreadInfo->taos);
      return NULL;
S
Shengliang Guan 已提交
6964
  }
6965

6966
  // start loop to consume result
6967

6968
  g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
6969
  while(1) {
6970
      if (ASYNC_MODE == g_queryInfo.specifiedQueryInfo.asyncMode) {
6971 6972
        continue;
      }
6973

6974 6975 6976
      g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID] = taos_consume(
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]);
      if (g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]) {
6977
          if (g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq][0] != 0) {
6978
              sprintf(pThreadInfo->filePath, "%s-%d",
6979 6980
                      g_queryInfo.specifiedQueryInfo.result[pThreadInfo->querySeq],
                      pThreadInfo->threadID);
6981
              fetchResult(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID], pThreadInfo);
6982 6983
          }

6984
          g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] ++;
6985
          if ((g_queryInfo.specifiedQueryInfo.subscribeKeepProgress)
6986
                && (g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] >=
6987 6988 6989 6990
                    g_queryInfo.specifiedQueryInfo.resubAfterConsume[pThreadInfo->querySeq])) {
              printf("keepProgress:%d, resub specified query: %"PRIu64"\n",
                    g_queryInfo.specifiedQueryInfo.subscribeKeepProgress,
                    pThreadInfo->querySeq);
6991 6992
              g_queryInfo.specifiedQueryInfo.consumed[pThreadInfo->threadID] = 0;
              taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID],
6993
                      g_queryInfo.specifiedQueryInfo.subscribeKeepProgress);
6994
              g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID] = subscribeImpl(
6995 6996 6997
                      SPECIFIED_CLASS,
                      pThreadInfo,
                      g_queryInfo.specifiedQueryInfo.sql[pThreadInfo->querySeq],
6998
                      g_queryInfo.specifiedQueryInfo.topic[pThreadInfo->threadID],
6999 7000
                      g_queryInfo.specifiedQueryInfo.subscribeRestart,
                      g_queryInfo.specifiedQueryInfo.subscribeInterval);
7001
              if (NULL == g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->threadID]) {
7002 7003
                taos_close(pThreadInfo->taos);
                return NULL;
7004 7005
              }
          }
7006 7007
      }
  }
7008 7009
  taos_free_result(g_queryInfo.specifiedQueryInfo.res[pThreadInfo->threadID]);
  taos_unsubscribe(g_queryInfo.specifiedQueryInfo.tsub[pThreadInfo->querySeq], 0);
7010
  taos_close(pThreadInfo->taos);
7011

H
hzcheng 已提交
7012 7013 7014
  return NULL;
}

7015
static int subscribeTestProcess() {
7016
  setupForAnsiEscape();
7017
  printfQueryMeta();
7018
  resetAfterAnsiEscape();
7019

7020
  prompt();
7021

7022 7023 7024 7025 7026
  TAOS * taos = NULL;
  taos = taos_connect(g_queryInfo.host,
          g_queryInfo.user,
          g_queryInfo.password,
          g_queryInfo.dbName,
7027
          g_queryInfo.port);
7028
  if (taos == NULL) {
7029 7030
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7031 7032 7033
    exit(-1);
  }

7034
  if (0 != g_queryInfo.superQueryInfo.sqlCount) {
7035 7036
    getAllChildNameOfSuperTable(taos,
            g_queryInfo.dbName,
7037 7038 7039
            g_queryInfo.superQueryInfo.sTblName,
            &g_queryInfo.superQueryInfo.childTblName,
            &g_queryInfo.superQueryInfo.childTblCount);
7040 7041
  }

7042 7043
  taos_close(taos); // TODO: workaround to use separate taos connection;

7044 7045
  pthread_t  *pids = NULL;
  threadInfo *infos = NULL;
7046 7047 7048 7049 7050

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

  //==== create threads for query for specified table
S
Shengliang Guan 已提交
7051
  if (g_queryInfo.specifiedQueryInfo.sqlCount <= 0) {
7052
    debugPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
7053
              __func__, __LINE__,
S
Shengliang Guan 已提交
7054 7055 7056 7057 7058 7059 7060 7061
              g_queryInfo.specifiedQueryInfo.sqlCount);
  } else {
    if (g_queryInfo.specifiedQueryInfo.concurrent <= 0) {
        errorPrint("%s() LN%d, sepcified query sqlCount %"PRIu64".\n",
              __func__, __LINE__,
              g_queryInfo.specifiedQueryInfo.sqlCount);
        exit(-1);
    }
7062

7063 7064 7065 7066 7067 7068 7069 7070
    pids  = malloc(
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(pthread_t));
    infos = malloc(
            g_queryInfo.specifiedQueryInfo.sqlCount *
            g_queryInfo.specifiedQueryInfo.concurrent *
            sizeof(threadInfo));
S
Shengliang Guan 已提交
7071 7072 7073 7074
    if ((NULL == pids) || (NULL == infos)) {
        errorPrint("%s() LN%d, malloc failed for create threads\n", __func__, __LINE__);
        exit(-1);
    }
7075

7076 7077 7078
    for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
        for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
            uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
7079 7080 7081 7082 7083
            threadInfo *pThreadInfo = infos + seq;
            pThreadInfo->threadID = seq;
            pThreadInfo->querySeq = i;
            pThreadInfo->taos = NULL;  // TODO: workaround to use separate taos connection;
            pthread_create(pids + seq, NULL, specifiedSubscribe, pThreadInfo);
7084
        }
S
Shengliang Guan 已提交
7085
    }
H
hzcheng 已提交
7086
  }
7087

7088 7089
  //==== create threads for super table query
  if (g_queryInfo.superQueryInfo.sqlCount <= 0) {
7090
    debugPrint("%s() LN%d, super table query sqlCount %"PRIu64".\n",
7091 7092 7093 7094
              __func__, __LINE__,
              g_queryInfo.superQueryInfo.sqlCount);
  } else {
    if ((g_queryInfo.superQueryInfo.sqlCount > 0)
7095
          && (g_queryInfo.superQueryInfo.threadCnt > 0)) {
7096 7097 7098
        pidsOfStable  = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7099
            sizeof(pthread_t));
7100 7101 7102
        infosOfStable = malloc(
                g_queryInfo.superQueryInfo.sqlCount *
                g_queryInfo.superQueryInfo.threadCnt *
7103
            sizeof(threadInfo));
7104 7105
        if ((NULL == pidsOfStable) || (NULL == infosOfStable)) {
            errorPrint("%s() LN%d, malloc failed for create threads\n",
7106
              __func__, __LINE__);
7107 7108 7109
            // taos_close(taos);
            exit(-1);
        }
7110

7111 7112
        int64_t ntables = g_queryInfo.superQueryInfo.childTblCount;
        int threads = g_queryInfo.superQueryInfo.threadCnt;
7113

7114 7115 7116 7117 7118
        int64_t a = ntables / threads;
        if (a < 1) {
            threads = ntables;
            a = 1;
        }
7119

7120 7121 7122 7123
        int64_t b = 0;
        if (threads != 0) {
            b = ntables % threads;
        }
7124

7125 7126 7127 7128
        for (uint64_t i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
            uint64_t startFrom = 0;
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
7129 7130 7131 7132 7133 7134 7135 7136 7137
                threadInfo *pThreadInfo = infosOfStable + seq;
                pThreadInfo->threadID = seq;
                pThreadInfo->querySeq = i;

                pThreadInfo->start_table_from = startFrom;
                pThreadInfo->ntables = j<b?a+1:a;
                pThreadInfo->end_table_to = j<b?startFrom+a:startFrom+a-1;
                startFrom = pThreadInfo->end_table_to + 1;
                pThreadInfo->taos = NULL; // TODO: workaround to use separate taos connection;
7138
                pthread_create(pidsOfStable + seq,
7139
                        NULL, superSubscribe, pThreadInfo);
7140 7141
            }
        }
7142

7143
        g_queryInfo.superQueryInfo.threadCnt = threads;
7144

7145 7146 7147 7148 7149 7150
        for (int i = 0; i < g_queryInfo.superQueryInfo.sqlCount; i++) {
            for (int j = 0; j < threads; j++) {
                uint64_t seq = i * threads + j;
                pthread_join(pidsOfStable[seq], NULL);
            }
        }
7151
    }
H
hzcheng 已提交
7152
  }
7153

7154 7155 7156 7157 7158
  for (int i = 0; i < g_queryInfo.specifiedQueryInfo.sqlCount; i++) {
    for (int j = 0; j < g_queryInfo.specifiedQueryInfo.concurrent; j++) {
        uint64_t seq = i * g_queryInfo.specifiedQueryInfo.concurrent + j;
        pthread_join(pids[seq], NULL);
    }
7159
  }
H
hzcheng 已提交
7160

7161
  tmfree((char*)pids);
7162
  tmfree((char*)infos);
H
hzcheng 已提交
7163

7164 7165
  tmfree((char*)pidsOfStable);
  tmfree((char*)infosOfStable);
7166
//   taos_close(taos);
7167
  return 0;
H
hzcheng 已提交
7168 7169
}

7170
static void initOfInsertMeta() {
7171
  memset(&g_Dbs, 0, sizeof(SDbs));
7172

7173
  // set default values
7174
  tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7175
  g_Dbs.port = 6030;
7176 7177
  tstrncpy(g_Dbs.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_Dbs.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
7178
  g_Dbs.threadCount = 2;
7179 7180

  g_Dbs.use_metric = g_args.use_metric;
L
Liu Tao 已提交
7181 7182
}

7183
static void initOfQueryMeta() {
7184
  memset(&g_queryInfo, 0, sizeof(SQueryMetaInfo));
7185

7186
  // set default values
7187
  tstrncpy(g_queryInfo.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7188
  g_queryInfo.port = 6030;
7189 7190
  tstrncpy(g_queryInfo.user, TSDB_DEFAULT_USER, MAX_USERNAME_SIZE);
  tstrncpy(g_queryInfo.password, TSDB_DEFAULT_PASS, MAX_PASSWORD_SIZE);
L
Liu Tao 已提交
7191 7192
}

7193
static void setParaFromArg(){
7194
  if (g_args.host) {
7195
    tstrncpy(g_Dbs.host, g_args.host, MAX_HOSTNAME_SIZE);
7196
  } else {
7197
    tstrncpy(g_Dbs.host, "127.0.0.1", MAX_HOSTNAME_SIZE);
7198
  }
L
Liu Tao 已提交
7199

7200
  if (g_args.user) {
7201
    tstrncpy(g_Dbs.user, g_args.user, MAX_USERNAME_SIZE);
7202
  }
7203 7204

  if (g_args.password) {
7205
    tstrncpy(g_Dbs.password, g_args.password, MAX_PASSWORD_SIZE);
7206 7207
  }

7208 7209
  if (g_args.port) {
    g_Dbs.port = g_args.port;
7210
  }
L
Liu Tao 已提交
7211

7212 7213 7214
  g_Dbs.threadCount = g_args.num_of_threads;
  g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;

7215 7216
  g_Dbs.dbCount = 1;
  g_Dbs.db[0].drop = 1;
7217

7218
  tstrncpy(g_Dbs.db[0].dbName, g_args.database, MAX_DB_NAME_SIZE);
7219
  g_Dbs.db[0].dbCfg.replica = g_args.replica;
7220
  tstrncpy(g_Dbs.db[0].dbCfg.precision, "ms", MAX_DB_NAME_SIZE);
L
Liu Tao 已提交
7221

7222
  tstrncpy(g_Dbs.resultFile, g_args.output_file, MAX_FILE_NAME_LEN);
7223 7224 7225 7226 7227

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

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

7229 7230
  char dataString[STRING_LEN];
  char **data_type = g_args.datatype;
7231

7232
  memset(dataString, 0, STRING_LEN);
L
Liu Tao 已提交
7233

7234 7235
  if (strcasecmp(data_type[0], "BINARY") == 0
          || strcasecmp(data_type[0], "BOOL") == 0
7236
          || strcasecmp(data_type[0], "NCHAR") == 0 ) {
7237
    g_Dbs.do_aggreFunc = false;
L
Liu Tao 已提交
7238
  }
H
hzcheng 已提交
7239

7240 7241 7242 7243 7244
  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;
7245
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
7246
    g_Dbs.asyncMode = g_args.async_mode;
7247

7248 7249 7250 7251
    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;
7252
    tstrncpy(g_Dbs.db[0].superTbls[0].childTblPrefix,
7253 7254
            g_args.tb_prefix, MAX_TB_NAME_SIZE);
    tstrncpy(g_Dbs.db[0].superTbls[0].dataSource, "rand", MAX_TB_NAME_SIZE);
S
Shuduo Sang 已提交
7255
    g_Dbs.db[0].superTbls[0].insertMode = g_args.iface;
7256
    tstrncpy(g_Dbs.db[0].superTbls[0].startTimestamp,
7257
            "2017-07-14 10:40:00.000", MAX_TB_NAME_SIZE);
7258
    g_Dbs.db[0].superTbls[0].timeStampStep = DEFAULT_TIMESTAMP_STEP;
7259

7260
    g_Dbs.db[0].superTbls[0].insertRows = g_args.num_of_DPT;
7261
    g_Dbs.db[0].superTbls[0].maxSqlLen = g_args.max_sql_len;
7262

7263 7264 7265 7266 7267
    g_Dbs.db[0].superTbls[0].columnCount = 0;
    for (int i = 0; i < MAX_NUM_DATATYPE; i++) {
      if (data_type[i] == NULL) {
        break;
      }
7268

7269
      tstrncpy(g_Dbs.db[0].superTbls[0].columns[i].dataType,
7270
              data_type[i], MAX_TB_NAME_SIZE);
7271
      g_Dbs.db[0].superTbls[0].columns[i].dataLen = g_args.len_of_binary;
7272 7273
      g_Dbs.db[0].superTbls[0].columnCount++;
    }
7274

7275 7276 7277
    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 {
7278 7279 7280 7281
      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);
7282
        g_Dbs.db[0].superTbls[0].columns[i].dataLen = 0;
7283 7284 7285
        g_Dbs.db[0].superTbls[0].columnCount++;
      }
    }
7286

7287 7288
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[0].dataType,
            "INT", MAX_TB_NAME_SIZE);
7289
    g_Dbs.db[0].superTbls[0].tags[0].dataLen = 0;
7290

7291 7292
    tstrncpy(g_Dbs.db[0].superTbls[0].tags[1].dataType,
            "BINARY", MAX_TB_NAME_SIZE);
7293 7294
    g_Dbs.db[0].superTbls[0].tags[1].dataLen = g_args.len_of_binary;
    g_Dbs.db[0].superTbls[0].tagCount = 2;
7295
  } else {
7296 7297
    g_Dbs.threadCountByCreateTbl = g_args.num_of_threads;
    g_Dbs.db[0].superTbls[0].tagCount = 0;
H
hzcheng 已提交
7298
  }
7299 7300 7301 7302 7303 7304
}

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

7306 7307 7308
  /* Compile regular expression */
  if (regcomp(&regex, reg, cflags) != 0) {
    printf("Fail to compile regex\n");
H
Hui Li 已提交
7309 7310 7311
    exit(-1);
  }

7312 7313 7314 7315 7316 7317 7318 7319 7320 7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335
  /* 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);
}

7336
static void querySqlFile(TAOS* taos, char* sqlFile)
7337 7338 7339 7340 7341 7342
{
  FILE *fp = fopen(sqlFile, "r");
  if (fp == NULL) {
    printf("failed to open file %s, reason:%s\n", sqlFile, strerror(errno));
    return;
  }
7343

7344 7345 7346 7347 7348 7349
  int       read_len = 0;
  char *    cmd = calloc(1, MAX_SQL_SIZE);
  size_t    cmd_len = 0;
  char *    line = NULL;
  size_t    line_len = 0;

7350
  double t = taosGetTimestampMs();
7351

7352
  while((read_len = tgetline(&line, &line_len, fp)) != -1) {
7353 7354 7355 7356 7357 7358 7359 7360 7361 7362 7363 7364
    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;
7365
    }
7366 7367

    memcpy(cmd + cmd_len, line, read_len);
7368
    verbosePrint("%s() LN%d cmd: %s\n", __func__, __LINE__, cmd);
7369 7370 7371
    if (0 != queryDbExec(taos, cmd, NO_INSERT_TYPE, false)) {
        errorPrint("%s() LN%d, queryDbExec %s failed!\n",
               __func__, __LINE__, cmd);
7372 7373 7374 7375 7376
        tmfree(cmd);
        tmfree(line);
        tmfclose(fp);
        return;
    }
7377 7378
    memset(cmd, 0, MAX_SQL_SIZE);
    cmd_len = 0;
H
hzcheng 已提交
7379 7380
  }

7381
  t = taosGetTimestampMs() - t;
7382
  printf("run %s took %.6f second(s)\n\n", sqlFile, t);
7383

7384 7385 7386 7387
  tmfree(cmd);
  tmfree(line);
  tmfclose(fp);
  return;
H
hzcheng 已提交
7388 7389
}

7390
static void testMetaFile() {
7391
    if (INSERT_TEST == g_args.test_mode) {
7392 7393
      if (g_Dbs.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_Dbs.cfgDir);
7394

7395
      insertTestProcess();
7396

7397
    } else if (QUERY_TEST == g_args.test_mode) {
7398 7399
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7400

7401
      queryTestProcess();
7402

7403
    } else if (SUBSCRIBE_TEST == g_args.test_mode) {
7404 7405
      if (g_queryInfo.cfgDir[0])
          taos_options(TSDB_OPTION_CONFIGDIR, g_queryInfo.cfgDir);
7406

7407
      subscribeTestProcess();
7408

7409 7410 7411
    }  else {
      ;
    }
7412
}
7413

7414
static void queryResult() {
7415
  // query data
7416

7417
  pthread_t read_id;
7418 7419 7420 7421
  threadInfo *pThreadInfo = malloc(sizeof(threadInfo));
  assert(pThreadInfo);
  pThreadInfo->start_time = 1500000000000;  // 2017-07-14 10:40:00.000
  pThreadInfo->start_table_from = 0;
7422

7423
  //pThreadInfo->do_aggreFunc = g_Dbs.do_aggreFunc;
7424
  if (g_args.use_metric) {
7425 7426 7427 7428
    pThreadInfo->ntables = g_Dbs.db[0].superTbls[0].childTblCount;
    pThreadInfo->end_table_to = g_Dbs.db[0].superTbls[0].childTblCount - 1;
    pThreadInfo->superTblInfo = &g_Dbs.db[0].superTbls[0];
    tstrncpy(pThreadInfo->tb_prefix,
7429 7430
          g_Dbs.db[0].superTbls[0].childTblPrefix, MAX_TB_NAME_SIZE);
  } else {
7431 7432 7433
    pThreadInfo->ntables = g_args.num_of_tables;
    pThreadInfo->end_table_to = g_args.num_of_tables -1;
    tstrncpy(pThreadInfo->tb_prefix, g_args.tb_prefix, MAX_TB_NAME_SIZE);
7434 7435
  }

7436
  pThreadInfo->taos = taos_connect(
7437 7438 7439 7440 7441
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
          g_Dbs.port);
7442
  if (pThreadInfo->taos == NULL) {
7443 7444
    errorPrint( "Failed to connect to TDengine, reason:%s\n",
            taos_errstr(NULL));
7445
    free(pThreadInfo);
7446 7447 7448
    exit(-1);
  }

7449
  tstrncpy(pThreadInfo->filePath, g_Dbs.resultFile, MAX_FILE_NAME_LEN);
7450 7451

  if (!g_Dbs.use_metric) {
7452
    pthread_create(&read_id, NULL, readTable, pThreadInfo);
7453
  } else {
7454
    pthread_create(&read_id, NULL, readMetric, pThreadInfo);
7455 7456
  }
  pthread_join(read_id, NULL);
7457 7458
  taos_close(pThreadInfo->taos);
  free(pThreadInfo);
7459 7460
}

7461 7462
static void testCmdLine() {

7463 7464 7465 7466 7467 7468 7469 7470 7471 7472
  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);
  }

7473 7474
  g_args.test_mode = INSERT_TEST;
  insertTestProcess();
7475

7476
  if (false == g_Dbs.insert_only)
7477
    queryResult();
7478 7479
}

7480 7481 7482
int main(int argc, char *argv[]) {
  parse_args(argc, argv, &g_args);

7483
  debugPrint("meta file: %s\n", g_args.metaFile);
7484 7485 7486

  if (g_args.metaFile) {
    initOfInsertMeta();
7487
    initOfQueryMeta();
7488 7489 7490 7491 7492 7493 7494 7495 7496 7497 7498 7499 7500

    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(
7501 7502 7503 7504
          g_Dbs.host,
          g_Dbs.user,
          g_Dbs.password,
          g_Dbs.db[0].dbName,
7505
          g_Dbs.port);
7506
      querySqlFile(qtaos, g_args.sqlFile);
7507 7508 7509 7510 7511
      taos_close(qtaos);

    } else {
      testCmdLine();
    }
7512 7513 7514

    if (g_dupstr)
        free(g_dupstr);
H
hzcheng 已提交
7515
  }
7516 7517

  return 0;
H
hzcheng 已提交
7518
}
7519